diff options
614 files changed, 16062 insertions, 7509 deletions
@@ -66,6 +66,7 @@ Juan Linietsky <reduzio@gmail.com> <red@kyoko> Julian Murgia <the.straton@gmail.com> Kanabenki <lucien.menassol@gmail.com> <18357657+Kanabenki@users.noreply.github.com> Kelly Thomas <kelly.thomas@hotmail.com.au> +Kongfa Waroros <gongpha@hotmail.com> K. S. Ernest (iFire) Lee <ernest.lee@chibifire.com> Leon Krause <lk@leonkrause.com> <eska@eska.me> Leon Krause <lk@leonkrause.com> <eska014@users.noreply.github.com> diff --git a/AUTHORS.md b/AUTHORS.md index 8c26d2892b..7c5eb0c56b 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -100,6 +100,7 @@ name is available. James Buck (jbuck3) Jérôme Gully (Nutriz) Jia Jun Chai (SkyLucilfer) + jmb462 Joan Fons Sanchez (JFonS) Johannes Witt (HaSa1002) Johan Manuel (29jm) @@ -108,6 +109,7 @@ name is available. Julian Murgia (StraToN) Justo Delgado (mrcdk) Kelly Thomas (KellyThomas) + Kongfa Waroros (gongpha) Kostadin Damyanov (Max-Might) K. S. Ernest (iFire) Lee (fire) lawnjelly diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index 96aedccd7f..6684978318 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -87,6 +87,8 @@ Files: ./servers/physics_3d/gjk_epa.cpp ./servers/physics_3d/joints/pin_joint_3d_sw.h ./servers/physics_3d/joints/slider_joint_3d_sw.cpp ./servers/physics_3d/joints/slider_joint_3d_sw.h + ./servers/physics_3d/soft_body_3d_sw.cpp + ./servers/physics_3d/soft_body_3d_sw.h Comment: Bullet Continuous Collision Detection and Physics Library Copyright: 2003-2008, Erwin Coumans 2007-2021, Juan Linietsky, Ariel Manzur. @@ -40,6 +40,7 @@ generous deed immortalized in the next stable release of Godot Engine. Alejandro Saucedo alex brown Andrew Dunai + anti666 Ben Nolan blurp CD @@ -51,6 +52,7 @@ generous deed immortalized in the next stable release of Godot Engine. Digital Grows Dov Zimring Edward Flick + Florian Neumann Gamechuck GameDev.net Hein-Pieter van Braam @@ -78,7 +80,6 @@ generous deed immortalized in the next stable release of Godot Engine. Steve Thomas Krampl Tristan Pemble - VilliHaukka Violin Iliev Xwdit @@ -98,7 +99,6 @@ generous deed immortalized in the next stable release of Godot Engine. Don B Ed Morley Ellen Poe - Florian Neumann Florian Rämisch Forge Gamejunkey @@ -110,6 +110,7 @@ generous deed immortalized in the next stable release of Godot Engine. Jon Woodward Karl Werf Klavdij Voncina + kuku Lex Steers Luke Maciej Pendolski @@ -144,14 +145,12 @@ generous deed immortalized in the next stable release of Godot Engine. Adam Nakonieczny Adrian Adamiak - Aleksey Korotkevich Alexander J Maynard Alex de la Mare Alexey Dyadchenko Alex Khayrullin alice gambrell Andreas Funke - André Frélicot Andrew Cunningham Antanas Paskauskas Antoni Batchelli @@ -180,7 +179,9 @@ generous deed immortalized in the next stable release of Godot Engine. Donn Eddy Easypete Edgar Sun + Eric Brand Eugenio Hugo Salgüero Jáñez + EXUREI flesk F S Gabrielius VaiÅ¡kÅ«nas @@ -207,6 +208,7 @@ generous deed immortalized in the next stable release of Godot Engine. Joshie Sparks Joshua Flores Joshua Lesperance + Juan T Chen Juan Velandia Judd Julian Todd @@ -217,7 +219,6 @@ generous deed immortalized in the next stable release of Godot Engine. kickmaniac kinfox Kos - kuku Lachie Lain Ballard Laszlo Kiss @@ -225,7 +226,7 @@ generous deed immortalized in the next stable release of Godot Engine. Leo Fidel R Liban Liam Smyth Luc-Frédéric Langis - luka duren + Åukasz Nowak MadScientistCarl Marcelo Dornbusch Lopes Marcus Dobler @@ -241,13 +242,13 @@ generous deed immortalized in the next stable release of Godot Engine. medecau Michael Michael Dürwald - Michael Noll Michael Policastro MightyPossum MikadoSC MuffinManKen + nate etan Nick Abousselam - Nick Barovic + Nicole Barovic Oliver Dick Oscar Campos Patrick Ting @@ -262,6 +263,7 @@ generous deed immortalized in the next stable release of Godot Engine. Raymond Harris Raz A Rene Tailleur + Rhodochrone Ricardo Alcantara Robert Larnach Robert Willes @@ -282,10 +284,11 @@ generous deed immortalized in the next stable release of Godot Engine. Shishir Tandale SKison Song Junwoo - spilldata + spacechase0 Stephan Hennion Steven Landow Stoned Xander + Sven F. Thomas Bjarnelöf Thomas Kurz Tim Howard @@ -310,6 +313,7 @@ generous deed immortalized in the next stable release of Godot Engine. 1D_Inc Abraham Haskins Adam + Adam Brown Adam Brunnmeier Adam Carr Adam Long @@ -322,7 +326,6 @@ generous deed immortalized in the next stable release of Godot Engine. Agustinus Arya Ahmet Kalyoncu Aidan O'Flannagain - AJ Austinson Aki Mimoto Alan Beauchamp Alberto Vilches @@ -335,7 +338,7 @@ generous deed immortalized in the next stable release of Godot Engine. Alexander Walter (SilvanuZ) Alexandre Beaudoin alex clavelle - Alex Schmidt + Alex (Well Done Games) Allan Davis Allen Schade Anders Marstein Kruke @@ -389,7 +392,6 @@ generous deed immortalized in the next stable release of Godot Engine. Chad Steadman Charles Alston Chris Chapin - Chris Jagusch Chris Langford Christian Clavet Christian Mauduit @@ -413,7 +415,9 @@ generous deed immortalized in the next stable release of Godot Engine. David May David Maziarka David Woodard + deadwithbread Devin Carraway + Diego Pereira Dmitry Fisher Dmytro Korchynskyi Dominik Wetzel @@ -431,20 +435,20 @@ generous deed immortalized in the next stable release of Godot Engine. Elgenzay Elias Nykrem Ephemeral + Eric Stokes Eric Walkingshaw Eric Williams Erkki Seppälä Evan Rose Faisal Alkubaisi Fancy Ants Studios + fby Fekinox Felix Bohmann Flaredown Forty Doubleu Francois Holland Frank - FuDiggity - gamedev by Celio Game Endeavor Gareth Knowles Gary Thomas @@ -477,12 +481,13 @@ generous deed immortalized in the next stable release of Godot Engine. Jako Danar James James A F Manley + James Quincy James Thomas Jamie Massey Jan Vetulani JARKKO PARVIAINEN + Jason Bolton Jason Uechi - Jean-Baptiste LEPESME Jeff Hungerford Jennifer Graves Jesse Dubay @@ -504,8 +509,9 @@ generous deed immortalized in the next stable release of Godot Engine. Jorge Araya Navarro Jose C. Rubio Joseph Catrambone + Josep Sanchez Josh Taylor - Josue David + Joshua Heidrich jromkjrom Juanfran Juan Uys @@ -526,7 +532,6 @@ generous deed immortalized in the next stable release of Godot Engine. Kenneth Lee Kent Jofur Ketafuki - Kevin McPhillips Kiri Jolly Kjetil Haugland Konstantin Goncharov @@ -544,7 +549,6 @@ generous deed immortalized in the next stable release of Godot Engine. Leonardo Dimano Lin Chear Linus Lind Lundgren - Lionel Gaillard Luigi Renna Luis Gaemperle Luis M @@ -564,6 +568,7 @@ generous deed immortalized in the next stable release of Godot Engine. Mathieu Matt Edwards Matthew Booe + Matt Sylvia Max Fiedler Maxime Blade Maxwell @@ -577,15 +582,17 @@ generous deed immortalized in the next stable release of Godot Engine. MichaÅ‚ Skwarek MidoriBunn 'tis BS Mikayla + Mike Mike Birkhead + Mike Copley Mike Cunningham Mitchell J. Wagner + MJacred Molinghu Molly Jameson MrAZIE Nathan Fish Nathaniel - Natrim nee neighty Neil Blakey-Milner @@ -593,7 +600,6 @@ generous deed immortalized in the next stable release of Godot Engine. Nerdforge Nerdyninja Nicholas - Nick Allen Nick Macholl Niclas Eriksen Nicolas Goll-Perrier @@ -602,16 +608,14 @@ generous deed immortalized in the next stable release of Godot Engine. Nima Farid NZ oceoh + Okatima OKV Oleg Reva Oleksandr Kryvonos Omar Delarosa Oriol Muñoz Princep Oscar Domingo - Parinya Teerakasemsuk - patricio lara briones Patrick Brock - Patrick Dully Patrick Nafarrete Paul Gieske PaweÅ‚ Kowal @@ -620,9 +624,9 @@ generous deed immortalized in the next stable release of Godot Engine. Peter Richmond Petrus Prinsloo Philip Cohoe + Philip Ludington (MrPhil) Pierre Caye Piotr Góral - Pipo Point08 Preethi Vaidyanathan pwab @@ -655,7 +659,6 @@ generous deed immortalized in the next stable release of Godot Engine. Sean Lynch Sebastian Michailidis SeongWan Kim - Serenitor Sergey Sergiy Onenko Shane @@ -671,6 +674,7 @@ generous deed immortalized in the next stable release of Godot Engine. smo1704 soft circles Squirrel + Stéphane Roussel Steve Cloete summerblind Sung soo Choi @@ -679,7 +683,6 @@ generous deed immortalized in the next stable release of Godot Engine. tannhauser_gate Tarch Terry - The Liquidator Theodore Lindsey TheVoiceInMyHead thomas @@ -690,12 +693,14 @@ generous deed immortalized in the next stable release of Godot Engine. Tim Erskine Tim Gleason Timothy B. MacDonald + TMoney Tobias Bradtke Tom Coxon Toni Duran Tony Zhao Torgeir Lilleskog Torsten Crass + toupeira Travis O'Brien Trent Skinner tril zerobyte @@ -725,8 +730,8 @@ generous deed immortalized in the next stable release of Godot Engine. x1212 xenomat Yegor Smirnov - Zack Yang Zak Stephens + Ðльдар Будагов è•æƒŸå… ## Bronze donors diff --git a/SConstruct b/SConstruct index 615ca447f9..3edf81129b 100644 --- a/SConstruct +++ b/SConstruct @@ -115,7 +115,7 @@ opts.Add(BoolVariable("tools", "Build the tools (a.k.a. the Godot editor)", True opts.Add(EnumVariable("target", "Compilation target", "debug", ("debug", "release_debug", "release"))) opts.Add("arch", "Platform-dependent architecture (arm/arm64/x86/x64/mips/...)", "") opts.Add(EnumVariable("bits", "Target platform bits", "default", ("default", "32", "64"))) -opts.Add(EnumVariable("optimize", "Optimization type", "speed", ("speed", "size"))) +opts.Add(EnumVariable("optimize", "Optimization type", "speed", ("speed", "size", "none"))) opts.Add(BoolVariable("production", "Set defaults to build Godot for use in production", False)) opts.Add(BoolVariable("use_lto", "Use link-time optimization", False)) @@ -302,10 +302,6 @@ if env_base["target"] == "debug": # http://scons.org/doc/production/HTML/scons-user/ch06s04.html env_base.SetOption("implicit_cache", 1) -if not env_base["tools"]: - # Export templates can't run unit test tool. - env_base["tests"] = False - if env_base["no_editor_splash"]: env_base.Append(CPPDEFINES=["NO_EDITOR_SPLASH"]) diff --git a/core/core_constants.cpp b/core/core_constants.cpp index 5abfee05bf..f40928350a 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -104,12 +104,12 @@ static Vector<_CoreConstant> _global_constants; #endif -VARIANT_ENUM_CAST(KeyList); +VARIANT_ENUM_CAST(Key); VARIANT_ENUM_CAST(KeyModifierMask); -VARIANT_ENUM_CAST(ButtonList); -VARIANT_ENUM_CAST(JoyButtonList); -VARIANT_ENUM_CAST(JoyAxisList); -VARIANT_ENUM_CAST(MidiMessageList); +VARIANT_ENUM_CAST(MouseButton); +VARIANT_ENUM_CAST(JoyButton); +VARIANT_ENUM_CAST(JoyAxis); +VARIANT_ENUM_CAST(MIDIMessage); void register_global_constants() { BIND_CORE_ENUM_CONSTANT(SIDE_LEFT); @@ -397,20 +397,20 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(KEY_MASK_GROUP_SWITCH); // mouse - BIND_CORE_ENUM_CONSTANT(BUTTON_LEFT); - BIND_CORE_ENUM_CONSTANT(BUTTON_RIGHT); - BIND_CORE_ENUM_CONSTANT(BUTTON_MIDDLE); - BIND_CORE_ENUM_CONSTANT(BUTTON_XBUTTON1); - BIND_CORE_ENUM_CONSTANT(BUTTON_XBUTTON2); - BIND_CORE_ENUM_CONSTANT(BUTTON_WHEEL_UP); - BIND_CORE_ENUM_CONSTANT(BUTTON_WHEEL_DOWN); - BIND_CORE_ENUM_CONSTANT(BUTTON_WHEEL_LEFT); - BIND_CORE_ENUM_CONSTANT(BUTTON_WHEEL_RIGHT); - BIND_CORE_ENUM_CONSTANT(BUTTON_MASK_LEFT); - BIND_CORE_ENUM_CONSTANT(BUTTON_MASK_RIGHT); - BIND_CORE_ENUM_CONSTANT(BUTTON_MASK_MIDDLE); - BIND_CORE_ENUM_CONSTANT(BUTTON_MASK_XBUTTON1); - BIND_CORE_ENUM_CONSTANT(BUTTON_MASK_XBUTTON2); + BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_LEFT); + BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_RIGHT); + BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MIDDLE); + BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_XBUTTON1); + BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_XBUTTON2); + BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_WHEEL_UP); + BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_WHEEL_DOWN); + BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_WHEEL_LEFT); + BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_WHEEL_RIGHT); + BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_LEFT); + BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_RIGHT); + BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_MIDDLE); + BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_XBUTTON1); + BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_XBUTTON2); // Joypad buttons BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_INVALID); diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp index 6b3953f588..fe913549c9 100644 --- a/core/crypto/crypto.cpp +++ b/core/crypto/crypto.cpp @@ -157,8 +157,9 @@ RES ResourceFormatLoaderCrypto::load(const String &p_path, const String &p_origi return key; } else if (el == "pub") { CryptoKey *key = CryptoKey::create(); - if (key) + if (key) { key->load(p_path, true); + } return key; } return nullptr; diff --git a/core/input/gamecontrollerdb.txt b/core/input/gamecontrollerdb.txt index 668a531b1f..f2a3135b05 100644 --- a/core/input/gamecontrollerdb.txt +++ b/core/input/gamecontrollerdb.txt @@ -13,10 +13,8 @@ 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, 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: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, -03000000c82d00015900000000000000,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, -03000000c82d00065280000000000000,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, 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, 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, @@ -40,6 +38,7 @@ 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, 03000000a00500003232000000000000,8Bitdo Zero GamePad,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, 030000008f0e00001200000000000000,Acme GA-02,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, +03000000c01100000355000011010000,ACRUX USB GAME PAD,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, 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, 030000006f0e00001413000000000000,Afterglow,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, 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, @@ -202,7 +201,7 @@ 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, 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, -030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,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, 03000000152000000182000000000000,NGDS,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:Windows, 03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, 030000007e0500000920000000000000,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:Windows, @@ -290,8 +289,8 @@ 03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, 0300000000050000289b000000000000,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,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, -03000000a30c00002500000000000000,Sega Genesis Mini 3B controller,a:b2,b:b1,start:b9,dpup:-a4,dpdown:+a4,dpleft:-a3,dpright:+a3,righttrigger:b5,platform:Windows, -03000000a30c00002400000000000000,Sega Mega Drive Mini 6B controller,a:b2,b:b1,start:b9,dpup:-a4,dpdown:+a4,dpleft:-a3,dpright:+a3,rightshoulder:b4,righttrigger:b5,x:b3,y:b0,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, 030000005e0400008e02000000007801,ShanWan PS3/PC Wired GamePad,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, 03000000341a00000208000000000000,SL-6555-SBK,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,SL-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, @@ -335,7 +334,7 @@ 03000000790000001b18000000000000,Venom Arcade Joystick,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, 030000006f0e00000302000000000000,Victrix Pro Fight Stick for 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, 030000006f0e00000702000000000000,Victrix Pro Fight Stick for 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,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, +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, 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, 030000005e040000ff02000000007801,Xbox One Elite 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, 030000005e040000130b000000000000,Xbox Series 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, @@ -383,6 +382,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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 Wired 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 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:Mac OS X, +030000008f0e00000300000007010000,GreenAsia Inc. USB Joystick,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,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: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, 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, 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, @@ -425,7 +425,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c62400002a89000000010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,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, 03000000c62400002b89000000010000,MOGA XP5-A 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, 03000000632500007505000000020000,NEOGEO mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X, -030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Mac OS X, +030000001008000001e5000006010000,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:Mac OS X, 03000000d620000011a7000000020000,Nintendo Switch Core (Plus) Wired 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, 030000007e0500000920000000000000,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:Mac OS X, 030000007e0500000920000001000000,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:Mac OS X, @@ -460,7 +460,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000b40400000a01000000000000,Sega Saturn USB Gamepad,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, 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,Sony DualSense,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:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000e60c000000010000,Sony DualSense,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, 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, 030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,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, @@ -468,6 +468,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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, 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, +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, 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, 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, @@ -526,13 +527,14 @@ 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 Gamepad,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, -030000005e0400008e02000020010000,8BitDo Wireless Adapter (XInput),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 Wireless Adapter (DInput),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, +030000005e0400008e02000020010000,8BitDo Wireless Adapter (XInput),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, 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, -050000005e040000e002000030110000,8BitDo Zero 2 (XInput),a:b0,b:b1,back:b6,leftshoulder:b4,rightshoulder:b5,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,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, +050000005e040000e002000030110000,8BitDo Zero 2 (XInput),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, 05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, 05000000a00500003232000008010000,8Bitdo Zero GamePad,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, +03000000c01100000355000011010000,ACRUX USB GAME PAD,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, 030000006f0e00001302000000010000,Afterglow,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, 030000006f0e00003901000020060000,Afterglow Controller for 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, 030000006f0e00003901000000430000,Afterglow Prismatic 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, @@ -565,6 +567,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006f0e00000104000000010000,Gamestop Logic3 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, 030000008f0e00000800000010010000,Gasia Co. Ltd PS(R) 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, 030000006f0e00001304000000010000,Generic X-Box pad,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, +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 Ltd USB 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 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:Linux, @@ -628,7 +631,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006d0400000ac2000010010000,Logitech Inc. 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:Linux, 030000006d04000018c2000010010000,Logitech RumblePad 2,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, 030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux, -050000004d4f435554452d3035305800,M54-PC,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,platform:Linux, +050000004d4f435554452d3035305800,M54-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, 05000000380700006652000025010000,Mad Catz C.T.R.L.R ,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, 03000000380700005032000011010000,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:Linux, 03000000380700005082000011010000,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:Linux, @@ -673,7 +676,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000250900006688000000010000,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: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, 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, -030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,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, 060000007e0500000820000000000000,Nintendo Combined Joy-Cons (joycond),a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,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, 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:b2,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:b0,y:b3,platform:Linux, @@ -690,6 +693,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 19000000010000000100000001010000,odroidgo2_joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux, 19000000010000000200000011000000,odroidgo2_joypad_v11,a:b1,b:b0,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b12,leftshoulder:b4,leftstick:b14,lefttrigger:b13,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b16,start:b17,x:b2,y:b3,platform:Linux, 030000005e0400000202000000010000,Old Xbox pad,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, +03000000c0160000dc27000001010000,OnyxSoft Dual JoyDivision,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:Linux, 05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, 05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, 03000000830500005020000010010000,Padix Co. Ltd. Rockfire PSX/USB Bridge,a:b0,b:b1,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:a3,start:b11,x:b2,y:b3,platform:Linux, @@ -705,8 +709,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006f0e00000901000011010000,PDP Versus Fighting Pad,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, 030000006f0e0000a802000023020000,PDP Wired Controller for Xbox One,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, 030000006f0e00008501000011010000,PDP Wired Fight Pad Pro for Nintendo Switch,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, -05000000491900000204000000000000,PG-9118,x:b76,a:b73,b:b74,y:b77,back:b83,start:b84,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b79,lefttrigger:b81,rightshoulder:b80,righttrigger:b82,leftstick:b86,rightstick:b87,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux, 0500000049190000030400001b010000,PG-9099,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:Linux, +05000000491900000204000000000000,PG-9118,a:b73,b:b74,back:b83,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b79,leftstick:b86,lefttrigger:b81,leftx:a0,lefty:a1,rightshoulder:b80,rightstick:b87,righttrigger:b82,rightx:a2,righty:a3,start:b84,x:b76,y:b77,platform:Linux, 030000004c050000da0c000011010000,Playstation 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, 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, @@ -783,8 +787,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000f025000021c1000010010000,ShanWan Gioteck PS3 Wired 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 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, 03000000bc2000000055000010010000,ShanWan PS3/PC Wired GamePad,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 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, 03000000632500002305000010010000,ShanWan 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:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 03000000341a00000908000010010000,SL-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:Linux, +030000004c050000e60c000011810000,Sony DualSense,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, +030000004c050000e60c000000006800,Sony DualSense,a:b0,b:b1,x:b2,y:b3,back:b4,guide:b5,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b9,rightshoulder:b10,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Linux, +050000004c050000e60c000000810000,Sony DualSense ,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, +030000004c050000e60c000000016800,Sony DualSense ,a:b0,b:b1,x:b2,y:b3,back:b4,guide:b5,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b9,rightshoulder:b10,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,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, 030000005e0400008e02000073050000,Speedlink TORID Wireless 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, 030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,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, @@ -792,7 +801,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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, 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, 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, -03000000de2800004211000001000000,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: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,rightshoulder:b7,righttrigger:b9,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, @@ -809,7 +817,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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, 03000000457500002211000010010000,SZMY-POWER CO. LTD. 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, 030000008f0e00000d31000010010000,SZMY-POWER CO. LTD. 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:Linux, -030000008f0e00001431000010010000,SZMY-POWER CO. LTD. PS3 gamepad,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux, +030000008f0e00001431000010010000,SZMY-POWER CO. LTD. PS3 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, 030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,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, 030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,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, 030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,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, @@ -864,7 +872,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, xinput,XInput 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, 03000000120c0000100e000011010000,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:Linux, 03000000120c0000101e000011010000,ZEROPLUS P4 Wired 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:Linux, -03000000c0160000dc27000001010000,OnyxSoft Dual JoyDivision,platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b6,leftshoulder:b4,rightshoulder:b5,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0, # Android 05000000c82d000006500000ffff3f00,8BitDo M30 Gamepad,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, @@ -888,7 +895,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 0500000031366332860c44aadfff0f00,GS Gamepad,a:b0,b:b1,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:b2,y:b3,platform:Android, 0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b1,b:b0,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b3,y:b2,platform:Android, 64633436313965656664373634323364,Microsoft X-Box 360 pad,a:b0,b:b1,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, -7573622067616d657061642020202020,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,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, 37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,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, 4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,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, @@ -936,8 +943,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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, 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, 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, -050000004c050000cc090000ff876d01,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,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,,platform:iOS, 050000004c050000cc090000ff870001,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,touchpad:b11,x:b2,y:b3,platform:iOS, +050000004c050000cc090000ff876d01,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,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, 05000000ac0500000300000000006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS, 05000000ac0500000300000043006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS, 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:iOS, diff --git a/core/input/godotcontrollerdb.txt b/core/input/godotcontrollerdb.txt index c43cd6c8ac..db612f04d2 100644 --- a/core/input/godotcontrollerdb.txt +++ b/core/input/godotcontrollerdb.txt @@ -28,6 +28,7 @@ MacOSX05832060,iBuffalo BSGP801,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulde Linux0e8f3013,HuiJia USB GamePad,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftshoulder:b6,rightshoulder:b7,dpup:-a1,dpleft:-a0,dpdown:+a1,dpright:+a0,platform:Javascript Windows0e8f3013,HuiJia USB GamePad,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftshoulder:b6,rightshoulder:b7,dpup:-a1,dpleft:-a0,dpdown:+a1,dpright:+a0,platform:Javascript MacOSX0e8f3013,HuiJia USB GamePad,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftshoulder:b6,rightshoulder:b7,dpup:-a4,dpleft:-a3,dpdown:+a4,dpright:+a3,platform:Javascript +Linux046dc216,046d-c216-Logitech Logitech Dual Action,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:-a5,dpleft:-a4,dpdown:+a5,dpright:+a4,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Javascript # UWP __UWP_GAMEPAD__,Xbox Controller,a:b2,b:b3,x:b4,y:b5,start:b0,back:b1,leftstick:b12,rightstick:b13,leftshoulder:b10,rightshoulder:b11,dpup:b6,dpdown:b7,dpleft:b8,dpright:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:UWP, diff --git a/core/input/input.cpp b/core/input/input.cpp index 3a8c1c1628..627944210f 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -560,11 +560,11 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em button_event->set_position(st->get_position()); button_event->set_global_position(st->get_position()); button_event->set_pressed(st->is_pressed()); - button_event->set_button_index(BUTTON_LEFT); + button_event->set_button_index(MOUSE_BUTTON_LEFT); if (st->is_pressed()) { - button_event->set_button_mask(mouse_button_mask | (1 << (BUTTON_LEFT - 1))); + button_event->set_button_mask(mouse_button_mask | (1 << (MOUSE_BUTTON_LEFT - 1))); } else { - button_event->set_button_mask(mouse_button_mask & ~(1 << (BUTTON_LEFT - 1))); + button_event->set_button_mask(mouse_button_mask & ~(1 << (MOUSE_BUTTON_LEFT - 1))); } _parse_input_event_impl(button_event, true); @@ -792,8 +792,8 @@ void Input::ensure_touch_mouse_raised() { button_event->set_position(mouse_pos); button_event->set_global_position(mouse_pos); button_event->set_pressed(false); - button_event->set_button_index(BUTTON_LEFT); - button_event->set_button_mask(mouse_button_mask & ~(1 << (BUTTON_LEFT - 1))); + button_event->set_button_index(MOUSE_BUTTON_LEFT); + button_event->set_button_mask(mouse_button_mask & ~(1 << (MOUSE_BUTTON_LEFT - 1))); _parse_input_event_impl(button_event, true); } @@ -907,7 +907,7 @@ void Input::joy_button(int p_device, int p_button, bool p_pressed) { // no event? } -void Input::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) { +void Input::joy_axis(int p_device, int p_axis, const JoyAxisValue &p_value) { _THREAD_SAFE_METHOD_; ERR_FAIL_INDEX(p_axis, JOY_AXIS_MAX); @@ -921,12 +921,12 @@ void Input::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) { //when changing direction quickly, insert fake event to release pending inputmap actions float last = joy.last_axis[p_axis]; if (p_value.min == 0 && (last < 0.25 || last > 0.75) && (last - 0.5) * (p_value.value - 0.5) < 0) { - JoyAxis jx; + JoyAxisValue jx; jx.min = p_value.min; jx.value = p_value.value < 0.5 ? 0.6 : 0.4; joy_axis(p_device, p_axis, jx); } else if (ABS(last) > 0.5 && last * p_value.value <= 0) { - JoyAxis jx; + JoyAxisValue jx; jx.min = p_value.min; jx.value = last > 0 ? 0.1 : -0.1; joy_axis(p_device, p_axis, jx); @@ -1206,22 +1206,22 @@ void Input::_get_mapped_hat_events(const JoyDeviceMapping &mapping, int p_hat, J } } -JoyButtonList Input::_get_output_button(String output) { +JoyButton Input::_get_output_button(String output) { for (int i = 0; i < JOY_BUTTON_SDL_MAX; i++) { if (output == _joy_buttons[i]) { - return JoyButtonList(i); + return JoyButton(i); } } - return JoyButtonList::JOY_BUTTON_INVALID; + return JoyButton::JOY_BUTTON_INVALID; } -JoyAxisList Input::_get_output_axis(String output) { +JoyAxis Input::_get_output_axis(String output) { for (int i = 0; i < JOY_AXIS_SDL_MAX; i++) { if (output == _joy_axes[i]) { - return JoyAxisList(i); + return JoyAxis(i); } } - return JoyAxisList::JOY_AXIS_INVALID; + return JoyAxis::JOY_AXIS_INVALID; } void Input::parse_mapping(String p_mapping) { @@ -1279,8 +1279,8 @@ void Input::parse_mapping(String p_mapping) { input = input.left(input.length() - 1); } - JoyButtonList output_button = _get_output_button(output); - JoyAxisList output_axis = _get_output_axis(output); + JoyButton output_button = _get_output_button(output); + JoyAxis output_axis = _get_output_axis(output); ERR_CONTINUE_MSG(output_button == JOY_BUTTON_INVALID && output_axis == JOY_AXIS_INVALID, String(entry[idx] + "\nUnrecognised output string: " + output)); ERR_CONTINUE_MSG(output_button != JOY_BUTTON_INVALID && output_axis != JOY_AXIS_INVALID, diff --git a/core/input/input.h b/core/input/input.h index 0e3af42381..99b45db325 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -91,7 +91,7 @@ public: JOYPADS_MAX = 16, }; - struct JoyAxis { + struct JoyAxisValue { int min; float value; }; @@ -199,10 +199,10 @@ private: JoyType outputType; union { - JoyButtonList button; + JoyButton button; struct { - JoyAxisList axis; + JoyAxis axis; JoyAxisRange range; } axis; @@ -220,8 +220,8 @@ private: JoyEvent _get_mapped_button_event(const JoyDeviceMapping &mapping, int p_button); JoyEvent _get_mapped_axis_event(const JoyDeviceMapping &mapping, int p_axis, float p_value); void _get_mapped_hat_events(const JoyDeviceMapping &mapping, int p_hat, JoyEvent r_events[HAT_MAX]); - JoyButtonList _get_output_button(String output); - JoyAxisList _get_output_axis(String output); + JoyButton _get_output_button(String output); + JoyAxis _get_output_axis(String output); void _button_event(int p_device, int p_index, bool p_pressed); void _axis_event(int p_device, int p_axis, float p_value); @@ -325,7 +325,7 @@ public: void parse_mapping(String p_mapping); void joy_button(int p_device, int p_button, bool p_pressed); - void joy_axis(int p_device, int p_axis, const JoyAxis &p_value); + void joy_axis(int p_device, int p_axis, const JoyAxisValue &p_value); void joy_hat(int p_device, int p_val); void add_joy_mapping(String p_mapping, bool p_update_existing = false); diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index c6910d2b1f..99cc51b95e 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -619,15 +619,15 @@ String InputEventMouseButton::as_text() const { // Button int idx = get_button_index(); switch (idx) { - case BUTTON_LEFT: - case BUTTON_RIGHT: - case BUTTON_MIDDLE: - case BUTTON_WHEEL_UP: - case BUTTON_WHEEL_DOWN: - case BUTTON_WHEEL_LEFT: - case BUTTON_WHEEL_RIGHT: - case BUTTON_XBUTTON1: - case BUTTON_XBUTTON2: + case MOUSE_BUTTON_LEFT: + case MOUSE_BUTTON_RIGHT: + case MOUSE_BUTTON_MIDDLE: + case MOUSE_BUTTON_WHEEL_UP: + case MOUSE_BUTTON_WHEEL_DOWN: + case MOUSE_BUTTON_WHEEL_LEFT: + case MOUSE_BUTTON_WHEEL_RIGHT: + case MOUSE_BUTTON_XBUTTON1: + case MOUSE_BUTTON_XBUTTON2: full_string += RTR(_mouse_button_descriptions[idx - 1]); // button index starts from 1, array index starts from 0, so subtract 1 break; default: @@ -651,15 +651,15 @@ String InputEventMouseButton::to_string() { String button_string = itos(idx); switch (idx) { - case BUTTON_LEFT: - case BUTTON_RIGHT: - case BUTTON_MIDDLE: - case BUTTON_WHEEL_UP: - case BUTTON_WHEEL_DOWN: - case BUTTON_WHEEL_LEFT: - case BUTTON_WHEEL_RIGHT: - case BUTTON_XBUTTON1: - case BUTTON_XBUTTON2: + case MOUSE_BUTTON_LEFT: + case MOUSE_BUTTON_RIGHT: + case MOUSE_BUTTON_MIDDLE: + case MOUSE_BUTTON_WHEEL_UP: + case MOUSE_BUTTON_WHEEL_DOWN: + case MOUSE_BUTTON_WHEEL_LEFT: + case MOUSE_BUTTON_WHEEL_RIGHT: + case MOUSE_BUTTON_XBUTTON1: + case MOUSE_BUTTON_XBUTTON2: button_string += " (" + RTR(_mouse_button_descriptions[idx - 1]) + ")"; // button index starts from 1, array index starts from 0, so subtract 1 break; default: @@ -761,20 +761,20 @@ String InputEventMouseMotion::to_string() { int button_mask = get_button_mask(); String button_mask_string = itos(button_mask); switch (get_button_mask()) { - case BUTTON_MASK_LEFT: - button_mask_string += " (" + RTR(_mouse_button_descriptions[BUTTON_LEFT - 1]) + ")"; + case MOUSE_BUTTON_MASK_LEFT: + button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_LEFT - 1]) + ")"; break; - case BUTTON_MASK_MIDDLE: - button_mask_string += " (" + RTR(_mouse_button_descriptions[BUTTON_MIDDLE - 1]) + ")"; + case MOUSE_BUTTON_MASK_MIDDLE: + button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_MIDDLE - 1]) + ")"; break; - case BUTTON_MASK_RIGHT: - button_mask_string += " (" + RTR(_mouse_button_descriptions[BUTTON_RIGHT - 1]) + ")"; + case MOUSE_BUTTON_MASK_RIGHT: + button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_RIGHT - 1]) + ")"; break; - case BUTTON_MASK_XBUTTON1: - button_mask_string += " (" + RTR(_mouse_button_descriptions[BUTTON_XBUTTON1 - 1]) + ")"; + case MOUSE_BUTTON_MASK_XBUTTON1: + button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_XBUTTON1 - 1]) + ")"; break; - case BUTTON_MASK_XBUTTON2: - button_mask_string += " (" + RTR(_mouse_button_descriptions[BUTTON_XBUTTON2 - 1]) + ")"; + case MOUSE_BUTTON_MASK_XBUTTON2: + button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_XBUTTON2 - 1]) + ")"; break; default: break; diff --git a/core/input/input_event.h b/core/input/input_event.h index df81b9fc75..a1e7df5969 100644 --- a/core/input/input_event.h +++ b/core/input/input_event.h @@ -42,24 +42,24 @@ * The events are pretty obvious. */ -enum ButtonList { - BUTTON_LEFT = 1, - BUTTON_RIGHT = 2, - BUTTON_MIDDLE = 3, - BUTTON_WHEEL_UP = 4, - BUTTON_WHEEL_DOWN = 5, - BUTTON_WHEEL_LEFT = 6, - BUTTON_WHEEL_RIGHT = 7, - BUTTON_XBUTTON1 = 8, - BUTTON_XBUTTON2 = 9, - BUTTON_MASK_LEFT = (1 << (BUTTON_LEFT - 1)), - BUTTON_MASK_RIGHT = (1 << (BUTTON_RIGHT - 1)), - BUTTON_MASK_MIDDLE = (1 << (BUTTON_MIDDLE - 1)), - BUTTON_MASK_XBUTTON1 = (1 << (BUTTON_XBUTTON1 - 1)), - BUTTON_MASK_XBUTTON2 = (1 << (BUTTON_XBUTTON2 - 1)) +enum MouseButton { + MOUSE_BUTTON_LEFT = 1, + MOUSE_BUTTON_RIGHT = 2, + MOUSE_BUTTON_MIDDLE = 3, + MOUSE_BUTTON_WHEEL_UP = 4, + MOUSE_BUTTON_WHEEL_DOWN = 5, + MOUSE_BUTTON_WHEEL_LEFT = 6, + MOUSE_BUTTON_WHEEL_RIGHT = 7, + MOUSE_BUTTON_XBUTTON1 = 8, + MOUSE_BUTTON_XBUTTON2 = 9, + MOUSE_BUTTON_MASK_LEFT = (1 << (MOUSE_BUTTON_LEFT - 1)), + MOUSE_BUTTON_MASK_RIGHT = (1 << (MOUSE_BUTTON_RIGHT - 1)), + MOUSE_BUTTON_MASK_MIDDLE = (1 << (MOUSE_BUTTON_MIDDLE - 1)), + MOUSE_BUTTON_MASK_XBUTTON1 = (1 << (MOUSE_BUTTON_XBUTTON1 - 1)), + MOUSE_BUTTON_MASK_XBUTTON2 = (1 << (MOUSE_BUTTON_XBUTTON2 - 1)) }; -enum JoyButtonList { +enum JoyButton { JOY_BUTTON_INVALID = -1, JOY_BUTTON_A = 0, JOY_BUTTON_B = 1, @@ -86,7 +86,7 @@ enum JoyButtonList { JOY_BUTTON_MAX = 36, // Android supports up to 36 buttons. }; -enum JoyAxisList { +enum JoyAxis { JOY_AXIS_INVALID = -1, JOY_AXIS_LEFT_X = 0, JOY_AXIS_LEFT_Y = 1, @@ -98,7 +98,7 @@ enum JoyAxisList { JOY_AXIS_MAX = 10, // OpenVR supports up to 5 Joysticks making a total of 10 axes. }; -enum MidiMessageList { +enum MIDIMessage { MIDI_MESSAGE_NOTE_OFF = 0x8, MIDI_MESSAGE_NOTE_ON = 0x9, MIDI_MESSAGE_AFTERTOUCH = 0xA, diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index 015c1f0d90..10f68f3cef 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -295,6 +295,9 @@ Error ConfigFile::_parse(const String &p_path, VariantParser::Stream *p_stream) return OK; } +void ConfigFile::clear() { + values.clear(); +} void ConfigFile::_bind_methods() { ClassDB::bind_method(D_METHOD("set_value", "section", "key", "value"), &ConfigFile::set_value); ClassDB::bind_method(D_METHOD("get_value", "section", "key", "default"), &ConfigFile::get_value, DEFVAL(Variant())); @@ -317,4 +320,6 @@ void ConfigFile::_bind_methods() { ClassDB::bind_method(D_METHOD("save_encrypted", "path", "key"), &ConfigFile::save_encrypted); ClassDB::bind_method(D_METHOD("save_encrypted_pass", "path", "password"), &ConfigFile::save_encrypted_pass); + + ClassDB::bind_method(D_METHOD("clear"), &ConfigFile::clear); } diff --git a/core/io/config_file.h b/core/io/config_file.h index 386d304f07..1b28257c60 100644 --- a/core/io/config_file.h +++ b/core/io/config_file.h @@ -68,6 +68,8 @@ public: Error load(const String &p_path); Error parse(const String &p_data); + void clear(); + Error load_encrypted(const String &p_path, const Vector<uint8_t> &p_key); Error load_encrypted_pass(const String &p_path, const String &p_pass); diff --git a/core/io/image.cpp b/core/io/image.cpp index 5d46d75efe..873eb66f33 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -3010,26 +3010,28 @@ Image::UsedChannels Image::detect_used_channels(CompressSource p_source) { ERR_FAIL_COND_V(is_compressed(), USED_CHANNELS_RGBA); bool r = false, g = false, b = false, a = false, c = false; - for (int i = 0; i < width; i++) { - for (int j = 0; j < height; j++) { - Color col = get_pixel(i, j); + const uint8_t *data_ptr = data.ptr(); - if (col.r > 0.001) { - r = true; - } - if (col.g > 0.001) { - g = true; - } - if (col.b > 0.001) { - b = true; - } - if (col.a < 0.999) { - a = true; - } + uint32_t data_total = width * height; - if (col.r != col.b || col.r != col.g || col.b != col.g) { - c = true; - } + for (uint32_t i = 0; i < data_total; i++) { + Color col = _get_color_at_ofs(data_ptr, i); + + if (col.r > 0.001) { + r = true; + } + if (col.g > 0.001) { + g = true; + } + if (col.b > 0.001) { + b = true; + } + if (col.a < 0.999) { + a = true; + } + + if (col.r != col.b || col.r != col.g || col.b != col.g) { + c = true; } } diff --git a/core/io/json.cpp b/core/io/json.cpp index 0d9117fdda..394cf216e8 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -347,7 +347,6 @@ Error JSON::_parse_value(Variant &value, Token &token, const char32_t *p_str, in return err; } value = d; - return OK; } else if (token.type == TK_BRACKET_OPEN) { Array a; Error err = _parse_array(a, p_str, index, p_len, line, r_err_str); @@ -355,8 +354,6 @@ Error JSON::_parse_value(Variant &value, Token &token, const char32_t *p_str, in return err; } value = a; - return OK; - } else if (token.type == TK_IDENTIFIER) { String id = token.value; if (id == "true") { @@ -369,18 +366,16 @@ Error JSON::_parse_value(Variant &value, Token &token, const char32_t *p_str, in r_err_str = "Expected 'true','false' or 'null', got '" + id + "'."; return ERR_PARSE_ERROR; } - return OK; - } else if (token.type == TK_NUMBER) { value = token.value; - return OK; } else if (token.type == TK_STRING) { value = token.value; - return OK; } else { r_err_str = "Expected value, got " + String(tk_name[token.type]) + "."; return ERR_PARSE_ERROR; } + + return OK; } Error JSON::_parse_array(Array &array, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str) { @@ -499,6 +494,19 @@ Error JSON::parse(const String &p_json, Variant &r_ret, String &r_err_str, int & err = _parse_value(r_ret, token, str, idx, len, r_err_line, r_err_str); + // Check if EOF is reached + // or it's a type of the next token. + if (err == OK && idx < len) { + err = _get_token(str, idx, len, token, r_err_line, r_err_str); + + if (err || token.type != TK_EOF) { + r_err_str = "Expected 'EOF'"; + // Reset return value to empty `Variant` + r_ret = Variant(); + return ERR_PARSE_ERROR; + } + } + return err; } diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h index 91efec5534..eeb486073e 100644 --- a/core/io/resource_importer.h +++ b/core/io/resource_importer.h @@ -115,6 +115,9 @@ public: ImportOption() {} }; + virtual bool has_advanced_options() const { return false; } + virtual void show_advanced_options(const String &p_path) {} + virtual int get_preset_count() const { return 0; } virtual String get_preset_name(int p_idx) const { return String(); } diff --git a/core/math/dynamic_bvh.cpp b/core/math/dynamic_bvh.cpp index 4639a52278..200095d8cb 100644 --- a/core/math/dynamic_bvh.cpp +++ b/core/math/dynamic_bvh.cpp @@ -61,7 +61,7 @@ DynamicBVH::Node *DynamicBVH::_create_node_with_volume(Node *p_parent, const Vol void DynamicBVH::_insert_leaf(Node *p_root, Node *p_leaf) { if (!bvh_root) { bvh_root = p_leaf; - p_leaf->parent = 0; + p_leaf->parent = nullptr; } else { if (!p_root->is_leaf()) { do { @@ -71,7 +71,7 @@ void DynamicBVH::_insert_leaf(Node *p_root, Node *p_leaf) { } while (!p_root->is_leaf()); } Node *prev = p_root->parent; - Node *node = _create_node_with_volume(prev, p_leaf->volume.merge(p_root->volume), 0); + Node *node = _create_node_with_volume(prev, p_leaf->volume.merge(p_root->volume), nullptr); if (prev) { prev->childs[p_root->get_index_in_parent()] = node; node->childs[0] = p_root; @@ -85,7 +85,7 @@ void DynamicBVH::_insert_leaf(Node *p_root, Node *p_leaf) { break; } node = prev; - } while (0 != (prev = node->parent)); + } while (nullptr != (prev = node->parent)); } else { node->childs[0] = p_root; p_root->parent = node; @@ -98,8 +98,8 @@ void DynamicBVH::_insert_leaf(Node *p_root, Node *p_leaf) { DynamicBVH::Node *DynamicBVH::_remove_leaf(Node *leaf) { if (leaf == bvh_root) { - bvh_root = 0; - return (0); + bvh_root = nullptr; + return (nullptr); } else { Node *parent = leaf->parent; Node *prev = parent->parent; @@ -113,13 +113,14 @@ DynamicBVH::Node *DynamicBVH::_remove_leaf(Node *leaf) { prev->volume = prev->childs[0]->volume.merge(prev->childs[1]->volume); if (pb.is_not_equal_to(prev->volume)) { prev = prev->parent; - } else + } else { break; + } } return (prev ? prev : bvh_root); } else { bvh_root = sibling; - sibling->parent = 0; + sibling->parent = nullptr; _delete_node(parent); return (bvh_root); } @@ -262,10 +263,11 @@ DynamicBVH::Node *DynamicBVH::_node_sort(Node *n, Node *&r) { Node *s = p->childs[j]; Node *q = p->parent; ERR_FAIL_COND_V(n != p->childs[i], nullptr); - if (q) + if (q) { q->childs[p->get_index_in_parent()] = n; - else + } else { r = n; + } s->parent = n; p->parent = n; n->parent = q; @@ -307,8 +309,9 @@ void DynamicBVH::optimize_top_down(int bu_threshold) { } void DynamicBVH::optimize_incremental(int passes) { - if (passes < 0) + if (passes < 0) { passes = total_leaves; + } if (bvh_root && (passes > 0)) { do { Node *node = bvh_root; @@ -345,8 +348,9 @@ void DynamicBVH::_update(Node *leaf, int lookahead) { for (int i = 0; (i < lookahead) && root->parent; ++i) { root = root->parent; } - } else + } else { root = bvh_root; + } } _insert_leaf(root, leaf); } @@ -370,8 +374,9 @@ bool DynamicBVH::update(const ID &p_id, const AABB &p_box) { for (int i = 0; (i < lkhd) && base->parent; ++i) { base = base->parent; } - } else + } else { base = bvh_root; + } } leaf->volume = volume; _insert_leaf(base, leaf); diff --git a/core/math/dynamic_bvh.h b/core/math/dynamic_bvh.h index c71db2d24d..3fb22515a2 100644 --- a/core/math/dynamic_bvh.h +++ b/core/math/dynamic_bvh.h @@ -87,14 +87,16 @@ private: _FORCE_INLINE_ Volume merge(const Volume &b) const { Volume r; for (int i = 0; i < 3; ++i) { - if (min[i] < b.min[i]) + if (min[i] < b.min[i]) { r.min[i] = min[i]; - else + } else { r.min[i] = b.min[i]; - if (max[i] > b.max[i]) + } + if (max[i] > b.max[i]) { r.max[i] = max[i]; - else + } else { r.max[i] = b.max[i]; + } } return r; } @@ -202,10 +204,11 @@ private: // int count_leaves() const { - if (is_internal()) + if (is_internal()) { return childs[0]->count_leaves() + childs[1]->count_leaves(); - else + } else { return (1); + } } bool is_left_of_axis(const Vector3 &org, const Vector3 &axis) const { @@ -254,31 +257,37 @@ private: tymin = (bounds[raySign[1]].y - rayFrom.y) * rayInvDirection.y; tymax = (bounds[1 - raySign[1]].y - rayFrom.y) * rayInvDirection.y; - if ((tmin > tymax) || (tymin > tmax)) + if ((tmin > tymax) || (tymin > tmax)) { return false; + } - if (tymin > tmin) + if (tymin > tmin) { tmin = tymin; + } - if (tymax < tmax) + if (tymax < tmax) { tmax = tymax; + } tzmin = (bounds[raySign[2]].z - rayFrom.z) * rayInvDirection.z; tzmax = (bounds[1 - raySign[2]].z - rayFrom.z) * rayInvDirection.z; - if ((tmin > tzmax) || (tzmin > tmax)) + if ((tmin > tzmax) || (tzmin > tmax)) { return false; - if (tzmin > tmin) + } + if (tzmin > tmin) { tmin = tzmin; - if (tzmax < tmax) + } + if (tzmax < tmax) { tmax = tzmax; + } return ((tmin < lambda_max) && (tmax > lambda_min)); } public: // Methods void clear(); - bool is_empty() const { return (0 == bvh_root); } + bool is_empty() const { return (nullptr == bvh_root); } void optimize_bottom_up(); void optimize_top_down(int bu_threshold = 128); void optimize_incremental(int passes); diff --git a/core/math/quat.cpp b/core/math/quat.cpp index a9a21a1ba3..6f13e04027 100644 --- a/core/math/quat.cpp +++ b/core/math/quat.cpp @@ -55,10 +55,13 @@ Vector3 Quat::get_euler_yxz() const { } void Quat::operator*=(const Quat &p_q) { - x = w * p_q.x + x * p_q.w + y * p_q.z - z * p_q.y; - y = w * p_q.y + y * p_q.w + z * p_q.x - x * p_q.z; - z = w * p_q.z + z * p_q.w + x * p_q.y - y * p_q.x; + real_t xx = w * p_q.x + x * p_q.w + y * p_q.z - z * p_q.y; + real_t yy = w * p_q.y + y * p_q.w + z * p_q.x - x * p_q.z; + real_t zz = w * p_q.z + z * p_q.w + x * p_q.y - y * p_q.x; w = w * p_q.w - x * p_q.x - y * p_q.y - z * p_q.z; + x = xx; + y = yy; + z = zz; } Quat Quat::operator*(const Quat &p_q) const { diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index 375ad8fae1..fb7eb42738 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -1095,6 +1095,8 @@ bool ClassDB::get_property_info(StringName p_class, StringName p_property, Prope } bool ClassDB::set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid) { + ERR_FAIL_NULL_V(p_object, false); + ClassInfo *type = classes.getptr(p_object->get_class_name()); ClassInfo *check = type; while (check) { @@ -1142,6 +1144,8 @@ bool ClassDB::set_property(Object *p_object, const StringName &p_property, const } bool ClassDB::get_property(Object *p_object, const StringName &p_property, Variant &r_value) { + ERR_FAIL_NULL_V(p_object, false); + ClassInfo *type = classes.getptr(p_object->get_class_name()); ClassInfo *check = type; while (check) { diff --git a/core/os/dir_access.h b/core/os/dir_access.h index c49c4cc4b8..7f0bcd372d 100644 --- a/core/os/dir_access.h +++ b/core/os/dir_access.h @@ -84,6 +84,8 @@ public: virtual bool file_exists(String p_file) = 0; virtual bool dir_exists(String p_dir) = 0; + virtual bool is_readable(String p_dir) { return true; }; + virtual bool is_writable(String p_dir) { return true; }; static bool exists(String p_dir); virtual size_t get_space_left() = 0; diff --git a/core/os/keyboard.h b/core/os/keyboard.h index 3ef70e786f..f6fe5fc070 100644 --- a/core/os/keyboard.h +++ b/core/os/keyboard.h @@ -45,7 +45,7 @@ enum { SPKEY = (1 << 24) }; -enum KeyList { +enum Key { /* CURSOR/FUNCTION/BROWSER/MULTIMEDIA/MISC KEYS */ KEY_ESCAPE = SPKEY | 0x01, KEY_TAB = SPKEY | 0x02, diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index b58abc81d1..d6a5eff10d 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -68,7 +68,7 @@ #include "core/object/class_db.h" #include "core/object/undo_redo.h" #include "core/os/main_loop.h" -#include "core/string/compressed_translation.h" +#include "core/string/optimized_translation.h" #include "core/string/translation.h" static Ref<ResourceFormatSaverBinary> resource_saver_binary; @@ -183,7 +183,7 @@ void register_core_types() { ClassDB::register_class<MultiplayerAPI>(); ClassDB::register_class<MainLoop>(); ClassDB::register_class<Translation>(); - ClassDB::register_class<PHashTranslation>(); + ClassDB::register_class<OptimizedTranslation>(); ClassDB::register_class<UndoRedo>(); ClassDB::register_class<HTTPClient>(); ClassDB::register_class<TriangleMesh>(); diff --git a/core/string/compressed_translation.cpp b/core/string/optimized_translation.cpp index 15abf63f7e..53d0a8924d 100644 --- a/core/string/compressed_translation.cpp +++ b/core/string/optimized_translation.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* compressed_translation.cpp */ +/* optimized_translation.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "compressed_translation.h" +#include "optimized_translation.h" #include "core/templates/pair.h" @@ -36,13 +36,13 @@ extern "C" { #include "thirdparty/misc/smaz.h" } -struct _PHashTranslationCmp { +struct CompressedString { int orig_len; CharString compressed; int offset; }; -void PHashTranslation::generate(const Ref<Translation> &p_from) { +void OptimizedTranslation::generate(const Ref<Translation> &p_from) { // This method compresses a Translation instance. // Right now, it doesn't handle context or plurals, so Translation subclasses using plurals or context (i.e TranslationPO) shouldn't be compressed. #ifdef TOOLS_ENABLED @@ -54,7 +54,7 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) { Vector<Vector<Pair<int, CharString>>> buckets; Vector<Map<uint32_t, int>> table; Vector<uint32_t> hfunc_table; - Vector<_PHashTranslationCmp> compressed; + Vector<CompressedString> compressed; table.resize(size); hfunc_table.resize(size); @@ -76,7 +76,7 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) { //compress string CharString src_s = p_from->get_message(E->get()).operator String().utf8(); - _PHashTranslationCmp ps; + CompressedString ps; ps.orig_len = src_s.size(); ps.offset = total_compression_size; @@ -182,7 +182,7 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) { #endif } -bool PHashTranslation::_set(const StringName &p_name, const Variant &p_value) { +bool OptimizedTranslation::_set(const StringName &p_name, const Variant &p_value) { String name = p_name.operator String(); if (name == "hash_table") { hash_table = p_value; @@ -199,7 +199,7 @@ bool PHashTranslation::_set(const StringName &p_name, const Variant &p_value) { return true; } -bool PHashTranslation::_get(const StringName &p_name, Variant &r_ret) const { +bool OptimizedTranslation::_get(const StringName &p_name, Variant &r_ret) const { String name = p_name.operator String(); if (name == "hash_table") { r_ret = hash_table; @@ -214,8 +214,8 @@ bool PHashTranslation::_get(const StringName &p_name, Variant &r_ret) const { return true; } -StringName PHashTranslation::get_message(const StringName &p_src_text, const StringName &p_context) const { - // p_context passed in is ignore. The use of context is not yet supported in PHashTranslation. +StringName OptimizedTranslation::get_message(const StringName &p_src_text, const StringName &p_context) const { + // p_context passed in is ignore. The use of context is not yet supported in OptimizedTranslation. int htsize = hash_table.size(); @@ -271,18 +271,18 @@ StringName PHashTranslation::get_message(const StringName &p_src_text, const Str } } -StringName PHashTranslation::get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context) const { - // The use of plurals translation is not yet supported in PHashTranslation. +StringName OptimizedTranslation::get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context) const { + // The use of plurals translation is not yet supported in OptimizedTranslation. return get_message(p_src_text, p_context); } -void PHashTranslation::_get_property_list(List<PropertyInfo> *p_list) const { +void OptimizedTranslation::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, "hash_table")); p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, "bucket_table")); p_list->push_back(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "strings")); p_list->push_back(PropertyInfo(Variant::OBJECT, "load_from", PROPERTY_HINT_RESOURCE_TYPE, "Translation", PROPERTY_USAGE_EDITOR)); } -void PHashTranslation::_bind_methods() { - ClassDB::bind_method(D_METHOD("generate", "from"), &PHashTranslation::generate); +void OptimizedTranslation::_bind_methods() { + ClassDB::bind_method(D_METHOD("generate", "from"), &OptimizedTranslation::generate); } diff --git a/core/string/compressed_translation.h b/core/string/optimized_translation.h index 0abb770178..bccf932383 100644 --- a/core/string/compressed_translation.h +++ b/core/string/optimized_translation.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* compressed_translation.h */ +/* optimized_translation.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef COMPRESSED_TRANSLATION_H -#define COMPRESSED_TRANSLATION_H +#ifndef OPTIMIZED_TRANSLATION_H +#define OPTIMIZED_TRANSLATION_H #include "core/string/translation.h" -class PHashTranslation : public Translation { - GDCLASS(PHashTranslation, Translation); +class OptimizedTranslation : public Translation { + GDCLASS(OptimizedTranslation, Translation); //this translation uses a sort of modified perfect hash algorithm //it requires hashing strings twice and then does a binary search, @@ -83,7 +83,7 @@ public: virtual StringName get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context = "") const override; void generate(const Ref<Translation> &p_from); - PHashTranslation() {} + OptimizedTranslation() {} }; -#endif // COMPRESSED_TRANSLATION_H +#endif // OPTIMIZED_TRANSLATION_H diff --git a/core/string/translation.cpp b/core/string/translation.cpp index 9cee218735..ade5f7b4d8 100644 --- a/core/string/translation.cpp +++ b/core/string/translation.cpp @@ -853,7 +853,7 @@ void Translation::set_locale(const String &p_locale) { locale = univ_locale; } - if (OS::get_singleton()->get_main_loop()) { + if (OS::get_singleton()->get_main_loop() && TranslationServer::get_singleton()->get_loaded_locales().has(this)) { OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_TRANSLATION_CHANGED); } } diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp index 42ba30fbe5..2efadaa9b7 100644 --- a/core/string/translation_po.cpp +++ b/core/string/translation_po.cpp @@ -275,7 +275,7 @@ void TranslationPO::erase_message(const StringName &p_src_text, const StringName } void TranslationPO::get_message_list(List<StringName> *r_messages) const { - // PHashTranslation uses this function to get the list of msgid. + // OptimizedTranslation uses this function to get the list of msgid. // Return all the keys of translation_map under "" context. List<StringName> context_l; diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 28228e4a83..05c80296c2 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -1138,7 +1138,7 @@ Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int remaining_len = left_edge; } - ret.invert(); + ret.reverse(); return ret; } diff --git a/core/templates/list.h b/core/templates/list.h index eaf1dbb4a0..010e35eed8 100644 --- a/core/templates/list.h +++ b/core/templates/list.h @@ -492,7 +492,7 @@ public: _data->last = p_I; } - void invert() { + void reverse() { int s = size() / 2; Element *F = front(); Element *B = back(); diff --git a/core/templates/vector.h b/core/templates/vector.h index 6a8902707c..a56a941dbc 100644 --- a/core/templates/vector.h +++ b/core/templates/vector.h @@ -74,7 +74,7 @@ public: remove(idx); } } - void invert(); + void reverse(); _FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); } _FORCE_INLINE_ const T *ptr() const { return _cowdata.ptr(); } @@ -194,7 +194,7 @@ public: }; template <class T> -void Vector<T>::invert() { +void Vector<T>::reverse() { for (int i = 0; i < size() / 2; i++) { T *p = ptrw(); SWAP(p[i], p[size() - i - 1]); diff --git a/core/variant/array.cpp b/core/variant/array.cpp index 347c6cd82e..2ad728ec5e 100644 --- a/core/variant/array.cpp +++ b/core/variant/array.cpp @@ -139,7 +139,7 @@ uint32_t Array::hash() const { return h; } -void Array::_assign(const Array &p_array) { +bool Array::_assign(const Array &p_array) { if (_p->typed.type != Variant::OBJECT && _p->typed.type == p_array._p->typed.type) { //same type or untyped, just reference, should be fine _ref(p_array); @@ -150,7 +150,7 @@ void Array::_assign(const Array &p_array) { //for objects, it needs full validation, either can be converted or fail for (int i = 0; i < p_array._p->array.size(); i++) { if (!_p->typed.validate(p_array._p->array[i], "assign")) { - return; + return false; } } _p->array = p_array._p->array; //then just copy, which is cheap anyway @@ -168,10 +168,10 @@ void Array::_assign(const Array &p_array) { Callable::CallError ce; Variant::construct(_p->typed.type, new_array.write[i], (const Variant **)&ptr, 1, ce); if (ce.error != Callable::CallError::CALL_OK) { - ERR_FAIL_MSG("Unable to convert array index " + itos(i) + " from '" + Variant::get_type_name(src_val.get_type()) + "' to '" + Variant::get_type_name(_p->typed.type) + "'."); + ERR_FAIL_V_MSG(false, "Unable to convert array index " + itos(i) + " from '" + Variant::get_type_name(src_val.get_type()) + "' to '" + Variant::get_type_name(_p->typed.type) + "'."); } } else { - ERR_FAIL_MSG("Unable to convert array index " + itos(i) + " from '" + Variant::get_type_name(src_val.get_type()) + "' to '" + Variant::get_type_name(_p->typed.type) + "'."); + ERR_FAIL_V_MSG(false, "Unable to convert array index " + itos(i) + " from '" + Variant::get_type_name(src_val.get_type()) + "' to '" + Variant::get_type_name(_p->typed.type) + "'."); } } @@ -180,12 +180,13 @@ void Array::_assign(const Array &p_array) { } else if (_p->typed.can_reference(p_array._p->typed)) { //same type or compatible _ref(p_array); } else { - ERR_FAIL_MSG("Assignment of arrays of incompatible types."); + ERR_FAIL_V_MSG(false, "Assignment of arrays of incompatible types."); } + return true; } void Array::operator=(const Array &p_array) { - _assign(p_array); + _ref(p_array); } void Array::push_back(const Variant &p_value) { @@ -445,8 +446,8 @@ int Array::bsearch_custom(const Variant &p_value, Callable p_callable, bool p_be return bisect(_p->array, p_value, p_before, less); } -void Array::invert() { - _p->array.invert(); +void Array::reverse() { + _p->array.reverse(); } void Array::push_front(const Variant &p_value) { @@ -528,6 +529,10 @@ Array::Array(const Array &p_from, uint32_t p_type, const StringName &p_class_nam _assign(p_from); } +bool Array::typed_assign(const Array &p_other) { + return _assign(p_other); +} + void Array::set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script) { ERR_FAIL_COND_MSG(_p->array.size() > 0, "Type can only be set when array is empty."); ERR_FAIL_COND_MSG(_p->refcount.get() > 1, "Type can only be set when array has no more than one user."); @@ -542,6 +547,22 @@ void Array::set_typed(uint32_t p_type, const StringName &p_class_name, const Var _p->typed.where = "TypedArray"; } +bool Array::is_typed() const { + return _p->typed.type != Variant::NIL; +} + +uint32_t Array::get_typed_builtin() const { + return _p->typed.type; +} + +StringName Array::get_typed_class_name() const { + return _p->typed.class_name; +} + +Variant Array::get_typed_script() const { + return _p->typed.script; +} + Array::Array(const Array &p_from) { _p = nullptr; _ref(p_from); diff --git a/core/variant/array.h b/core/variant/array.h index d8f2402330..6b58ed12cb 100644 --- a/core/variant/array.h +++ b/core/variant/array.h @@ -48,7 +48,7 @@ class Array { protected: Array(const Array &p_base, uint32_t p_type, const StringName &p_class_name, const Variant &p_script); - void _assign(const Array &p_array); + bool _assign(const Array &p_array); public: Variant &operator[](int p_idx); @@ -83,7 +83,7 @@ public: void shuffle(); int bsearch(const Variant &p_value, bool p_before = true); int bsearch_custom(const Variant &p_value, Callable p_callable, bool p_before = true); - void invert(); + void reverse(); int find(const Variant &p_value, int p_from = 0) const; int rfind(const Variant &p_value, int p_from = -1) const; @@ -111,7 +111,12 @@ public: const void *id() const; + bool typed_assign(const Array &p_other); void set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script); + bool is_typed() const; + uint32_t get_typed_builtin() const; + StringName get_typed_class_name() const; + Variant get_typed_script() const; Array(const Array &p_from); Array(); ~Array(); diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 8c1d8066d6..8f2d252810 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1460,7 +1460,7 @@ static void _register_variant_builtin_methods() { bind_method(Array, shuffle, sarray(), varray()); bind_method(Array, bsearch, sarray("value", "before"), varray(true)); bind_method(Array, bsearch_custom, sarray("value", "func", "before"), varray(true)); - bind_method(Array, invert, sarray(), varray()); + bind_method(Array, reverse, sarray(), varray()); bind_method(Array, duplicate, sarray("deep"), varray(false)); bind_method(Array, slice, sarray("begin", "end", "step", "deep"), varray(1, false)); bind_method(Array, max, sarray(), varray()); @@ -1477,7 +1477,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedByteArray, insert, sarray("at_index", "value"), varray()); bind_method(PackedByteArray, resize, sarray("new_size"), varray()); bind_method(PackedByteArray, has, sarray("value"), varray()); - bind_method(PackedByteArray, invert, sarray(), varray()); + bind_method(PackedByteArray, reverse, sarray(), varray()); bind_method(PackedByteArray, subarray, sarray("from", "to"), varray()); bind_method(PackedByteArray, sort, sarray(), varray()); bind_method(PackedByteArray, duplicate, sarray(), varray()); @@ -1503,7 +1503,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedInt32Array, insert, sarray("at_index", "value"), varray()); bind_method(PackedInt32Array, resize, sarray("new_size"), varray()); bind_method(PackedInt32Array, has, sarray("value"), varray()); - bind_method(PackedInt32Array, invert, sarray(), varray()); + bind_method(PackedInt32Array, reverse, sarray(), varray()); bind_method(PackedInt32Array, subarray, sarray("from", "to"), varray()); bind_method(PackedInt32Array, to_byte_array, sarray(), varray()); bind_method(PackedInt32Array, sort, sarray(), varray()); @@ -1521,7 +1521,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedInt64Array, insert, sarray("at_index", "value"), varray()); bind_method(PackedInt64Array, resize, sarray("new_size"), varray()); bind_method(PackedInt64Array, has, sarray("value"), varray()); - bind_method(PackedInt64Array, invert, sarray(), varray()); + bind_method(PackedInt64Array, reverse, sarray(), varray()); bind_method(PackedInt64Array, subarray, sarray("from", "to"), varray()); bind_method(PackedInt64Array, to_byte_array, sarray(), varray()); bind_method(PackedInt64Array, sort, sarray(), varray()); @@ -1539,7 +1539,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedFloat32Array, insert, sarray("at_index", "value"), varray()); bind_method(PackedFloat32Array, resize, sarray("new_size"), varray()); bind_method(PackedFloat32Array, has, sarray("value"), varray()); - bind_method(PackedFloat32Array, invert, sarray(), varray()); + bind_method(PackedFloat32Array, reverse, sarray(), varray()); bind_method(PackedFloat32Array, subarray, sarray("from", "to"), varray()); bind_method(PackedFloat32Array, to_byte_array, sarray(), varray()); bind_method(PackedFloat32Array, sort, sarray(), varray()); @@ -1557,7 +1557,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedFloat64Array, insert, sarray("at_index", "value"), varray()); bind_method(PackedFloat64Array, resize, sarray("new_size"), varray()); bind_method(PackedFloat64Array, has, sarray("value"), varray()); - bind_method(PackedFloat64Array, invert, sarray(), varray()); + bind_method(PackedFloat64Array, reverse, sarray(), varray()); bind_method(PackedFloat64Array, subarray, sarray("from", "to"), varray()); bind_method(PackedFloat64Array, to_byte_array, sarray(), varray()); bind_method(PackedFloat64Array, sort, sarray(), varray()); @@ -1575,7 +1575,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedStringArray, insert, sarray("at_index", "value"), varray()); bind_method(PackedStringArray, resize, sarray("new_size"), varray()); bind_method(PackedStringArray, has, sarray("value"), varray()); - bind_method(PackedStringArray, invert, sarray(), varray()); + bind_method(PackedStringArray, reverse, sarray(), varray()); bind_method(PackedStringArray, subarray, sarray("from", "to"), varray()); bind_method(PackedStringArray, to_byte_array, sarray(), varray()); bind_method(PackedStringArray, sort, sarray(), varray()); @@ -1593,7 +1593,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedVector2Array, insert, sarray("at_index", "value"), varray()); bind_method(PackedVector2Array, resize, sarray("new_size"), varray()); bind_method(PackedVector2Array, has, sarray("value"), varray()); - bind_method(PackedVector2Array, invert, sarray(), varray()); + bind_method(PackedVector2Array, reverse, sarray(), varray()); bind_method(PackedVector2Array, subarray, sarray("from", "to"), varray()); bind_method(PackedVector2Array, to_byte_array, sarray(), varray()); bind_method(PackedVector2Array, sort, sarray(), varray()); @@ -1611,7 +1611,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedVector3Array, insert, sarray("at_index", "value"), varray()); bind_method(PackedVector3Array, resize, sarray("new_size"), varray()); bind_method(PackedVector3Array, has, sarray("value"), varray()); - bind_method(PackedVector3Array, invert, sarray(), varray()); + bind_method(PackedVector3Array, reverse, sarray(), varray()); bind_method(PackedVector3Array, subarray, sarray("from", "to"), varray()); bind_method(PackedVector3Array, to_byte_array, sarray(), varray()); bind_method(PackedVector3Array, sort, sarray(), varray()); @@ -1629,7 +1629,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedColorArray, insert, sarray("at_index", "value"), varray()); bind_method(PackedColorArray, resize, sarray("new_size"), varray()); bind_method(PackedColorArray, has, sarray("value"), varray()); - bind_method(PackedColorArray, invert, sarray(), varray()); + bind_method(PackedColorArray, reverse, sarray(), varray()); bind_method(PackedColorArray, subarray, sarray("from", "to"), varray()); bind_method(PackedColorArray, to_byte_array, sarray(), varray()); bind_method(PackedColorArray, sort, sarray(), varray()); diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp index ed936c626b..edaeddbf27 100644 --- a/core/variant/variant_parser.cpp +++ b/core/variant/variant_parser.cpp @@ -381,7 +381,6 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri r_token.value = num.as_int(); } return OK; - } else if ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_') { StringBuffer<> id; bool first = true; @@ -508,8 +507,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } else if (id == "nan") { value = Math_NAN; } else if (id == "Vector2") { - Vector<float> args; - Error err = _parse_construct<float>(p_stream, args, line, r_err_str); + Vector<real_t> args; + Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str); if (err) { return err; } @@ -534,8 +533,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, value = Vector2i(args[0], args[1]); } else if (id == "Rect2") { - Vector<float> args; - Error err = _parse_construct<float>(p_stream, args, line, r_err_str); + Vector<real_t> args; + Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str); if (err) { return err; } @@ -560,8 +559,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, value = Rect2i(args[0], args[1], args[2], args[3]); } else if (id == "Vector3") { - Vector<float> args; - Error err = _parse_construct<float>(p_stream, args, line, r_err_str); + Vector<real_t> args; + Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str); if (err) { return err; } @@ -586,8 +585,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, value = Vector3i(args[0], args[1], args[2]); } else if (id == "Transform2D" || id == "Matrix32") { //compatibility - Vector<float> args; - Error err = _parse_construct<float>(p_stream, args, line, r_err_str); + Vector<real_t> args; + Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str); if (err) { return err; } @@ -603,8 +602,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, m[2] = Vector2(args[4], args[5]); value = m; } else if (id == "Plane") { - Vector<float> args; - Error err = _parse_construct<float>(p_stream, args, line, r_err_str); + Vector<real_t> args; + Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str); if (err) { return err; } @@ -616,8 +615,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, value = Plane(args[0], args[1], args[2], args[3]); } else if (id == "Quat") { - Vector<float> args; - Error err = _parse_construct<float>(p_stream, args, line, r_err_str); + Vector<real_t> args; + Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str); if (err) { return err; } @@ -629,8 +628,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, value = Quat(args[0], args[1], args[2], args[3]); } else if (id == "AABB" || id == "Rect3") { - Vector<float> args; - Error err = _parse_construct<float>(p_stream, args, line, r_err_str); + Vector<real_t> args; + Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str); if (err) { return err; } @@ -642,8 +641,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, value = AABB(Vector3(args[0], args[1], args[2]), Vector3(args[3], args[4], args[5])); } else if (id == "Basis" || id == "Matrix3") { //compatibility - Vector<float> args; - Error err = _parse_construct<float>(p_stream, args, line, r_err_str); + Vector<real_t> args; + Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str); if (err) { return err; } @@ -655,8 +654,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, value = Basis(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); } else if (id == "Transform") { - Vector<float> args; - Error err = _parse_construct<float>(p_stream, args, line, r_err_str); + Vector<real_t> args; + Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str); if (err) { return err; } @@ -1006,8 +1005,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, value = arr; } else if (id == "PackedVector2Array" || id == "PoolVector2Array" || id == "Vector2Array") { - Vector<float> args; - Error err = _parse_construct<float>(p_stream, args, line, r_err_str); + Vector<real_t> args; + Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str); if (err) { return err; } @@ -1024,8 +1023,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, value = arr; } else if (id == "PackedVector3Array" || id == "PoolVector3Array" || id == "Vector3Array") { - Vector<float> args; - Error err = _parse_construct<float>(p_stream, args, line, r_err_str); + Vector<real_t> args; + Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str); if (err) { return err; } diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp index f9cc7c4ff4..f319631ce5 100644 --- a/core/variant/variant_setget.cpp +++ b/core/variant/variant_setget.cpp @@ -875,65 +875,66 @@ Variant Variant::get_named(const StringName &p_member, bool &r_valid) const { static uint64_t get_indexed_size(const Variant *base) { return m_max; } \ }; -#define INDEXED_SETGET_STRUCT_VARIANT(m_base_type) \ - struct VariantIndexedSetGet_##m_base_type { \ - static void get(const Variant *base, int64_t index, Variant *value, bool *oob) { \ - int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \ - if (index < 0) { \ - index += size; \ - } \ - if (index < 0 || index >= size) { \ - *oob = true; \ - return; \ - } \ - *value = (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index]; \ - *oob = false; \ - } \ - static void ptr_get(const void *base, int64_t index, void *member) { \ - /* avoid ptrconvert for performance*/ \ - const m_base_type &v = *reinterpret_cast<const m_base_type *>(base); \ - if (index < 0) \ - index += v.size(); \ - OOB_TEST(index, v.size()); \ - PtrToArg<Variant>::encode(v[index], member); \ - } \ - static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { \ - int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \ - if (index < 0) { \ - index += size; \ - } \ - if (index < 0 || index >= size) { \ - *oob = true; \ - *valid = false; \ - return; \ - } \ - (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = *value; \ - *oob = false; \ - *valid = true; \ - } \ - static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { \ - int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \ - if (index < 0) { \ - index += size; \ - } \ - if (index < 0 || index >= size) { \ - *oob = true; \ - return; \ - } \ - (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = *value; \ - *oob = false; \ - } \ - static void ptr_set(void *base, int64_t index, const void *member) { \ - /* avoid ptrconvert for performance*/ \ - m_base_type &v = *reinterpret_cast<m_base_type *>(base); \ - if (index < 0) \ - index += v.size(); \ - OOB_TEST(index, v.size()); \ - v[index] = PtrToArg<Variant>::convert(member); \ - } \ - static Variant::Type get_index_type() { return Variant::NIL; } \ - static uint64_t get_indexed_size(const Variant *base) { return 0; } \ - }; +struct VariantIndexedSetGet_Array { + static void get(const Variant *base, int64_t index, Variant *value, bool *oob) { + int64_t size = VariantGetInternalPtr<Array>::get_ptr(base)->size(); + if (index < 0) { + index += size; + } + if (index < 0 || index >= size) { + *oob = true; + return; + } + *value = (*VariantGetInternalPtr<Array>::get_ptr(base))[index]; + *oob = false; + } + static void ptr_get(const void *base, int64_t index, void *member) { + /* avoid ptrconvert for performance*/ + const Array &v = *reinterpret_cast<const Array *>(base); + if (index < 0) { + index += v.size(); + } + OOB_TEST(index, v.size()); + PtrToArg<Variant>::encode(v[index], member); + } + static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { + int64_t size = VariantGetInternalPtr<Array>::get_ptr(base)->size(); + if (index < 0) { + index += size; + } + if (index < 0 || index >= size) { + *oob = true; + *valid = false; + return; + } + VariantGetInternalPtr<Array>::get_ptr(base)->set(index, *value); + *oob = false; + *valid = true; + } + static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { + int64_t size = VariantGetInternalPtr<Array>::get_ptr(base)->size(); + if (index < 0) { + index += size; + } + if (index < 0 || index >= size) { + *oob = true; + return; + } + VariantGetInternalPtr<Array>::get_ptr(base)->set(index, *value); + *oob = false; + } + static void ptr_set(void *base, int64_t index, const void *member) { + /* avoid ptrconvert for performance*/ + Array &v = *reinterpret_cast<Array *>(base); + if (index < 0) { + index += v.size(); + } + OOB_TEST(index, v.size()); + v.set(index, PtrToArg<Variant>::convert(member)); + } + static Variant::Type get_index_type() { return Variant::NIL; } + static uint64_t get_indexed_size(const Variant *base) { return 0; } +}; #define INDEXED_SETGET_STRUCT_DICT(m_base_type) \ struct VariantIndexedSetGet_##m_base_type { \ @@ -990,7 +991,6 @@ INDEXED_SETGET_STRUCT_TYPED(PackedVector3Array, Vector3) INDEXED_SETGET_STRUCT_TYPED(PackedStringArray, String) INDEXED_SETGET_STRUCT_TYPED(PackedColorArray, Color) -INDEXED_SETGET_STRUCT_VARIANT(Array) INDEXED_SETGET_STRUCT_DICT(Dictionary) struct VariantIndexedSetterGetterInfo { diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index e192e85cd1..25f8f22d44 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -777,7 +777,7 @@ <return type="int"> </return> <description> - Returns a random unsigned 32 bit integer. Use remainder to obtain a random value in the interval [code][0, N - 1][/code] (where N is smaller than 2^32). + Returns a random unsigned 32-bit integer. Use remainder to obtain a random value in the interval [code][0, N - 1][/code] (where N is smaller than 2^32). [codeblock] randi() # Returns random integer between 0 and 2^32 - 1 randi() % 20 # Returns random integer between 0 and 19 @@ -1308,730 +1308,730 @@ <constant name="SPKEY" value="16777216"> Keycodes with this bit applied are non-printable. </constant> - <constant name="KEY_ESCAPE" value="16777217" enum="KeyList"> + <constant name="KEY_ESCAPE" value="16777217" enum="Key"> Escape key. </constant> - <constant name="KEY_TAB" value="16777218" enum="KeyList"> + <constant name="KEY_TAB" value="16777218" enum="Key"> Tab key. </constant> - <constant name="KEY_BACKTAB" value="16777219" enum="KeyList"> + <constant name="KEY_BACKTAB" value="16777219" enum="Key"> Shift + Tab key. </constant> - <constant name="KEY_BACKSPACE" value="16777220" enum="KeyList"> + <constant name="KEY_BACKSPACE" value="16777220" enum="Key"> Backspace key. </constant> - <constant name="KEY_ENTER" value="16777221" enum="KeyList"> + <constant name="KEY_ENTER" value="16777221" enum="Key"> Return key (on the main keyboard). </constant> - <constant name="KEY_KP_ENTER" value="16777222" enum="KeyList"> + <constant name="KEY_KP_ENTER" value="16777222" enum="Key"> Enter key on the numeric keypad. </constant> - <constant name="KEY_INSERT" value="16777223" enum="KeyList"> + <constant name="KEY_INSERT" value="16777223" enum="Key"> Insert key. </constant> - <constant name="KEY_DELETE" value="16777224" enum="KeyList"> + <constant name="KEY_DELETE" value="16777224" enum="Key"> Delete key. </constant> - <constant name="KEY_PAUSE" value="16777225" enum="KeyList"> + <constant name="KEY_PAUSE" value="16777225" enum="Key"> Pause key. </constant> - <constant name="KEY_PRINT" value="16777226" enum="KeyList"> + <constant name="KEY_PRINT" value="16777226" enum="Key"> Print Screen key. </constant> - <constant name="KEY_SYSREQ" value="16777227" enum="KeyList"> + <constant name="KEY_SYSREQ" value="16777227" enum="Key"> System Request key. </constant> - <constant name="KEY_CLEAR" value="16777228" enum="KeyList"> + <constant name="KEY_CLEAR" value="16777228" enum="Key"> Clear key. </constant> - <constant name="KEY_HOME" value="16777229" enum="KeyList"> + <constant name="KEY_HOME" value="16777229" enum="Key"> Home key. </constant> - <constant name="KEY_END" value="16777230" enum="KeyList"> + <constant name="KEY_END" value="16777230" enum="Key"> End key. </constant> - <constant name="KEY_LEFT" value="16777231" enum="KeyList"> + <constant name="KEY_LEFT" value="16777231" enum="Key"> Left arrow key. </constant> - <constant name="KEY_UP" value="16777232" enum="KeyList"> + <constant name="KEY_UP" value="16777232" enum="Key"> Up arrow key. </constant> - <constant name="KEY_RIGHT" value="16777233" enum="KeyList"> + <constant name="KEY_RIGHT" value="16777233" enum="Key"> Right arrow key. </constant> - <constant name="KEY_DOWN" value="16777234" enum="KeyList"> + <constant name="KEY_DOWN" value="16777234" enum="Key"> Down arrow key. </constant> - <constant name="KEY_PAGEUP" value="16777235" enum="KeyList"> + <constant name="KEY_PAGEUP" value="16777235" enum="Key"> Page Up key. </constant> - <constant name="KEY_PAGEDOWN" value="16777236" enum="KeyList"> + <constant name="KEY_PAGEDOWN" value="16777236" enum="Key"> Page Down key. </constant> - <constant name="KEY_SHIFT" value="16777237" enum="KeyList"> + <constant name="KEY_SHIFT" value="16777237" enum="Key"> Shift key. </constant> - <constant name="KEY_CONTROL" value="16777238" enum="KeyList"> + <constant name="KEY_CONTROL" value="16777238" enum="Key"> Control key. </constant> - <constant name="KEY_META" value="16777239" enum="KeyList"> + <constant name="KEY_META" value="16777239" enum="Key"> Meta key. </constant> - <constant name="KEY_ALT" value="16777240" enum="KeyList"> + <constant name="KEY_ALT" value="16777240" enum="Key"> Alt key. </constant> - <constant name="KEY_CAPSLOCK" value="16777241" enum="KeyList"> + <constant name="KEY_CAPSLOCK" value="16777241" enum="Key"> Caps Lock key. </constant> - <constant name="KEY_NUMLOCK" value="16777242" enum="KeyList"> + <constant name="KEY_NUMLOCK" value="16777242" enum="Key"> Num Lock key. </constant> - <constant name="KEY_SCROLLLOCK" value="16777243" enum="KeyList"> + <constant name="KEY_SCROLLLOCK" value="16777243" enum="Key"> Scroll Lock key. </constant> - <constant name="KEY_F1" value="16777244" enum="KeyList"> + <constant name="KEY_F1" value="16777244" enum="Key"> F1 key. </constant> - <constant name="KEY_F2" value="16777245" enum="KeyList"> + <constant name="KEY_F2" value="16777245" enum="Key"> F2 key. </constant> - <constant name="KEY_F3" value="16777246" enum="KeyList"> + <constant name="KEY_F3" value="16777246" enum="Key"> F3 key. </constant> - <constant name="KEY_F4" value="16777247" enum="KeyList"> + <constant name="KEY_F4" value="16777247" enum="Key"> F4 key. </constant> - <constant name="KEY_F5" value="16777248" enum="KeyList"> + <constant name="KEY_F5" value="16777248" enum="Key"> F5 key. </constant> - <constant name="KEY_F6" value="16777249" enum="KeyList"> + <constant name="KEY_F6" value="16777249" enum="Key"> F6 key. </constant> - <constant name="KEY_F7" value="16777250" enum="KeyList"> + <constant name="KEY_F7" value="16777250" enum="Key"> F7 key. </constant> - <constant name="KEY_F8" value="16777251" enum="KeyList"> + <constant name="KEY_F8" value="16777251" enum="Key"> F8 key. </constant> - <constant name="KEY_F9" value="16777252" enum="KeyList"> + <constant name="KEY_F9" value="16777252" enum="Key"> F9 key. </constant> - <constant name="KEY_F10" value="16777253" enum="KeyList"> + <constant name="KEY_F10" value="16777253" enum="Key"> F10 key. </constant> - <constant name="KEY_F11" value="16777254" enum="KeyList"> + <constant name="KEY_F11" value="16777254" enum="Key"> F11 key. </constant> - <constant name="KEY_F12" value="16777255" enum="KeyList"> + <constant name="KEY_F12" value="16777255" enum="Key"> F12 key. </constant> - <constant name="KEY_F13" value="16777256" enum="KeyList"> + <constant name="KEY_F13" value="16777256" enum="Key"> F13 key. </constant> - <constant name="KEY_F14" value="16777257" enum="KeyList"> + <constant name="KEY_F14" value="16777257" enum="Key"> F14 key. </constant> - <constant name="KEY_F15" value="16777258" enum="KeyList"> + <constant name="KEY_F15" value="16777258" enum="Key"> F15 key. </constant> - <constant name="KEY_F16" value="16777259" enum="KeyList"> + <constant name="KEY_F16" value="16777259" enum="Key"> F16 key. </constant> - <constant name="KEY_KP_MULTIPLY" value="16777345" enum="KeyList"> + <constant name="KEY_KP_MULTIPLY" value="16777345" enum="Key"> Multiply (*) key on the numeric keypad. </constant> - <constant name="KEY_KP_DIVIDE" value="16777346" enum="KeyList"> + <constant name="KEY_KP_DIVIDE" value="16777346" enum="Key"> Divide (/) key on the numeric keypad. </constant> - <constant name="KEY_KP_SUBTRACT" value="16777347" enum="KeyList"> + <constant name="KEY_KP_SUBTRACT" value="16777347" enum="Key"> Subtract (-) key on the numeric keypad. </constant> - <constant name="KEY_KP_PERIOD" value="16777348" enum="KeyList"> + <constant name="KEY_KP_PERIOD" value="16777348" enum="Key"> Period (.) key on the numeric keypad. </constant> - <constant name="KEY_KP_ADD" value="16777349" enum="KeyList"> + <constant name="KEY_KP_ADD" value="16777349" enum="Key"> Add (+) key on the numeric keypad. </constant> - <constant name="KEY_KP_0" value="16777350" enum="KeyList"> + <constant name="KEY_KP_0" value="16777350" enum="Key"> Number 0 on the numeric keypad. </constant> - <constant name="KEY_KP_1" value="16777351" enum="KeyList"> + <constant name="KEY_KP_1" value="16777351" enum="Key"> Number 1 on the numeric keypad. </constant> - <constant name="KEY_KP_2" value="16777352" enum="KeyList"> + <constant name="KEY_KP_2" value="16777352" enum="Key"> Number 2 on the numeric keypad. </constant> - <constant name="KEY_KP_3" value="16777353" enum="KeyList"> + <constant name="KEY_KP_3" value="16777353" enum="Key"> Number 3 on the numeric keypad. </constant> - <constant name="KEY_KP_4" value="16777354" enum="KeyList"> + <constant name="KEY_KP_4" value="16777354" enum="Key"> Number 4 on the numeric keypad. </constant> - <constant name="KEY_KP_5" value="16777355" enum="KeyList"> + <constant name="KEY_KP_5" value="16777355" enum="Key"> Number 5 on the numeric keypad. </constant> - <constant name="KEY_KP_6" value="16777356" enum="KeyList"> + <constant name="KEY_KP_6" value="16777356" enum="Key"> Number 6 on the numeric keypad. </constant> - <constant name="KEY_KP_7" value="16777357" enum="KeyList"> + <constant name="KEY_KP_7" value="16777357" enum="Key"> Number 7 on the numeric keypad. </constant> - <constant name="KEY_KP_8" value="16777358" enum="KeyList"> + <constant name="KEY_KP_8" value="16777358" enum="Key"> Number 8 on the numeric keypad. </constant> - <constant name="KEY_KP_9" value="16777359" enum="KeyList"> + <constant name="KEY_KP_9" value="16777359" enum="Key"> Number 9 on the numeric keypad. </constant> - <constant name="KEY_SUPER_L" value="16777260" enum="KeyList"> + <constant name="KEY_SUPER_L" value="16777260" enum="Key"> Left Super key (Windows key). </constant> - <constant name="KEY_SUPER_R" value="16777261" enum="KeyList"> + <constant name="KEY_SUPER_R" value="16777261" enum="Key"> Right Super key (Windows key). </constant> - <constant name="KEY_MENU" value="16777262" enum="KeyList"> + <constant name="KEY_MENU" value="16777262" enum="Key"> Context menu key. </constant> - <constant name="KEY_HYPER_L" value="16777263" enum="KeyList"> + <constant name="KEY_HYPER_L" value="16777263" enum="Key"> Left Hyper key. </constant> - <constant name="KEY_HYPER_R" value="16777264" enum="KeyList"> + <constant name="KEY_HYPER_R" value="16777264" enum="Key"> Right Hyper key. </constant> - <constant name="KEY_HELP" value="16777265" enum="KeyList"> + <constant name="KEY_HELP" value="16777265" enum="Key"> Help key. </constant> - <constant name="KEY_DIRECTION_L" value="16777266" enum="KeyList"> + <constant name="KEY_DIRECTION_L" value="16777266" enum="Key"> Left Direction key. </constant> - <constant name="KEY_DIRECTION_R" value="16777267" enum="KeyList"> + <constant name="KEY_DIRECTION_R" value="16777267" enum="Key"> Right Direction key. </constant> - <constant name="KEY_BACK" value="16777280" enum="KeyList"> + <constant name="KEY_BACK" value="16777280" enum="Key"> Media back key. Not to be confused with the Back button on an Android device. </constant> - <constant name="KEY_FORWARD" value="16777281" enum="KeyList"> + <constant name="KEY_FORWARD" value="16777281" enum="Key"> Media forward key. </constant> - <constant name="KEY_STOP" value="16777282" enum="KeyList"> + <constant name="KEY_STOP" value="16777282" enum="Key"> Media stop key. </constant> - <constant name="KEY_REFRESH" value="16777283" enum="KeyList"> + <constant name="KEY_REFRESH" value="16777283" enum="Key"> Media refresh key. </constant> - <constant name="KEY_VOLUMEDOWN" value="16777284" enum="KeyList"> + <constant name="KEY_VOLUMEDOWN" value="16777284" enum="Key"> Volume down key. </constant> - <constant name="KEY_VOLUMEMUTE" value="16777285" enum="KeyList"> + <constant name="KEY_VOLUMEMUTE" value="16777285" enum="Key"> Mute volume key. </constant> - <constant name="KEY_VOLUMEUP" value="16777286" enum="KeyList"> + <constant name="KEY_VOLUMEUP" value="16777286" enum="Key"> Volume up key. </constant> - <constant name="KEY_BASSBOOST" value="16777287" enum="KeyList"> + <constant name="KEY_BASSBOOST" value="16777287" enum="Key"> Bass Boost key. </constant> - <constant name="KEY_BASSUP" value="16777288" enum="KeyList"> + <constant name="KEY_BASSUP" value="16777288" enum="Key"> Bass up key. </constant> - <constant name="KEY_BASSDOWN" value="16777289" enum="KeyList"> + <constant name="KEY_BASSDOWN" value="16777289" enum="Key"> Bass down key. </constant> - <constant name="KEY_TREBLEUP" value="16777290" enum="KeyList"> + <constant name="KEY_TREBLEUP" value="16777290" enum="Key"> Treble up key. </constant> - <constant name="KEY_TREBLEDOWN" value="16777291" enum="KeyList"> + <constant name="KEY_TREBLEDOWN" value="16777291" enum="Key"> Treble down key. </constant> - <constant name="KEY_MEDIAPLAY" value="16777292" enum="KeyList"> + <constant name="KEY_MEDIAPLAY" value="16777292" enum="Key"> Media play key. </constant> - <constant name="KEY_MEDIASTOP" value="16777293" enum="KeyList"> + <constant name="KEY_MEDIASTOP" value="16777293" enum="Key"> Media stop key. </constant> - <constant name="KEY_MEDIAPREVIOUS" value="16777294" enum="KeyList"> + <constant name="KEY_MEDIAPREVIOUS" value="16777294" enum="Key"> Previous song key. </constant> - <constant name="KEY_MEDIANEXT" value="16777295" enum="KeyList"> + <constant name="KEY_MEDIANEXT" value="16777295" enum="Key"> Next song key. </constant> - <constant name="KEY_MEDIARECORD" value="16777296" enum="KeyList"> + <constant name="KEY_MEDIARECORD" value="16777296" enum="Key"> Media record key. </constant> - <constant name="KEY_HOMEPAGE" value="16777297" enum="KeyList"> + <constant name="KEY_HOMEPAGE" value="16777297" enum="Key"> Home page key. </constant> - <constant name="KEY_FAVORITES" value="16777298" enum="KeyList"> + <constant name="KEY_FAVORITES" value="16777298" enum="Key"> Favorites key. </constant> - <constant name="KEY_SEARCH" value="16777299" enum="KeyList"> + <constant name="KEY_SEARCH" value="16777299" enum="Key"> Search key. </constant> - <constant name="KEY_STANDBY" value="16777300" enum="KeyList"> + <constant name="KEY_STANDBY" value="16777300" enum="Key"> Standby key. </constant> - <constant name="KEY_OPENURL" value="16777301" enum="KeyList"> + <constant name="KEY_OPENURL" value="16777301" enum="Key"> Open URL / Launch Browser key. </constant> - <constant name="KEY_LAUNCHMAIL" value="16777302" enum="KeyList"> + <constant name="KEY_LAUNCHMAIL" value="16777302" enum="Key"> Launch Mail key. </constant> - <constant name="KEY_LAUNCHMEDIA" value="16777303" enum="KeyList"> + <constant name="KEY_LAUNCHMEDIA" value="16777303" enum="Key"> Launch Media key. </constant> - <constant name="KEY_LAUNCH0" value="16777304" enum="KeyList"> + <constant name="KEY_LAUNCH0" value="16777304" enum="Key"> Launch Shortcut 0 key. </constant> - <constant name="KEY_LAUNCH1" value="16777305" enum="KeyList"> + <constant name="KEY_LAUNCH1" value="16777305" enum="Key"> Launch Shortcut 1 key. </constant> - <constant name="KEY_LAUNCH2" value="16777306" enum="KeyList"> + <constant name="KEY_LAUNCH2" value="16777306" enum="Key"> Launch Shortcut 2 key. </constant> - <constant name="KEY_LAUNCH3" value="16777307" enum="KeyList"> + <constant name="KEY_LAUNCH3" value="16777307" enum="Key"> Launch Shortcut 3 key. </constant> - <constant name="KEY_LAUNCH4" value="16777308" enum="KeyList"> + <constant name="KEY_LAUNCH4" value="16777308" enum="Key"> Launch Shortcut 4 key. </constant> - <constant name="KEY_LAUNCH5" value="16777309" enum="KeyList"> + <constant name="KEY_LAUNCH5" value="16777309" enum="Key"> Launch Shortcut 5 key. </constant> - <constant name="KEY_LAUNCH6" value="16777310" enum="KeyList"> + <constant name="KEY_LAUNCH6" value="16777310" enum="Key"> Launch Shortcut 6 key. </constant> - <constant name="KEY_LAUNCH7" value="16777311" enum="KeyList"> + <constant name="KEY_LAUNCH7" value="16777311" enum="Key"> Launch Shortcut 7 key. </constant> - <constant name="KEY_LAUNCH8" value="16777312" enum="KeyList"> + <constant name="KEY_LAUNCH8" value="16777312" enum="Key"> Launch Shortcut 8 key. </constant> - <constant name="KEY_LAUNCH9" value="16777313" enum="KeyList"> + <constant name="KEY_LAUNCH9" value="16777313" enum="Key"> Launch Shortcut 9 key. </constant> - <constant name="KEY_LAUNCHA" value="16777314" enum="KeyList"> + <constant name="KEY_LAUNCHA" value="16777314" enum="Key"> Launch Shortcut A key. </constant> - <constant name="KEY_LAUNCHB" value="16777315" enum="KeyList"> + <constant name="KEY_LAUNCHB" value="16777315" enum="Key"> Launch Shortcut B key. </constant> - <constant name="KEY_LAUNCHC" value="16777316" enum="KeyList"> + <constant name="KEY_LAUNCHC" value="16777316" enum="Key"> Launch Shortcut C key. </constant> - <constant name="KEY_LAUNCHD" value="16777317" enum="KeyList"> + <constant name="KEY_LAUNCHD" value="16777317" enum="Key"> Launch Shortcut D key. </constant> - <constant name="KEY_LAUNCHE" value="16777318" enum="KeyList"> + <constant name="KEY_LAUNCHE" value="16777318" enum="Key"> Launch Shortcut E key. </constant> - <constant name="KEY_LAUNCHF" value="16777319" enum="KeyList"> + <constant name="KEY_LAUNCHF" value="16777319" enum="Key"> Launch Shortcut F key. </constant> - <constant name="KEY_UNKNOWN" value="33554431" enum="KeyList"> + <constant name="KEY_UNKNOWN" value="33554431" enum="Key"> Unknown key. </constant> - <constant name="KEY_SPACE" value="32" enum="KeyList"> + <constant name="KEY_SPACE" value="32" enum="Key"> Space key. </constant> - <constant name="KEY_EXCLAM" value="33" enum="KeyList"> + <constant name="KEY_EXCLAM" value="33" enum="Key"> ! key. </constant> - <constant name="KEY_QUOTEDBL" value="34" enum="KeyList"> + <constant name="KEY_QUOTEDBL" value="34" enum="Key"> " key. </constant> - <constant name="KEY_NUMBERSIGN" value="35" enum="KeyList"> + <constant name="KEY_NUMBERSIGN" value="35" enum="Key"> # key. </constant> - <constant name="KEY_DOLLAR" value="36" enum="KeyList"> + <constant name="KEY_DOLLAR" value="36" enum="Key"> $ key. </constant> - <constant name="KEY_PERCENT" value="37" enum="KeyList"> + <constant name="KEY_PERCENT" value="37" enum="Key"> % key. </constant> - <constant name="KEY_AMPERSAND" value="38" enum="KeyList"> + <constant name="KEY_AMPERSAND" value="38" enum="Key"> & key. </constant> - <constant name="KEY_APOSTROPHE" value="39" enum="KeyList"> + <constant name="KEY_APOSTROPHE" value="39" enum="Key"> ' key. </constant> - <constant name="KEY_PARENLEFT" value="40" enum="KeyList"> + <constant name="KEY_PARENLEFT" value="40" enum="Key"> ( key. </constant> - <constant name="KEY_PARENRIGHT" value="41" enum="KeyList"> + <constant name="KEY_PARENRIGHT" value="41" enum="Key"> ) key. </constant> - <constant name="KEY_ASTERISK" value="42" enum="KeyList"> + <constant name="KEY_ASTERISK" value="42" enum="Key"> * key. </constant> - <constant name="KEY_PLUS" value="43" enum="KeyList"> + <constant name="KEY_PLUS" value="43" enum="Key"> + key. </constant> - <constant name="KEY_COMMA" value="44" enum="KeyList"> + <constant name="KEY_COMMA" value="44" enum="Key"> , key. </constant> - <constant name="KEY_MINUS" value="45" enum="KeyList"> + <constant name="KEY_MINUS" value="45" enum="Key"> - key. </constant> - <constant name="KEY_PERIOD" value="46" enum="KeyList"> + <constant name="KEY_PERIOD" value="46" enum="Key"> . key. </constant> - <constant name="KEY_SLASH" value="47" enum="KeyList"> + <constant name="KEY_SLASH" value="47" enum="Key"> / key. </constant> - <constant name="KEY_0" value="48" enum="KeyList"> + <constant name="KEY_0" value="48" enum="Key"> Number 0. </constant> - <constant name="KEY_1" value="49" enum="KeyList"> + <constant name="KEY_1" value="49" enum="Key"> Number 1. </constant> - <constant name="KEY_2" value="50" enum="KeyList"> + <constant name="KEY_2" value="50" enum="Key"> Number 2. </constant> - <constant name="KEY_3" value="51" enum="KeyList"> + <constant name="KEY_3" value="51" enum="Key"> Number 3. </constant> - <constant name="KEY_4" value="52" enum="KeyList"> + <constant name="KEY_4" value="52" enum="Key"> Number 4. </constant> - <constant name="KEY_5" value="53" enum="KeyList"> + <constant name="KEY_5" value="53" enum="Key"> Number 5. </constant> - <constant name="KEY_6" value="54" enum="KeyList"> + <constant name="KEY_6" value="54" enum="Key"> Number 6. </constant> - <constant name="KEY_7" value="55" enum="KeyList"> + <constant name="KEY_7" value="55" enum="Key"> Number 7. </constant> - <constant name="KEY_8" value="56" enum="KeyList"> + <constant name="KEY_8" value="56" enum="Key"> Number 8. </constant> - <constant name="KEY_9" value="57" enum="KeyList"> + <constant name="KEY_9" value="57" enum="Key"> Number 9. </constant> - <constant name="KEY_COLON" value="58" enum="KeyList"> + <constant name="KEY_COLON" value="58" enum="Key"> : key. </constant> - <constant name="KEY_SEMICOLON" value="59" enum="KeyList"> + <constant name="KEY_SEMICOLON" value="59" enum="Key"> ; key. </constant> - <constant name="KEY_LESS" value="60" enum="KeyList"> + <constant name="KEY_LESS" value="60" enum="Key"> < key. </constant> - <constant name="KEY_EQUAL" value="61" enum="KeyList"> + <constant name="KEY_EQUAL" value="61" enum="Key"> = key. </constant> - <constant name="KEY_GREATER" value="62" enum="KeyList"> + <constant name="KEY_GREATER" value="62" enum="Key"> > key. </constant> - <constant name="KEY_QUESTION" value="63" enum="KeyList"> + <constant name="KEY_QUESTION" value="63" enum="Key"> ? key. </constant> - <constant name="KEY_AT" value="64" enum="KeyList"> + <constant name="KEY_AT" value="64" enum="Key"> @ key. </constant> - <constant name="KEY_A" value="65" enum="KeyList"> + <constant name="KEY_A" value="65" enum="Key"> A key. </constant> - <constant name="KEY_B" value="66" enum="KeyList"> + <constant name="KEY_B" value="66" enum="Key"> B key. </constant> - <constant name="KEY_C" value="67" enum="KeyList"> + <constant name="KEY_C" value="67" enum="Key"> C key. </constant> - <constant name="KEY_D" value="68" enum="KeyList"> + <constant name="KEY_D" value="68" enum="Key"> D key. </constant> - <constant name="KEY_E" value="69" enum="KeyList"> + <constant name="KEY_E" value="69" enum="Key"> E key. </constant> - <constant name="KEY_F" value="70" enum="KeyList"> + <constant name="KEY_F" value="70" enum="Key"> F key. </constant> - <constant name="KEY_G" value="71" enum="KeyList"> + <constant name="KEY_G" value="71" enum="Key"> G key. </constant> - <constant name="KEY_H" value="72" enum="KeyList"> + <constant name="KEY_H" value="72" enum="Key"> H key. </constant> - <constant name="KEY_I" value="73" enum="KeyList"> + <constant name="KEY_I" value="73" enum="Key"> I key. </constant> - <constant name="KEY_J" value="74" enum="KeyList"> + <constant name="KEY_J" value="74" enum="Key"> J key. </constant> - <constant name="KEY_K" value="75" enum="KeyList"> + <constant name="KEY_K" value="75" enum="Key"> K key. </constant> - <constant name="KEY_L" value="76" enum="KeyList"> + <constant name="KEY_L" value="76" enum="Key"> L key. </constant> - <constant name="KEY_M" value="77" enum="KeyList"> + <constant name="KEY_M" value="77" enum="Key"> M key. </constant> - <constant name="KEY_N" value="78" enum="KeyList"> + <constant name="KEY_N" value="78" enum="Key"> N key. </constant> - <constant name="KEY_O" value="79" enum="KeyList"> + <constant name="KEY_O" value="79" enum="Key"> O key. </constant> - <constant name="KEY_P" value="80" enum="KeyList"> + <constant name="KEY_P" value="80" enum="Key"> P key. </constant> - <constant name="KEY_Q" value="81" enum="KeyList"> + <constant name="KEY_Q" value="81" enum="Key"> Q key. </constant> - <constant name="KEY_R" value="82" enum="KeyList"> + <constant name="KEY_R" value="82" enum="Key"> R key. </constant> - <constant name="KEY_S" value="83" enum="KeyList"> + <constant name="KEY_S" value="83" enum="Key"> S key. </constant> - <constant name="KEY_T" value="84" enum="KeyList"> + <constant name="KEY_T" value="84" enum="Key"> T key. </constant> - <constant name="KEY_U" value="85" enum="KeyList"> + <constant name="KEY_U" value="85" enum="Key"> U key. </constant> - <constant name="KEY_V" value="86" enum="KeyList"> + <constant name="KEY_V" value="86" enum="Key"> V key. </constant> - <constant name="KEY_W" value="87" enum="KeyList"> + <constant name="KEY_W" value="87" enum="Key"> W key. </constant> - <constant name="KEY_X" value="88" enum="KeyList"> + <constant name="KEY_X" value="88" enum="Key"> X key. </constant> - <constant name="KEY_Y" value="89" enum="KeyList"> + <constant name="KEY_Y" value="89" enum="Key"> Y key. </constant> - <constant name="KEY_Z" value="90" enum="KeyList"> + <constant name="KEY_Z" value="90" enum="Key"> Z key. </constant> - <constant name="KEY_BRACKETLEFT" value="91" enum="KeyList"> + <constant name="KEY_BRACKETLEFT" value="91" enum="Key"> [ key. </constant> - <constant name="KEY_BACKSLASH" value="92" enum="KeyList"> + <constant name="KEY_BACKSLASH" value="92" enum="Key"> \ key. </constant> - <constant name="KEY_BRACKETRIGHT" value="93" enum="KeyList"> + <constant name="KEY_BRACKETRIGHT" value="93" enum="Key"> ] key. </constant> - <constant name="KEY_ASCIICIRCUM" value="94" enum="KeyList"> + <constant name="KEY_ASCIICIRCUM" value="94" enum="Key"> ^ key. </constant> - <constant name="KEY_UNDERSCORE" value="95" enum="KeyList"> + <constant name="KEY_UNDERSCORE" value="95" enum="Key"> _ key. </constant> - <constant name="KEY_QUOTELEFT" value="96" enum="KeyList"> + <constant name="KEY_QUOTELEFT" value="96" enum="Key"> ` key. </constant> - <constant name="KEY_BRACELEFT" value="123" enum="KeyList"> + <constant name="KEY_BRACELEFT" value="123" enum="Key"> { key. </constant> - <constant name="KEY_BAR" value="124" enum="KeyList"> + <constant name="KEY_BAR" value="124" enum="Key"> | key. </constant> - <constant name="KEY_BRACERIGHT" value="125" enum="KeyList"> + <constant name="KEY_BRACERIGHT" value="125" enum="Key"> } key. </constant> - <constant name="KEY_ASCIITILDE" value="126" enum="KeyList"> + <constant name="KEY_ASCIITILDE" value="126" enum="Key"> ~ key. </constant> - <constant name="KEY_NOBREAKSPACE" value="160" enum="KeyList"> + <constant name="KEY_NOBREAKSPACE" value="160" enum="Key"> Non-breakable space key. </constant> - <constant name="KEY_EXCLAMDOWN" value="161" enum="KeyList"> + <constant name="KEY_EXCLAMDOWN" value="161" enum="Key"> ¡ key. </constant> - <constant name="KEY_CENT" value="162" enum="KeyList"> + <constant name="KEY_CENT" value="162" enum="Key"> ¢ key. </constant> - <constant name="KEY_STERLING" value="163" enum="KeyList"> + <constant name="KEY_STERLING" value="163" enum="Key"> £ key. </constant> - <constant name="KEY_CURRENCY" value="164" enum="KeyList"> + <constant name="KEY_CURRENCY" value="164" enum="Key"> ¤ key. </constant> - <constant name="KEY_YEN" value="165" enum="KeyList"> + <constant name="KEY_YEN" value="165" enum="Key"> Â¥ key. </constant> - <constant name="KEY_BROKENBAR" value="166" enum="KeyList"> + <constant name="KEY_BROKENBAR" value="166" enum="Key"> ¦ key. </constant> - <constant name="KEY_SECTION" value="167" enum="KeyList"> + <constant name="KEY_SECTION" value="167" enum="Key"> § key. </constant> - <constant name="KEY_DIAERESIS" value="168" enum="KeyList"> + <constant name="KEY_DIAERESIS" value="168" enum="Key"> ¨ key. </constant> - <constant name="KEY_COPYRIGHT" value="169" enum="KeyList"> + <constant name="KEY_COPYRIGHT" value="169" enum="Key"> © key. </constant> - <constant name="KEY_ORDFEMININE" value="170" enum="KeyList"> + <constant name="KEY_ORDFEMININE" value="170" enum="Key"> ª key. </constant> - <constant name="KEY_GUILLEMOTLEFT" value="171" enum="KeyList"> + <constant name="KEY_GUILLEMOTLEFT" value="171" enum="Key"> « key. </constant> - <constant name="KEY_NOTSIGN" value="172" enum="KeyList"> + <constant name="KEY_NOTSIGN" value="172" enum="Key"> ¬ key. </constant> - <constant name="KEY_HYPHEN" value="173" enum="KeyList"> + <constant name="KEY_HYPHEN" value="173" enum="Key"> Soft hyphen key. </constant> - <constant name="KEY_REGISTERED" value="174" enum="KeyList"> + <constant name="KEY_REGISTERED" value="174" enum="Key"> ® key. </constant> - <constant name="KEY_MACRON" value="175" enum="KeyList"> + <constant name="KEY_MACRON" value="175" enum="Key"> ¯ key. </constant> - <constant name="KEY_DEGREE" value="176" enum="KeyList"> + <constant name="KEY_DEGREE" value="176" enum="Key"> ° key. </constant> - <constant name="KEY_PLUSMINUS" value="177" enum="KeyList"> + <constant name="KEY_PLUSMINUS" value="177" enum="Key"> ± key. </constant> - <constant name="KEY_TWOSUPERIOR" value="178" enum="KeyList"> + <constant name="KEY_TWOSUPERIOR" value="178" enum="Key"> ² key. </constant> - <constant name="KEY_THREESUPERIOR" value="179" enum="KeyList"> + <constant name="KEY_THREESUPERIOR" value="179" enum="Key"> ³ key. </constant> - <constant name="KEY_ACUTE" value="180" enum="KeyList"> + <constant name="KEY_ACUTE" value="180" enum="Key"> ´ key. </constant> - <constant name="KEY_MU" value="181" enum="KeyList"> + <constant name="KEY_MU" value="181" enum="Key"> µ key. </constant> - <constant name="KEY_PARAGRAPH" value="182" enum="KeyList"> + <constant name="KEY_PARAGRAPH" value="182" enum="Key"> ¶ key. </constant> - <constant name="KEY_PERIODCENTERED" value="183" enum="KeyList"> + <constant name="KEY_PERIODCENTERED" value="183" enum="Key"> · key. </constant> - <constant name="KEY_CEDILLA" value="184" enum="KeyList"> + <constant name="KEY_CEDILLA" value="184" enum="Key"> ¸ key. </constant> - <constant name="KEY_ONESUPERIOR" value="185" enum="KeyList"> + <constant name="KEY_ONESUPERIOR" value="185" enum="Key"> ¹ key. </constant> - <constant name="KEY_MASCULINE" value="186" enum="KeyList"> + <constant name="KEY_MASCULINE" value="186" enum="Key"> º key. </constant> - <constant name="KEY_GUILLEMOTRIGHT" value="187" enum="KeyList"> + <constant name="KEY_GUILLEMOTRIGHT" value="187" enum="Key"> » key. </constant> - <constant name="KEY_ONEQUARTER" value="188" enum="KeyList"> + <constant name="KEY_ONEQUARTER" value="188" enum="Key"> ¼ key. </constant> - <constant name="KEY_ONEHALF" value="189" enum="KeyList"> + <constant name="KEY_ONEHALF" value="189" enum="Key"> ½ key. </constant> - <constant name="KEY_THREEQUARTERS" value="190" enum="KeyList"> + <constant name="KEY_THREEQUARTERS" value="190" enum="Key"> ¾ key. </constant> - <constant name="KEY_QUESTIONDOWN" value="191" enum="KeyList"> + <constant name="KEY_QUESTIONDOWN" value="191" enum="Key"> ¿ key. </constant> - <constant name="KEY_AGRAVE" value="192" enum="KeyList"> + <constant name="KEY_AGRAVE" value="192" enum="Key"> À key. </constant> - <constant name="KEY_AACUTE" value="193" enum="KeyList"> + <constant name="KEY_AACUTE" value="193" enum="Key"> à key. </constant> - <constant name="KEY_ACIRCUMFLEX" value="194" enum="KeyList"> + <constant name="KEY_ACIRCUMFLEX" value="194" enum="Key">  key. </constant> - <constant name="KEY_ATILDE" value="195" enum="KeyList"> + <constant name="KEY_ATILDE" value="195" enum="Key"> à key. </constant> - <constant name="KEY_ADIAERESIS" value="196" enum="KeyList"> + <constant name="KEY_ADIAERESIS" value="196" enum="Key"> Ä key. </constant> - <constant name="KEY_ARING" value="197" enum="KeyList"> + <constant name="KEY_ARING" value="197" enum="Key"> Ã… key. </constant> - <constant name="KEY_AE" value="198" enum="KeyList"> + <constant name="KEY_AE" value="198" enum="Key"> Æ key. </constant> - <constant name="KEY_CCEDILLA" value="199" enum="KeyList"> + <constant name="KEY_CCEDILLA" value="199" enum="Key"> Ç key. </constant> - <constant name="KEY_EGRAVE" value="200" enum="KeyList"> + <constant name="KEY_EGRAVE" value="200" enum="Key"> È key. </constant> - <constant name="KEY_EACUTE" value="201" enum="KeyList"> + <constant name="KEY_EACUTE" value="201" enum="Key"> É key. </constant> - <constant name="KEY_ECIRCUMFLEX" value="202" enum="KeyList"> + <constant name="KEY_ECIRCUMFLEX" value="202" enum="Key"> Ê key. </constant> - <constant name="KEY_EDIAERESIS" value="203" enum="KeyList"> + <constant name="KEY_EDIAERESIS" value="203" enum="Key"> Ë key. </constant> - <constant name="KEY_IGRAVE" value="204" enum="KeyList"> + <constant name="KEY_IGRAVE" value="204" enum="Key"> ÃŒ key. </constant> - <constant name="KEY_IACUTE" value="205" enum="KeyList"> + <constant name="KEY_IACUTE" value="205" enum="Key"> à key. </constant> - <constant name="KEY_ICIRCUMFLEX" value="206" enum="KeyList"> + <constant name="KEY_ICIRCUMFLEX" value="206" enum="Key"> ÃŽ key. </constant> - <constant name="KEY_IDIAERESIS" value="207" enum="KeyList"> + <constant name="KEY_IDIAERESIS" value="207" enum="Key"> à key. </constant> - <constant name="KEY_ETH" value="208" enum="KeyList"> + <constant name="KEY_ETH" value="208" enum="Key"> à key. </constant> - <constant name="KEY_NTILDE" value="209" enum="KeyList"> + <constant name="KEY_NTILDE" value="209" enum="Key"> Ñ key. </constant> - <constant name="KEY_OGRAVE" value="210" enum="KeyList"> + <constant name="KEY_OGRAVE" value="210" enum="Key"> Ã’ key. </constant> - <constant name="KEY_OACUTE" value="211" enum="KeyList"> + <constant name="KEY_OACUTE" value="211" enum="Key"> Ó key. </constant> - <constant name="KEY_OCIRCUMFLEX" value="212" enum="KeyList"> + <constant name="KEY_OCIRCUMFLEX" value="212" enum="Key"> Ô key. </constant> - <constant name="KEY_OTILDE" value="213" enum="KeyList"> + <constant name="KEY_OTILDE" value="213" enum="Key"> Õ key. </constant> - <constant name="KEY_ODIAERESIS" value="214" enum="KeyList"> + <constant name="KEY_ODIAERESIS" value="214" enum="Key"> Ö key. </constant> - <constant name="KEY_MULTIPLY" value="215" enum="KeyList"> + <constant name="KEY_MULTIPLY" value="215" enum="Key"> × key. </constant> - <constant name="KEY_OOBLIQUE" value="216" enum="KeyList"> + <constant name="KEY_OOBLIQUE" value="216" enum="Key"> Ø key. </constant> - <constant name="KEY_UGRAVE" value="217" enum="KeyList"> + <constant name="KEY_UGRAVE" value="217" enum="Key"> Ù key. </constant> - <constant name="KEY_UACUTE" value="218" enum="KeyList"> + <constant name="KEY_UACUTE" value="218" enum="Key"> Ú key. </constant> - <constant name="KEY_UCIRCUMFLEX" value="219" enum="KeyList"> + <constant name="KEY_UCIRCUMFLEX" value="219" enum="Key"> Û key. </constant> - <constant name="KEY_UDIAERESIS" value="220" enum="KeyList"> + <constant name="KEY_UDIAERESIS" value="220" enum="Key"> Ãœ key. </constant> - <constant name="KEY_YACUTE" value="221" enum="KeyList"> + <constant name="KEY_YACUTE" value="221" enum="Key"> à key. </constant> - <constant name="KEY_THORN" value="222" enum="KeyList"> + <constant name="KEY_THORN" value="222" enum="Key"> Þ key. </constant> - <constant name="KEY_SSHARP" value="223" enum="KeyList"> + <constant name="KEY_SSHARP" value="223" enum="Key"> ß key. </constant> - <constant name="KEY_DIVISION" value="247" enum="KeyList"> + <constant name="KEY_DIVISION" value="247" enum="Key"> ÷ key. </constant> - <constant name="KEY_YDIAERESIS" value="255" enum="KeyList"> + <constant name="KEY_YDIAERESIS" value="255" enum="Key"> ÿ key. </constant> <constant name="KEY_CODE_MASK" value="33554431" enum="KeyModifierMask"> @@ -2061,166 +2061,166 @@ <constant name="KEY_MASK_GROUP_SWITCH" value="1073741824" enum="KeyModifierMask"> Group Switch key mask. </constant> - <constant name="BUTTON_LEFT" value="1" enum="ButtonList"> + <constant name="MOUSE_BUTTON_LEFT" value="1" enum="MouseButton"> Left mouse button. </constant> - <constant name="BUTTON_RIGHT" value="2" enum="ButtonList"> + <constant name="MOUSE_BUTTON_RIGHT" value="2" enum="MouseButton"> Right mouse button. </constant> - <constant name="BUTTON_MIDDLE" value="3" enum="ButtonList"> + <constant name="MOUSE_BUTTON_MIDDLE" value="3" enum="MouseButton"> Middle mouse button. </constant> - <constant name="BUTTON_XBUTTON1" value="8" enum="ButtonList"> + <constant name="MOUSE_BUTTON_XBUTTON1" value="8" enum="MouseButton"> Extra mouse button 1 (only present on some mice). </constant> - <constant name="BUTTON_XBUTTON2" value="9" enum="ButtonList"> + <constant name="MOUSE_BUTTON_XBUTTON2" value="9" enum="MouseButton"> Extra mouse button 2 (only present on some mice). </constant> - <constant name="BUTTON_WHEEL_UP" value="4" enum="ButtonList"> + <constant name="MOUSE_BUTTON_WHEEL_UP" value="4" enum="MouseButton"> Mouse wheel up. </constant> - <constant name="BUTTON_WHEEL_DOWN" value="5" enum="ButtonList"> + <constant name="MOUSE_BUTTON_WHEEL_DOWN" value="5" enum="MouseButton"> Mouse wheel down. </constant> - <constant name="BUTTON_WHEEL_LEFT" value="6" enum="ButtonList"> + <constant name="MOUSE_BUTTON_WHEEL_LEFT" value="6" enum="MouseButton"> Mouse wheel left button (only present on some mice). </constant> - <constant name="BUTTON_WHEEL_RIGHT" value="7" enum="ButtonList"> + <constant name="MOUSE_BUTTON_WHEEL_RIGHT" value="7" enum="MouseButton"> Mouse wheel right button (only present on some mice). </constant> - <constant name="BUTTON_MASK_LEFT" value="1" enum="ButtonList"> + <constant name="MOUSE_BUTTON_MASK_LEFT" value="1" enum="MouseButton"> Left mouse button mask. </constant> - <constant name="BUTTON_MASK_RIGHT" value="2" enum="ButtonList"> + <constant name="MOUSE_BUTTON_MASK_RIGHT" value="2" enum="MouseButton"> Right mouse button mask. </constant> - <constant name="BUTTON_MASK_MIDDLE" value="4" enum="ButtonList"> + <constant name="MOUSE_BUTTON_MASK_MIDDLE" value="4" enum="MouseButton"> Middle mouse button mask. </constant> - <constant name="BUTTON_MASK_XBUTTON1" value="128" enum="ButtonList"> + <constant name="MOUSE_BUTTON_MASK_XBUTTON1" value="128" enum="MouseButton"> Extra mouse button 1 mask. </constant> - <constant name="BUTTON_MASK_XBUTTON2" value="256" enum="ButtonList"> + <constant name="MOUSE_BUTTON_MASK_XBUTTON2" value="256" enum="MouseButton"> Extra mouse button 2 mask. </constant> - <constant name="JOY_BUTTON_INVALID" value="-1" enum="JoyButtonList"> + <constant name="JOY_BUTTON_INVALID" value="-1" enum="JoyButton"> An invalid game controller button. </constant> - <constant name="JOY_BUTTON_A" value="0" enum="JoyButtonList"> + <constant name="JOY_BUTTON_A" value="0" enum="JoyButton"> Game controller SDL button A. Corresponds to the bottom action button: Sony Cross, Xbox A, Nintendo B. </constant> - <constant name="JOY_BUTTON_B" value="1" enum="JoyButtonList"> + <constant name="JOY_BUTTON_B" value="1" enum="JoyButton"> Game controller SDL button B. Corresponds to the right action button: Sony Circle, Xbox B, Nintendo A. </constant> - <constant name="JOY_BUTTON_X" value="2" enum="JoyButtonList"> + <constant name="JOY_BUTTON_X" value="2" enum="JoyButton"> Game controller SDL button X. Corresponds to the left action button: Sony Square, Xbox X, Nintendo Y. </constant> - <constant name="JOY_BUTTON_Y" value="3" enum="JoyButtonList"> + <constant name="JOY_BUTTON_Y" value="3" enum="JoyButton"> Game controller SDL button Y. Corresponds to the top action button: Sony Triangle, Xbox Y, Nintendo X. </constant> - <constant name="JOY_BUTTON_BACK" value="4" enum="JoyButtonList"> + <constant name="JOY_BUTTON_BACK" value="4" enum="JoyButton"> Game controller SDL back button. Corresponds to the Sony Select, Xbox Back, Nintendo - button. </constant> - <constant name="JOY_BUTTON_GUIDE" value="5" enum="JoyButtonList"> + <constant name="JOY_BUTTON_GUIDE" value="5" enum="JoyButton"> Game controller SDL guide button. Corresponds to the Sony PS, Xbox Home button. </constant> - <constant name="JOY_BUTTON_START" value="6" enum="JoyButtonList"> + <constant name="JOY_BUTTON_START" value="6" enum="JoyButton"> Game controller SDL start button. Corresponds to the Nintendo + button. </constant> - <constant name="JOY_BUTTON_LEFT_STICK" value="7" enum="JoyButtonList"> + <constant name="JOY_BUTTON_LEFT_STICK" value="7" enum="JoyButton"> Game controller SDL left stick button. Corresponds to the Sony L3, Xbox L/LS button. </constant> - <constant name="JOY_BUTTON_RIGHT_STICK" value="8" enum="JoyButtonList"> + <constant name="JOY_BUTTON_RIGHT_STICK" value="8" enum="JoyButton"> Game controller SDL right stick button. Corresponds to the Sony R3, Xbox R/RS button. </constant> - <constant name="JOY_BUTTON_LEFT_SHOULDER" value="9" enum="JoyButtonList"> + <constant name="JOY_BUTTON_LEFT_SHOULDER" value="9" enum="JoyButton"> Game controller SDL left shoulder button. Corresponds to the Sony L1, Xbox LB button. </constant> - <constant name="JOY_BUTTON_RIGHT_SHOULDER" value="10" enum="JoyButtonList"> + <constant name="JOY_BUTTON_RIGHT_SHOULDER" value="10" enum="JoyButton"> Game controller SDL right shoulder button. Corresponds to the Sony R1, Xbox RB button. </constant> - <constant name="JOY_BUTTON_DPAD_UP" value="11" enum="JoyButtonList"> + <constant name="JOY_BUTTON_DPAD_UP" value="11" enum="JoyButton"> Game controller D-pad up button. </constant> - <constant name="JOY_BUTTON_DPAD_DOWN" value="12" enum="JoyButtonList"> + <constant name="JOY_BUTTON_DPAD_DOWN" value="12" enum="JoyButton"> Game controller D-pad down button. </constant> - <constant name="JOY_BUTTON_DPAD_LEFT" value="13" enum="JoyButtonList"> + <constant name="JOY_BUTTON_DPAD_LEFT" value="13" enum="JoyButton"> Game controller D-pad left button. </constant> - <constant name="JOY_BUTTON_DPAD_RIGHT" value="14" enum="JoyButtonList"> + <constant name="JOY_BUTTON_DPAD_RIGHT" value="14" enum="JoyButton"> Game controller D-pad right button. </constant> - <constant name="JOY_BUTTON_MISC1" value="15" enum="JoyButtonList"> + <constant name="JOY_BUTTON_MISC1" value="15" enum="JoyButton"> Game controller SDL miscellaneous button. Corresponds to Xbox share button, PS5 microphone button, Nintendo capture button. </constant> - <constant name="JOY_BUTTON_PADDLE1" value="16" enum="JoyButtonList"> + <constant name="JOY_BUTTON_PADDLE1" value="16" enum="JoyButton"> Game controller SDL paddle 1 button. </constant> - <constant name="JOY_BUTTON_PADDLE2" value="17" enum="JoyButtonList"> + <constant name="JOY_BUTTON_PADDLE2" value="17" enum="JoyButton"> Game controller SDL paddle 2 button. </constant> - <constant name="JOY_BUTTON_PADDLE3" value="18" enum="JoyButtonList"> + <constant name="JOY_BUTTON_PADDLE3" value="18" enum="JoyButton"> Game controller SDL paddle 3 button. </constant> - <constant name="JOY_BUTTON_PADDLE4" value="19" enum="JoyButtonList"> + <constant name="JOY_BUTTON_PADDLE4" value="19" enum="JoyButton"> Game controller SDL paddle 4 button. </constant> - <constant name="JOY_BUTTON_TOUCHPAD" value="20" enum="JoyButtonList"> + <constant name="JOY_BUTTON_TOUCHPAD" value="20" enum="JoyButton"> Game controller SDL touchpad button. </constant> - <constant name="JOY_BUTTON_SDL_MAX" value="21" enum="JoyButtonList"> + <constant name="JOY_BUTTON_SDL_MAX" value="21" enum="JoyButton"> The number of SDL game controller buttons. </constant> - <constant name="JOY_BUTTON_MAX" value="36" enum="JoyButtonList"> + <constant name="JOY_BUTTON_MAX" value="36" enum="JoyButton"> The maximum number of game controller buttons: Android supports up to 36 buttons. </constant> - <constant name="JOY_AXIS_INVALID" value="-1" enum="JoyAxisList"> + <constant name="JOY_AXIS_INVALID" value="-1" enum="JoyAxis"> An invalid game controller axis. </constant> - <constant name="JOY_AXIS_LEFT_X" value="0" enum="JoyAxisList"> + <constant name="JOY_AXIS_LEFT_X" value="0" enum="JoyAxis"> Game controller left joystick x-axis. </constant> - <constant name="JOY_AXIS_LEFT_Y" value="1" enum="JoyAxisList"> + <constant name="JOY_AXIS_LEFT_Y" value="1" enum="JoyAxis"> Game controller left joystick y-axis. </constant> - <constant name="JOY_AXIS_RIGHT_X" value="2" enum="JoyAxisList"> + <constant name="JOY_AXIS_RIGHT_X" value="2" enum="JoyAxis"> Game controller right joystick x-axis. </constant> - <constant name="JOY_AXIS_RIGHT_Y" value="3" enum="JoyAxisList"> + <constant name="JOY_AXIS_RIGHT_Y" value="3" enum="JoyAxis"> Game controller right joystick y-axis. </constant> - <constant name="JOY_AXIS_TRIGGER_LEFT" value="4" enum="JoyAxisList"> + <constant name="JOY_AXIS_TRIGGER_LEFT" value="4" enum="JoyAxis"> Game controller left trigger axis. </constant> - <constant name="JOY_AXIS_TRIGGER_RIGHT" value="5" enum="JoyAxisList"> + <constant name="JOY_AXIS_TRIGGER_RIGHT" value="5" enum="JoyAxis"> Game controller right trigger axis. </constant> - <constant name="JOY_AXIS_SDL_MAX" value="6" enum="JoyAxisList"> + <constant name="JOY_AXIS_SDL_MAX" value="6" enum="JoyAxis"> The number of SDL game controller axes. </constant> - <constant name="JOY_AXIS_MAX" value="10" enum="JoyAxisList"> + <constant name="JOY_AXIS_MAX" value="10" enum="JoyAxis"> The maximum number of game controller axes: OpenVR supports up to 5 Joysticks making a total of 10 axes. </constant> - <constant name="MIDI_MESSAGE_NOTE_OFF" value="8" enum="MidiMessageList"> + <constant name="MIDI_MESSAGE_NOTE_OFF" value="8" enum="MIDIMessage"> MIDI note OFF message. </constant> - <constant name="MIDI_MESSAGE_NOTE_ON" value="9" enum="MidiMessageList"> + <constant name="MIDI_MESSAGE_NOTE_ON" value="9" enum="MIDIMessage"> MIDI note ON message. </constant> - <constant name="MIDI_MESSAGE_AFTERTOUCH" value="10" enum="MidiMessageList"> + <constant name="MIDI_MESSAGE_AFTERTOUCH" value="10" enum="MIDIMessage"> MIDI aftertouch message. </constant> - <constant name="MIDI_MESSAGE_CONTROL_CHANGE" value="11" enum="MidiMessageList"> + <constant name="MIDI_MESSAGE_CONTROL_CHANGE" value="11" enum="MIDIMessage"> MIDI control change message. </constant> - <constant name="MIDI_MESSAGE_PROGRAM_CHANGE" value="12" enum="MidiMessageList"> + <constant name="MIDI_MESSAGE_PROGRAM_CHANGE" value="12" enum="MIDIMessage"> MIDI program change message. </constant> - <constant name="MIDI_MESSAGE_CHANNEL_PRESSURE" value="13" enum="MidiMessageList"> + <constant name="MIDI_MESSAGE_CHANNEL_PRESSURE" value="13" enum="MIDIMessage"> MIDI channel pressure message. </constant> - <constant name="MIDI_MESSAGE_PITCH_BEND" value="14" enum="MidiMessageList"> + <constant name="MIDI_MESSAGE_PITCH_BEND" value="14" enum="MIDIMessage"> MIDI pitch bend message. </constant> <constant name="OK" value="0" enum="Error"> diff --git a/doc/classes/AABB.xml b/doc/classes/AABB.xml index b66f4d11f2..a28bde9946 100644 --- a/doc/classes/AABB.xml +++ b/doc/classes/AABB.xml @@ -264,7 +264,7 @@ Beginning corner. Typically has values lower than [member end]. </member> <member name="size" type="Vector3" setter="" getter="" default="Vector3( 0, 0, 0 )"> - Size from [member position] to [member end]. Typically all components are positive. + Size from [member position] to [member end]. Typically, all components are positive. If the size is negative, you can use [method abs] to fix it. </member> </members> diff --git a/doc/classes/AStar.xml b/doc/classes/AStar.xml index bfdc66623d..e975b8ed28 100644 --- a/doc/classes/AStar.xml +++ b/doc/classes/AStar.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="AStar" inherits="Reference" version="4.0"> <brief_description> - An implementation of A* to find shortest paths among connected points in space. + An implementation of A* to find the shortest paths among connected points in space. </brief_description> <description> A* (A star) is a computer algorithm that is widely used in pathfinding and graph traversal, the process of plotting short paths among vertices (points), passing through a given set of edges (segments). It enjoys widespread use due to its performance and accuracy. Godot's A* implementation uses points in three-dimensional space and Euclidean distances by default. diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml index 9720405ffd..7ceb21d22e 100644 --- a/doc/classes/Animation.xml +++ b/doc/classes/Animation.xml @@ -710,7 +710,7 @@ [b]Note:[/b] Length is not delimited by the last key, as this one may be before or after the end to ensure correct interpolation and looping. </member> <member name="loop" type="bool" setter="set_loop" getter="has_loop" default="false"> - A flag indicating that the animation must loop. This is uses for correct interpolation of animation cycles, and for hinting the player that it must restart the animation. + A flag indicating that the animation must loop. This is used for correct interpolation of animation cycles, and for hinting the player that it must restart the animation. </member> <member name="step" type="float" setter="set_step" getter="get_step" default="0.1"> The animation step value. diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml index e5ba1d58f7..7696f36009 100644 --- a/doc/classes/AnimationPlayer.xml +++ b/doc/classes/AnimationPlayer.xml @@ -237,7 +237,7 @@ </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. - [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]. + [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. diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml index dcfb91eb61..54bbe7a94b 100644 --- a/doc/classes/Array.xml +++ b/doc/classes/Array.xml @@ -328,13 +328,6 @@ [b]Note:[/b] On large arrays, this method will be slower if the inserted element is close to the beginning of the array (index 0). This is because all elements placed after the newly inserted element have to be reindexed. </description> </method> - <method name="invert"> - <return type="void"> - </return> - <description> - Reverses the order of the elements in the array. - </description> - </method> <method name="is_empty" qualifiers="const"> <return type="bool"> </return> @@ -474,6 +467,13 @@ Resizes the array to contain a different number of elements. If the array size is smaller, elements are cleared, if bigger, new elements are [code]null[/code]. </description> </method> + <method name="reverse"> + <return type="void"> + </return> + <description> + Reverses the order of the elements in the array. + </description> + </method> <method name="rfind" qualifiers="const"> <return type="int"> </return> diff --git a/doc/classes/ArrayMesh.xml b/doc/classes/ArrayMesh.xml index e2c4ed1430..7c1c4656f8 100644 --- a/doc/classes/ArrayMesh.xml +++ b/doc/classes/ArrayMesh.xml @@ -128,6 +128,16 @@ Will regenerate normal maps for the [ArrayMesh]. </description> </method> + <method name="set_blend_shape_name"> + <return type="void"> + </return> + <argument index="0" name="index" type="int"> + </argument> + <argument index="1" name="name" type="StringName"> + </argument> + <description> + </description> + </method> <method name="surface_find_by_name" qualifiers="const"> <return type="int"> </return> diff --git a/doc/classes/BackBufferCopy.xml b/doc/classes/BackBufferCopy.xml index 7cc6a5613b..9a70b8f20c 100644 --- a/doc/classes/BackBufferCopy.xml +++ b/doc/classes/BackBufferCopy.xml @@ -4,7 +4,7 @@ Copies a region of the screen (or the whole screen) to a buffer so it can be accessed in your shader scripts through the [code]texture(SCREEN_TEXTURE, ...)[/code] function. </brief_description> <description> - Node for back-buffering the currently-displayed screen. The region defined in the BackBufferCopy node is bufferized with the content of the screen it covers, or the entire screen according to the copy mode set. Use the [code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to access the buffer. + Node for back-buffering the currently-displayed screen. The region defined in the BackBufferCopy node is buffered with the content of the screen it covers, or the entire screen according to the copy mode set. Use the [code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to access the buffer. [b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), anchors and margins won't apply to child [Control]-derived nodes. This can be problematic when resizing the window. To avoid this, add [Control]-derived nodes as [i]siblings[/i] to the BackBufferCopy node instead of adding them as children. </description> <tutorials> diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml index 45ef4cb14c..f7e31f5f9c 100644 --- a/doc/classes/BaseButton.xml +++ b/doc/classes/BaseButton.xml @@ -49,7 +49,7 @@ </member> <member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask" default="1"> Binary mask to choose which mouse buttons this button will respond to. - To allow both left-click and right-click, use [code]BUTTON_MASK_LEFT | BUTTON_MASK_RIGHT[/code]. + To allow both left-click and right-click, use [code]MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT[/code]. </member> <member name="disabled" type="bool" setter="set_disabled" getter="is_disabled" default="false"> If [code]true[/code], the button is in disabled state and can't be clicked or toggled. diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml index fa0c3b167a..c87398ac8f 100644 --- a/doc/classes/BaseMaterial3D.xml +++ b/doc/classes/BaseMaterial3D.xml @@ -82,7 +82,7 @@ Texture to multiply by [member albedo_color]. Used for basic texturing of objects. </member> <member name="alpha_antialiasing_edge" type="float" setter="set_alpha_antialiasing_edge" getter="get_alpha_antialiasing_edge"> - Threshold at which antialiasing will by applied on the alpha channel. + Threshold at which antialiasing will be applied on the alpha channel. </member> <member name="alpha_antialiasing_mode" type="int" setter="set_alpha_antialiasing" getter="get_alpha_antialiasing" enum="BaseMaterial3D.AlphaAntiAliasing"> The type of alpha antialiasing to apply. See [enum AlphaAntiAliasing]. @@ -127,7 +127,7 @@ Texture used to control the backlight effect per-pixel. Added to [member backlight]. </member> <member name="billboard_keep_scale" type="bool" setter="set_flag" getter="get_flag" default="false"> - If [code]true[/code], the shader will keep the scale set for the mesh. Otherwise the scale is lost when billboarding. Only applies when [member billboard_mode] is [constant BILLBOARD_ENABLED]. + If [code]true[/code], the shader will keep the scale set for the mesh. Otherwise, the scale is lost when billboarding. Only applies when [member billboard_mode] is [constant BILLBOARD_ENABLED]. </member> <member name="billboard_mode" type="int" setter="set_billboard_mode" getter="get_billboard_mode" enum="BaseMaterial3D.BillboardMode" default="0"> Controls how the object faces the camera. See [enum BillboardMode]. diff --git a/doc/classes/BoxContainer.xml b/doc/classes/BoxContainer.xml index 0d8233e6ff..ffa7c9066a 100644 --- a/doc/classes/BoxContainer.xml +++ b/doc/classes/BoxContainer.xml @@ -10,7 +10,7 @@ </tutorials> <methods> <method name="add_spacer"> - <return type="void"> + <return type="Control"> </return> <argument index="0" name="begin" type="bool"> </argument> diff --git a/doc/classes/Camera3D.xml b/doc/classes/Camera3D.xml index 034b2e9629..9f1d6d8e31 100644 --- a/doc/classes/Camera3D.xml +++ b/doc/classes/Camera3D.xml @@ -194,7 +194,7 @@ </member> <member name="fov" type="float" setter="set_fov" getter="get_fov" default="75.0"> The camera's field of view angle (in degrees). Only applicable in perspective mode. Since [member keep_aspect] locks one axis, [code]fov[/code] sets the other axis' field of view angle. - For reference, the default vertical field of view value ([code]75.0[/code]) is equivalent to an horizontal FOV of: + For reference, the default vertical field of view value ([code]75.0[/code]) is equivalent to a horizontal FOV of: - ~91.31 degrees in a 4:3 viewport - ~101.67 degrees in a 16:10 viewport - ~107.51 degrees in a 16:9 viewport diff --git a/doc/classes/CheckBox.xml b/doc/classes/CheckBox.xml index 80febfbfe7..05e412e9da 100644 --- a/doc/classes/CheckBox.xml +++ b/doc/classes/CheckBox.xml @@ -24,6 +24,8 @@ <theme_item name="checked" type="Texture2D"> The check icon to display when the [CheckBox] is checked. </theme_item> + <theme_item name="checked_disabled" type="Texture2D"> + </theme_item> <theme_item name="disabled" type="StyleBox"> The [StyleBox] to display as a background when the [CheckBox] is disabled. </theme_item> @@ -75,11 +77,17 @@ <theme_item name="radio_checked" type="Texture2D"> If the [CheckBox] is configured as a radio button, the icon to display when the [CheckBox] is checked. </theme_item> + <theme_item name="radio_checked_disabled" type="Texture2D"> + </theme_item> <theme_item name="radio_unchecked" type="Texture2D"> If the [CheckBox] is configured as a radio button, the icon to display when the [CheckBox] is unchecked. </theme_item> + <theme_item name="radio_unchecked_disabled" type="Texture2D"> + </theme_item> <theme_item name="unchecked" type="Texture2D"> The check icon to display when the [CheckBox] is unchecked. </theme_item> + <theme_item name="unchecked_disabled" type="Texture2D"> + </theme_item> </theme_items> </class> diff --git a/doc/classes/CodeEdit.xml b/doc/classes/CodeEdit.xml index d1483ac88e..81795abcdd 100644 --- a/doc/classes/CodeEdit.xml +++ b/doc/classes/CodeEdit.xml @@ -3,7 +3,7 @@ <brief_description> </brief_description> <description> - [b]Note[/b]: By default [CodeEdit] always use left-to-right text direction to correcly display source code. + [b]Note[/b]: By default [CodeEdit] always use left-to-right text direction to correctly display source code. </description> <tutorials> </tutorials> diff --git a/doc/classes/ConcavePolygonShape3D.xml b/doc/classes/ConcavePolygonShape3D.xml index 3e83202472..a9687abedc 100644 --- a/doc/classes/ConcavePolygonShape3D.xml +++ b/doc/classes/ConcavePolygonShape3D.xml @@ -28,6 +28,11 @@ </description> </method> </methods> + <members> + <member name="backface_collision" type="bool" setter="set_backface_collision_enabled" getter="is_backface_collision_enabled" default="false"> + If set to [code]true[/code], collisions occur on both sides of the concave shape faces. Otherwise they occur only along the face normals. + </member> + </members> <constants> </constants> </class> diff --git a/doc/classes/ConfigFile.xml b/doc/classes/ConfigFile.xml index da17d993e3..38948a2d6e 100644 --- a/doc/classes/ConfigFile.xml +++ b/doc/classes/ConfigFile.xml @@ -49,6 +49,12 @@ <tutorials> </tutorials> <methods> + <method name="clear"> + <return type="void"> + </return> + <description> + </description> + </method> <method name="erase_section"> <return type="void"> </return> @@ -158,7 +164,7 @@ <argument index="0" name="data" type="String"> </argument> <description> - Parses the the passed string as the contents of a config file. The string is parsed and loaded in the ConfigFile object which the method was called on. + Parses the passed string as the contents of a config file. The string is parsed and loaded in the ConfigFile object which the method was called on. Returns one of the [enum Error] code constants ([code]OK[/code] on success). </description> </method> diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index c5e820e9fe..c0f918a01f 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -50,7 +50,7 @@ [gdscript] func _gui_input(event): if event is InputEventMouseButton: - if event.button_index == BUTTON_LEFT and event.pressed: + if event.button_index == MOUSE_BUTTON_LEFT and event.pressed: print("I've been clicked D:") [/gdscript] [csharp] @@ -150,7 +150,6 @@ </argument> <description> Overrides the [Color] with given [code]name[/code] in the [member theme] resource the control uses. - [b]Note:[/b] Unlike other theme overrides, there is no way to undo a color override without manually assigning the previous color. [b]Example of overriding a label's color and resetting it later:[/b] [codeblocks] [gdscript] @@ -178,7 +177,7 @@ <argument index="1" name="constant" type="int"> </argument> <description> - Overrides an integer constant with given [code]name[/code] in the [member theme] resource the control uses. If the [code]constant[/code] is [code]0[/code], the override is cleared and the constant from assigned [Theme] is used. + Overrides an integer constant with given [code]name[/code] in the [member theme] resource the control uses. </description> </method> <method name="add_theme_font_override"> @@ -189,7 +188,7 @@ <argument index="1" name="font" type="Font"> </argument> <description> - Overrides the font with given [code]name[/code] in the [member theme] resource the control uses. If [code]font[/code] is [code]null[/code] or invalid, the override is cleared and the font from assigned [Theme] is used. + Overrides the font with given [code]name[/code] in the [member theme] resource the control uses. </description> </method> <method name="add_theme_font_size_override"> @@ -200,7 +199,7 @@ <argument index="1" name="font_size" type="int"> </argument> <description> - Overrides the font size with given [code]name[/code] in the [member theme] resource the control uses. If [code]font_size[/code] is [code]-1[/code], the override is cleared and the font size from assigned [Theme] is used. + Overrides the font size with given [code]name[/code] in the [member theme] resource the control uses. </description> </method> <method name="add_theme_icon_override"> @@ -211,7 +210,7 @@ <argument index="1" name="texture" type="Texture2D"> </argument> <description> - Overrides the icon with given [code]name[/code] in the [member theme] resource the control uses. If [code]icon[/code] is [code]null[/code] or invalid, the override is cleared and the icon from assigned [Theme] is used. + Overrides the icon with given [code]name[/code] in the [member theme] resource the control uses. </description> </method> <method name="add_theme_stylebox_override"> @@ -222,7 +221,7 @@ <argument index="1" name="stylebox" type="StyleBox"> </argument> <description> - Overrides the [StyleBox] with given [code]name[/code] in the [member theme] resource the control uses. If [code]stylebox[/code] is empty or invalid, the override is cleared and the [StyleBox] from assigned [Theme] is used. + Overrides the [StyleBox] with given [code]name[/code] in the [member theme] resource the control uses. [b]Example of modifying a property in a StyleBox by duplicating it:[/b] [codeblocks] [gdscript] @@ -730,6 +729,60 @@ Give up the focus. No other control will be able to receive keyboard input. </description> </method> + <method name="remove_theme_color_override"> + <return type="void"> + </return> + <argument index="0" name="name" type="StringName"> + </argument> + <description> + Removes a theme override for a [Color] with the given [code]name[/code]. + </description> + </method> + <method name="remove_theme_constant_override"> + <return type="void"> + </return> + <argument index="0" name="name" type="StringName"> + </argument> + <description> + Removes a theme override for a constant with the given [code]name[/code]. + </description> + </method> + <method name="remove_theme_font_override"> + <return type="void"> + </return> + <argument index="0" name="name" type="StringName"> + </argument> + <description> + Removes a theme override for a [Font] with the given [code]name[/code]. + </description> + </method> + <method name="remove_theme_font_size_override"> + <return type="void"> + </return> + <argument index="0" name="name" type="StringName"> + </argument> + <description> + Removes a theme override for a font size with the given [code]name[/code]. + </description> + </method> + <method name="remove_theme_icon_override"> + <return type="void"> + </return> + <argument index="0" name="name" type="StringName"> + </argument> + <description> + Removes a theme override for an icon with the given [code]name[/code]. + </description> + </method> + <method name="remove_theme_stylebox_override"> + <return type="void"> + </return> + <argument index="0" name="name" type="StringName"> + </argument> + <description> + Removes a theme override for a [StyleBox] with the given [code]name[/code]. + </description> + </method> <method name="set_anchor"> <return type="void"> </return> diff --git a/doc/classes/CryptoKey.xml b/doc/classes/CryptoKey.xml index 410c2262f9..26b3087b21 100644 --- a/doc/classes/CryptoKey.xml +++ b/doc/classes/CryptoKey.xml @@ -27,7 +27,7 @@ </argument> <description> Loads a key from [code]path[/code]. If [code]public_only[/code] is [code]true[/code], only the public key will be loaded. - [b]Note[/b]: [code]path[/code] should should be a "*.pub" file if [code]public_only[/code] is [code]true[/code], a "*.key" file otherwise. + [b]Note[/b]: [code]path[/code] should be a "*.pub" file if [code]public_only[/code] is [code]true[/code], a "*.key" file otherwise. </description> </method> <method name="load_from_string"> @@ -50,7 +50,7 @@ </argument> <description> Saves a key to the given [code]path[/code]. If [code]public_only[/code] is [code]true[/code], only the public key will be saved. - [b]Note[/b]: [code]path[/code] should should be a "*.pub" file if [code]public_only[/code] is [code]true[/code], a "*.key" file otherwise. + [b]Note[/b]: [code]path[/code] should be a "*.pub" file if [code]public_only[/code] is [code]true[/code], a "*.key" file otherwise. </description> </method> <method name="save_to_string"> diff --git a/doc/classes/Decal.xml b/doc/classes/Decal.xml index ca36b2400c..14c35ae6d3 100644 --- a/doc/classes/Decal.xml +++ b/doc/classes/Decal.xml @@ -6,7 +6,7 @@ <description> [Decal]s are used to project a texture onto a [Mesh] in the scene. Use Decals to add detail to a scene without affecting the underlying [Mesh]. They are often used to add weathering to building, add dirt or mud to the ground, or add variety to props. Decals can be moved at any time, making them suitable for things like blob shadows or laser sight dots. They are made of an [AABB] and a group of [Texture2D]s specifying [Color], normal, ORM (ambient occlusion, roughness, metallic), and emission. Decals are projected within their [AABB] so altering the orientation of the Decal affects the direction in which they are projected. By default, Decals are projected down (i.e. from positive Y to negative Y). - The [Texture2D]s associated with the Decal are automatically stored in a texture atlas which is used for drawing the decals so all decals can be drawn at once. Godot uses clustered decals, meaning they are stored in cluster data and drawn when the mesh is drawn, they are not drawn as a postprocessing effect after. + The [Texture2D]s associated with the Decal are automatically stored in a texture atlas which is used for drawing the decals so all decals can be drawn at once. Godot uses clustered decals, meaning they are stored in cluster data and drawn when the mesh is drawn, they are not drawn as a post-processing effect after. </description> <tutorials> </tutorials> @@ -65,7 +65,7 @@ Blends the albedo [Color] of the decal with albedo [Color] of the underlying mesh. </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 an ensure that dynamic objects don't accidentally receive a Decal intended for the terrain under them. + 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. diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml index 05ffd7b2ac..16c4348994 100644 --- a/doc/classes/Dictionary.xml +++ b/doc/classes/Dictionary.xml @@ -4,7 +4,7 @@ Dictionary type. </brief_description> <description> - Dictionary type. Associative container which contains values referenced by unique keys. Dictionaries are composed of pairs of keys (which must be unique) and values. Dictionaries will preserve the insertion order when adding elements, even though this may not be reflected when printing the dictionary. In other programming languages, this data structure is sometimes referred to as an hash map or associative array. + Dictionary type. Associative container which contains values referenced by unique keys. Dictionaries are composed of pairs of keys (which must be unique) and values. Dictionaries will preserve the insertion order when adding elements, even though this may not be reflected when printing the dictionary. In other programming languages, this data structure is sometimes referred to as a hash map or associative array. You can define a dictionary by placing a comma-separated list of [code]key: value[/code] pairs in curly braces [code]{}[/code]. Erasing elements while iterating over them [b]is not supported[/b] and will result in undefined behavior. [b]Note:[/b] Dictionaries are always passed by reference. To get a copy of a dictionary which can be modified independently of the original dictionary, use [method duplicate]. @@ -266,7 +266,7 @@ <argument index="0" name="keys" type="Array"> </argument> <description> - Returns [code]true[/code] if the dictionary has all of the keys in the given array. + Returns [code]true[/code] if the dictionary has all the keys in the given array. </description> </method> <method name="hash" qualifiers="const"> diff --git a/doc/classes/Directory.xml b/doc/classes/Directory.xml index 2d7292717d..a9d7960501 100644 --- a/doc/classes/Directory.xml +++ b/doc/classes/Directory.xml @@ -6,6 +6,7 @@ <description> Directory type. It is used to manage directories and their content (not restricted to the project folder). When creating a new [Directory], it must be explicitly opened using [method open] before most methods can be used. However, [method file_exists] and [method dir_exists] can be used without opening a directory. If so, they use a path relative to [code]res://[/code]. + [b]Note:[/b] Many resources types are imported (e.g. textures or sound files), and their source asset will not be included in the exported game, as only the imported version is used. Use [ResourceLoader] to access imported resources. Here is an example on how to iterate through the files of a directory: [codeblocks] [gdscript] @@ -125,7 +126,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> - On Windows, returns the name of the drive (partition) passed as an argument (e.g. [code]C:[/code]). On other platforms, or if the requested drive does not existed, the method returns an empty String. + On Windows, returns the name of the drive (partition) passed as an argument (e.g. [code]C:[/code]). On other platforms, or if the requested drive does not exist, the method returns an empty String. </description> </method> <method name="get_drive_count"> @@ -167,7 +168,7 @@ <return type="void"> </return> <description> - Closes the current stream opened with [method list_dir_begin] (whether it has been fully processed with [method get_next] or not does not matter). + Closes the current stream opened with [method list_dir_begin] (whether it has been fully processed with [method get_next] does not matter). </description> </method> <method name="make_dir"> diff --git a/doc/classes/EditorFileSystem.xml b/doc/classes/EditorFileSystem.xml index 5461dccd27..3a045817c2 100644 --- a/doc/classes/EditorFileSystem.xml +++ b/doc/classes/EditorFileSystem.xml @@ -90,7 +90,7 @@ <argument index="0" name="resources" type="PackedStringArray"> </argument> <description> - Remitted if a resource is reimported. + Emitted if a resource is reimported. </description> </signal> <signal name="resources_reload"> diff --git a/doc/classes/EditorInspectorPlugin.xml b/doc/classes/EditorInspectorPlugin.xml index 3cc624f49b..8204dc931e 100644 --- a/doc/classes/EditorInspectorPlugin.xml +++ b/doc/classes/EditorInspectorPlugin.xml @@ -4,12 +4,12 @@ Plugin for adding custom property editors on inspector. </brief_description> <description> - This plugins allows adding custom property editors to [EditorInspector]. + These plugins allow adding custom property editors to [EditorInspector]. Plugins are registered via [method EditorPlugin.add_inspector_plugin]. When an object is edited, the [method can_handle] function is called and must return [code]true[/code] if the object type is supported. If supported, the function [method parse_begin] will be called, allowing to place custom controls at the beginning of the class. Subsequently, the [method parse_category] and [method parse_property] are called for every category and property. They offer the ability to add custom controls to the inspector too. - Finally [method parse_end] will be called. + Finally, [method parse_end] will be called. On each of these calls, the "add" functions can be called. </description> <tutorials> diff --git a/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml index b01af71852..4d0e11fb19 100644 --- a/doc/classes/EditorInterface.xml +++ b/doc/classes/EditorInterface.xml @@ -48,6 +48,14 @@ [b]Note:[/b] This returns the main editor control containing the whole editor, not the 2D or 3D viewports specifically. </description> </method> + <method name="get_editor_scale" qualifiers="const"> + <return type="float"> + </return> + <description> + Returns the actual scale of the editor UI ([code]1.0[/code] being 100% scale). This can be used to adjust position and dimensions of the UI added by plugins. + [b]Note:[/b] This value is set via the [code]interface/editor/display_scale[/code] and [code]interface/editor/custom_display_scale[/code] editor settings. Editor must be restarted for changes to be properly applied. + </description> + </method> <method name="get_editor_settings"> <return type="EditorSettings"> </return> diff --git a/doc/classes/EditorNode3DGizmoPlugin.xml b/doc/classes/EditorNode3DGizmoPlugin.xml index 1e9d089962..34657a1c08 100644 --- a/doc/classes/EditorNode3DGizmoPlugin.xml +++ b/doc/classes/EditorNode3DGizmoPlugin.xml @@ -170,7 +170,7 @@ <return type="bool"> </return> <description> - Override this method to define whether Node3D with this gizmo should be selecteble even when the gizmo is hidden. + Override this method to define whether Node3D with this gizmo should be selectable even when the gizmo is hidden. </description> </method> <method name="redraw" qualifiers="virtual"> diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml index a24e4bbdc5..8dcffb0b74 100644 --- a/doc/classes/EditorPlugin.xml +++ b/doc/classes/EditorPlugin.xml @@ -561,7 +561,7 @@ <argument index="0" name="script" type="Script"> </argument> <description> - Removes the debugger plugin with given script fromm the Debugger. + Removes the debugger plugin with given script from the Debugger. </description> </method> <method name="remove_export_plugin"> diff --git a/doc/classes/EditorSceneImporter.xml b/doc/classes/EditorSceneImporter.xml index db85b859e5..aa55a1653d 100644 --- a/doc/classes/EditorSceneImporter.xml +++ b/doc/classes/EditorSceneImporter.xml @@ -74,21 +74,11 @@ </constant> <constant name="IMPORT_ANIMATION" value="2"> </constant> - <constant name="IMPORT_ANIMATION_DETECT_LOOP" value="4"> + <constant name="IMPORT_FAIL_ON_MISSING_DEPENDENCIES" value="4"> </constant> - <constant name="IMPORT_ANIMATION_OPTIMIZE" value="8"> + <constant name="IMPORT_GENERATE_TANGENT_ARRAYS" value="8"> </constant> - <constant name="IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS" value="16"> - </constant> - <constant name="IMPORT_ANIMATION_KEEP_VALUE_TRACKS" value="32"> - </constant> - <constant name="IMPORT_GENERATE_TANGENT_ARRAYS" value="256"> - </constant> - <constant name="IMPORT_FAIL_ON_MISSING_DEPENDENCIES" value="512"> - </constant> - <constant name="IMPORT_MATERIALS_IN_INSTANCES" value="1024"> - </constant> - <constant name="IMPORT_USE_COMPRESSION" value="2048"> + <constant name="IMPORT_USE_NAMED_SKIN_BINDS" value="16"> </constant> </constants> </class> diff --git a/doc/classes/EditorSceneImporterMesh.xml b/doc/classes/EditorSceneImporterMesh.xml index 58b7104667..9daa3f16bc 100644 --- a/doc/classes/EditorSceneImporterMesh.xml +++ b/doc/classes/EditorSceneImporterMesh.xml @@ -60,9 +60,17 @@ <description> </description> </method> + <method name="get_lightmap_size_hint" qualifiers="const"> + <return type="Vector2i"> + </return> + <description> + </description> + </method> <method name="get_mesh"> <return type="ArrayMesh"> </return> + <argument index="0" name="arg0" type="Mesh"> + </argument> <description> </description> </method> @@ -150,6 +158,14 @@ <description> </description> </method> + <method name="set_lightmap_size_hint"> + <return type="void"> + </return> + <argument index="0" name="size" type="Vector2i"> + </argument> + <description> + </description> + </method> </methods> <members> <member name="_data" type="Dictionary" setter="_set_data" getter="_get_data" default="{"surfaces": [ ]}"> diff --git a/doc/classes/EditorScenePostImport.xml b/doc/classes/EditorScenePostImport.xml index 5cddecffa8..d1cdc4e43e 100644 --- a/doc/classes/EditorScenePostImport.xml +++ b/doc/classes/EditorScenePostImport.xml @@ -62,13 +62,6 @@ Returns the source file path which got imported (e.g. [code]res://scene.dae[/code]). </description> </method> - <method name="get_source_folder" qualifiers="const"> - <return type="String"> - </return> - <description> - Returns the resource folder the imported scene file is located in. - </description> - </method> <method name="post_import" qualifiers="virtual"> <return type="Object"> </return> diff --git a/doc/classes/EditorVCSInterface.xml b/doc/classes/EditorVCSInterface.xml index bb356c2183..0056b5ce16 100644 --- a/doc/classes/EditorVCSInterface.xml +++ b/doc/classes/EditorVCSInterface.xml @@ -38,7 +38,7 @@ <return type="Dictionary"> </return> <description> - Returns a [Dictionary] containing the path of the detected file change mapped to an integer signifying what kind of a change the corresponding file has experienced. + Returns a [Dictionary] containing the path of the detected file change mapped to an integer signifying what kind of change the corresponding file has experienced. The following integer values are being used to signify that the detected file is: - [code]0[/code]: New to the VCS working directory - [code]1[/code]: Modified diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml index 02b81ee9b7..f9d8cf574a 100644 --- a/doc/classes/Engine.xml +++ b/doc/classes/Engine.xml @@ -162,7 +162,7 @@ The number of fixed iterations per second. This controls how often physics simulation and [method Node._physics_process] methods are run. This value should generally always be set to [code]60[/code] or above, as Godot doesn't interpolate the physics step. As a result, values lower than [code]60[/code] will look stuttery. This value can be increased to make input more reactive or work around tunneling issues, but keep in mind doing so will increase CPU usage. </member> <member name="physics_jitter_fix" type="float" setter="set_physics_jitter_fix" getter="get_physics_jitter_fix" default="0.5"> - Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of in-game clock and real clock, but allows to smooth out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended. + Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of in-game clock and real clock, but allows smoothing out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended. </member> <member name="target_fps" type="int" setter="set_target_fps" getter="get_target_fps" default="0"> The desired frames per second. If the hardware cannot keep up, this setting may not be respected. A value of 0 means no limit. diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml index 821aa91d21..6909fac2b7 100644 --- a/doc/classes/Environment.xml +++ b/doc/classes/Environment.xml @@ -176,6 +176,8 @@ <member name="sdfgi_cascades" type="int" setter="set_sdfgi_cascades" getter="get_sdfgi_cascades" enum="Environment.SDFGICascades" default="1"> </member> <member name="sdfgi_enabled" type="bool" setter="set_sdfgi_enabled" getter="is_sdfgi_enabled" default="false"> + If [code]true[/code], enables signed distance field global illumination. + [b]Note:[/b] Meshes should have sufficiently thick walls to avoid light leaks (avoid one-sided walls). For interior levels, enclose your level geometry in a sufficiently large box and bridge the loops to close the mesh. </member> <member name="sdfgi_energy" type="float" setter="set_sdfgi_energy" getter="get_sdfgi_energy" default="1.0"> </member> diff --git a/doc/classes/FileDialog.xml b/doc/classes/FileDialog.xml index ed437aefd5..966be0a981 100644 --- a/doc/classes/FileDialog.xml +++ b/doc/classes/FileDialog.xml @@ -133,6 +133,9 @@ </constant> </constants> <theme_items> + <theme_item name="back_folder" type="Texture2D"> + Custom icon for the back arrow. + </theme_item> <theme_item name="file" type="Texture2D"> Custom icon for files. </theme_item> @@ -148,6 +151,9 @@ <theme_item name="folder_icon_modulate" type="Color" default="Color( 1, 1, 1, 1 )"> The color modulation applied to the folder icon. </theme_item> + <theme_item name="forward_folder" type="Texture2D"> + Custom icon for the forward arrow. + </theme_item> <theme_item name="parent_folder" type="Texture2D"> Custom icon for the parent folder arrow. </theme_item> diff --git a/doc/classes/Font.xml b/doc/classes/Font.xml index bf5237422b..20d5b6ce9b 100644 --- a/doc/classes/Font.xml +++ b/doc/classes/Font.xml @@ -247,7 +247,7 @@ <argument index="1" name="size" type="int" default="-1"> </argument> <description> - Returns the size size of a bounding box of a string, taking kerning and advance into account. + Returns the size of a bounding box of a string, taking kerning and advance into account. [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> diff --git a/doc/classes/FontData.xml b/doc/classes/FontData.xml index 6c54af05cd..e426c8fb36 100644 --- a/doc/classes/FontData.xml +++ b/doc/classes/FontData.xml @@ -391,7 +391,7 @@ If [code]true[/code], distance field hint is enabled. </member> <member name="extra_spacing_glyph" type="int" setter="set_spacing" getter="get_spacing" default="0"> - Extra spacing for each glyphs in pixels. + Extra spacing for each glyph in pixels. This can be a negative number to make the distance between glyphs smaller. </member> <member name="extra_spacing_space" type="int" setter="set_spacing" getter="get_spacing" default="0"> diff --git a/doc/classes/GIProbe.xml b/doc/classes/GIProbe.xml index dd51248fd9..4f56d1ad3e 100644 --- a/doc/classes/GIProbe.xml +++ b/doc/classes/GIProbe.xml @@ -6,6 +6,7 @@ <description> [GIProbe]s are used to provide high-quality real-time indirect light to scenes. They precompute the effect of objects that emit light and the effect of static geometry to simulate the behavior of complex light in real-time. [GIProbe]s need to be baked before using, however, once baked, dynamic objects will receive light from them. Further, lights can be fully dynamic or baked. Having [GIProbe]s in a scene can be expensive, the quality of the probe can be turned down in exchange for better performance in the [ProjectSettings] using [member ProjectSettings.rendering/global_illumination/gi_probes/quality]. + [b]Note:[/b] Meshes should have sufficiently thick walls to avoid light leaks (avoid one-sided walls). For interior levels, enclose your level geometry in a sufficiently large box and bridge the loops to close the mesh. </description> <tutorials> <link title="GI probes">https://docs.godotengine.org/en/latest/tutorials/3d/gi_probes.html</link> diff --git a/doc/classes/Geometry3D.xml b/doc/classes/Geometry3D.xml index d0b930defb..9f012008e3 100644 --- a/doc/classes/Geometry3D.xml +++ b/doc/classes/Geometry3D.xml @@ -129,7 +129,7 @@ <argument index="2" name="planes" type="Array"> </argument> <description> - Given a convex hull defined though the [Plane]s in the array [code]planes[/code], tests if the segment ([code]from[/code], [code]to[/code]) intersects with that hull. If an intersection is found, returns a [PackedVector3Array] containing the point the intersection and the hull's normal. If no intersecion is found, an the returned array is empty. + Given a convex hull defined though the [Plane]s in the array [code]planes[/code], tests if the segment ([code]from[/code], [code]to[/code]) intersects with that hull. If an intersection is found, returns a [PackedVector3Array] containing the point the intersection and the hull's normal. Otherwise, returns an empty array. </description> </method> <method name="segment_intersects_cylinder"> diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml index 10afa4c339..b4536c0589 100644 --- a/doc/classes/GraphEdit.xml +++ b/doc/classes/GraphEdit.xml @@ -88,7 +88,7 @@ </return> <description> Gets the [HBoxContainer] that contains the zooming and grid snap controls in the top left of the graph. - Warning: The intended usage of this function is to allow you to reposition or add your own custom controls to the container. This is an internal control and as such should not be freed. If you wish to hide this or any of it's children use their [member CanvasItem.visible] property instead. + Warning: The intended usage of this function is to allow you to reposition or add your own custom controls to the container. This is an internal control and as such should not be freed. If you wish to hide this or any of its children, use their [member CanvasItem.visible] property instead. </description> </method> <method name="is_node_connected"> diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml index 279c4c4c94..aae3126c0f 100644 --- a/doc/classes/GraphNode.xml +++ b/doc/classes/GraphNode.xml @@ -6,7 +6,7 @@ <description> A GraphNode is a container. Each GraphNode can have several input and output slots, sometimes referred to as ports, allowing connections between GraphNodes. To add a slot to GraphNode, add any [Control]-derived child node to it. After adding at least one child to GraphNode new sections will be automatically created in the Inspector called 'Slot'. When 'Slot' is expanded you will see list with index number for each slot. You can click on each of them to expand further. - In the Inspector you can enable (show) or disable (hide) slots. By default all slots are disabled so you may not see any slots on your GraphNode initially. You can assign a type to each slot. Only slots of the same type will be able to connect to each other. You can also assign colors to slots. A tuple of input and output slots is defined for each GUI element included in the GraphNode. Input connections are on the left and output connections are on the right side of GraphNode. Only enabled slots are counted as connections. + In the Inspector you can enable (show) or disable (hide) slots. By default, all slots are disabled so you may not see any slots on your GraphNode initially. You can assign a type to each slot. Only slots of the same type will be able to connect to each other. You can also assign colors to slots. A tuple of input and output slots is defined for each GUI element included in the GraphNode. Input connections are on the left and output connections are on the right side of GraphNode. Only enabled slots are counted as connections. </description> <tutorials> </tutorials> diff --git a/doc/classes/HTTPClient.xml b/doc/classes/HTTPClient.xml index 9ff682f79d..ddfcdf7724 100644 --- a/doc/classes/HTTPClient.xml +++ b/doc/classes/HTTPClient.xml @@ -4,7 +4,7 @@ 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 an 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. [b]See the [HTTPRequest] node for a higher-level alternative.[/b] [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 a65f66c72a..25667d8f79 100644 --- a/doc/classes/HTTPRequest.xml +++ b/doc/classes/HTTPRequest.xml @@ -229,7 +229,7 @@ <member name="accept_gzip" type="bool" setter="set_accept_gzip" getter="is_accepting_gzip" default="true"> If [code]true[/code], this header will be added to each request: [code]Accept-Encoding: gzip, deflate[/code] telling servers that it's okay to compress response bodies. Any Response body declaring a [code]Content-Encoding[/code] of either [code]gzip[/code] or [code]deflate[/code] will then be automatically decompressed, and the uncompressed bytes will be delivered via [code]request_completed[/code]. - If the user has specified their own [code]Accept-Encoding[/code] header, then no header will be added regaurdless of [code]accept_gzip[/code]. + If the user has specified their own [code]Accept-Encoding[/code] header, then no header will be added regardless of [code]accept_gzip[/code]. If [code]false[/code] no header will be added, and no decompression will be performed on response bodies. The raw bytes of the response body will be returned via [code]request_completed[/code]. </member> <member name="body_size_limit" type="int" setter="set_body_size_limit" getter="get_body_size_limit" default="-1"> diff --git a/doc/classes/IP.xml b/doc/classes/IP.xml index 152f381a83..849f036bbd 100644 --- a/doc/classes/IP.xml +++ b/doc/classes/IP.xml @@ -31,7 +31,7 @@ <return type="Array"> </return> <description> - Returns all of the user's current IPv4 and IPv6 addresses as an array. + Returns all the user's current IPv4 and IPv6 addresses as an array. </description> </method> <method name="get_local_interfaces" qualifiers="const"> diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index bad8127c03..9d87c9bf9a 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -240,7 +240,7 @@ <argument index="0" name="renormalize" type="bool" default="false"> </argument> <description> - Generates mipmaps for the image. Mipmaps are pre-calculated and lower resolution copies of the image. Mipmaps are automatically used if the image needs to be scaled down when rendered. This improves image quality and the performance of the rendering. Returns an error if the image is compressed, in a custom format or if the image's width/height is 0. + Generates mipmaps for the image. Mipmaps are precalculated and lower resolution copies of the image. Mipmaps are automatically used if the image needs to be scaled down when rendered. This improves image quality and the performance of the rendering. Returns an error if the image is compressed, in a custom format or if the image's width/height is 0. </description> </method> <method name="get_data" qualifiers="const"> @@ -560,7 +560,7 @@ </methods> <members> <member name="data" type="Dictionary" setter="_set_data" getter="_get_data" default="{"data": PackedByteArray( ),"format": "Lum8","height": 0,"mipmaps": false,"width": 0}"> - Holds all of the image's color data in a given format. See [enum Format] constants. + Holds all the image's color data in a given format. See [enum Format] constants. </member> </members> <constants> diff --git a/doc/classes/ImageTexture.xml b/doc/classes/ImageTexture.xml index 2bea482bc1..5fef56e354 100644 --- a/doc/classes/ImageTexture.xml +++ b/doc/classes/ImageTexture.xml @@ -18,11 +18,11 @@ var texture = load("res://icon.png") $Sprite2D.texture = texture [/codeblock] - This is because images have to be imported as [StreamTexture2D] first to be loaded with [method @GDScript.load]. If you'd still like to load an image file just like any other [Resource], import it as an [Image] resource instead, and then load it normally using the [method @GDScript.load] method. - But do note that the image data can still be retrieved from an imported texture as well using the [method Texture2D.get_data] method, which returns a copy of the data: + This is because images have to be imported as a [StreamTexture2D] first to be loaded with [method @GDScript.load]. If you'd still like to load an image file just like any other [Resource], import it as an [Image] resource instead, and then load it normally using the [method @GDScript.load] method. + [b]Note:[/b] The image can be retrieved from an imported texture using the [method Texture2D.get_image] method, which returns a copy of the image: [codeblock] var texture = load("res://icon.png") - var image : Image = texture.get_data() + var image : Image = texture.get_image() [/codeblock] An [ImageTexture] is not meant to be operated from within the editor interface directly, and is mostly useful for rendering images on screen dynamically via code. If you need to generate images procedurally from within the editor, consider saving and importing images as custom texture resources implementing a new [EditorImportPlugin]. [b]Note:[/b] The maximum texture size is 16384×16384 pixels due to graphics hardware limitations. diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index 977f2bb565..d7408cd0ff 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -85,7 +85,7 @@ </argument> <description> Get axis input by specifying two actions, one negative and one positive. - This is a horthand for writing [code]Input.get_action_strength("positive_action") - Input.get_action_strength("negative_action")[/code]. + This is a shorthand for writing [code]Input.get_action_strength("positive_action") - Input.get_action_strength("negative_action")[/code]. </description> </method> <method name="get_connected_joypads"> @@ -126,7 +126,7 @@ <argument index="1" name="axis" type="int"> </argument> <description> - Returns the current value of the joypad axis at given index (see [enum JoyAxisList]). + Returns the current value of the joypad axis at given index (see [enum JoyAxis]). </description> </method> <method name="get_joy_guid" qualifiers="const"> @@ -176,7 +176,7 @@ <return type="Vector3"> </return> <description> - Returns the the magnetic field strength in micro-Tesla for all axes of the device's magnetometer sensor, if the device has one. Otherwise, the method returns [constant Vector3.ZERO]. + Returns the magnetic field strength in micro-Tesla for all axes of the device's magnetometer sensor, if the device has one. Otherwise, the method returns [constant Vector3.ZERO]. [b]Note:[/b] This method only works on Android, iOS and UWP. On other platforms, it always returns [constant Vector3.ZERO]. </description> </method> @@ -255,7 +255,7 @@ <argument index="1" name="button" type="int"> </argument> <description> - Returns [code]true[/code] if you are pressing the joypad button (see [enum JoyButtonList]). + Returns [code]true[/code] if you are pressing the joypad button (see [enum JoyButton]). </description> </method> <method name="is_joy_known"> @@ -273,7 +273,7 @@ <argument index="0" name="keycode" type="int"> </argument> <description> - Returns [code]true[/code] if you are pressing the key in the current keyboard layout. You can pass a [enum KeyList] constant. + Returns [code]true[/code] if you are pressing the key in the current keyboard layout. You can pass a [enum Key] constant. </description> </method> <method name="is_mouse_button_pressed" qualifiers="const"> @@ -282,7 +282,7 @@ <argument index="0" name="button" type="int"> </argument> <description> - Returns [code]true[/code] if you are pressing the mouse button specified with [enum ButtonList]. + Returns [code]true[/code] if you are pressing the mouse button specified with [enum MouseButton]. </description> </method> <method name="joy_connection_changed"> diff --git a/doc/classes/InputEventAction.xml b/doc/classes/InputEventAction.xml index 1fe85a5ae8..ed290fc7e2 100644 --- a/doc/classes/InputEventAction.xml +++ b/doc/classes/InputEventAction.xml @@ -21,7 +21,7 @@ If [code]true[/code], the action's state is pressed. If [code]false[/code], the action's state is released. </member> <member name="strength" type="float" setter="set_strength" getter="get_strength" default="1.0"> - The action's strength between 0 and 1. This value is considered as equal to 0 if pressed is [code]false[/code]. The event strength allows faking analog joypad motion events, by precising how strongly is the joypad axis bent or pressed. + The action's strength between 0 and 1. This value is considered as equal to 0 if pressed is [code]false[/code]. The event strength allows faking analog joypad motion events, by specifying how strongly the joypad axis is bent or pressed. </member> </members> <constants> diff --git a/doc/classes/InputEventJoypadButton.xml b/doc/classes/InputEventJoypadButton.xml index 6ab4942f85..b1f4836f6e 100644 --- a/doc/classes/InputEventJoypadButton.xml +++ b/doc/classes/InputEventJoypadButton.xml @@ -13,7 +13,7 @@ </methods> <members> <member name="button_index" type="int" setter="set_button_index" getter="get_button_index" default="0"> - Button identifier. One of the [enum JoyButtonList] button constants. + Button identifier. One of the [enum JoyButton] button constants. </member> <member name="pressed" type="bool" setter="set_pressed" getter="is_pressed" default="false"> If [code]true[/code], the button's state is pressed. If [code]false[/code], the button's state is released. diff --git a/doc/classes/InputEventJoypadMotion.xml b/doc/classes/InputEventJoypadMotion.xml index 2d7787b568..39fdb14016 100644 --- a/doc/classes/InputEventJoypadMotion.xml +++ b/doc/classes/InputEventJoypadMotion.xml @@ -13,7 +13,7 @@ </methods> <members> <member name="axis" type="int" setter="set_axis" getter="get_axis" default="0"> - Axis identifier. Use one of the [enum JoyAxisList] axis constants. + Axis identifier. Use one of the [enum JoyAxis] axis constants. </member> <member name="axis_value" type="float" setter="set_axis_value" getter="get_axis_value" default="0.0"> Current position of the joystick on the given axis. The value ranges from [code]-1.0[/code] to [code]1.0[/code]. A value of [code]0[/code] means the axis is in its resting position. diff --git a/doc/classes/InputEventKey.xml b/doc/classes/InputEventKey.xml index fe91b9c13e..9f2b829823 100644 --- a/doc/classes/InputEventKey.xml +++ b/doc/classes/InputEventKey.xml @@ -32,11 +32,11 @@ If [code]true[/code], the key was already pressed before this event. It means the user is holding the key down. </member> <member name="keycode" type="int" setter="set_keycode" getter="get_keycode" default="0"> - The key keycode, which corresponds to one of the [enum KeyList] constants. Represent key in the current keyboard layout. + The key keycode, which corresponds to one of the [enum Key] constants. Represent key in the current keyboard layout. To get a human-readable representation of the [InputEventKey], use [code]OS.get_keycode_string(event.keycode)[/code] where [code]event[/code] is the [InputEventKey]. </member> <member name="physical_keycode" type="int" setter="set_physical_keycode" getter="get_physical_keycode" default="0"> - Key physical keycode, which corresponds to one of the [enum KeyList] constants. Represent the physical location of a key on the 101/102-key US QWERTY keyboard. + Key physical keycode, which corresponds to one of the [enum Key] constants. Represent the physical location of a key on the 101/102-key US QWERTY keyboard. To get a human-readable representation of the [InputEventKey], use [code]OS.get_keycode_string(event.keycode)[/code] where [code]event[/code] is the [InputEventKey]. </member> <member name="pressed" type="bool" setter="set_pressed" getter="is_pressed" default="false"> diff --git a/doc/classes/InputEventMouse.xml b/doc/classes/InputEventMouse.xml index 31e82bbaed..e54c3224da 100644 --- a/doc/classes/InputEventMouse.xml +++ b/doc/classes/InputEventMouse.xml @@ -13,7 +13,7 @@ </methods> <members> <member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask" default="0"> - The mouse button mask identifier, one of or a bitwise combination of the [enum ButtonList] button masks. + The mouse button mask identifier, one of or a bitwise combination of the [enum MouseButton] button masks. </member> <member name="global_position" type="Vector2" setter="set_global_position" getter="get_global_position" default="Vector2( 0, 0 )"> The global mouse position relative to the current [Viewport] when used in [method Control._gui_input], otherwise is at 0,0. diff --git a/doc/classes/InputEventMouseButton.xml b/doc/classes/InputEventMouseButton.xml index d7b64a9a2d..d7e92f8bca 100644 --- a/doc/classes/InputEventMouseButton.xml +++ b/doc/classes/InputEventMouseButton.xml @@ -13,7 +13,7 @@ </methods> <members> <member name="button_index" type="int" setter="set_button_index" getter="get_button_index" default="0"> - The mouse button identifier, one of the [enum ButtonList] button or button wheel constants. + The mouse button identifier, one of the [enum MouseButton] button or button wheel constants. </member> <member name="doubleclick" type="bool" setter="set_doubleclick" getter="is_doubleclick" default="false"> If [code]true[/code], the mouse button's state is a double-click. diff --git a/doc/classes/KinematicBody2D.xml b/doc/classes/KinematicBody2D.xml index 476b64a336..fdd4db6115 100644 --- a/doc/classes/KinematicBody2D.xml +++ b/doc/classes/KinematicBody2D.xml @@ -162,7 +162,10 @@ </methods> <members> <member name="collision/safe_margin" type="float" setter="set_safe_margin" getter="get_safe_margin" default="0.08"> - If the body is at least this close to another body, this body will consider them to be colliding. + Extra margin used for collision recovery in motion functions (see [method move_and_collide], [method move_and_slide], [method move_and_slide_with_snap]). + If the body is at least this close to another body, it will consider them to be colliding and will be pushed away before performing the actual motion. + A higher value means it's more flexible for detecting collision, which helps with consistently detecting walls and floors. + A lower value forces the collision algorithm to use more exact detection, so it can be used in cases that specifically require precision, e.g at very low scale to avoid visible jittering, or for stability with a stack of kinematic bodies. </member> <member name="motion/sync_to_physics" type="bool" setter="set_sync_to_physics" getter="is_sync_to_physics_enabled" default="false"> If [code]true[/code], the body's movement will be synchronized to the physics frame. This is useful when animating movement via [AnimationPlayer], for example on moving platforms. Do [b]not[/b] use together with [method move_and_slide] or [method move_and_collide] functions. diff --git a/doc/classes/KinematicBody3D.xml b/doc/classes/KinematicBody3D.xml index a21496de54..efd3f58f88 100644 --- a/doc/classes/KinematicBody3D.xml +++ b/doc/classes/KinematicBody3D.xml @@ -177,7 +177,10 @@ Lock the body's Z axis movement. </member> <member name="collision/safe_margin" type="float" setter="set_safe_margin" getter="get_safe_margin" default="0.001"> - If the body is at least this close to another body, this body will consider them to be colliding. + Extra margin used for collision recovery in motion functions (see [method move_and_collide], [method move_and_slide], [method move_and_slide_with_snap]). + If the body is at least this close to another body, it will consider them to be colliding and will be pushed away before performing the actual motion. + A higher value means it's more flexible for detecting collision, which helps with consistently detecting walls and floors. + A lower value forces the collision algorithm to use more exact detection, so it can be used in cases that specifically require precision, e.g at very low scale to avoid visible jittering, or for stability with a stack of kinematic bodies. </member> </members> <constants> diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml index 8574ff9836..76b9686393 100644 --- a/doc/classes/Label.xml +++ b/doc/classes/Label.xml @@ -32,7 +32,7 @@ </argument> <description> Returns the height of the line [code]line[/code]. - If [code]line[/code] is set to [code]-1[/code], returns biggest line height. + If [code]line[/code] is set to [code]-1[/code], returns the biggest line height. If there're no lines returns font size in pixels. </description> </method> diff --git a/doc/classes/Light3D.xml b/doc/classes/Light3D.xml index 111473e098..6bae612c9f 100644 --- a/doc/classes/Light3D.xml +++ b/doc/classes/Light3D.xml @@ -58,7 +58,7 @@ If [code]true[/code], the light's effect is reversed, darkening areas and casting bright shadows. </member> <member name="light_projector" type="Texture2D" setter="set_projector" getter="get_projector"> - [Texture2D] projected by light. [member shadow_enabled] must be on for the projector to work. Light projectors make the light appear as if it is shining through a colored but transparent object, almost like light shining through stained glass. + [Texture2D] projected by light. [member shadow_enabled] must be on for the projector to work. Light projectors make the light appear as if it is shining through a colored but transparent object, almost like light shining through stained-glass. </member> <member name="light_size" type="float" setter="set_param" getter="get_param" default="0.0"> The size of the light in Godot units. Only available for [OmniLight3D]s and [SpotLight3D]s. Increasing this value will make the light fade out slower and shadows appear blurrier. This can be used to simulate area lights to an extent. diff --git a/doc/classes/MenuButton.xml b/doc/classes/MenuButton.xml index 481b737eee..7cbf9d3dfe 100644 --- a/doc/classes/MenuButton.xml +++ b/doc/classes/MenuButton.xml @@ -5,7 +5,7 @@ </brief_description> <description> Special button that brings up a [PopupMenu] when clicked. - New items can be created inside this [PopupMenu] using [code]get_popup().add_item("My Item Name")[/code]. You can also create them directly from the editor. To do so, select the [MenuButton] node, then in the toolbar at the top of the 2D editor, click [b]Items[/b] then click [b]Add[/b] in the popup. You will be able to give each items new properties. + New items can be created inside this [PopupMenu] using [code]get_popup().add_item("My Item Name")[/code]. You can also create them directly from the editor. To do so, select the [MenuButton] node, then in the toolbar at the top of the 2D editor, click [b]Items[/b] then click [b]Add[/b] in the popup. You will be able to give each item new properties. See also [BaseButton] which contains common properties and methods associated with this node. </description> <tutorials> diff --git a/doc/classes/MultiMesh.xml b/doc/classes/MultiMesh.xml index 6ebfc946dc..2adebdb306 100644 --- a/doc/classes/MultiMesh.xml +++ b/doc/classes/MultiMesh.xml @@ -6,7 +6,7 @@ <description> MultiMesh provides low-level mesh instancing. Drawing thousands of [MeshInstance3D] nodes can be slow, since each object is submitted to the GPU then drawn individually. MultiMesh is much faster as it can draw thousands of instances with a single draw call, resulting in less API overhead. - As a drawback, if the instances are too far away of each other, performance may be reduced as every single instance will always rendered (they are spatially indexed as one, for the whole object). + As a drawback, if the instances are too far away of each other, performance may be reduced as every single instance will always render (they are spatially indexed as one, for the whole object). Since instances may have any behavior, the AABB used for visibility must be provided by the user. </description> <tutorials> diff --git a/doc/classes/NavigationAgent2D.xml b/doc/classes/NavigationAgent2D.xml index 59bf06eaf2..1060e2de41 100644 --- a/doc/classes/NavigationAgent2D.xml +++ b/doc/classes/NavigationAgent2D.xml @@ -111,7 +111,7 @@ The distance threshold before a target is considered to be reached. This will allow an agent to not have to hit a point on the path exactly, but in the area. </member> <member name="time_horizon" type="float" setter="set_time_horizon" getter="get_time_horizon" default="20.0"> - The minimal amount of time for which this agent's velocities, that are computed with the collision avoidance algorithim, are safe with respect to other agents. The larger the number, the sooner the agent will respond to other agents, but less freedom in choosing its velocities. Must be positive. + The minimal amount of time for which this agent's velocities, that are computed with the collision avoidance algorithm, are safe with respect to other agents. The larger the number, the sooner the agent will respond to other agents, but less freedom in choosing its velocities. Must be positive. </member> </members> <signals> diff --git a/doc/classes/NavigationAgent3D.xml b/doc/classes/NavigationAgent3D.xml index 7a130e9591..00e9db0a33 100644 --- a/doc/classes/NavigationAgent3D.xml +++ b/doc/classes/NavigationAgent3D.xml @@ -117,7 +117,7 @@ The distance threshold before a target is considered to be reached. This will allow an agent to not have to hit a point on the path exactly, but in the area. </member> <member name="time_horizon" type="float" setter="set_time_horizon" getter="get_time_horizon" default="5.0"> - The minimal amount of time for which this agent's velocities, that are computed with the collision avoidance algorithim, are safe with respect to other agents. The larger the number, the sooner the agent will respond to other agents, but less freedom in choosing its velocities. Must be positive. + The minimal amount of time for which this agent's velocities, that are computed with the collision avoidance algorithm, are safe with respect to other agents. The larger the number, the sooner the agent will respond to other agents, but less freedom in choosing its velocities. Must be positive. </member> </members> <signals> diff --git a/doc/classes/NavigationMesh.xml b/doc/classes/NavigationMesh.xml index dd7464ac0e..871c92798a 100644 --- a/doc/classes/NavigationMesh.xml +++ b/doc/classes/NavigationMesh.xml @@ -79,6 +79,7 @@ </methods> <members> <member name="agent/height" type="float" setter="set_agent_height" getter="get_agent_height" default="2.0"> + The minimum Y space needed for navigation to be generated. </member> <member name="agent/max_climb" type="float" setter="set_agent_max_climb" getter="get_agent_max_climb" default="0.9"> The maximum height difference between two areas for navigation to be generated between them. @@ -87,8 +88,10 @@ The maximum angle a slope can be at for navigation to be generated on it. </member> <member name="agent/radius" type="float" setter="set_agent_radius" getter="get_agent_radius" default="0.6"> + Determines where the edge of a navigation mesh is. This way an agent will not overlap with another mesh or stand over nothing. </member> <member name="cell/height" type="float" setter="set_cell_height" getter="get_cell_height" default="0.2"> + The height of a cell. </member> <member name="cell/size" type="float" setter="set_cell_size" getter="get_cell_size" default="0.3"> The size of cells in the [NavigationMesh]. @@ -111,7 +114,7 @@ The physics layers used to generate the [NavigationMesh]. </member> <member name="geometry/parsed_geometry_type" type="int" setter="set_parsed_geometry_type" getter="get_parsed_geometry_type" default="0"> - What kind of geomerty is used to generate the [NavigationMesh]. + What kind of geometry is used to generate the [NavigationMesh]. </member> <member name="geometry/source_geometry_mode" type="int" setter="set_source_geometry_mode" getter="get_source_geometry_mode" default="0"> Which geometry is used to generate the [NavigationMesh]. diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml index b811607bad..b0a57ed227 100644 --- a/doc/classes/NavigationServer2D.xml +++ b/doc/classes/NavigationServer2D.xml @@ -5,7 +5,7 @@ </brief_description> <description> NavigationServer2D is the server responsible for all 2D navigation. It handles several objects, namely maps, regions and agents. - Maps are made up of regions, which are made of navigation polygons. Together, they define the navigable areas in the 2D world. For two regions to be connected to each other, they must share a similar edge. An edges is considered connected to another if both of its two vertices are at a distance less than [code]edge_connection_margin[/code] to the respective other edge's vertex. + Maps are made up of regions, which are made of navigation polygons. Together, they define the navigable areas in the 2D world. For two regions to be connected to each other, they must share a similar edge. An edge is considered connected to another if both of its two vertices are at a distance less than [code]edge_connection_margin[/code] to the respective other edge's vertex. You may assign navigation layers to regions with [method NavigationServer2D.region_set_layers], which then can be checked upon when requesting a path with [method NavigationServer2D.map_get_path]. This allows allowing or forbidding some areas to 2D objects. To use the collision avoidance system, you may use agents. You can set an agent's target velocity, then the servers will emit a callback with a modified velocity. [b]Note:[/b] the collision avoidance system ignores regions. Using the modified velocity as-is might lead to pushing and agent outside of a navigable area. This is a limitation of the collision avoidance system, any more complex situation may require the use of the physics engine. diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml index 6d56428933..b098a7fc20 100644 --- a/doc/classes/NavigationServer3D.xml +++ b/doc/classes/NavigationServer3D.xml @@ -5,7 +5,7 @@ </brief_description> <description> NavigationServer3D is the server responsible for all 3D navigation. It handles several objects, namely maps, regions and agents. - Maps are made up of regions, which are made of navigation meshes. Together, they define the navigable areas in the 3D world. For two regions to be connected to each other, they must share a similar edge. An edges is considered connected to another if both of its two vertices are at a distance less than [code]edge_connection_margin[/code] to the respective other edge's vertex. + Maps are made up of regions, which are made of navigation meshes. Together, they define the navigable areas in the 3D world. For two regions to be connected to each other, they must share a similar edge. An edge is considered connected to another if both of its two vertices are at a distance less than [code]edge_connection_margin[/code] to the respective other edge's vertex. You may assign navigation layers to regions with [method NavigationServer3D.region_set_layers], which then can be checked upon when requesting a path with [method NavigationServer3D.map_get_path]. This allows allowing or forbidding some areas to 3D objects. To use the collision avoidance system, you may use agents. You can set an agent's target velocity, then the servers will emit a callback with a modified velocity. [b]Note:[/b] the collision avoidance system ignores regions. Using the modified velocity as-is might lead to pushing and agent outside of a navigable area. This is a limitation of the collision avoidance system, any more complex situation may require the use of the physics engine. diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 7ee6860dfc..7750d45226 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -128,7 +128,7 @@ </argument> <description> Adds a child node. Nodes can have any number of children, but every child must have a unique name. Child nodes are automatically deleted when the parent node is deleted, so an entire scene can be removed by deleting its topmost node. - If [code]legible_unique_name[/code] is [code]true[/code], the child node will have an human-readable name based on the name of the node being instanced instead of its type. + If [code]legible_unique_name[/code] is [code]true[/code], the child node will have a human-readable name based on the name of the node being instanced instead of its type. [b]Note:[/b] If the child node already has a parent, the function will fail. Use [method remove_child] first to remove the node from its current parent. For example: [codeblocks] [gdscript] @@ -158,8 +158,8 @@ <argument index="1" name="legible_unique_name" type="bool" default="false"> </argument> <description> - Adds a [code]sibling[/code] node to current's node parent, at the the same level as that node, right below it. - If [code]legible_unique_name[/code] is [code]true[/code], the child node will have an human-readable name based on the name of the node being instanced instead of its type. + Adds a [code]sibling[/code] node to current's node parent, at the same level as that node, right below it. + If [code]legible_unique_name[/code] is [code]true[/code], the child node will have a human-readable name based on the name of the node being instanced instead of its type. Use [method add_child] instead of this method if you don't need the child node to be added below a specific node in the list of children. </description> </method> diff --git a/doc/classes/NodePath.xml b/doc/classes/NodePath.xml index e3f5fa1ce5..817ccd5160 100644 --- a/doc/classes/NodePath.xml +++ b/doc/classes/NodePath.xml @@ -70,7 +70,7 @@ <return type="NodePath"> </return> <description> - Returns a node path with a colon character ([code]:[/code]) prepended, transforming it to a pure property path with no node name (defaults to resolving from the from the current node). + Returns a node path with a colon character ([code]:[/code]) prepended, transforming it to a pure property path with no node name (defaults to resolving from the current node). [codeblocks] [gdscript] # This will be parsed as a node path to the "x" property in the "position" node. diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 548147beab..8c90108aef 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -244,9 +244,9 @@ </return> <description> Returns the host OS locale as a string of the form [code]language_Script_COUNTRY_VARIANT@extra[/code]. - [code]language[/code] - 2 or 3 letter [url=https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes]language code[/url], in lower case. - [code]Script[/code] - optional, 4 letter [url=https://en.wikipedia.org/wiki/ISO_15924]script code[/url], in title case. - [code]COUNTRY[/code] - optional, 2 or 3 letter [url=https://en.wikipedia.org/wiki/ISO_3166-1]country code[/url], in upper case. + [code]language[/code] - 2 or 3-letter [url=https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes]language code[/url], in lower case. + [code]Script[/code] - optional, 4-letter [url=https://en.wikipedia.org/wiki/ISO_15924]script code[/url], in title case. + [code]COUNTRY[/code] - optional, 2 or 3-letter [url=https://en.wikipedia.org/wiki/ISO_3166-1]country code[/url], in upper case. [code]VARIANT[/code] - optional, language variant, region and sort order. Variant can have any number of underscored key words. [code]extra[/code] - optional, semicolon separated list of additional key words. Currency, calendar, sort order and numbering system information. </description> @@ -355,7 +355,7 @@ <return type="float"> </return> <description> - Returns the current UNIX epoch timestamp. + Returns the current UNIX epoch timestamp in seconds. [b]Important:[/b] This is the system clock that the user can manully set. [b]Never use[/b] this method for precise time calculation since its results are also subject to automatic adjustments by the operating system. [b]Always use[/b] [method get_ticks_usec] or [method get_ticks_msec] for precise time calculation instead, since they are guaranteed to be monotonic (i.e. never decrease). </description> </method> diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml index ad3ce8e93e..7da9c1ac38 100644 --- a/doc/classes/Object.xml +++ b/doc/classes/Object.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="Object" version="4.0"> <brief_description> - Base class for all non built-in types. + Base class for all non-built-in types. </brief_description> <description> Every class which is not a built-in type inherits from this class. @@ -179,7 +179,7 @@ </argument> <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 recommend 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. + [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. A signal can only be connected once to a [Callable]. It will throw 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/PHashTranslation.xml b/doc/classes/OptimizedTranslation.xml index 30194e9495..a5ca93c7ff 100644 --- a/doc/classes/PHashTranslation.xml +++ b/doc/classes/OptimizedTranslation.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PHashTranslation" inherits="Translation" version="4.0"> +<class name="OptimizedTranslation" inherits="Translation" version="4.0"> <brief_description> Optimized translation. </brief_description> diff --git a/doc/classes/PackedByteArray.xml b/doc/classes/PackedByteArray.xml index 34a55d4fe7..21f835a53c 100644 --- a/doc/classes/PackedByteArray.xml +++ b/doc/classes/PackedByteArray.xml @@ -81,7 +81,7 @@ </argument> <description> Returns a new [PackedByteArray] with the data decompressed. Set the compression mode using one of [enum File.CompressionMode]'s constants. [b]This method only accepts gzip and deflate compression modes.[/b] - This method is potentially slower than [code]decompress[/code], as it may have to re-allocate it's output buffer multiple times while decompressing, where as [code]decompress[/code] knows it's output buffer size from the beginning. + This method is potentially slower than [code]decompress[/code], as it may have to re-allocate its output buffer multiple times while decompressing, whereas [code]decompress[/code] knows it's output buffer size from the beginning. GZIP has a maximal compression ratio of 1032:1, meaning it's very possible for a small compressed payload to decompress to a potentially very large output. To guard against this, you may provide a maximum size this function is allowed to allocate in bytes via [code]max_output_size[/code]. Passing -1 will allow for unbounded output. If any positive value is passed, and the decompression exceeds that amount in bytes, then an error will be returned. </description> </method> @@ -157,13 +157,6 @@ Inserts a new element at a given position in the array. The position must be valid, or at the end of the array ([code]idx == size()[/code]). </description> </method> - <method name="invert"> - <return type="void"> - </return> - <description> - Reverses the order of the elements in the array. - </description> - </method> <method name="is_empty" qualifiers="const"> <return type="bool"> </return> @@ -230,6 +223,13 @@ Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. </description> </method> + <method name="reverse"> + <return type="void"> + </return> + <description> + Reverses the order of the elements in the array. + </description> + </method> <method name="set"> <return type="void"> </return> diff --git a/doc/classes/PackedColorArray.xml b/doc/classes/PackedColorArray.xml index abfedc84cc..38240b3154 100644 --- a/doc/classes/PackedColorArray.xml +++ b/doc/classes/PackedColorArray.xml @@ -79,13 +79,6 @@ Inserts a new element at a given position in the array. The position must be valid, or at the end of the array ([code]idx == size()[/code]). </description> </method> - <method name="invert"> - <return type="void"> - </return> - <description> - Reverses the order of the elements in the array. - </description> - </method> <method name="is_empty" qualifiers="const"> <return type="bool"> </return> @@ -152,6 +145,13 @@ Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. </description> </method> + <method name="reverse"> + <return type="void"> + </return> + <description> + Reverses the order of the elements in the array. + </description> + </method> <method name="set"> <return type="void"> </return> diff --git a/doc/classes/PackedFloat32Array.xml b/doc/classes/PackedFloat32Array.xml index 8918312dc7..6be1d24b5d 100644 --- a/doc/classes/PackedFloat32Array.xml +++ b/doc/classes/PackedFloat32Array.xml @@ -80,13 +80,6 @@ Inserts a new element at a given position in the array. The position must be valid, or at the end of the array ([code]idx == size()[/code]). </description> </method> - <method name="invert"> - <return type="void"> - </return> - <description> - Reverses the order of the elements in the array. - </description> - </method> <method name="is_empty" qualifiers="const"> <return type="bool"> </return> @@ -145,6 +138,13 @@ Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. </description> </method> + <method name="reverse"> + <return type="void"> + </return> + <description> + Reverses the order of the elements in the array. + </description> + </method> <method name="set"> <return type="void"> </return> diff --git a/doc/classes/PackedFloat64Array.xml b/doc/classes/PackedFloat64Array.xml index fbb832299e..fb7817cb41 100644 --- a/doc/classes/PackedFloat64Array.xml +++ b/doc/classes/PackedFloat64Array.xml @@ -80,13 +80,6 @@ Inserts a new element at a given position in the array. The position must be valid, or at the end of the array ([code]idx == size()[/code]). </description> </method> - <method name="invert"> - <return type="void"> - </return> - <description> - Reverses the order of the elements in the array. - </description> - </method> <method name="is_empty" qualifiers="const"> <return type="bool"> </return> @@ -153,6 +146,13 @@ Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. </description> </method> + <method name="reverse"> + <return type="void"> + </return> + <description> + Reverses the order of the elements in the array. + </description> + </method> <method name="set"> <return type="void"> </return> diff --git a/doc/classes/PackedInt32Array.xml b/doc/classes/PackedInt32Array.xml index ecef2d508b..4ee428dfbc 100644 --- a/doc/classes/PackedInt32Array.xml +++ b/doc/classes/PackedInt32Array.xml @@ -80,13 +80,6 @@ Inserts a new integer at a given position in the array. The position must be valid, or at the end of the array ([code]idx == size()[/code]). </description> </method> - <method name="invert"> - <return type="void"> - </return> - <description> - Reverses the order of the elements in the array. - </description> - </method> <method name="is_empty" qualifiers="const"> <return type="bool"> </return> @@ -153,6 +146,13 @@ Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. </description> </method> + <method name="reverse"> + <return type="void"> + </return> + <description> + Reverses the order of the elements in the array. + </description> + </method> <method name="set"> <return type="void"> </return> diff --git a/doc/classes/PackedInt64Array.xml b/doc/classes/PackedInt64Array.xml index 19619d60cf..51948fcbc8 100644 --- a/doc/classes/PackedInt64Array.xml +++ b/doc/classes/PackedInt64Array.xml @@ -80,13 +80,6 @@ Inserts a new integer at a given position in the array. The position must be valid, or at the end of the array ([code]idx == size()[/code]). </description> </method> - <method name="invert"> - <return type="void"> - </return> - <description> - Reverses the order of the elements in the array. - </description> - </method> <method name="is_empty" qualifiers="const"> <return type="bool"> </return> @@ -153,6 +146,13 @@ Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. </description> </method> + <method name="reverse"> + <return type="void"> + </return> + <description> + Reverses the order of the elements in the array. + </description> + </method> <method name="set"> <return type="void"> </return> diff --git a/doc/classes/PackedStringArray.xml b/doc/classes/PackedStringArray.xml index c241573b93..9748301dae 100644 --- a/doc/classes/PackedStringArray.xml +++ b/doc/classes/PackedStringArray.xml @@ -80,13 +80,6 @@ Inserts a new element at a given position in the array. The position must be valid, or at the end of the array ([code]idx == size()[/code]). </description> </method> - <method name="invert"> - <return type="void"> - </return> - <description> - Reverses the order of the elements in the array. - </description> - </method> <method name="is_empty" qualifiers="const"> <return type="bool"> </return> @@ -153,6 +146,13 @@ Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. </description> </method> + <method name="reverse"> + <return type="void"> + </return> + <description> + Reverses the order of the elements in the array. + </description> + </method> <method name="set"> <return type="void"> </return> diff --git a/doc/classes/PackedVector2Array.xml b/doc/classes/PackedVector2Array.xml index 9138dc68e1..1b3201b072 100644 --- a/doc/classes/PackedVector2Array.xml +++ b/doc/classes/PackedVector2Array.xml @@ -80,13 +80,6 @@ Inserts a new element at a given position in the array. The position must be valid, or at the end of the array ([code]idx == size()[/code]). </description> </method> - <method name="invert"> - <return type="void"> - </return> - <description> - Reverses the order of the elements in the array. - </description> - </method> <method name="is_empty" qualifiers="const"> <return type="bool"> </return> @@ -161,6 +154,13 @@ Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. </description> </method> + <method name="reverse"> + <return type="void"> + </return> + <description> + Reverses the order of the elements in the array. + </description> + </method> <method name="set"> <return type="void"> </return> diff --git a/doc/classes/PackedVector3Array.xml b/doc/classes/PackedVector3Array.xml index 0a3b0cf2c0..25d854016a 100644 --- a/doc/classes/PackedVector3Array.xml +++ b/doc/classes/PackedVector3Array.xml @@ -79,13 +79,6 @@ Inserts a new element at a given position in the array. The position must be valid, or at the end of the array ([code]idx == size()[/code]). </description> </method> - <method name="invert"> - <return type="void"> - </return> - <description> - Reverses the order of the elements in the array. - </description> - </method> <method name="is_empty" qualifiers="const"> <return type="bool"> </return> @@ -160,6 +153,13 @@ Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. </description> </method> + <method name="reverse"> + <return type="void"> + </return> + <description> + Reverses the order of the elements in the array. + </description> + </method> <method name="set"> <return type="void"> </return> diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticlesMaterial.xml index 85058cb9d4..6d7f99a55b 100644 --- a/doc/classes/ParticlesMaterial.xml +++ b/doc/classes/ParticlesMaterial.xml @@ -181,7 +181,7 @@ The sphere's radius if [code]emission_shape[/code] is set to [constant EMISSION_SHAPE_SPHERE]. </member> <member name="flatness" type="float" setter="set_flatness" getter="get_flatness" default="0.0"> - Amount of [member spread] in Y/Z plane. A value of [code]1[/code] restricts particles to X/Z plane. + Amount of [member spread] along the Y axis. </member> <member name="gravity" type="Vector3" setter="set_gravity" getter="get_gravity" default="Vector3( 0, -9.8, 0 )"> Gravity applied to every particle. @@ -251,7 +251,7 @@ Scale randomness ratio. </member> <member name="spread" type="float" setter="set_spread" getter="get_spread" default="45.0"> - Each particle's initial direction range from [code]+spread[/code] to [code]-spread[/code] degrees. Applied to X/Z plane and Y/Z planes. + Each particle's initial direction range from [code]+spread[/code] to [code]-spread[/code] degrees. </member> <member name="sub_emitter_amount_at_end" type="int" setter="set_sub_emitter_amount_at_end" getter="get_sub_emitter_amount_at_end"> </member> diff --git a/doc/classes/PhysicalBone3D.xml b/doc/classes/PhysicalBone3D.xml index dcf24c1d32..38d9f722b1 100644 --- a/doc/classes/PhysicalBone3D.xml +++ b/doc/classes/PhysicalBone3D.xml @@ -91,7 +91,7 @@ The body's bounciness. Values range from [code]0[/code] (no bounce) to [code]1[/code] (full bounciness). </member> <member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep" default="true"> - If [code]true[/code], the body is deactivated when there is no movement, so it will not take part in the simulation until it is awaken by an external force. + If [code]true[/code], the body is deactivated when there is no movement, so it will not take part in the simulation until it is awakened by an external force. </member> <member name="friction" type="float" setter="set_friction" getter="get_friction" default="1.0"> The body's friction, from [code]0[/code] (frictionless) to [code]1[/code] (max friction). diff --git a/doc/classes/PhysicalSkyMaterial.xml b/doc/classes/PhysicalSkyMaterial.xml index 2e0f9c52f2..381371b973 100644 --- a/doc/classes/PhysicalSkyMaterial.xml +++ b/doc/classes/PhysicalSkyMaterial.xml @@ -23,22 +23,22 @@ Modulates the [Color] on the bottom half of the sky to represent the ground. </member> <member name="mie_coefficient" type="float" setter="set_mie_coefficient" getter="get_mie_coefficient" default="0.005"> - Controls the strength of mie scattering for the sky. Mie scattering results from light colliding with larger particles (like water). On earth, mie scattering results in a whiteish color around the sun and horizon. + Controls the strength of mie scattering for the sky. Mie scattering results from light colliding with larger particles (like water). On earth, mie scattering results in a whitish color around the sun and horizon. </member> <member name="mie_color" type="Color" setter="set_mie_color" getter="get_mie_color" default="Color( 0.36, 0.56, 0.82, 1 )"> Controls the [Color] of the mie scattering effect. While not physically accurate, this allows for the creation of alien looking planets. </member> <member name="mie_eccentricity" type="float" setter="set_mie_eccentricity" getter="get_mie_eccentricity" default="0.8"> - Controls the direction of the mie scattering. A value of [code]1[/code] means that when light hits a particle it passing through straight forward. A value of [code]-1[/code] means that all light is scatter backwards. + Controls the direction of the mie scattering. A value of [code]1[/code] means that when light hits a particle it's passing through straight forward. A value of [code]-1[/code] means that all light is scatter backwards. </member> <member name="night_sky" type="Texture2D" setter="set_night_sky" getter="get_night_sky"> [Texture2D] for the night sky. This is added to the sky, so if it is bright enough, it may be visible during the day. </member> <member name="rayleigh_coefficient" type="float" setter="set_rayleigh_coefficient" getter="get_rayleigh_coefficient" default="2.0"> - Controls the strength of the rayleigh scattering. Rayleigh scattering results from light colliding with small particles. It is responsible for the blue color of the sky. + Controls the strength of the Rayleigh scattering. Rayleigh scattering results from light colliding with small particles. It is responsible for the blue color of the sky. </member> <member name="rayleigh_color" type="Color" setter="set_rayleigh_color" getter="get_rayleigh_color" default="Color( 0.056, 0.14, 0.3, 1 )"> - Controls the [Color] of the rayleigh scattering. While not physically accurate, this allows for the creation of alien looking planets. For example, setting this to a red [Color] results in a mars looking atmosphere with a corresponding blue sunset. + Controls the [Color] of the Rayleigh scattering. While not physically accurate, this allows for the creation of alien looking planets. For example, setting this to a red [Color] results in a Mars looking atmosphere with a corresponding blue sunset. </member> <member name="sun_disk_scale" type="float" setter="set_sun_disk_scale" getter="get_sun_disk_scale" default="1.0"> Sets the size of the sun disk. Default value is based on Sol's perceived size from Earth. diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml index 9a7926e937..c61347ba0b 100644 --- a/doc/classes/PhysicsServer3D.xml +++ b/doc/classes/PhysicsServer3D.xml @@ -1241,6 +1241,14 @@ Gets a slider_joint parameter (see [enum SliderJointParam] constants). </description> </method> + <method name="soft_body_get_bounds" qualifiers="const"> + <return type="AABB"> + </return> + <argument index="0" name="body" type="RID"> + </argument> + <description> + </description> + </method> <method name="space_create"> <return type="RID"> </return> @@ -1543,7 +1551,10 @@ <constant name="SHAPE_HEIGHTMAP" value="8" enum="ShapeType"> The [Shape3D] is a [HeightMapShape3D]. </constant> - <constant name="SHAPE_CUSTOM" value="9" enum="ShapeType"> + <constant name="SHAPE_SOFT_BODY" value="9" enum="ShapeType"> + The [Shape3D] is a [SoftBody3D]. + </constant> + <constant name="SHAPE_CUSTOM" value="10" enum="ShapeType"> This constant is used internally by the engine. Any attempt to create this kind of shape results in an error. </constant> <constant name="AREA_PARAM_GRAVITY" value="0" enum="AreaParameter"> diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml index 51ec509a14..418785222e 100644 --- a/doc/classes/PopupMenu.xml +++ b/doc/classes/PopupMenu.xml @@ -565,7 +565,7 @@ <argument index="1" name="state" type="int"> </argument> <description> - Sets the state of an multistate item. See [method add_multistate_item] for details. + Sets the state of a multistate item. See [method add_multistate_item] for details. </description> </method> <method name="set_item_opentype_feature"> @@ -664,13 +664,13 @@ <argument index="0" name="idx" type="int"> </argument> <description> - Cycle to the next state of an multistate item. See [method add_multistate_item] for details. + Cycle to the next state of a multistate item. See [method add_multistate_item] for details. </description> </method> </methods> <members> <member name="allow_search" type="bool" setter="set_allow_search" getter="get_allow_search" default="true"> - If [code]true[/code], allows to navigate [PopupMenu] with letter keys. + If [code]true[/code], allows navigating [PopupMenu] with letter keys. </member> <member name="hide_on_checkable_item_selection" type="bool" setter="set_hide_on_checkable_item_selection" getter="is_hide_on_checkable_item_selection" default="true"> If [code]true[/code], hides the [PopupMenu] when a checkbox or radio button is selected. diff --git a/doc/classes/PrimitiveMesh.xml b/doc/classes/PrimitiveMesh.xml index 25943f6d47..8b73bcb9c1 100644 --- a/doc/classes/PrimitiveMesh.xml +++ b/doc/classes/PrimitiveMesh.xml @@ -31,7 +31,7 @@ </methods> <members> <member name="custom_aabb" type="AABB" setter="set_custom_aabb" getter="get_custom_aabb" default="AABB( 0, 0, 0, 0, 0, 0 )"> - Overrides the [AABB] with one defined by user for use with frustum culling. Especially useful to avoid unnexpected culling when using a shader to offset vertices. + Overrides the [AABB] with one defined by user for use with frustum culling. Especially useful to avoid unexpected culling when using a shader to offset vertices. </member> <member name="flip_faces" type="bool" setter="set_flip_faces" getter="get_flip_faces" default="false"> If set, the order of the vertices in each triangle are reversed resulting in the backside of the mesh being drawn. diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 9dad01e6dc..5b9150ab04 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -443,7 +443,7 @@ <member name="debug/settings/fps/force_fps" type="int" setter="" getter="" default="0"> Maximum number of frames per second allowed. The actual number of frames per second may still be below this value if the game is lagging. If [member display/window/vsync/use_vsync] is enabled, it takes precedence and the forced FPS number cannot exceed the monitor's refresh rate. - This setting is therefore mostly relevant for lowering the maximum FPS below VSync, e.g. to perform non real-time rendering of static frames, or test the project under lag conditions. + This setting is therefore mostly relevant for lowering the maximum FPS below VSync, e.g. to perform non-real-time rendering of static frames, or test the project under lag conditions. </member> <member name="debug/settings/gdscript/max_call_stack" type="int" setter="" getter="" default="1024"> Maximum call stack allowed for debugging GDScript. @@ -734,7 +734,7 @@ <member name="input_devices/pen_tablet/driver" type="String" setter="" getter=""> Specifies the tablet driver to use. If left empty, the default driver will be used. </member> - <member name="input_devices/pen_tablet/driver.windows" type="String" setter="" getter=""> + <member name="input_devices/pen_tablet/driver.Windows" type="String" setter="" getter=""> Override for [member input_devices/pen_tablet/driver] on Windows. </member> <member name="input_devices/pointing/emulate_mouse_from_touch" type="bool" setter="" getter="" default="true"> diff --git a/doc/classes/Quat.xml b/doc/classes/Quat.xml index e801de1254..1c0a3e37c0 100644 --- a/doc/classes/Quat.xml +++ b/doc/classes/Quat.xml @@ -127,7 +127,7 @@ <argument index="0" name="to" type="Quat"> </argument> <description> - Returns [code]true[/code] if this quaterion and [code]quat[/code] are approximately equal, by running [method @GlobalScope.is_equal_approx] on each component. + Returns [code]true[/code] if this quaternion and [code]quat[/code] are approximately equal, by running [method @GlobalScope.is_equal_approx] on each component. </description> </method> <method name="is_normalized" qualifiers="const"> diff --git a/doc/classes/Rect2.xml b/doc/classes/Rect2.xml index ba6342ec24..352a18e326 100644 --- a/doc/classes/Rect2.xml +++ b/doc/classes/Rect2.xml @@ -221,7 +221,7 @@ Beginning corner. Typically has values lower than [member end]. </member> <member name="size" type="Vector2" setter="" getter="" default="Vector2( 0, 0 )"> - Size from [member position] to [member end]. Typically all components are positive. + Size from [member position] to [member end]. Typically, all components are positive. If the size is negative, you can use [method abs] to fix it. </member> </members> diff --git a/doc/classes/Rect2i.xml b/doc/classes/Rect2i.xml index dd71b5a630..84bef9b406 100644 --- a/doc/classes/Rect2i.xml +++ b/doc/classes/Rect2i.xml @@ -200,7 +200,7 @@ Beginning corner. Typically has values lower than [member end]. </member> <member name="size" type="Vector2i" setter="" getter="" default="Vector2i( 0, 0 )"> - Size from [member position] to [member end]. Typically all components are positive. + Size from [member position] to [member end]. Typically, all components are positive. If the size is negative, you can use [method abs] to fix it. </member> </members> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index d2b95fda20..f82301bcf4 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -10,7 +10,7 @@ Resources are created using the [code]*_create[/code] functions. All objects are drawn to a viewport. You can use the [Viewport] attached to the [SceneTree] or you can create one yourself with [method viewport_create]. When using a custom scenario or canvas, the scenario or canvas needs to be attached to the viewport using [method viewport_set_scenario] or [method viewport_attach_canvas]. In 3D, all visual objects must be associated with a scenario. The scenario is a visual representation of the world. If accessing the rendering server from a running game, the scenario can be accessed from the scene tree from any [Node3D] node with [method Node3D.get_world_3d]. Otherwise, a scenario can be created with [method scenario_create]. - Similarly in 2D, a canvas is needed to draw all canvas items. + Similarly, in 2D, a canvas is needed to draw all canvas items. In 3D, all visible objects are comprised of a resource and an instance. A resource can be a mesh, a particle system, a light, or any other 3D object. In order to be visible resources must be attached to an instance using [method instance_set_base]. The instance must also be attached to the scenario using [method instance_set_scenario] in order to be visible. In 2D, all visible objects are some form of canvas item. In order to be visible, a canvas item needs to be the child of a canvas attached to a viewport, or it needs to be the child of another canvas item that is eventually attached to the canvas. </description> @@ -1292,7 +1292,7 @@ <argument index="1" name="margin" type="float"> </argument> <description> - Sets a margin to increase the size of the AABB when culling objects from the view frustum. This allows you avoid culling objects that fall outside the view frustum. Equivalent to [member GeometryInstance3D.extra_cull_margin]. + Sets a margin to increase the size of the AABB when culling objects from the view frustum. This allows you to avoid culling objects that fall outside the view frustum. Equivalent to [member GeometryInstance3D.extra_cull_margin]. </description> </method> <method name="instance_set_layer_mask"> @@ -1520,7 +1520,7 @@ <argument index="1" name="enabled" type="bool"> </argument> <description> - 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 [method instance_geometry_set_cast_shadows_setting]. Equivalent to [member Light3D.shadow_reverse_cull_face]. + 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 [method instance_geometry_set_cast_shadows_setting]. Equivalent to [member Light3D.shadow_reverse_cull_face]. </description> </method> <method name="light_set_shadow"> @@ -2204,7 +2204,7 @@ <argument index="1" name="time" type="float"> </argument> <description> - Sets the preprocess time for the particles animation. This lets you delay starting an animation until after the particles have begun emitting. Equivalent to [member GPUParticles3D.preprocess]. + Sets the preprocess time for the particles' animation. This lets you delay starting an animation until after the particles have begun emitting. Equivalent to [member GPUParticles3D.preprocess]. </description> </method> <method name="particles_set_process_material"> diff --git a/doc/classes/ResourceFormatLoader.xml b/doc/classes/ResourceFormatLoader.xml index 2683156ec5..9943f644cf 100644 --- a/doc/classes/ResourceFormatLoader.xml +++ b/doc/classes/ResourceFormatLoader.xml @@ -6,7 +6,7 @@ <description> Godot loads resources in the editor or in exported games using ResourceFormatLoaders. They are queried automatically via the [ResourceLoader] singleton, or when a resource with internal dependencies is loaded. Each file type may load as a different resource type, so multiple ResourceFormatLoaders are registered in the engine. Extending this class allows you to define your own loader. Be sure to respect the documented return types and values. You should give it a global class name with [code]class_name[/code] for it to be registered. Like built-in ResourceFormatLoaders, it will be called automatically when loading resources of its handled type(s). You may also implement a [ResourceFormatSaver]. - [b]Note:[/b] You can also extend [EditorImportPlugin] if the resource type you need exists but Godot is unable to load its format. Choosing one way over another depends if the format is suitable or not for the final exported game. For example, it's better to import [code].png[/code] textures as [code].stex[/code] ([StreamTexture2D]) first, so they can be loaded with better efficiency on the graphics card. + [b]Note:[/b] You can also extend [EditorImportPlugin] if the resource type you need exists but Godot is unable to load its format. Choosing one way over another depends on if the format is suitable or not for the final exported game. For example, it's better to import [code].png[/code] textures as [code].stex[/code] ([StreamTexture2D]) first, so they can be loaded with better efficiency on the graphics card. </description> <tutorials> </tutorials> diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml index 6b27c77f26..ed375a8b1e 100644 --- a/doc/classes/RigidBody2D.xml +++ b/doc/classes/RigidBody2D.xml @@ -4,7 +4,7 @@ A body that is controlled by the 2D physics engine. </brief_description> <description> - This node implements simulated 2D physics. You do not control a RigidBody2D directly. Instead you apply forces to it (gravity, impulses, etc.) and the physics simulation calculates the resulting movement based on its mass, friction, and other physical properties. + This node implements simulated 2D physics. You do not control a RigidBody2D directly. Instead, you apply forces to it (gravity, impulses, etc.) and the physics simulation calculates the resulting movement based on its mass, friction, and other physical properties. A RigidBody2D has 4 behavior [member mode]s: Rigid, Static, Character, and Kinematic. [b]Note:[/b] You should not change a RigidBody2D's [code]position[/code] or [code]linear_velocity[/code] every frame or even very often. If you need to directly affect the body's state, use [method _integrate_forces], which allows you to directly access the physics state. Please also keep in mind that physics bodies manage their own transform which overwrites the ones you set. So any direct or indirect transformation (including scaling of the node or its parent) will be visible in the editor only, and immediately reset at runtime. diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index e1f6830eb2..9366d7dd44 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -5,7 +5,7 @@ </brief_description> <description> As one of the most important classes, the [SceneTree] manages the hierarchy of nodes in a scene as well as scenes themselves. Nodes can be added, retrieved and removed. The whole scene tree (and thus the current scene) can be paused. Scenes can be loaded, switched and reloaded. - You can also use the [SceneTree] to organize your nodes into groups: every node can be assigned as many groups as you want to create, e.g. a "enemy" group. You can then iterate these groups or even call methods and set properties on all the group's members at once. + You can also use the [SceneTree] to organize your nodes into groups: every node can be assigned as many groups as you want to create, e.g. an "enemy" group. You can then iterate these groups or even call methods and set properties on all the group's members at once. [SceneTree] is the default [MainLoop] implementation used by scenes, and is thus in charge of the game loop. </description> <tutorials> diff --git a/doc/classes/Shape3D.xml b/doc/classes/Shape3D.xml index f3e62175c6..f8b749aebf 100644 --- a/doc/classes/Shape3D.xml +++ b/doc/classes/Shape3D.xml @@ -14,7 +14,7 @@ <members> <member name="margin" type="float" setter="set_margin" getter="get_margin" default="0.04"> The collision margin for the shape. Used in Bullet Physics only. - Collision margins allows collision detection to be more efficient by adding an extra shell around shapes. Collision algorithms are more expensive when objects overlap by more than their margin, so a higher value for margins is better for performance, at the cost of accuracy around edges as it makes them less sharp. + Collision margins allow collision detection to be more efficient by adding an extra shell around shapes. Collision algorithms are more expensive when objects overlap by more than their margin, so a higher value for margins is better for performance, at the cost of accuracy around edges as it makes them less sharp. </member> </members> <constants> diff --git a/doc/classes/Skeleton3D.xml b/doc/classes/Skeleton3D.xml index fe2cc1f5ad..c6dd6fb142 100644 --- a/doc/classes/Skeleton3D.xml +++ b/doc/classes/Skeleton3D.xml @@ -245,6 +245,16 @@ [b]Note[/b]: The pose transform needs to be in bone space. Use [method world_transform_to_bone_transform] to convert a world transform, like one you can get from a [Node3D], to bone space. </description> </method> + <method name="set_bone_name"> + <return type="void"> + </return> + <argument index="0" name="bone_idx" type="int"> + </argument> + <argument index="1" name="name" type="String"> + </argument> + <description> + </description> + </method> <method name="set_bone_parent"> <return type="void"> </return> @@ -297,7 +307,7 @@ <argument index="0" name="bone_idx" type="int"> </argument> <description> - Unparents the bone at [code]bone_idx[/code] and sets its rest position to that of it's parent prior to being reset. + Unparents the bone at [code]bone_idx[/code] and sets its rest position to that of its parent prior to being reset. </description> </method> <method name="world_transform_to_bone_transform"> diff --git a/doc/classes/SoftBody3D.xml b/doc/classes/SoftBody3D.xml index 04e201e1bd..7999ad774d 100644 --- a/doc/classes/SoftBody3D.xml +++ b/doc/classes/SoftBody3D.xml @@ -44,6 +44,12 @@ Returns an individual bit on the collision mask. </description> </method> + <method name="get_physics_rid" qualifiers="const"> + <return type="RID"> + </return> + <description> + </description> + </method> <method name="remove_collision_exception_with"> <return type="void"> </return> @@ -77,8 +83,6 @@ </method> </methods> <members> - <member name="angular_stiffness" type="float" setter="set_angular_stiffness" getter="get_angular_stiffness" default="0.0"> - </member> <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer" default="1"> The physics layers this SoftBody3D is in. Collidable objects can exist in any of 32 different layers. These layers work like a tagging system, and are not visual. A collidable can use these layers to select with which objects it can collide, using the collision_mask property. @@ -87,30 +91,26 @@ <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> The physics layers this SoftBody3D scans for collisions. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> - <member name="damping_coefficient" type="float" setter="set_damping_coefficient" getter="get_damping_coefficient" default="0.0"> + <member name="damping_coefficient" type="float" setter="set_damping_coefficient" getter="get_damping_coefficient" default="0.01"> </member> <member name="drag_coefficient" type="float" setter="set_drag_coefficient" getter="get_drag_coefficient" default="0.0"> </member> - <member name="linear_stiffness" type="float" setter="set_linear_stiffness" getter="get_linear_stiffness" default="0.0"> + <member name="linear_stiffness" type="float" setter="set_linear_stiffness" getter="get_linear_stiffness" default="0.5"> </member> <member name="parent_collision_ignore" type="NodePath" setter="set_parent_collision_ignore" getter="get_parent_collision_ignore" default="NodePath("")"> [NodePath] to a [CollisionObject3D] this SoftBody3D should avoid clipping. </member> - <member name="pose_matching_coefficient" type="float" setter="set_pose_matching_coefficient" getter="get_pose_matching_coefficient" default="0.0"> - </member> <member name="pressure_coefficient" type="float" setter="set_pressure_coefficient" getter="get_pressure_coefficient" default="0.0"> </member> <member name="ray_pickable" type="bool" setter="set_ray_pickable" getter="is_ray_pickable" default="true"> If [code]true[/code], the [SoftBody3D] will respond to [RayCast3D]s. </member> - <member name="simulation_precision" type="int" setter="set_simulation_precision" getter="get_simulation_precision" default="0"> + <member name="simulation_precision" type="int" setter="set_simulation_precision" getter="get_simulation_precision" default="5"> Increasing this value will improve the resulting simulation, but can affect performance. Use with care. </member> - <member name="total_mass" type="float" setter="set_total_mass" getter="get_total_mass" default="0.0"> + <member name="total_mass" type="float" setter="set_total_mass" getter="get_total_mass" default="1.0"> The SoftBody3D's mass. </member> - <member name="volume_stiffness" type="float" setter="set_volume_stiffness" getter="get_volume_stiffness" default="0.0"> - </member> </members> <constants> </constants> diff --git a/doc/classes/Sprite2D.xml b/doc/classes/Sprite2D.xml index e4df753674..617ad3a371 100644 --- a/doc/classes/Sprite2D.xml +++ b/doc/classes/Sprite2D.xml @@ -18,7 +18,7 @@ [codeblocks] [gdscript] func _input(event): - if event is InputEventMouseButton and event.pressed and event.button_index == BUTTON_LEFT: + if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: if get_rect().has_point(to_local(event.position)): print("A click!") [/gdscript] @@ -73,10 +73,10 @@ <member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2( 0, 0 )"> The texture's drawing offset. </member> - <member name="region_enabled" type="bool" setter="set_region" getter="is_region" default="false"> + <member name="region_enabled" type="bool" setter="set_region_enabled" getter="is_region_enabled" default="false"> If [code]true[/code], texture is cut from a larger atlas texture. See [member region_rect]. </member> - <member name="region_filter_clip" type="bool" setter="set_region_filter_clip" getter="is_region_filter_clip_enabled" default="false"> + <member name="region_filter_clip_enabled" type="bool" setter="set_region_filter_clip_enabled" getter="is_region_filter_clip_enabled" default="false"> If [code]true[/code], the outermost pixels get blurred out. [member region_enabled] must be [code]true[/code]. </member> <member name="region_rect" type="Rect2" setter="set_region_rect" getter="get_region_rect" default="Rect2( 0, 0, 0, 0 )"> diff --git a/doc/classes/Sprite3D.xml b/doc/classes/Sprite3D.xml index f9b947fa3d..658fd1a4f2 100644 --- a/doc/classes/Sprite3D.xml +++ b/doc/classes/Sprite3D.xml @@ -20,7 +20,7 @@ <member name="hframes" type="int" setter="set_hframes" getter="get_hframes" default="1"> The number of columns in the sprite sheet. </member> - <member name="region_enabled" type="bool" setter="set_region" getter="is_region" default="false"> + <member name="region_enabled" type="bool" setter="set_region_enabled" getter="is_region_enabled" default="false"> If [code]true[/code], texture will be cut from a larger atlas texture. See [member region_rect]. </member> <member name="region_rect" type="Rect2" setter="set_region_rect" getter="get_region_rect" default="Rect2( 0, 0, 0, 0 )"> diff --git a/doc/classes/SpriteBase3D.xml b/doc/classes/SpriteBase3D.xml index 078520a095..06b9c2b042 100644 --- a/doc/classes/SpriteBase3D.xml +++ b/doc/classes/SpriteBase3D.xml @@ -73,7 +73,7 @@ The texture's drawing offset. </member> <member name="opacity" type="float" setter="set_opacity" getter="get_opacity" default="1.0"> - The objects visibility on a scale from [code]0[/code] fully invisible to [code]1[/code] fully visible. + The objects' visibility on a scale from [code]0[/code] fully invisible to [code]1[/code] fully visible. </member> <member name="pixel_size" type="float" setter="set_pixel_size" getter="get_pixel_size" default="0.01"> The size of one pixel's width on the sprite to scale it in 3D. diff --git a/doc/classes/StringName.xml b/doc/classes/StringName.xml index af0074f080..be32f6a234 100644 --- a/doc/classes/StringName.xml +++ b/doc/classes/StringName.xml @@ -4,7 +4,7 @@ An optimized string type for unique names. </brief_description> <description> - [StringName]s are immutable strings designed for general-purpose represention of unique names. [StringName] ensures that only one instance of a given name exists (so two [StringName]s with the same value are the same object). Comparing them is much faster than with regular [String]s, because only the pointers are compared, not the whole strings. + [StringName]s are immutable strings designed for general-purpose representation of unique names. [StringName] ensures that only one instance of a given name exists (so two [StringName]s with the same value are the same object). Comparing them is much faster than with regular [String]s, because only the pointers are compared, not the whole strings. </description> <tutorials> </tutorials> diff --git a/doc/classes/SurfaceTool.xml b/doc/classes/SurfaceTool.xml index d145b4ce97..1195e4aa2b 100644 --- a/doc/classes/SurfaceTool.xml +++ b/doc/classes/SurfaceTool.xml @@ -189,6 +189,12 @@ <description> </description> </method> + <method name="get_primitive" qualifiers="const"> + <return type="int" enum="Mesh.PrimitiveType"> + </return> + <description> + </description> + </method> <method name="get_skin_weight_count" qualifiers="const"> <return type="int" enum="SurfaceTool.SkinWeightCount"> </return> @@ -199,7 +205,7 @@ <return type="void"> </return> <description> - Shrinks the vertex array by creating an index array (avoids reusing vertices). + Shrinks the vertex array by creating an index array. This can improve performance by avoiding vertex reuse. </description> </method> <method name="optimize_indices_for_cache"> @@ -214,7 +220,7 @@ <argument index="0" name="bones" type="PackedInt32Array"> </argument> <description> - Specifies an array of bones for the next vertex to use. [code]bones[/code] must contain 4 integers. + Specifies an array of bones to use for the [i]next[/i] vertex. [code]bones[/code] must contain 4 integers. </description> </method> <method name="set_color"> @@ -223,7 +229,7 @@ <argument index="0" name="color" type="Color"> </argument> <description> - Specifies a [Color] for the next vertex to use. + Specifies a [Color] to use for the [i]next[/i] vertex. If every vertex needs to have this information set and you fail to submit it for the first vertex, this information may not be used at all. [b]Note:[/b] The material must have [member BaseMaterial3D.vertex_color_use_as_albedo] enabled for the vertex color to be visible. </description> </method> @@ -262,7 +268,7 @@ <argument index="0" name="normal" type="Vector3"> </argument> <description> - Specifies a normal for the next vertex to use. + Specifies a normal to use for the [i]next[/i] vertex. If every vertex needs to have this information set and you fail to submit it for the first vertex, this information may not be used at all. </description> </method> <method name="set_skin_weight_count"> @@ -288,7 +294,7 @@ <argument index="0" name="tangent" type="Plane"> </argument> <description> - Specifies a tangent for the next vertex to use. + Specifies a tangent to use for the [i]next[/i] vertex. If every vertex needs to have this information set and you fail to submit it for the first vertex, this information may not be used at all. </description> </method> <method name="set_uv"> @@ -297,7 +303,7 @@ <argument index="0" name="uv" type="Vector2"> </argument> <description> - Specifies a set of UV coordinates to use for the next vertex. + Specifies a set of UV coordinates to use for the [i]next[/i] vertex. If every vertex needs to have this information set and you fail to submit it for the first vertex, this information may not be used at all. </description> </method> <method name="set_uv2"> @@ -306,7 +312,7 @@ <argument index="0" name="uv2" type="Vector2"> </argument> <description> - Specifies an optional second set of UV coordinates to use for the next vertex. + Specifies an optional second set of UV coordinates to use for the [i]next[/i] vertex. If every vertex needs to have this information set and you fail to submit it for the first vertex, this information may not be used at all. </description> </method> <method name="set_weights"> @@ -315,7 +321,7 @@ <argument index="0" name="weights" type="PackedFloat32Array"> </argument> <description> - Specifies weight values for next vertex to use. [code]weights[/code] must contain 4 values. + Specifies weight values to use for the [i]next[/i] vertex. [code]weights[/code] must contain 4 values. If every vertex needs to have this information set and you fail to submit it for the first vertex, this information may not be used at all. </description> </method> </methods> diff --git a/doc/classes/Tabs.xml b/doc/classes/Tabs.xml index df9680bf28..79fa8896e3 100644 --- a/doc/classes/Tabs.xml +++ b/doc/classes/Tabs.xml @@ -254,6 +254,9 @@ </method> </methods> <members> + <member name="clip_tabs" type="bool" setter="set_clip_tabs" getter="get_clip_tabs" default="true"> + If [code]true[/code], tabs overflowing this node's width will be hidden, displaying two navigation buttons instead. Otherwise, this node's minimum size is updated so that all tabs are visible. + </member> <member name="current_tab" type="int" setter="set_current_tab" getter="get_current_tab" default="0"> Select tab at index [code]tab_idx[/code]. </member> @@ -261,7 +264,7 @@ If [code]true[/code], tabs can be rearranged with mouse drag. </member> <member name="scrolling_enabled" type="bool" setter="set_scrolling_enabled" getter="get_scrolling_enabled" default="true"> - if [code]true[/code], the mouse's scroll wheel cab be used to navigate the scroll view. + if [code]true[/code], the mouse's scroll wheel can be used to navigate the scroll view. </member> <member name="tab_align" type="int" setter="set_tab_align" getter="get_tab_align" enum="Tabs.TabAlign" default="1"> The alignment of all tabs. See [enum TabAlign] for details. diff --git a/doc/classes/TextParagraph.xml b/doc/classes/TextParagraph.xml index 99eb8b81d4..8df53b8423 100644 --- a/doc/classes/TextParagraph.xml +++ b/doc/classes/TextParagraph.xml @@ -145,7 +145,7 @@ <argument index="4" name="dc_color" type="Color" default="Color( 1, 1, 1, 1 )"> </argument> <description> - Draw outilines of all lines of the text and drop cap into a canvas item at a given position, with [code]color[/code]. [code]pos[/code] specifies the top left corner of the bounding box. + Draw outlines of all lines of the text and drop cap into a canvas item at a given position, with [code]color[/code]. [code]pos[/code] specifies the top left corner of the bounding box. </description> </method> <method name="get_dropcap_lines" qualifiers="const"> @@ -289,6 +289,20 @@ Returns the size of the bounding box of the paragraph. </description> </method> + <method name="get_spacing_bottom" qualifiers="const"> + <return type="int"> + </return> + <description> + Returns extra spacing at the bottom of the line. See [member Font.extra_spacing_bottom]. + </description> + </method> + <method name="get_spacing_top" qualifiers="const"> + <return type="int"> + </return> + <description> + Returns extra spacing at the top of the line. See [member Font.extra_spacing_top]. + </description> + </method> <method name="hit_test" qualifiers="const"> <return type="int"> </return> diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml index 5635ec2be0..fe63e434c9 100644 --- a/doc/classes/TextServer.xml +++ b/doc/classes/TextServer.xml @@ -258,6 +258,22 @@ Returns advance of the glyph. </description> </method> + <method name="font_get_glyph_contours" qualifiers="const"> + <return type="Dictionary"> + </return> + <argument index="0" name="font" type="RID"> + </argument> + <argument index="1" name="size" type="int"> + </argument> + <argument index="2" name="index" type="int"> + </argument> + <description> + Returns outline contours of the glyph in a Dictionary. + [code]points[/code] - [PackedVector3Array], containing outline points. [code]x[/code] and [code]y[/code] are point coordinates. [code]z[/code] is the type of the point, using the [enum ContourPointTag] values. + [code]contours[/code] - [PackedInt32Array], containing indices the end points of each contour. + [code]orientation[/code] - [bool], contour orientation. If [code]true[/code], clockwise contours must be filled. + </description> + </method> <method name="font_get_glyph_index" qualifiers="const"> <return type="int"> </return> @@ -359,7 +375,7 @@ <argument index="0" name="font" type="RID"> </argument> <description> - Returns extra spacing for each glyphs in pixels. + Returns extra spacing for each glyph in pixels. </description> </method> <method name="font_get_spacing_space" qualifiers="const"> @@ -368,7 +384,7 @@ <argument index="0" name="font" type="RID"> </argument> <description> - Sets extra spacing for each glyphs in pixels. + Sets extra spacing for each glyph in pixels. </description> </method> <method name="font_get_supported_chars" qualifiers="const"> @@ -1301,5 +1317,14 @@ <constant name="FEATURE_USE_SUPPORT_DATA" value="128" enum="Feature"> TextServer require external data file for some features. </constant> + <constant name="CONTOUR_CURVE_TAG_ON" value="1" enum="ContourPointTag"> + Contour point is on the curve. + </constant> + <constant name="CONTOUR_CURVE_TAG_OFF_CONIC" value="0" enum="ContourPointTag"> + Contour point isn't on the curve, but serves as a control point for a conic (quadratic) Bézier arc. + </constant> + <constant name="CONTOUR_CURVE_TAG_OFF_CUBIC" value="2" enum="ContourPointTag"> + Contour point isn't on the curve, but serves as a control point for a cubic Bézier arc. + </constant> </constants> </class> diff --git a/doc/classes/Texture2D.xml b/doc/classes/Texture2D.xml index 2270b95c63..c33f32c9e4 100644 --- a/doc/classes/Texture2D.xml +++ b/doc/classes/Texture2D.xml @@ -63,18 +63,18 @@ Draws a part of the texture using a [CanvasItem] with the [RenderingServer] API. </description> </method> - <method name="get_data" qualifiers="const"> - <return type="Image"> + <method name="get_height" qualifiers="const"> + <return type="int"> </return> <description> - Returns an [Image] that is a copy of data from this [Texture2D]. [Image]s can be accessed and manipulated directly. + Returns the texture height. </description> </method> - <method name="get_height" qualifiers="const"> - <return type="int"> + <method name="get_image" qualifiers="const"> + <return type="Image"> </return> <description> - Returns the texture height. + Returns an [Image] that is a copy of data from this [Texture2D]. [Image]s can be accessed and manipulated directly. </description> </method> <method name="get_size" qualifiers="const"> diff --git a/doc/classes/Theme.xml b/doc/classes/Theme.xml index 9f976838e9..3173dddb42 100644 --- a/doc/classes/Theme.xml +++ b/doc/classes/Theme.xml @@ -84,6 +84,19 @@ Clears [StyleBox] at [code]name[/code] if the theme has [code]node_type[/code]. </description> </method> + <method name="clear_theme_item"> + <return type="void"> + </return> + <argument index="0" name="data_type" type="int" enum="Theme.DataType"> + </argument> + <argument index="1" name="name" type="StringName"> + </argument> + <argument index="2" name="node_type" type="StringName"> + </argument> + <description> + Clears the theme item of [code]data_type[/code] at [code]name[/code] if the theme has [code]node_type[/code]. + </description> + </method> <method name="copy_default_theme"> <return type="void"> </return> @@ -194,6 +207,13 @@ Returns all the font sizes as a [PackedStringArray] filled with each font size name, for use in [method get_font_size], if the theme has [code]node_type[/code]. </description> </method> + <method name="get_font_size_type_list" qualifiers="const"> + <return type="PackedStringArray"> + </return> + <description> + Returns all the font size types as a [PackedStringArray] filled with unique type names, for use in [method get_font_size] and/or [method get_font_size_list]. + </description> + </method> <method name="get_font_type_list" qualifiers="const"> <return type="PackedStringArray"> </return> @@ -257,6 +277,41 @@ Returns all the [StyleBox] types as a [PackedStringArray] filled with unique type names, for use in [method get_stylebox] and/or [method get_stylebox_list]. </description> </method> + <method name="get_theme_item" qualifiers="const"> + <return type="Variant"> + </return> + <argument index="0" name="data_type" type="int" enum="Theme.DataType"> + </argument> + <argument index="1" name="name" type="StringName"> + </argument> + <argument index="2" name="node_type" type="StringName"> + </argument> + <description> + Returns the theme item of [code]data_type[/code] at [code]name[/code] if the theme has [code]node_type[/code]. + Valid [code]name[/code]s may be found using [method get_theme_item_list] or a data type specific method. Valid [code]node_type[/code]s may be found using [method get_theme_item_type_list] or a data type specific method. + </description> + </method> + <method name="get_theme_item_list" qualifiers="const"> + <return type="PackedStringArray"> + </return> + <argument index="0" name="data_type" type="int" enum="Theme.DataType"> + </argument> + <argument index="1" name="node_type" type="String"> + </argument> + <description> + Returns all the theme items of [code]data_type[/code] as a [PackedStringArray] filled with each theme items's name, for use in [method get_theme_item] or a data type specific method, if the theme has [code]node_type[/code]. + Valid [code]node_type[/code]s may be found using [method get_theme_item_type_list] or a data type specific method. + </description> + </method> + <method name="get_theme_item_type_list" qualifiers="const"> + <return type="PackedStringArray"> + </return> + <argument index="0" name="data_type" type="int" enum="Theme.DataType"> + </argument> + <description> + Returns all the theme items of [code]data_type[/code] types as a [PackedStringArray] filled with unique type names, for use in [method get_theme_item], [method get_theme_item_list] or data type specific methods. + </description> + </method> <method name="get_type_list" qualifiers="const"> <return type="PackedStringArray"> </return> @@ -336,6 +391,113 @@ Returns [code]false[/code] if the theme does not have [code]node_type[/code]. </description> </method> + <method name="has_theme_item" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="data_type" type="int" enum="Theme.DataType"> + </argument> + <argument index="1" name="name" type="StringName"> + </argument> + <argument index="2" name="node_type" type="StringName"> + </argument> + <description> + Returns [code]true[/code] if a theme item of [code]data_type[/code] with [code]name[/code] is in [code]node_type[/code]. + Returns [code]false[/code] if the theme does not have [code]node_type[/code]. + </description> + </method> + <method name="rename_color"> + <return type="void"> + </return> + <argument index="0" name="old_name" type="StringName"> + </argument> + <argument index="1" name="name" type="StringName"> + </argument> + <argument index="2" name="node_type" type="StringName"> + </argument> + <description> + Renames the [Color] at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails. + </description> + </method> + <method name="rename_constant"> + <return type="void"> + </return> + <argument index="0" name="old_name" type="StringName"> + </argument> + <argument index="1" name="name" type="StringName"> + </argument> + <argument index="2" name="node_type" type="StringName"> + </argument> + <description> + Renames the constant at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails. + </description> + </method> + <method name="rename_font"> + <return type="void"> + </return> + <argument index="0" name="old_name" type="StringName"> + </argument> + <argument index="1" name="name" type="StringName"> + </argument> + <argument index="2" name="node_type" type="StringName"> + </argument> + <description> + Renames the [Font] at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails. + </description> + </method> + <method name="rename_font_size"> + <return type="void"> + </return> + <argument index="0" name="old_name" type="StringName"> + </argument> + <argument index="1" name="name" type="StringName"> + </argument> + <argument index="2" name="node_type" type="StringName"> + </argument> + <description> + Renames the font size [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails. + </description> + </method> + <method name="rename_icon"> + <return type="void"> + </return> + <argument index="0" name="old_name" type="StringName"> + </argument> + <argument index="1" name="name" type="StringName"> + </argument> + <argument index="2" name="node_type" type="StringName"> + </argument> + <description> + Renames the icon at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails. + </description> + </method> + <method name="rename_stylebox"> + <return type="void"> + </return> + <argument index="0" name="old_name" type="StringName"> + </argument> + <argument index="1" name="name" type="StringName"> + </argument> + <argument index="2" name="node_type" type="StringName"> + </argument> + <description> + Renames [StyleBox] at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails. + </description> + </method> + <method name="rename_theme_item"> + <return type="void"> + </return> + <argument index="0" name="data_type" type="int" enum="Theme.DataType"> + </argument> + <argument index="1" name="old_name" type="StringName"> + </argument> + <argument index="2" name="name" type="StringName"> + </argument> + <argument index="3" name="node_type" type="StringName"> + </argument> + <description> + Renames the theme item of [code]data_type[/code] at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails. + </description> + </method> <method name="set_color"> <return type="void"> </return> @@ -347,7 +509,7 @@ </argument> <description> Sets the theme's [Color] to [code]color[/code] at [code]name[/code] in [code]node_type[/code]. - Does nothing if the theme does not have [code]node_type[/code]. + Creates [code]node_type[/code] if the theme does not have it. </description> </method> <method name="set_constant"> @@ -361,7 +523,7 @@ </argument> <description> Sets the theme's constant to [code]constant[/code] at [code]name[/code] in [code]node_type[/code]. - Does nothing if the theme does not have [code]node_type[/code]. + Creates [code]node_type[/code] if the theme does not have it. </description> </method> <method name="set_font"> @@ -375,7 +537,7 @@ </argument> <description> Sets the theme's [Font] to [code]font[/code] at [code]name[/code] in [code]node_type[/code]. - Does nothing if the theme does not have [code]node_type[/code]. + Creates [code]node_type[/code] if the theme does not have it. </description> </method> <method name="set_font_size"> @@ -389,7 +551,7 @@ </argument> <description> Sets the theme's font size to [code]font_size[/code] at [code]name[/code] in [code]node_type[/code]. - Does nothing if the theme does not have [code]node_type[/code]. + Creates [code]node_type[/code] if the theme does not have it. </description> </method> <method name="set_icon"> @@ -403,7 +565,7 @@ </argument> <description> Sets the theme's icon [Texture2D] to [code]texture[/code] at [code]name[/code] in [code]node_type[/code]. - Does nothing if the theme does not have [code]node_type[/code]. + Creates [code]node_type[/code] if the theme does not have it. </description> </method> <method name="set_stylebox"> @@ -417,7 +579,24 @@ </argument> <description> Sets theme's [StyleBox] to [code]stylebox[/code] at [code]name[/code] in [code]node_type[/code]. - Does nothing if the theme does not have [code]node_type[/code]. + Creates [code]node_type[/code] if the theme does not have it. + </description> + </method> + <method name="set_theme_item"> + <return type="void"> + </return> + <argument index="0" name="data_type" type="int" enum="Theme.DataType"> + </argument> + <argument index="1" name="name" type="StringName"> + </argument> + <argument index="2" name="node_type" type="StringName"> + </argument> + <argument index="3" name="value" type="Variant"> + </argument> + <description> + Sets the theme item of [code]data_type[/code] to [code]value[/code] at [code]name[/code] in [code]node_type[/code]. + Does nothing if the [code]value[/code] type does not match [code]data_type[/code]. + Creates [code]node_type[/code] if the theme does not have it. </description> </method> </methods> @@ -430,5 +609,26 @@ </member> </members> <constants> + <constant name="DATA_TYPE_COLOR" value="0" enum="DataType"> + Theme's [Color] item type. + </constant> + <constant name="DATA_TYPE_CONSTANT" value="1" enum="DataType"> + Theme's constant item type. + </constant> + <constant name="DATA_TYPE_FONT" value="2" enum="DataType"> + Theme's [Font] item type. + </constant> + <constant name="DATA_TYPE_FONT_SIZE" value="3" enum="DataType"> + Theme's font size item type. + </constant> + <constant name="DATA_TYPE_ICON" value="4" enum="DataType"> + Theme's icon [Texture2D] item type. + </constant> + <constant name="DATA_TYPE_STYLEBOX" value="5" enum="DataType"> + Theme's [StyleBox] item type. + </constant> + <constant name="DATA_TYPE_MAX" value="6" enum="DataType"> + Maximum value for the DataType enum. + </constant> </constants> </class> diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml index 7ed8ad6d4a..205b342ba8 100644 --- a/doc/classes/TileMap.xml +++ b/doc/classes/TileMap.xml @@ -174,7 +174,7 @@ Overriding this method also overrides it internally, allowing custom logic to be implemented when tiles are placed/removed: [codeblocks] [gdscript] - func set_cell(x, y, tile, flip_x=false, flip_y=false, transpose=false, autotile_coord=Vector2()) + func set_cell(x, y, tile, flip_x=false, flip_y=false, transpose=false, autotile_coord=Vector2()): # Write your custom logic here. # To call the default method: .set_cell(x, y, tile, flip_x, flip_y, transpose, autotile_coord) diff --git a/doc/classes/Timer.xml b/doc/classes/Timer.xml index 5265e75429..807d8033c1 100644 --- a/doc/classes/Timer.xml +++ b/doc/classes/Timer.xml @@ -5,7 +5,7 @@ </brief_description> <description> Counts down a specified interval and emits a signal on reaching 0. Can be set to repeat or "one-shot" mode. - [b]Note:[/b] To create an one-shot timer without instantiating a node, use [method SceneTree.create_timer]. + [b]Note:[/b] To create a one-shot timer without instantiating a node, use [method SceneTree.create_timer]. </description> <tutorials> <link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link> diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml index fd157e5eb9..add23c2ce6 100644 --- a/doc/classes/TreeItem.xml +++ b/doc/classes/TreeItem.xml @@ -741,6 +741,12 @@ Sets the given column's tooltip text. </description> </method> + <method name="uncollapse_tree"> + <return type="void"> + </return> + <description> + </description> + </method> </methods> <members> <member name="collapsed" type="bool" setter="set_collapsed" getter="is_collapsed"> diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml index b32bb1e2d9..00cca40093 100644 --- a/doc/classes/Tween.xml +++ b/doc/classes/Tween.xml @@ -23,7 +23,7 @@ tween.Start(); [/csharp] [/codeblocks] - Many methods require a property name, such as [code]"position"[/code] above. You can find the correct property name by hovering over the property in the Inspector. You can also provide the components of a property directly by using [code]"property:component"[/code] (eg. [code]position:x[/code]), where it would only apply to that particular component. + Many methods require a property name, such as [code]"position"[/code] above. You can find the correct property name by hovering over the property in the Inspector. You can also provide the components of a property directly by using [code]"property:component"[/code] (e.g. [code]position:x[/code]), where it would only apply to that particular component. Many of the methods accept [code]trans_type[/code] and [code]ease_type[/code]. The first accepts an [enum TransitionType] constant, and refers to the way the timing of the animation is handled (see [url=https://easings.net/]easings.net[/url] for some examples). The second accepts an [enum EaseType] constant, and controls where the [code]trans_type[/code] is applied to the interpolation (in the beginning, the end, or both). If you don't know which transition and easing to pick, you can try different [enum TransitionType] constants with [constant EASE_IN_OUT], and use the one that looks best. [url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/tween_cheatsheet.png]Tween easing and transition types cheatsheet[/url] </description> diff --git a/doc/classes/UndoRedo.xml b/doc/classes/UndoRedo.xml index a0330de4fa..aba6183124 100644 --- a/doc/classes/UndoRedo.xml +++ b/doc/classes/UndoRedo.xml @@ -186,7 +186,7 @@ <return type="int"> </return> <description> - Return how many element are in the history. + Return how many elements are in the history. </description> </method> <method name="get_version" qualifiers="const"> diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index 8120ae539e..471d21374d 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -80,9 +80,9 @@ </return> <description> Returns the viewport's texture. - [b]Note:[/b] Due to the way OpenGL works, the resulting [ViewportTexture] is flipped vertically. You can use [method Image.flip_y] on the result of [method Texture2D.get_data] to flip it back, for example: + [b]Note:[/b] Due to the way OpenGL works, the resulting [ViewportTexture] is flipped vertically. You can use [method Image.flip_y] on the result of [method Texture2D.get_image] to flip it back, for example: [codeblock] - var img = get_viewport().get_texture().get_data() + var img = get_viewport().get_texture().get_image() img.flip_y() [/codeblock] </description> diff --git a/doc/classes/VisualShaderNodeComment.xml b/doc/classes/VisualShaderNodeComment.xml new file mode 100644 index 0000000000..8970e2fabb --- /dev/null +++ b/doc/classes/VisualShaderNodeComment.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualShaderNodeComment" inherits="VisualShaderNodeResizableBase" version="4.0"> + <brief_description> + A comment node to be placed on visual shader graph. + </brief_description> + <description> + A resizable rectangular area with changeable [member title] and [member description] used for better organizing of other visual shader nodes. + </description> + <tutorials> + </tutorials> + <methods> + </methods> + <members> + <member name="description" type="String" setter="set_description" getter="get_description" default=""""> + An additional description which placed below the title. + </member> + <member name="title" type="String" setter="set_title" getter="get_title" default=""Comment""> + A title of the node. + </member> + </members> + <constants> + </constants> +</class> diff --git a/doc/classes/VisualShaderNodeCustom.xml b/doc/classes/VisualShaderNodeCustom.xml index 59b501660a..17fc2f8c4d 100644 --- a/doc/classes/VisualShaderNodeCustom.xml +++ b/doc/classes/VisualShaderNodeCustom.xml @@ -20,7 +20,7 @@ <return type="String"> </return> <description> - Override this method to define the path to the associated custom node in the Visual Shader Editor's members dialog. The path may looks like [code]"MyGame/MyFunctions/Noise"[/code]. + Override this method to define the path to the associated custom node in the Visual Shader Editor's members dialog. The path may look like [code]"MyGame/MyFunctions/Noise"[/code]. Defining this method is [b]optional[/b]. If not overridden, the node will be filed under the "Addons" category. </description> </method> diff --git a/doc/classes/VisualShaderNodeDeterminant.xml b/doc/classes/VisualShaderNodeDeterminant.xml index 72be31872d..6b042f6172 100644 --- a/doc/classes/VisualShaderNodeDeterminant.xml +++ b/doc/classes/VisualShaderNodeDeterminant.xml @@ -4,7 +4,7 @@ Calculates the determinant of a [Transform] within the visual shader graph. </brief_description> <description> - Translates to [code]deteminant(x)[/code] in the shader language. + Translates to [code]determinant(x)[/code] in the shader language. </description> <tutorials> </tutorials> diff --git a/doc/classes/VisualShaderNodeExpression.xml b/doc/classes/VisualShaderNodeExpression.xml index f571edaab3..c2cbf41f45 100644 --- a/doc/classes/VisualShaderNodeExpression.xml +++ b/doc/classes/VisualShaderNodeExpression.xml @@ -5,7 +5,7 @@ </brief_description> <description> Custom Godot Shading Language expression, with a custom amount of input and output ports. - The provided code is directly injected into the graph's matching shader function ([code]vertex[/code], [code]fragment[/code], or [code]light[/code]), so it cannot be used to to declare functions, varyings, uniforms, or global constants. See [VisualShaderNodeGlobalExpression] for such global definitions. + The provided code is directly injected into the graph's matching shader function ([code]vertex[/code], [code]fragment[/code], or [code]light[/code]), so it cannot be used to declare functions, varyings, uniforms, or global constants. See [VisualShaderNodeGlobalExpression] for such global definitions. </description> <tutorials> </tutorials> diff --git a/doc/classes/VisualShaderNodeFaceForward.xml b/doc/classes/VisualShaderNodeFaceForward.xml index 5ef08ea8c2..48f84e5495 100644 --- a/doc/classes/VisualShaderNodeFaceForward.xml +++ b/doc/classes/VisualShaderNodeFaceForward.xml @@ -4,7 +4,7 @@ Returns the vector that points in the same direction as a reference vector within the visual shader graph. </brief_description> <description> - Translates to [code]faceforward(N, I, Nref)[/code] in the shader language. The function has three vector parameters: [code]N[/code], the vector to orient, [code]I[/code], the incident vector, and [code]Nref[/code], the reference vector. If the dot product of [code]I[/code] and [code]Nref[/code] is smaller than zero the return value is [code]N[/code]. Otherwise [code]-N[/code] is returned. + Translates to [code]faceforward(N, I, Nref)[/code] in the shader language. The function has three vector parameters: [code]N[/code], the vector to orient, [code]I[/code], the incident vector, and [code]Nref[/code], the reference vector. If the dot product of [code]I[/code] and [code]Nref[/code] is smaller than zero the return value is [code]N[/code]. Otherwise, [code]-N[/code] is returned. </description> <tutorials> </tutorials> diff --git a/doc/classes/VisualShaderNodeGroupBase.xml b/doc/classes/VisualShaderNodeGroupBase.xml index afa14c776e..be3f7f173d 100644 --- a/doc/classes/VisualShaderNodeGroupBase.xml +++ b/doc/classes/VisualShaderNodeGroupBase.xml @@ -74,7 +74,7 @@ <return type="String"> </return> <description> - Returns a [String] description of the input ports as as colon-separated list using the format [code]id,type,name;[/code] (see [method add_input_port]). + Returns a [String] description of the input ports as a colon-separated list using the format [code]id,type,name;[/code] (see [method add_input_port]). </description> </method> <method name="get_output_port_count" qualifiers="const"> @@ -88,7 +88,7 @@ <return type="String"> </return> <description> - Returns a [String] description of the output ports as as colon-separated list using the format [code]id,type,name;[/code] (see [method add_output_port]). + Returns a [String] description of the output ports as a colon-separated list using the format [code]id,type,name;[/code] (see [method add_output_port]). </description> </method> <method name="has_input_port" qualifiers="const"> diff --git a/doc/classes/VisualShaderNodeIf.xml b/doc/classes/VisualShaderNodeIf.xml index ad0b21a370..418999863b 100644 --- a/doc/classes/VisualShaderNodeIf.xml +++ b/doc/classes/VisualShaderNodeIf.xml @@ -4,7 +4,7 @@ Compares two floating-point numbers in order to return a required vector within the visual shader graph. </brief_description> <description> - First two ports are scalar floatin-point numbers to compare, third is tolerance comparison amount and last three ports represents a vectors returned if [code]a == b[/code], [code]a > b[/code] and [code]a < b[/code] respectively. + First two ports are scalar floating-point numbers to compare, third is tolerance comparison amount and last three ports represents a vectors returned if [code]a == b[/code], [code]a > b[/code] and [code]a < b[/code] respectively. </description> <tutorials> </tutorials> diff --git a/doc/classes/VisualShaderNodeInput.xml b/doc/classes/VisualShaderNodeInput.xml index 8e819b011c..067f78dffe 100644 --- a/doc/classes/VisualShaderNodeInput.xml +++ b/doc/classes/VisualShaderNodeInput.xml @@ -14,7 +14,7 @@ <return type="String"> </return> <description> - Returns a translated name of the current constant in the Godot Shader Language. eg. [code]"ALBEDO"[/code] if the [member input_name] equal to [code]"albedo"[/code]. + Returns a translated name of the current constant in the Godot Shader Language. E.g. [code]"ALBEDO"[/code] if the [member input_name] equal to [code]"albedo"[/code]. </description> </method> </methods> diff --git a/doc/classes/VisualShaderNodeSDFToScreenUV.xml b/doc/classes/VisualShaderNodeSDFToScreenUV.xml index ea04180095..40fb66e364 100644 --- a/doc/classes/VisualShaderNodeSDFToScreenUV.xml +++ b/doc/classes/VisualShaderNodeSDFToScreenUV.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualShaderNodeSDFToScreenUV" inherits="VisualShaderNode" version="4.0"> <brief_description> - A function to convert a SDF (signed-distance field) to screen UV, to be used within the visual shader graph. + A function to convert an SDF (signed-distance field) to screen UV, to be used within the visual shader graph. </brief_description> <description> Translates to [code]sdf_to_screen_uv(sdf_pos)[/code] in the shader language. diff --git a/doc/classes/VisualShaderNodeScreenUVToSDF.xml b/doc/classes/VisualShaderNodeScreenUVToSDF.xml index 438c8dc67b..2e121ffc54 100644 --- a/doc/classes/VisualShaderNodeScreenUVToSDF.xml +++ b/doc/classes/VisualShaderNodeScreenUVToSDF.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualShaderNodeScreenUVToSDF" inherits="VisualShaderNode" version="4.0"> <brief_description> - A function to convert screen UV to a SDF (signed-distance field), to be used within the visual shader graph. + A function to convert screen UV to an SDF (signed-distance field), to be used within the visual shader graph. </brief_description> <description> Translates to [code]screen_uv_to_sdf(uv)[/code] in the shader language. If the UV port isn't connected, [code]SCREEN_UV[/code] is used instead. diff --git a/doc/classes/VisualShaderNodeSmoothStep.xml b/doc/classes/VisualShaderNodeSmoothStep.xml index fa22d16da8..0ed53a8c26 100644 --- a/doc/classes/VisualShaderNodeSmoothStep.xml +++ b/doc/classes/VisualShaderNodeSmoothStep.xml @@ -5,7 +5,7 @@ </brief_description> <description> Translates to [code]smoothstep(edge0, edge1, x)[/code] in the shader language. - Returns [code]0.0[/code] if [code]x[/code] is smaller than [code]edge0[/code] and [code]1.0[/code] if [code]x[/code] is larger than [code]edge1[/code]. Otherwise the return value is interpolated between [code]0.0[/code] and [code]1.0[/code] using Hermite polynomials. + Returns [code]0.0[/code] if [code]x[/code] is smaller than [code]edge0[/code] and [code]1.0[/code] if [code]x[/code] is larger than [code]edge1[/code]. Otherwise, the return value is interpolated between [code]0.0[/code] and [code]1.0[/code] using Hermite polynomials. </description> <tutorials> </tutorials> diff --git a/doc/classes/VisualShaderNodeTextureSDF.xml b/doc/classes/VisualShaderNodeTextureSDF.xml index 7d3d654bd0..b5c89c2c31 100644 --- a/doc/classes/VisualShaderNodeTextureSDF.xml +++ b/doc/classes/VisualShaderNodeTextureSDF.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualShaderNodeTextureSDF" inherits="VisualShaderNode" version="4.0"> <brief_description> - Performs a SDF (signed-distance field) texture lookup within the visual shader graph. + Performs an SDF (signed-distance field) texture lookup within the visual shader graph. </brief_description> <description> Translates to [code]texture_sdf(sdf_pos)[/code] in the shader language. diff --git a/doc/classes/VisualShaderNodeTextureSDFNormal.xml b/doc/classes/VisualShaderNodeTextureSDFNormal.xml index 5dbf3e545a..25fe1c4b28 100644 --- a/doc/classes/VisualShaderNodeTextureSDFNormal.xml +++ b/doc/classes/VisualShaderNodeTextureSDFNormal.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualShaderNodeTextureSDFNormal" inherits="VisualShaderNode" version="4.0"> <brief_description> - Performs a SDF (signed-distance field) normal texture lookup within the visual shader graph. + Performs an SDF (signed-distance field) normal texture lookup within the visual shader graph. </brief_description> <description> Translates to [code]texture_sdf_normal(sdf_pos)[/code] in the shader language. diff --git a/doc/classes/XRController3D.xml b/doc/classes/XRController3D.xml index a4a86cc22a..5d8c23bd6f 100644 --- a/doc/classes/XRController3D.xml +++ b/doc/classes/XRController3D.xml @@ -62,7 +62,7 @@ <argument index="0" name="button" type="int"> </argument> <description> - Returns [code]true[/code] if the button at index [code]button[/code] is pressed. See [enum JoyButtonList]. + Returns [code]true[/code] if the button at index [code]button[/code] is pressed. See [enum JoyButton]. </description> </method> </methods> diff --git a/doc/classes/XRPositionalTracker.xml b/doc/classes/XRPositionalTracker.xml index 36cd6e2ea0..5274d952fd 100644 --- a/doc/classes/XRPositionalTracker.xml +++ b/doc/classes/XRPositionalTracker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="XRPositionalTracker" inherits="Object" version="4.0"> +<class name="XRPositionalTracker" inherits="Reference" version="4.0"> <brief_description> A tracked object. </brief_description> diff --git a/doc/classes/XRServer.xml b/doc/classes/XRServer.xml index 75a05bef17..d0edf91fed 100644 --- a/doc/classes/XRServer.xml +++ b/doc/classes/XRServer.xml @@ -10,6 +10,24 @@ <link title="VR tutorial index">https://docs.godotengine.org/en/latest/tutorials/vr/index.html</link> </tutorials> <methods> + <method name="add_interface"> + <return type="void"> + </return> + <argument index="0" name="interface" type="XRInterface"> + </argument> + <description> + Registers an [XRInterface] object. + </description> + </method> + <method name="add_tracker"> + <return type="void"> + </return> + <argument index="0" name="tracker" type="XRPositionalTracker"> + </argument> + <description> + Registers a new [XRPositionalTracker] that tracks a spatial location in real space. + </description> + </method> <method name="center_on_hmd"> <return type="void"> </return> @@ -26,6 +44,15 @@ You should call this method after a few seconds have passed. For instance, when the user requests a realignment of the display holding a designated button on a controller for a short period of time, or when implementing a teleport mechanism. </description> </method> + <method name="clear_primary_interface_if"> + <return type="void"> + </return> + <argument index="0" name="interface" type="XRInterface"> + </argument> + <description> + Clears our current primary interface if it is set to the provided interface. + </description> + </method> <method name="find_interface" qualifiers="const"> <return type="XRInterface"> </return> @@ -109,6 +136,24 @@ Returns the number of trackers currently registered. </description> </method> + <method name="remove_interface"> + <return type="void"> + </return> + <argument index="0" name="interface" type="XRInterface"> + </argument> + <description> + Removes this interface. + </description> + </method> + <method name="remove_tracker"> + <return type="void"> + </return> + <argument index="0" name="tracker" type="XRPositionalTracker"> + </argument> + <description> + Removes this positional tracker. + </description> + </method> </methods> <members> <member name="primary_interface" type="XRInterface" setter="set_primary_interface" getter="get_primary_interface"> diff --git a/doc/classes/bool.xml b/doc/classes/bool.xml index 03e8bee7d5..48f336d58c 100644 --- a/doc/classes/bool.xml +++ b/doc/classes/bool.xml @@ -4,7 +4,7 @@ Boolean built-in type. </brief_description> <description> - Boolean is a built-in type. There are two boolean values: [code]true[/code] and [code]false[/code]. You can think of it as an switch with on or off (1 or 0) setting. Booleans are used in programming for logic in condition statements, like [code]if[/code] statements. + Boolean is a built-in type. There are two boolean values: [code]true[/code] and [code]false[/code]. You can think of it as a switch with on or off (1 or 0) setting. Booleans are used in programming for logic in condition statements, like [code]if[/code] statements. Booleans can be directly used in [code]if[/code] statements. The code below demonstrates this on the [code]if can_shoot:[/code] line. You don't need to use [code]== true[/code], you only need [code]if can_shoot:[/code]. Similarly, use [code]if not can_shoot:[/code] rather than [code]== false[/code]. [codeblocks] [gdscript] @@ -49,6 +49,7 @@ [/csharp] [/codeblocks] The following code will set [code]can_shoot[/code] to [code]false[/code] and start a timer. This will prevent player from shooting until the timer runs out. Next [code]can_shoot[/code] will be set to [code]true[/code] again allowing player to shoot once again. + [codeblocks] [gdscript] var _can_shoot = true onready var _cool_down = $CoolDownTimer @@ -131,6 +132,7 @@ <argument index="0" name="right" type="bool"> </argument> <description> + Returns [code]true[/code] if two bools are different, i.e. one is [code]true[/code] and the other is [code]false[/code]. </description> </method> <method name="operator <" qualifiers="operator"> @@ -139,6 +141,7 @@ <argument index="0" name="right" type="bool"> </argument> <description> + Returns [code]true[/code] if left operand is [code]false[/code] and right operand is [code]true[/code]. </description> </method> <method name="operator ==" qualifiers="operator"> @@ -147,6 +150,7 @@ <argument index="0" name="right" type="bool"> </argument> <description> + Returns [code]true[/code] if two bools are equal, i.e. both are [code]true[/code] or both are [code]false[/code]. </description> </method> <method name="operator >" qualifiers="operator"> @@ -155,6 +159,7 @@ <argument index="0" name="right" type="bool"> </argument> <description> + Returns [code]true[/code] if left operand is [code]true[/code] and right operand is [code]false[/code]. </description> </method> </methods> diff --git a/doc/classes/float.xml b/doc/classes/float.xml index 85fe31eec8..11f6d91b05 100644 --- a/doc/classes/float.xml +++ b/doc/classes/float.xml @@ -49,6 +49,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Returns [code]true[/code] if two floats are different from each other. </description> </method> <method name="operator !=" qualifiers="operator"> @@ -57,6 +58,7 @@ <argument index="0" name="right" type="int"> </argument> <description> + Returns [code]true[/code] if the integer has different value than the float. </description> </method> <method name="operator *" qualifiers="operator"> @@ -65,6 +67,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Multiplies two [float]s. </description> </method> <method name="operator *" qualifiers="operator"> @@ -73,6 +76,10 @@ <argument index="0" name="right" type="Vector2"> </argument> <description> + Multiplies each component of the [Vector2] by the given [float]. + [codeblock] + print(2.5 * Vector2(1, 1)) # Vector2(2.5, 2.5) + [/codeblock] </description> </method> <method name="operator *" qualifiers="operator"> @@ -81,6 +88,10 @@ <argument index="0" name="right" type="Vector2i"> </argument> <description> + Multiplies each component of the [Vector2i] by the given [float]. + [codeblock] + print(2.0 * Vector2i(1, 1)) # Vector2i(2.0, 2.0) + [/codeblock] </description> </method> <method name="operator *" qualifiers="operator"> @@ -89,6 +100,7 @@ <argument index="0" name="right" type="Vector3"> </argument> <description> + Multiplies each component of the [Vector3] by the given [float]. </description> </method> <method name="operator *" qualifiers="operator"> @@ -97,6 +109,7 @@ <argument index="0" name="right" type="Vector3i"> </argument> <description> + Multiplies each component of the [Vector3i] by the given [float]. </description> </method> <method name="operator *" qualifiers="operator"> @@ -105,6 +118,7 @@ <argument index="0" name="right" type="Quat"> </argument> <description> + Multiplies each component of the [Quat] by the given [float]. </description> </method> <method name="operator *" qualifiers="operator"> @@ -113,6 +127,10 @@ <argument index="0" name="right" type="Color"> </argument> <description> + Multiplies each component of the [Color] by the given [float]. + [codeblock] + print(1.5 * Color(0.5, 0.5, 0.5)) # Color(0.75, 0.75, 0.75) + [/codeblock] </description> </method> <method name="operator *" qualifiers="operator"> @@ -121,12 +139,17 @@ <argument index="0" name="right" type="int"> </argument> <description> + Multiplies a [float] and an [int]. The result is a [float]. </description> </method> <method name="operator +" qualifiers="operator"> <return type="float"> </return> <description> + Unary plus operator. Doesn't have any effect. + [codeblock] + var a = +2.5 # a is 2.5. + [/codeblock] </description> </method> <method name="operator +" qualifiers="operator"> @@ -135,6 +158,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Adds two floats. </description> </method> <method name="operator +" qualifiers="operator"> @@ -143,12 +167,18 @@ <argument index="0" name="right" type="int"> </argument> <description> + Adds a [float] and an [int]. The result is a [float]. </description> </method> <method name="operator -" qualifiers="operator"> <return type="float"> </return> <description> + Unary minus operator. Negates the number. + [codeblock] + var a = -2.5 # a is -2.5. + print(-a) # 2.5 + [/codeblock] </description> </method> <method name="operator -" qualifiers="operator"> @@ -157,6 +187,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Subtracts a float from a float. </description> </method> <method name="operator -" qualifiers="operator"> @@ -165,6 +196,7 @@ <argument index="0" name="right" type="int"> </argument> <description> + Subtracts an [int] from a [float]. The result is a [float]. </description> </method> <method name="operator /" qualifiers="operator"> @@ -173,6 +205,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Divides two floats. </description> </method> <method name="operator /" qualifiers="operator"> @@ -181,6 +214,7 @@ <argument index="0" name="right" type="int"> </argument> <description> + Divides a [float] by an [int]. The result is a [float]. </description> </method> <method name="operator <" qualifiers="operator"> @@ -189,6 +223,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Returns [code]true[/code] the left float is less than the right one. </description> </method> <method name="operator <" qualifiers="operator"> @@ -197,6 +232,7 @@ <argument index="0" name="right" type="int"> </argument> <description> + Returns [code]true[/code] if this [float] is less than the given [int]. </description> </method> <method name="operator <=" qualifiers="operator"> @@ -205,6 +241,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Returns [code]true[/code] the left integer is less than or equal to the right one. </description> </method> <method name="operator <=" qualifiers="operator"> @@ -213,6 +250,7 @@ <argument index="0" name="right" type="int"> </argument> <description> + Returns [code]true[/code] if this [float] is less than or equal to the given [int]. </description> </method> <method name="operator ==" qualifiers="operator"> @@ -221,6 +259,8 @@ <argument index="0" name="right" type="float"> </argument> <description> + Returns [code]true[/code] if both floats are exactly equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method @GlobalScope.is_equal_approx] or [method @GlobalScope.is_zero_approx] instead, which are more reliable. </description> </method> <method name="operator ==" qualifiers="operator"> @@ -229,6 +269,7 @@ <argument index="0" name="right" type="int"> </argument> <description> + Returns [code]true[/code] if the [float] and the given [int] are equal. </description> </method> <method name="operator >" qualifiers="operator"> @@ -237,6 +278,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Returns [code]true[/code] the left float is greater than the right one. </description> </method> <method name="operator >" qualifiers="operator"> @@ -245,6 +287,7 @@ <argument index="0" name="right" type="int"> </argument> <description> + Returns [code]true[/code] if this [float] is greater than the given [int]. </description> </method> <method name="operator >=" qualifiers="operator"> @@ -253,6 +296,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Returns [code]true[/code] the left float is greater than or equal to the right one. </description> </method> <method name="operator >=" qualifiers="operator"> @@ -261,6 +305,7 @@ <argument index="0" name="right" type="int"> </argument> <description> + Returns [code]true[/code] if this [float] is greater than or equal to the given [int]. </description> </method> </methods> diff --git a/doc/classes/int.xml b/doc/classes/int.xml index a63c509937..119cdf8eeb 100644 --- a/doc/classes/int.xml +++ b/doc/classes/int.xml @@ -79,6 +79,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Returns [code]true[/code] if operands are different from each other. </description> </method> <method name="operator !=" qualifiers="operator"> @@ -87,6 +88,7 @@ <argument index="0" name="right" type="int"> </argument> <description> + Returns [code]true[/code] if operands are different from each other. </description> </method> <method name="operator %" qualifiers="operator"> @@ -95,6 +97,12 @@ <argument index="0" name="right" type="int"> </argument> <description> + Returns the result of the modulo operator for two integers, i.e. the remainder after dividing both numbers. + [codeblock] + print(5 % 2) # 1 + print(12 % 4) # 0 + print(12 % 2) # 2 + [/codeblock] </description> </method> <method name="operator &" qualifiers="operator"> @@ -103,6 +111,18 @@ <argument index="0" name="right" type="int"> </argument> <description> + Returns the result of bitwise [code]AND[/code] operation for two integers. + [codeblock] + print(3 & 1) # 1 + print(11 & 3) # 3 + [/codeblock] + It's useful to retrieve binary flags from a variable. + [codeblock] + var flags = 5 + # Do something if the first bit is enabled. + if flags & 1: + do_stuff() + [/codeblock] </description> </method> <method name="operator *" qualifiers="operator"> @@ -111,6 +131,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Multiplies an [int] and a [float]. The result is a [float]. </description> </method> <method name="operator *" qualifiers="operator"> @@ -119,6 +140,7 @@ <argument index="0" name="right" type="int"> </argument> <description> + Multiplies two [int]s. </description> </method> <method name="operator *" qualifiers="operator"> @@ -127,6 +149,10 @@ <argument index="0" name="right" type="Vector2"> </argument> <description> + Multiplies each component of the vector by the given integer. + [codeblock] + print(2 * Vector2(1, 1)) # Vector2(2, 2) + [/codeblock] </description> </method> <method name="operator *" qualifiers="operator"> @@ -135,6 +161,7 @@ <argument index="0" name="right" type="Vector2i"> </argument> <description> + Multiplies each component of the integer vector by the given integer. </description> </method> <method name="operator *" qualifiers="operator"> @@ -143,6 +170,7 @@ <argument index="0" name="right" type="Vector3"> </argument> <description> + Multiplies each component of the vector by the given integer. </description> </method> <method name="operator *" qualifiers="operator"> @@ -151,6 +179,7 @@ <argument index="0" name="right" type="Vector3i"> </argument> <description> + Multiplies each component of the integer vector by the given integer. </description> </method> <method name="operator *" qualifiers="operator"> @@ -159,6 +188,7 @@ <argument index="0" name="right" type="Quat"> </argument> <description> + Multiplies each component of the quaternion by the given integer. </description> </method> <method name="operator *" qualifiers="operator"> @@ -167,12 +197,20 @@ <argument index="0" name="right" type="Color"> </argument> <description> + Multiplies each component of the color by the given integer. + [codeblock] + print(2 * Color(0.5, 0.5, 0.5)) # Color(1, 1, 1) + [/codeblock] </description> </method> <method name="operator +" qualifiers="operator"> <return type="int"> </return> <description> + Unary plus operator. Doesn't have any effect. + [codeblock] + var a = +1 # a is 1. + [/codeblock] </description> </method> <method name="operator +" qualifiers="operator"> @@ -181,6 +219,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Adds an [int] to a [float]. The result is a [float]. </description> </method> <method name="operator +" qualifiers="operator"> @@ -189,12 +228,18 @@ <argument index="0" name="right" type="int"> </argument> <description> + Adds two integers. </description> </method> <method name="operator -" qualifiers="operator"> <return type="int"> </return> <description> + Unary minus operator. Negates the number. + [codeblock] + var a = -1 # a is -1. + print(-a) # 1 + [/codeblock] </description> </method> <method name="operator -" qualifiers="operator"> @@ -203,6 +248,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Subtracts a [float] from an [int]. The result is a [float]. </description> </method> <method name="operator -" qualifiers="operator"> @@ -211,6 +257,7 @@ <argument index="0" name="right" type="int"> </argument> <description> + Subtracts two integers. </description> </method> <method name="operator /" qualifiers="operator"> @@ -219,6 +266,10 @@ <argument index="0" name="right" type="float"> </argument> <description> + Divides an [int] by a [float]. The result is a [float]. + [codeblock] + print(10 / 3.0) # 3.333... + [/codeblock] </description> </method> <method name="operator /" qualifiers="operator"> @@ -227,6 +278,11 @@ <argument index="0" name="right" type="int"> </argument> <description> + Divides two integers. The decimal part of the result is discarded (truncated). + [codeblock] + print(10 / 2) # 5 + print(10 / 3) # 3 + [/codeblock] </description> </method> <method name="operator <" qualifiers="operator"> @@ -235,6 +291,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Returns [code]true[/code] if this [int] is less than the given [float]. </description> </method> <method name="operator <" qualifiers="operator"> @@ -243,6 +300,7 @@ <argument index="0" name="right" type="int"> </argument> <description> + Returns [code]true[/code] the left integer is less than the right one. </description> </method> <method name="operator <<" qualifiers="operator"> @@ -251,6 +309,11 @@ <argument index="0" name="right" type="int"> </argument> <description> + Performs bitwise shift left operation on the integer. Effectively the same as multiplying by a power of 2. + [codeblock] + print(10 << 1) # 20 + print(10 << 4) # 160 + [/codeblock] </description> </method> <method name="operator <=" qualifiers="operator"> @@ -259,6 +322,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Returns [code]true[/code] if this [int] is less than or equal to the given [float]. </description> </method> <method name="operator <=" qualifiers="operator"> @@ -267,6 +331,7 @@ <argument index="0" name="right" type="int"> </argument> <description> + Returns [code]true[/code] the left integer is less than or equal to the right one. </description> </method> <method name="operator ==" qualifiers="operator"> @@ -275,6 +340,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Returns [code]true[/code] if the integer is equal to the given [float]. </description> </method> <method name="operator ==" qualifiers="operator"> @@ -283,6 +349,7 @@ <argument index="0" name="right" type="int"> </argument> <description> + Returns [code]true[/code] if both integers are equal. </description> </method> <method name="operator >" qualifiers="operator"> @@ -291,6 +358,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Returns [code]true[/code] if this [int] is greater than the given [float]. </description> </method> <method name="operator >" qualifiers="operator"> @@ -299,6 +367,7 @@ <argument index="0" name="right" type="int"> </argument> <description> + Returns [code]true[/code] the left integer is greater than the right one. </description> </method> <method name="operator >=" qualifiers="operator"> @@ -307,6 +376,7 @@ <argument index="0" name="right" type="float"> </argument> <description> + Returns [code]true[/code] if this [int] is greater than or equal to the given [float]. </description> </method> <method name="operator >=" qualifiers="operator"> @@ -315,6 +385,7 @@ <argument index="0" name="right" type="int"> </argument> <description> + Returns [code]true[/code] the left integer is greater than or equal to the right one. </description> </method> <method name="operator >>" qualifiers="operator"> @@ -323,6 +394,11 @@ <argument index="0" name="right" type="int"> </argument> <description> + Performs bitwise shift right operation on the integer. Effectively the same as dividing by a power of 2. + [codeblock] + print(10 >> 1) # 5 + print(10 >> 2) # 2 + [/codeblock] </description> </method> <method name="operator ^" qualifiers="operator"> @@ -331,6 +407,11 @@ <argument index="0" name="right" type="int"> </argument> <description> + Returns the result of bitwise [code]XOR[/code] operation for two integers. + [codeblock] + print(5 ^ 1) # 4 + print(4 ^ 7) # 3 + [/codeblock] </description> </method> <method name="operator |" qualifiers="operator"> @@ -339,12 +420,29 @@ <argument index="0" name="right" type="int"> </argument> <description> + Returns the result of bitwise [code]OR[/code] operation for two integers. + [codeblock] + print(2 | 4) # 6 + print(1 | 3) # 3 + [/codeblock] + It's useful to store binary flags in a variable. + [codeblock] + var flags = 0 + # Turn first and third bit on. + flags |= 1 + flags |= 4 + [/codeblock] </description> </method> <method name="operator ~" qualifiers="operator"> <return type="int"> </return> <description> + Returns the result of bitwise [code]NOT[/code] operation for the integer. It's effectively equal to [code]-int + 1[/code]. + [codeblock] + print(~4) # -3 + print(~7) # -6 + [/codeblock] </description> </method> </methods> diff --git a/doc/translations/classes.pot b/doc/translations/classes.pot index 4cd89924ee..d14b0d9b1f 100644 --- a/doc/translations/classes.pot +++ b/doc/translations/classes.pot @@ -25583,7 +25583,7 @@ msgstr "" #: doc/classes/Input.xml:99 msgid "" "Returns the current value of the joypad axis at given index (see [enum " -"JoyAxisList])." +"JoyAxis])." msgstr "" #: doc/classes/Input.xml:108 @@ -25592,7 +25592,7 @@ msgstr "" #: doc/classes/Input.xml:117 msgid "" -"Receives a [enum JoyAxisList] axis and returns its equivalent name as a " +"Receives a [enum JoyAxis] axis and returns its equivalent name as a " "string." msgstr "" @@ -25602,7 +25602,7 @@ msgstr "" #: doc/classes/Input.xml:135 msgid "" -"Receives a gamepad button from [enum JoyButtonList] and returns its " +"Receives a gamepad button from [enum JoyButton] and returns its " "equivalent name as a string." msgstr "" @@ -25677,7 +25677,7 @@ msgstr "" #: doc/classes/Input.xml:238 msgid "" "Returns [code]true[/code] if you are pressing the joypad button (see [enum " -"JoyButtonList])." +"JoyButton])." msgstr "" #: doc/classes/Input.xml:247 @@ -26077,7 +26077,7 @@ msgid "" msgstr "" #: doc/classes/InputEventJoypadButton.xml:16 -msgid "Button identifier. One of the [enum JoyButtonList] button constants." +msgid "Button identifier. One of the [enum JoyButton] button constants." msgstr "" #: doc/classes/InputEventJoypadButton.xml:19 @@ -26105,7 +26105,7 @@ msgid "" msgstr "" #: doc/classes/InputEventJoypadMotion.xml:16 -msgid "Axis identifier. Use one of the [enum JoyAxisList] axis constants." +msgid "Axis identifier. Use one of the [enum JoyAxis] axis constants." msgstr "" #: doc/classes/InputEventJoypadMotion.xml:19 @@ -60259,7 +60259,7 @@ msgstr "" #: doc/classes/XRController3D.xml:65 msgid "" "Returns [code]true[/code] if the button at index [code]button[/code] is " -"pressed. See [enum JoyButtonList]." +"pressed. See [enum JoyButton]." msgstr "" #: doc/classes/XRController3D.xml:71 diff --git a/doc/translations/fr.po b/doc/translations/fr.po index c4fe08e67b..f3e26ebc61 100644 --- a/doc/translations/fr.po +++ b/doc/translations/fr.po @@ -25946,7 +25946,7 @@ msgstr "" #: doc/classes/Input.xml:99 msgid "" "Returns the current value of the joypad axis at given index (see [enum " -"JoyAxisList])." +"JoyAxis])." msgstr "" #: doc/classes/Input.xml:108 @@ -25955,7 +25955,7 @@ msgstr "" #: doc/classes/Input.xml:117 msgid "" -"Receives a [enum JoyAxisList] axis and returns its equivalent name as a " +"Receives a [enum JoyAxis] axis and returns its equivalent name as a " "string." msgstr "" @@ -25965,7 +25965,7 @@ msgstr "" #: doc/classes/Input.xml:135 msgid "" -"Receives a gamepad button from [enum JoyButtonList] and returns its " +"Receives a gamepad button from [enum JoyButton] and returns its " "equivalent name as a string." msgstr "" @@ -26041,7 +26041,7 @@ msgstr "" #, fuzzy msgid "" "Returns [code]true[/code] if you are pressing the joypad button (see [enum " -"JoyButtonList])." +"JoyButton])." msgstr "" "Retourne [code]true[/code] (vrai) si la chaîne de caractères finit par la " "chaîne de caractères donnée." @@ -26443,7 +26443,7 @@ msgid "" msgstr "" #: doc/classes/InputEventJoypadButton.xml:16 -msgid "Button identifier. One of the [enum JoyButtonList] button constants." +msgid "Button identifier. One of the [enum JoyButton] button constants." msgstr "" #: doc/classes/InputEventJoypadButton.xml:19 @@ -26471,7 +26471,7 @@ msgid "" msgstr "" #: doc/classes/InputEventJoypadMotion.xml:16 -msgid "Axis identifier. Use one of the [enum JoyAxisList] axis constants." +msgid "Axis identifier. Use one of the [enum JoyAxis] axis constants." msgstr "" #: doc/classes/InputEventJoypadMotion.xml:19 @@ -60738,7 +60738,7 @@ msgstr "" #, fuzzy msgid "" "Returns [code]true[/code] if the button at index [code]button[/code] is " -"pressed. See [enum JoyButtonList]." +"pressed. See [enum JoyButton]." msgstr "" "Renvoie [code]true[/code] (vrai) si [code]s[/code] vaut zéro ou quasiment " "zéro." diff --git a/drivers/png/resource_saver_png.cpp b/drivers/png/resource_saver_png.cpp index f47fc403cc..b737a287d1 100644 --- a/drivers/png/resource_saver_png.cpp +++ b/drivers/png/resource_saver_png.cpp @@ -41,7 +41,7 @@ Error ResourceSaverPNG::save(const String &p_path, const RES &p_resource, uint32 ERR_FAIL_COND_V_MSG(!texture.is_valid(), ERR_INVALID_PARAMETER, "Can't save invalid texture as PNG."); ERR_FAIL_COND_V_MSG(!texture->get_width(), ERR_INVALID_PARAMETER, "Can't save empty texture as PNG."); - Ref<Image> img = texture->get_data(); + Ref<Image> img = texture->get_image(); Error err = save_image(p_path, img); diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp index eda929850c..34ef6f3ce6 100644 --- a/drivers/unix/dir_access_unix.cpp +++ b/drivers/unix/dir_access_unix.cpp @@ -102,6 +102,28 @@ bool DirAccessUnix::dir_exists(String p_dir) { return (success && S_ISDIR(flags.st_mode)); } +bool DirAccessUnix::is_readable(String p_dir) { + GLOBAL_LOCK_FUNCTION + + if (p_dir.is_rel_path()) { + p_dir = get_current_dir().plus_file(p_dir); + } + + p_dir = fix_path(p_dir); + return (access(p_dir.utf8().get_data(), R_OK) == 0); +} + +bool DirAccessUnix::is_writable(String p_dir) { + GLOBAL_LOCK_FUNCTION + + if (p_dir.is_rel_path()) { + p_dir = get_current_dir().plus_file(p_dir); + } + + p_dir = fix_path(p_dir); + return (access(p_dir.utf8().get_data(), W_OK) == 0); +} + uint64_t DirAccessUnix::get_modified_time(String p_file) { if (p_file.is_rel_path()) { p_file = current_dir.plus_file(p_file); diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h index b70df1ca02..54f4a5c312 100644 --- a/drivers/unix/dir_access_unix.h +++ b/drivers/unix/dir_access_unix.h @@ -71,6 +71,8 @@ public: 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 uint64_t get_modified_time(String p_file); diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 469d80368d..09e2b4546a 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -1486,7 +1486,7 @@ Error RenderingDeviceVulkan::_staging_buffer_allocate(uint32_t p_amount, uint32_ // possible in a single frame if (staging_buffer_blocks[staging_buffer_current].frame_used == frames_drawn) { //guess we did.. ok, let's see if we can insert a new block.. - if (staging_buffer_blocks.size() * staging_buffer_block_size < staging_buffer_max_size) { + if ((uint64_t)staging_buffer_blocks.size() * staging_buffer_block_size < staging_buffer_max_size) { //we can, so we are safe Error err = _insert_staging_block(); if (err) { @@ -1530,7 +1530,7 @@ Error RenderingDeviceVulkan::_staging_buffer_allocate(uint32_t p_amount, uint32_ staging_buffer_blocks.write[staging_buffer_current].fill_amount = 0; } else if (staging_buffer_blocks[staging_buffer_current].frame_used > frames_drawn - frame_count) { //this block may still be in use, let's not touch it unless we have to, so.. can we create a new one? - if (staging_buffer_blocks.size() * staging_buffer_block_size < staging_buffer_max_size) { + if ((uint64_t)staging_buffer_blocks.size() * staging_buffer_block_size < staging_buffer_max_size) { //we are still allowed to create a new block, so let's do that and insert it for current pos Error err = _insert_staging_block(); if (err) { @@ -2566,7 +2566,7 @@ Vector<uint8_t> RenderingDeviceVulkan::_texture_get_data_from_image(Texture *tex for (uint32_t y = 0; y < height; y++) { const uint8_t *rptr = slice_read_ptr + y * layout.rowPitch; uint8_t *wptr = write_ptr + y * pixel_size * width; - copymem(wptr, rptr, pixel_size * width); + copymem(wptr, rptr, (uint64_t)pixel_size * width); } } } @@ -7834,6 +7834,18 @@ void RenderingDeviceVulkan::_flush(bool p_current_frame) { } void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_device) { + // get our device capabilities + { + 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(); + } + context = p_context; device = p_context->get_device(); if (p_local_device) { @@ -8253,6 +8265,7 @@ RenderingDevice *RenderingDeviceVulkan::create_local_device() { } RenderingDeviceVulkan::RenderingDeviceVulkan() { + device_capabilities.device_family = DEVICE_VULKAN; } RenderingDeviceVulkan::~RenderingDeviceVulkan() { diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index 69517b17ba..504e63392f 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -34,6 +34,7 @@ #include "core/config/project_settings.h" #include "core/string/ustring.h" #include "core/version.h" +#include "servers/rendering/rendering_device.h" #include "vk_enum_string_helper.h" @@ -163,6 +164,35 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::_debug_messenger_callback( return VK_FALSE; } +VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::_debug_report_callback( + VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, + size_t location, + int32_t messageCode, + const char *pLayerPrefix, + const char *pMessage, + void *pUserData) { + String debugMessage = String("Vulkan Debug Report: object - ") + + String::num_int64(object) + "\n" + pMessage; + + switch (flags) { + case VK_DEBUG_REPORT_DEBUG_BIT_EXT: + case VK_DEBUG_REPORT_INFORMATION_BIT_EXT: + print_line(debugMessage); + break; + case VK_DEBUG_REPORT_WARNING_BIT_EXT: + case VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT: + WARN_PRINT(debugMessage); + break; + case VK_DEBUG_REPORT_ERROR_BIT_EXT: + ERR_PRINT(debugMessage); + break; + } + + return VK_FALSE; +} + VkBool32 VulkanContext::_check_layers(uint32_t check_count, const char **check_names, uint32_t layer_count, VkLayerProperties *layers) { for (uint32_t i = 0; i < check_count; i++) { VkBool32 found = 0; @@ -234,12 +264,46 @@ Error VulkanContext::_create_validation_layers() { return OK; } +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. + _vkEnumerateInstanceVersion func = (_vkEnumerateInstanceVersion)vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"); + if (func != nullptr) { + uint32_t api_version; + VkResult res = func(&api_version); + if (res == VK_SUCCESS) { + vulkan_major = VK_VERSION_MAJOR(api_version); + vulkan_minor = VK_VERSION_MINOR(api_version); + uint32_t vulkan_patch = VK_VERSION_PATCH(api_version); + + print_line("Vulkan API " + itos(vulkan_major) + "." + itos(vulkan_minor) + "." + itos(vulkan_patch)); + } 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 + ERR_FAIL_V(ERR_CANT_CREATE); + } + } else { + print_line("vkEnumerateInstanceVersion not available, assuming Vulkan 1.0"); + } + + // we don't go above 1.2 + if ((vulkan_major > 1) || (vulkan_major == 1 && vulkan_minor > 2)) { + vulkan_major = 1; + vulkan_minor = 2; + } + + return OK; +} + Error VulkanContext::_initialize_extensions() { uint32_t instance_extension_count = 0; enabled_extension_count = 0; enabled_layer_count = 0; enabled_debug_utils = false; + enabled_debug_report = false; /* Look for instance extensions */ VkBool32 surfaceExtFound = 0; VkBool32 platformSurfaceExtFound = 0; @@ -268,6 +332,7 @@ Error VulkanContext::_initialize_extensions() { if (!strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, instance_extensions[i].extensionName)) { if (use_validation_layers) { extension_names[enabled_extension_count++] = VK_EXT_DEBUG_REPORT_EXTENSION_NAME; + enabled_debug_report = true; } } if (!strcmp(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, instance_extensions[i].extensionName)) { @@ -289,12 +354,200 @@ Error VulkanContext::_initialize_extensions() { return OK; } +typedef void(VKAPI_PTR *_vkGetPhysicalDeviceProperties2)(VkPhysicalDevice, VkPhysicalDeviceProperties2 *); + +uint32_t VulkanContext::SubgroupCapabilities::supported_stages_flags_rd() const { + uint32_t flags = 0; + + if (supportedStages & VK_SHADER_STAGE_VERTEX_BIT) { + flags += RenderingDevice::ShaderStage::SHADER_STAGE_VERTEX_BIT; + } + if (supportedStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) { + flags += RenderingDevice::ShaderStage::SHADER_STAGE_TESSELATION_CONTROL_BIT; + } + if (supportedStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) { + flags += RenderingDevice::ShaderStage::SHADER_STAGE_TESSELATION_EVALUATION_BIT; + } + // if (supportedStages & VK_SHADER_STAGE_GEOMETRY_BIT) { + // flags += RenderingDevice::ShaderStage::SHADER_STAGE_GEOMETRY_BIT; + // } + if (supportedStages & VK_SHADER_STAGE_FRAGMENT_BIT) { + flags += RenderingDevice::ShaderStage::SHADER_STAGE_FRAGMENT_BIT; + } + if (supportedStages & VK_SHADER_STAGE_COMPUTE_BIT) { + flags += RenderingDevice::ShaderStage::SHADER_STAGE_COMPUTE_BIT; + } + + return flags; +} + +String VulkanContext::SubgroupCapabilities::supported_stages_desc() const { + String res; + + if (supportedStages & VK_SHADER_STAGE_VERTEX_BIT) { + res += ", STAGE_VERTEX"; + } + if (supportedStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) { + res += ", STAGE_TESSELLATION_CONTROL"; + } + if (supportedStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) { + res += ", STAGE_TESSELLATION_EVALUATION"; + } + if (supportedStages & VK_SHADER_STAGE_GEOMETRY_BIT) { + res += ", STAGE_GEOMETRY"; + } + if (supportedStages & VK_SHADER_STAGE_FRAGMENT_BIT) { + res += ", STAGE_FRAGMENT"; + } + if (supportedStages & VK_SHADER_STAGE_COMPUTE_BIT) { + res += ", STAGE_COMPUTE"; + } + + /* these are not defined on Android GRMBL */ + if (supportedStages & 0x00000100 /* VK_SHADER_STAGE_RAYGEN_BIT_KHR */) { + res += ", STAGE_RAYGEN_KHR"; + } + if (supportedStages & 0x00000200 /* VK_SHADER_STAGE_ANY_HIT_BIT_KHR */) { + res += ", STAGE_ANY_HIT_KHR"; + } + if (supportedStages & 0x00000400 /* VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR */) { + res += ", STAGE_CLOSEST_HIT_KHR"; + } + if (supportedStages & 0x00000800 /* VK_SHADER_STAGE_MISS_BIT_KHR */) { + res += ", STAGE_MISS_KHR"; + } + if (supportedStages & 0x00001000 /* VK_SHADER_STAGE_INTERSECTION_BIT_KHR */) { + res += ", STAGE_INTERSECTION_KHR"; + } + if (supportedStages & 0x00002000 /* VK_SHADER_STAGE_CALLABLE_BIT_KHR */) { + res += ", STAGE_CALLABLE_KHR"; + } + if (supportedStages & 0x00000040 /* VK_SHADER_STAGE_TASK_BIT_NV */) { + res += ", STAGE_TASK_NV"; + } + if (supportedStages & 0x00000080 /* VK_SHADER_STAGE_MESH_BIT_NV */) { + res += ", STAGE_MESH_NV"; + } + + return res.substr(2); // remove first ", " +} + +uint32_t VulkanContext::SubgroupCapabilities::supported_operations_flags_rd() const { + uint32_t flags = 0; + + if (supportedOperations & VK_SUBGROUP_FEATURE_BASIC_BIT) { + flags += RenderingDevice::SubgroupOperations::SUBGROUP_BASIC_BIT; + } + if (supportedOperations & VK_SUBGROUP_FEATURE_VOTE_BIT) { + flags += RenderingDevice::SubgroupOperations::SUBGROUP_VOTE_BIT; + } + if (supportedOperations & VK_SUBGROUP_FEATURE_ARITHMETIC_BIT) { + flags += RenderingDevice::SubgroupOperations::SUBGROUP_ARITHMETIC_BIT; + } + if (supportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT) { + flags += RenderingDevice::SubgroupOperations::SUBGROUP_BALLOT_BIT; + } + if (supportedOperations & VK_SUBGROUP_FEATURE_SHUFFLE_BIT) { + flags += RenderingDevice::SubgroupOperations::SUBGROUP_SHUFFLE_BIT; + } + if (supportedOperations & VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT) { + flags += RenderingDevice::SubgroupOperations::SUBGROUP_SHUFFLE_RELATIVE_BIT; + } + if (supportedOperations & VK_SUBGROUP_FEATURE_CLUSTERED_BIT) { + flags += RenderingDevice::SubgroupOperations::SUBGROUP_CLUSTERED_BIT; + } + if (supportedOperations & VK_SUBGROUP_FEATURE_QUAD_BIT) { + flags += RenderingDevice::SubgroupOperations::SUBGROUP_QUAD_BIT; + } + + return flags; +} + +String VulkanContext::SubgroupCapabilities::supported_operations_desc() const { + String res; + + if (supportedOperations & VK_SUBGROUP_FEATURE_BASIC_BIT) { + res += ", FEATURE_BASIC"; + } + if (supportedOperations & VK_SUBGROUP_FEATURE_VOTE_BIT) { + res += ", FEATURE_VOTE"; + } + if (supportedOperations & VK_SUBGROUP_FEATURE_ARITHMETIC_BIT) { + res += ", FEATURE_ARITHMETIC"; + } + if (supportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT) { + res += ", FEATURE_BALLOT"; + } + if (supportedOperations & VK_SUBGROUP_FEATURE_SHUFFLE_BIT) { + res += ", FEATURE_SHUFFLE"; + } + if (supportedOperations & VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT) { + res += ", FEATURE_SHUFFLE_RELATIVE"; + } + if (supportedOperations & VK_SUBGROUP_FEATURE_CLUSTERED_BIT) { + res += ", FEATURE_CLUSTERED"; + } + if (supportedOperations & VK_SUBGROUP_FEATURE_QUAD_BIT) { + res += ", FEATURE_QUAD"; + } + if (supportedOperations & VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV) { + res += ", FEATURE_PARTITIONED_NV"; + } + + return res.substr(2); // remove first ", " +} + +Error VulkanContext::_check_capabilities() { + // check subgroups + // 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. + _vkGetPhysicalDeviceProperties2 func = (_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2"); + if (func != nullptr) { + VkPhysicalDeviceSubgroupProperties subgroupProperties; + subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES; + subgroupProperties.pNext = nullptr; + + VkPhysicalDeviceProperties2 physicalDeviceProperties; + physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + physicalDeviceProperties.pNext = &subgroupProperties; + + func(gpu, &physicalDeviceProperties); + + subgroup_capabilities.size = subgroupProperties.subgroupSize; + subgroup_capabilities.supportedStages = subgroupProperties.supportedStages; + subgroup_capabilities.supportedOperations = subgroupProperties.supportedOperations; + // Note: quadOperationsInAllStages will be true if: + // - supportedStages has VK_SHADER_STAGE_ALL_GRAPHICS + VK_SHADER_STAGE_COMPUTE_BIT + // - supportedOperations has VK_SUBGROUP_FEATURE_QUAD_BIT + subgroup_capabilities.quadOperationsInAllStages = subgroupProperties.quadOperationsInAllStages; + + // only output this when debugging? + print_line("- Vulkan subgroup size " + itos(subgroup_capabilities.size)); + print_line("- Vulkan subgroup stages " + subgroup_capabilities.supported_stages_desc()); + print_line("- Vulkan subgroup supported ops " + subgroup_capabilities.supported_operations_desc()); + if (subgroup_capabilities.quadOperationsInAllStages) { + print_line("- Vulkan subgroup quad operations in all stages"); + } + } else { + subgroup_capabilities.size = 0; + subgroup_capabilities.supportedStages = 0; + subgroup_capabilities.supportedOperations = 0; + subgroup_capabilities.quadOperationsInAllStages = false; + } + + return OK; +} + Error VulkanContext::_create_physical_device() { + /* obtain version */ + _obtain_vulkan_version(); + /* Look for validation layers */ if (use_validation_layers) { _create_validation_layers(); } + /* initialise extensions */ { Error err = _initialize_extensions(); if (err != OK) { @@ -312,7 +565,7 @@ Error VulkanContext::_create_physical_device() { /*applicationVersion*/ 0, /*pEngineName*/ namecs.get_data(), /*engineVersion*/ 0, - /*apiVersion*/ VK_API_VERSION_1_0, + /*apiVersion*/ VK_MAKE_VERSION(vulkan_major, vulkan_minor, 0) }; VkInstanceCreateInfo inst_info = { /*sType*/ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, @@ -331,6 +584,7 @@ Error VulkanContext::_create_physical_device() { * function to register the final callback. */ VkDebugUtilsMessengerCreateInfoEXT dbg_messenger_create_info; + VkDebugReportCallbackCreateInfoEXT dbg_report_callback_create_info{}; if (enabled_debug_utils) { // VK_EXT_debug_utils style dbg_messenger_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; @@ -344,6 +598,16 @@ Error VulkanContext::_create_physical_device() { dbg_messenger_create_info.pfnUserCallback = _debug_messenger_callback; dbg_messenger_create_info.pUserData = this; inst_info.pNext = &dbg_messenger_create_info; + } else if (enabled_debug_report) { + dbg_report_callback_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; + dbg_report_callback_create_info.flags = VK_DEBUG_REPORT_INFORMATION_BIT_EXT | + VK_DEBUG_REPORT_WARNING_BIT_EXT | + VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT | + VK_DEBUG_REPORT_ERROR_BIT_EXT | + VK_DEBUG_REPORT_DEBUG_BIT_EXT; + dbg_report_callback_create_info.pfnCallback = _debug_report_callback; + dbg_report_callback_create_info.pUserData = this; + inst_info.pNext = &dbg_report_callback_create_info; } uint32_t gpu_count; @@ -532,6 +796,33 @@ Error VulkanContext::_create_physical_device() { ERR_FAIL_V(ERR_CANT_CREATE); break; } + } else if (enabled_debug_report) { + CreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT"); + DebugReportMessageEXT = (PFN_vkDebugReportMessageEXT)vkGetInstanceProcAddr(inst, "vkDebugReportMessageEXT"); + DestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT"); + + if (nullptr == CreateDebugReportCallbackEXT || nullptr == DebugReportMessageEXT || nullptr == DestroyDebugReportCallbackEXT) { + ERR_FAIL_V_MSG(ERR_CANT_CREATE, + "GetProcAddr: Failed to init VK_EXT_debug_report\n" + "GetProcAddr: Failure"); + } + + err = CreateDebugReportCallbackEXT(inst, &dbg_report_callback_create_info, nullptr, &dbg_debug_report); + switch (err) { + case VK_SUCCESS: + break; + case VK_ERROR_OUT_OF_HOST_MEMORY: + ERR_FAIL_V_MSG(ERR_CANT_CREATE, + "CreateDebugReportCallbackEXT: out of host memory\n" + "CreateDebugReportCallbackEXT Failure"); + break; + default: + ERR_FAIL_V_MSG(ERR_CANT_CREATE, + "CreateDebugReportCallbackEXT: unknown failure\n" + "CreateDebugReportCallbackEXT Failure"); + ERR_FAIL_V(ERR_CANT_CREATE); + break; + } } /* Call with NULL data to get count */ @@ -561,6 +852,14 @@ Error VulkanContext::_create_physical_device() { GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfacePresentModesKHR); GET_INSTANCE_PROC_ADDR(inst, GetSwapchainImagesKHR); + // get info about what our vulkan driver is capable off + { + Error res = _check_capabilities(); + if (res != OK) { + return res; + } + } + return OK; } @@ -692,16 +991,39 @@ Error VulkanContext::_initialize_queues(VkSurfaceKHR surface) { // If the format list includes just one entry of VK_FORMAT_UNDEFINED, // the surface has no preferred format. Otherwise, at least one // supported format will be returned. - if (true || (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)) { + if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED) { format = VK_FORMAT_B8G8R8A8_UNORM; + 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 + const VkFormat allowed_formats[] = { + VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_R8G8B8A8_UNORM + }; + uint32_t allowed_formats_count = sizeof(allowed_formats) / sizeof(VkFormat); + if (formatCount < 1) { free(surfFormats); ERR_FAIL_V_MSG(ERR_CANT_CREATE, "formatCount less than 1"); } - format = surfFormats[0].format; + + // 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++) { + if (surfFormats[sf].format == allowed_formats[af]) { + format = surfFormats[sf].format; + color_space = surfFormats[sf].colorSpace; + } + } + } + + if (format == VK_FORMAT_UNDEFINED) { + free(surfFormats); + ERR_FAIL_V_MSG(ERR_CANT_CREATE, "No usable surface format found."); + } } - color_space = surfFormats[0].colorSpace; free(surfFormats); @@ -1708,6 +2030,9 @@ VulkanContext::~VulkanContext() { if (inst_initialized && enabled_debug_utils) { DestroyDebugUtilsMessengerEXT(inst, dbg_messenger, nullptr); } + if (inst_initialized && dbg_debug_report != VK_NULL_HANDLE) { + DestroyDebugReportCallbackEXT(inst, dbg_debug_report, nullptr); + } vkDestroyDevice(device, nullptr); } if (inst_initialized) { diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h index dc6b0410bc..b788181ab9 100644 --- a/drivers/vulkan/vulkan_context.h +++ b/drivers/vulkan/vulkan_context.h @@ -41,6 +41,20 @@ #include <vulkan/vulkan.h> class VulkanContext { +public: + struct SubgroupCapabilities { + uint32_t size; + VkShaderStageFlags supportedStages; + VkSubgroupFeatureFlags supportedOperations; + VkBool32 quadOperationsInAllStages; + + uint32_t supported_stages_flags_rd() const; + String supported_stages_desc() const; + uint32_t supported_operations_flags_rd() const; + String supported_operations_desc() const; + }; + +private: enum { MAX_EXTENSIONS = 128, MAX_LAYERS = 64, @@ -57,6 +71,11 @@ class VulkanContext { bool device_initialized = false; bool inst_initialized = false; + // Vulkan 1.0 doesn't return version info so we assume this by default until we know otherwise + uint32_t vulkan_major = 1; + uint32_t vulkan_minor = 0; + SubgroupCapabilities subgroup_capabilities; + String device_vendor; String device_name; String pipeline_cache_id; @@ -126,6 +145,12 @@ class VulkanContext { const char *extension_names[MAX_EXTENSIONS]; bool enabled_debug_utils = false; + /** + * True if VK_EXT_debug_report extension is used. VK_EXT_debug_report is deprecated but it is + * still used if VK_EXT_debug_utils is not available. + */ + bool enabled_debug_report = false; + uint32_t enabled_layer_count = 0; const char *enabled_layers[MAX_LAYERS]; @@ -136,6 +161,9 @@ class VulkanContext { PFN_vkCmdEndDebugUtilsLabelEXT CmdEndDebugUtilsLabelEXT; PFN_vkCmdInsertDebugUtilsLabelEXT CmdInsertDebugUtilsLabelEXT; PFN_vkSetDebugUtilsObjectNameEXT SetDebugUtilsObjectNameEXT; + PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT; + PFN_vkDebugReportMessageEXT DebugReportMessageEXT; + PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT; PFN_vkGetPhysicalDeviceSurfaceSupportKHR fpGetPhysicalDeviceSurfaceSupportKHR; PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR fpGetPhysicalDeviceSurfaceCapabilitiesKHR; PFN_vkGetPhysicalDeviceSurfaceFormatsKHR fpGetPhysicalDeviceSurfaceFormatsKHR; @@ -149,9 +177,12 @@ class VulkanContext { PFN_vkGetPastPresentationTimingGOOGLE fpGetPastPresentationTimingGOOGLE; VkDebugUtilsMessengerEXT dbg_messenger = VK_NULL_HANDLE; + VkDebugReportCallbackEXT dbg_debug_report = VK_NULL_HANDLE; + Error _obtain_vulkan_version(); Error _create_validation_layers(); Error _initialize_extensions(); + Error _check_capabilities(); VkBool32 _check_layers(uint32_t check_count, const char **check_names, uint32_t layer_count, VkLayerProperties *layers); static VKAPI_ATTR VkBool32 VKAPI_CALL _debug_messenger_callback( @@ -160,6 +191,16 @@ class VulkanContext { const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData); + static VKAPI_ATTR VkBool32 VKAPI_CALL _debug_report_callback( + VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, + size_t location, + int32_t messageCode, + const char *pLayerPrefix, + const char *pMessage, + void *pUserData); + Error _create_physical_device(); Error _initialize_queues(VkSurfaceKHR surface); @@ -186,6 +227,10 @@ protected: } public: + 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; }; + VkDevice get_device(); VkPhysicalDevice get_physical_device(); int get_swapchain_image_count() const; diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp index 55640ca590..9949fd8199 100644 --- a/editor/action_map_editor.cpp +++ b/editor/action_map_editor.cpp @@ -307,7 +307,7 @@ void InputEventConfigurationDialog::_update_input_list() { mouse_root->set_collapsed(collapse); mouse_root->set_meta("__type", INPUT_MOUSE_BUTTON); - int mouse_buttons[9] = { BUTTON_LEFT, BUTTON_RIGHT, BUTTON_MIDDLE, BUTTON_WHEEL_UP, BUTTON_WHEEL_DOWN, BUTTON_WHEEL_LEFT, BUTTON_WHEEL_RIGHT, BUTTON_XBUTTON1, BUTTON_XBUTTON2 }; + MouseButton mouse_buttons[9] = { MOUSE_BUTTON_LEFT, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MIDDLE, MOUSE_BUTTON_WHEEL_UP, MOUSE_BUTTON_WHEEL_DOWN, MOUSE_BUTTON_WHEEL_LEFT, MOUSE_BUTTON_WHEEL_RIGHT, MOUSE_BUTTON_XBUTTON1, MOUSE_BUTTON_XBUTTON2 }; for (int i = 0; i < 9; i++) { Ref<InputEventMouseButton> mb; mb.instance(); diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 5d2b825c4f..ab8ae71904 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -602,6 +602,8 @@ void AnimationBezierTrackEdit::_select_at_anim(const Ref<Animation> &p_anim, int } void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (p_event->is_pressed()) { if (ED_GET_SHORTCUT("animation_editor/duplicate_selection")->is_shortcut(p_event)) { duplicate_selection(); @@ -615,7 +617,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_DOWN) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { float v_zoom_orig = v_zoom; if (mb->get_command()) { timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05); @@ -628,7 +630,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { update(); } - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { float v_zoom_orig = v_zoom; if (mb->get_command()) { timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05); @@ -641,7 +643,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { update(); } - if (mb.is_valid() && mb->get_button_index() == BUTTON_MIDDLE) { + if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_MIDDLE) { if (mb->is_pressed()) { int x = mb->get_position().x - timeline->get_name_limit(); panning_timeline_from = x / timeline->get_zoom_scale(); @@ -652,7 +654,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { } } - if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) { menu_insert_key = mb->get_position(); if (menu_insert_key.x >= timeline->get_name_limit() && menu_insert_key.x <= get_size().width - timeline->get_buttons_width()) { Vector2 popup_pos = get_global_transform().xform(mb->get_position()); @@ -672,7 +674,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { } } - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (close_icon_rect.has_point(mb->get_position())) { emit_signal("close_request"); return; @@ -789,7 +791,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { } } - if (box_selecting_attempt && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (box_selecting_attempt && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (box_selecting) { //do actual select if (!box_selecting_add) { @@ -819,7 +821,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { update(); } - if (moving_handle != 0 && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (moving_handle != 0 && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { undo_redo->create_action(TTR("Move Bezier Points")); undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_in_handle", track, moving_handle_key, moving_handle_left); undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_out_handle", track, moving_handle_key, moving_handle_right); @@ -831,7 +833,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { update(); } - if (moving_selection_attempt && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (moving_selection_attempt && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (moving_selection) { //combit it @@ -927,7 +929,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_MIDDLE) { + if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) { v_scroll += mm->get_relative().y * v_zoom; if (v_scroll > 100000) { v_scroll = 100000; diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 804f02765c..4fe2d2bb2a 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -1641,26 +1641,28 @@ void AnimationTimelineEdit::_play_position_draw() { } void AnimationTimelineEdit::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && hsize_rect.has_point(mb->get_position())) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && hsize_rect.has_point(mb->get_position())) { dragging_hsize = true; dragging_hsize_from = mb->get_position().x; dragging_hsize_at = name_limit; } - if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && dragging_hsize) { + if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && dragging_hsize) { dragging_hsize = false; } if (mb.is_valid() && mb->get_position().x > get_name_limit() && mb->get_position().x < (get_size().width - get_buttons_width())) { - if (!panning_timeline && mb->get_button_index() == BUTTON_LEFT) { + if (!panning_timeline && mb->get_button_index() == MOUSE_BUTTON_LEFT) { int x = mb->get_position().x - get_name_limit(); float ofs = x / get_zoom_scale() + get_value(); emit_signal("timeline_changed", ofs, false); dragging_timeline = true; } - if (!dragging_timeline && mb->get_button_index() == BUTTON_MIDDLE) { + if (!dragging_timeline && mb->get_button_index() == MOUSE_BUTTON_MIDDLE) { int x = mb->get_position().x - get_name_limit(); panning_timeline_from = x / get_zoom_scale(); panning_timeline = true; @@ -1668,11 +1670,11 @@ void AnimationTimelineEdit::_gui_input(const Ref<InputEvent> &p_event) { } } - if (dragging_timeline && mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && !mb->is_pressed()) { + if (dragging_timeline && mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && !mb->is_pressed()) { dragging_timeline = false; } - if (panning_timeline && mb.is_valid() && mb->get_button_index() == BUTTON_MIDDLE && !mb->is_pressed()) { + if (panning_timeline && mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_MIDDLE && !mb->is_pressed()) { panning_timeline = false; } @@ -2522,6 +2524,8 @@ String AnimationTrackEdit::get_tooltip(const Point2 &p_pos) const { } void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (p_event->is_pressed()) { if (ED_GET_SHORTCUT("animation_editor/duplicate_selection")->is_shortcut(p_event)) { emit_signal("duplicate_request"); @@ -2540,7 +2544,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { Point2 pos = mb->get_position(); if (check_rect.has_point(pos)) { @@ -2683,7 +2687,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { } } - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { Point2 pos = mb->get_position(); if (pos.x >= timeline->get_name_limit() && pos.x <= get_size().width - timeline->get_buttons_width()) { // Can do something with menu too! show insert key. @@ -2713,7 +2717,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { } } - if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && clicking_on_name) { + if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && clicking_on_name) { if (!path) { path_popup = memnew(Popup); path_popup->set_wrap_controls(true); @@ -2735,7 +2739,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { } if (mb.is_valid() && moving_selection_attempt) { - if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (!mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { moving_selection_attempt = false; if (moving_selection) { emit_signal("move_selection_commit"); @@ -2746,7 +2750,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { select_single_attempt = -1; } - if (moving_selection && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) { + if (moving_selection && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { moving_selection_attempt = false; moving_selection = false; emit_signal("move_selection_cancel"); @@ -2754,7 +2758,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT && moving_selection_attempt) { + if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT && moving_selection_attempt) { if (!moving_selection) { moving_selection = true; emit_signal("move_selection_begin"); @@ -4439,6 +4443,8 @@ void AnimationTrackEditor::_add_track(int p_type) { } adding_track_type = p_type; pick_track->popup_scenetree_dialog(); + pick_track->get_filter_line_edit()->clear(); + pick_track->get_filter_line_edit()->grab_focus(); } void AnimationTrackEditor::_new_track_property_selected(String p_name) { @@ -4953,17 +4959,17 @@ void AnimationTrackEditor::_box_selection_draw() { void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == BUTTON_WHEEL_UP) { + if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05); scroll->accept_event(); } - if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == BUTTON_WHEEL_DOWN) { + if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05); scroll->accept_event(); } - if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->is_pressed()) { box_selecting = true; box_selecting_from = scroll->get_global_transform().xform(mb->get_position()); @@ -4991,12 +4997,12 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_MIDDLE) { + if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) { timeline->set_value(timeline->get_value() - mm->get_relative().x / timeline->get_zoom_scale()); } if (mm.is_valid() && box_selecting) { - if (!(mm->get_button_mask() & BUTTON_MASK_LEFT)) { + if (!(mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT)) { //no longer box_selection->hide(); box_selecting = false; @@ -5635,6 +5641,70 @@ void AnimationTrackEditor::_bind_methods() { ADD_SIGNAL(MethodInfo("animation_step_changed", PropertyInfo(Variant::FLOAT, "step"))); } +void AnimationTrackEditor::_pick_track_filter_text_changed(const String &p_newtext) { + TreeItem *root_item = pick_track->get_scene_tree()->get_scene_tree()->get_root(); + + Vector<Node *> select_candidates; + Node *to_select = nullptr; + + String filter = pick_track->get_filter_line_edit()->get_text(); + + _pick_track_select_recursive(root_item, filter, select_candidates); + + if (!select_candidates.is_empty()) { + for (int i = 0; i < select_candidates.size(); ++i) { + Node *candidate = select_candidates[i]; + + if (((String)candidate->get_name()).to_lower().begins_with(filter.to_lower())) { + to_select = candidate; + break; + } + } + + if (!to_select) { + to_select = select_candidates[0]; + } + } + + pick_track->get_scene_tree()->set_selected(to_select); +} + +void AnimationTrackEditor::_pick_track_select_recursive(TreeItem *p_item, const String &p_filter, Vector<Node *> &p_select_candidates) { + if (!p_item) { + return; + } + + NodePath np = p_item->get_metadata(0); + Node *node = get_node(np); + + if (p_filter != String() && ((String)node->get_name()).findn(p_filter) != -1) { + p_select_candidates.push_back(node); + } + + TreeItem *c = p_item->get_children(); + + while (c) { + _pick_track_select_recursive(c, p_filter, p_select_candidates); + c = c->get_next(); + } +} + +void AnimationTrackEditor::_pick_track_filter_input(const Ref<InputEvent> &p_ie) { + Ref<InputEventKey> k = p_ie; + + if (k.is_valid()) { + switch (k->get_keycode()) { + case KEY_UP: + case KEY_DOWN: + case KEY_PAGEUP: + case KEY_PAGEDOWN: { + pick_track->get_scene_tree()->get_scene_tree()->call("_gui_input", k); + pick_track->get_filter_line_edit()->accept_event(); + } break; + } + } +} + AnimationTrackEditor::AnimationTrackEditor() { root = nullptr; @@ -5805,8 +5875,12 @@ AnimationTrackEditor::AnimationTrackEditor() { pick_track = memnew(SceneTreeDialog); add_child(pick_track); + pick_track->register_text_enter(pick_track->get_filter_line_edit()); pick_track->set_title(TTR("Pick a node to animate:")); pick_track->connect("selected", callable_mp(this, &AnimationTrackEditor::_new_track_node_selected)); + pick_track->get_filter_line_edit()->connect("text_changed", callable_mp(this, &AnimationTrackEditor::_pick_track_filter_text_changed)); + pick_track->get_filter_line_edit()->connect("gui_input", callable_mp(this, &AnimationTrackEditor::_pick_track_filter_input)); + prop_selector = memnew(PropertySelector); add_child(prop_selector); prop_selector->connect("selected", callable_mp(this, &AnimationTrackEditor::_new_track_property_selected)); diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index e8e4f915fa..c25865effb 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -499,6 +499,10 @@ class AnimationTrackEditor : public VBoxContainer { void _insert_animation_key(NodePath p_path, const Variant &p_value); + void _pick_track_filter_text_changed(const String &p_newtext); + void _pick_track_select_recursive(TreeItem *p_item, const String &p_filter, Vector<Node *> &p_select_candidates); + void _pick_track_filter_input(const Ref<InputEvent> &p_ie); + protected: static void _bind_methods(); void _notification(int p_what); diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp index 0c0ee2856e..506a327ffc 100644 --- a/editor/animation_track_editor_plugins.cpp +++ b/editor/animation_track_editor_plugins.cpp @@ -101,47 +101,67 @@ void AnimationTrackEditColor::draw_key_link(int p_index, float p_pixels_sec, int int font_size = get_theme_font_size("font_size", "Label"); int fh = (font->get_height(font_size) * 0.8); + fh /= 3; + int x_from = p_x + fh / 2 - 1; int x_to = p_next_x - fh / 2 + 1; - fh /= 3; + x_from = MAX(x_from, p_clip_left); + x_to = MIN(x_to, p_clip_right); + + int y_from = (get_size().height - fh) / 2; if (x_from > p_clip_right || x_to < p_clip_left) { return; } - Color color = get_animation()->track_get_key_value(get_track(), p_index); - Color color_next = get_animation()->track_get_key_value(get_track(), p_index + 1); + Vector<Color> color_samples; + color_samples.append(get_animation()->track_get_key_value(get_track(), p_index)); - if (x_from < p_clip_left) { - float c = float(p_clip_left - x_from) / (x_to - x_from); - color = color.lerp(color_next, c); - x_from = p_clip_left; - } + if (get_animation()->track_get_type(get_track()) == Animation::TYPE_VALUE) { + if (get_animation()->track_get_interpolation_type(get_track()) != Animation::INTERPOLATION_NEAREST && + (get_animation()->value_track_get_update_mode(get_track()) == Animation::UPDATE_CONTINUOUS || + get_animation()->value_track_get_update_mode(get_track()) == Animation::UPDATE_CAPTURE) && + !Math::is_zero_approx(get_animation()->track_get_key_transition(get_track(), p_index))) { + float start_time = get_animation()->track_get_key_time(get_track(), p_index); + float end_time = get_animation()->track_get_key_time(get_track(), p_index + 1); - if (x_to > p_clip_right) { - float c = float(p_clip_right - x_from) / (x_to - x_from); - color_next = color.lerp(color_next, c); - x_to = p_clip_right; - } + Color color_next = get_animation()->value_track_interpolate(get_track(), end_time); - int y_from = (get_size().height - fh) / 2; + if (!color_samples[0].is_equal_approx(color_next)) { + color_samples.resize(1 + (x_to - x_from) / 64); // Make a color sample every 64 px. + for (int i = 1; i < color_samples.size(); i++) { + float j = i; + color_samples.write[i] = get_animation()->value_track_interpolate( + get_track(), + Math::lerp(start_time, end_time, j / color_samples.size())); + } + } + color_samples.append(color_next); + } else { + color_samples.append(color_samples[0]); + } + } else { + color_samples.append(get_animation()->track_get_key_value(get_track(), p_index + 1)); + } - Vector<Vector2> points; - Vector<Color> colors; + for (int i = 0; i < color_samples.size() - 1; i++) { + Vector<Vector2> points; + Vector<Color> colors; - points.push_back(Vector2(x_from, y_from)); - colors.push_back(color); + points.push_back(Vector2(Math::lerp(x_from, x_to, float(i) / (color_samples.size() - 1)), y_from)); + colors.push_back(color_samples[i]); - points.push_back(Vector2(x_to, y_from)); - colors.push_back(color_next); + points.push_back(Vector2(Math::lerp(x_from, x_to, float(i + 1) / (color_samples.size() - 1)), y_from)); + colors.push_back(color_samples[i + 1]); - points.push_back(Vector2(x_to, y_from + fh)); - colors.push_back(color_next); + points.push_back(Vector2(Math::lerp(x_from, x_to, float(i + 1) / (color_samples.size() - 1)), y_from + fh)); + colors.push_back(color_samples[i + 1]); - points.push_back(Vector2(x_from, y_from + fh)); - colors.push_back(color); + points.push_back(Vector2(Math::lerp(x_from, x_to, float(i) / (color_samples.size() - 1)), y_from + fh)); + colors.push_back(color_samples[i]); - draw_primitive(points, colors, Vector<Vector2>()); + draw_primitive(points, colors, Vector<Vector2>()); + } } void AnimationTrackEditColor::draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right) { @@ -1016,6 +1036,8 @@ void AnimationTrackEditTypeAudio::drop_data(const Point2 &p_point, const Variant } void AnimationTrackEditTypeAudio::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventMouseMotion> mm = p_event; if (!len_resizing && mm.is_valid()) { bool use_hsize_cursor = false; @@ -1076,7 +1098,7 @@ void AnimationTrackEditTypeAudio::_gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && get_default_cursor_shape() == CURSOR_HSIZE) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && get_default_cursor_shape() == CURSOR_HSIZE) { len_resizing = true; len_resizing_start = mb->get_shift(); len_resizing_from_px = mb->get_position().x; @@ -1086,7 +1108,7 @@ void AnimationTrackEditTypeAudio::_gui_input(const Ref<InputEvent> &p_event) { return; } - if (len_resizing && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (len_resizing && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { float ofs_local = -len_resizing_rel / get_timeline()->get_zoom_scale(); if (len_resizing_start) { float prev_ofs = get_animation()->audio_track_get_key_start_offset(get_track(), len_resizing_index); diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index f4717830bc..ac8bef817b 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -109,6 +109,8 @@ void FindReplaceBar::_notification(int p_what) { } void FindReplaceBar::_unhandled_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventKey> k = p_event; if (!k.is_valid() || !k->is_pressed()) { return; @@ -691,6 +693,8 @@ FindReplaceBar::FindReplaceBar() { // This function should be used to handle shortcuts that could otherwise // be handled too late if they weren't handled here. void CodeTextEditor::_input(const Ref<InputEvent> &event) { + ERR_FAIL_COND(event.is_null()); + const Ref<InputEventKey> key_event = event; if (!key_event.is_valid() || !key_event->is_pressed() || !text_editor->has_focus()) { return; @@ -723,9 +727,9 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) { if (mb.is_valid()) { if (mb->is_pressed() && mb->get_command()) { - if (mb->get_button_index() == BUTTON_WHEEL_UP) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { _zoom_in(); - } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN) { + } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { _zoom_out(); } } @@ -1548,7 +1552,7 @@ void CodeTextEditor::validate_script() { void CodeTextEditor::_warning_label_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { _warning_button_pressed(); } } @@ -1572,7 +1576,7 @@ void CodeTextEditor::_toggle_scripts_pressed() { void CodeTextEditor::_error_pressed(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { goto_error(); } } diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp index 33d08a2f6b..fc0104c07a 100644 --- a/editor/debugger/editor_performance_profiler.cpp +++ b/editor/debugger/editor_performance_profiler.cpp @@ -249,7 +249,7 @@ TreeItem *EditorPerformanceProfiler::_create_monitor_item(const StringName &p_mo void EditorPerformanceProfiler::_marker_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { Vector<StringName> active; for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { if (i.value().item->is_checked(0)) { diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp index 9304b116d0..c4290b7cca 100644 --- a/editor/debugger/editor_profiler.cpp +++ b/editor/debugger/editor_profiler.cpp @@ -482,7 +482,7 @@ void EditorProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) { Ref<InputEventMouseMotion> mm = p_ev; if ( - (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) || + (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) || (mm.is_valid())) { int x = me->get_position().x; x = x * frame_metrics.size() / graph->get_size().width; @@ -510,7 +510,7 @@ void EditorProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) { hover_metric = -1; } - if (mb.is_valid() || mm->get_button_mask() & BUTTON_MASK_LEFT) { + if (mb.is_valid() || mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { //cursor_metric=x; updating_frame = true; diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp index d825a980c7..5bb10b3794 100644 --- a/editor/debugger/editor_visual_profiler.cpp +++ b/editor/debugger/editor_visual_profiler.cpp @@ -517,7 +517,7 @@ void EditorVisualProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) { Ref<InputEventMouseMotion> mm = p_ev; if ( - (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) || + (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) || (mm.is_valid())) { int half_w = graph->get_size().width / 2; int x = me->get_position().x; @@ -549,7 +549,7 @@ void EditorVisualProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) { hover_metric = -1; } - if (mb.is_valid() || mm->get_button_mask() & BUTTON_MASK_LEFT) { + if (mb.is_valid() || mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { //cursor_metric=x; updating_frame = true; diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index 25e155aafe..57d44ca56c 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -86,11 +86,11 @@ void DependencyEditor::_fix_and_find(EditorFileSystemDirectory *efsd, Map<String String lost = E->key().replace_first("res://", ""); Vector<String> existingv = existing.split("/"); - existingv.invert(); + existingv.reverse(); Vector<String> currentv = current.split("/"); - currentv.invert(); + currentv.reverse(); Vector<String> lostv = lost.split("/"); - lostv.invert(); + lostv.reverse(); int existing_score = 0; int current_score = 0; diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index 9a826ab106..e7934bed0a 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -531,8 +531,10 @@ void EditorAudioBus::_effect_add(int p_which) { } void EditorAudioBus::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) { Vector2 pos = Vector2(mb->get_position().x, mb->get_position().y); bus_popup->set_position(get_global_position() + pos); bus_popup->popup(); diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index 213c3f5631..fa4703d425 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -741,7 +741,7 @@ Ref<Script> EditorData::get_scene_root_script(int p_idx) const { return s; } -String EditorData::get_scene_title(int p_idx) const { +String EditorData::get_scene_title(int p_idx, bool p_always_strip_extension) const { ERR_FAIL_INDEX_V(p_idx, edited_scene.size(), String()); if (!edited_scene[p_idx].root) { return TTR("[empty]"); @@ -749,12 +749,28 @@ String EditorData::get_scene_title(int p_idx) const { if (edited_scene[p_idx].root->get_filename() == "") { return TTR("[unsaved]"); } - bool show_ext = EDITOR_DEF("interface/scene_tabs/show_extension", false); - String name = edited_scene[p_idx].root->get_filename().get_file(); - if (!show_ext) { - name = name.get_basename(); + + const String filename = edited_scene[p_idx].root->get_filename().get_file(); + const String basename = filename.get_basename(); + + if (p_always_strip_extension) { + return basename; + } + + // Return the filename including the extension if there's ambiguity (e.g. both `foo.tscn` and `foo.scn` are being edited). + for (int i = 0; i < edited_scene.size(); i++) { + if (i == p_idx) { + // Don't compare the edited scene against itself. + continue; + } + + if (edited_scene[i].root && basename == edited_scene[i].root->get_filename().get_file().get_basename()) { + return filename; + } } - return name; + + // Else, return just the basename as there's no ambiguity. + return basename; } void EditorData::set_scene_path(int p_idx, const String &p_path) { diff --git a/editor/editor_data.h b/editor/editor_data.h index 18b4137162..dbe729d9d9 100644 --- a/editor/editor_data.h +++ b/editor/editor_data.h @@ -184,7 +184,7 @@ public: Node *get_edited_scene_root(int p_idx = -1); int get_edited_scene_count() const; Vector<EditedScene> get_edited_scenes() const; - String get_scene_title(int p_idx) const; + String get_scene_title(int p_idx, bool p_always_strip_extension = false) const; String get_scene_path(int p_idx) const; String get_scene_type(int p_idx) const; void set_scene_path(int p_idx, const String &p_path); diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index 7f5f51cf70..a5ebfbfb8a 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -730,6 +730,12 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & if (p_preset->get_export_filter() == EditorExportPreset::EXPORT_ALL_RESOURCES) { //find stuff _export_find_resources(EditorFileSystem::get_singleton()->get_filesystem(), paths); + } else if (p_preset->get_export_filter() == EditorExportPreset::EXCLUDE_SELECTED_RESOURCES) { + _export_find_resources(EditorFileSystem::get_singleton()->get_filesystem(), paths); + Vector<String> files = p_preset->get_files_to_export(); + for (int i = 0; i < files.size(); i++) { + paths.erase(files[i]); + } } else { bool scenes_only = p_preset->get_export_filter() == EditorExportPreset::EXPORT_SELECTED_SCENES; @@ -874,6 +880,20 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & continue; } + String importer_type = config->get_value("remap", "importer"); + + if (importer_type == "keep") { + //just keep file as-is + Vector<uint8_t> array = FileAccess::get_file_as_array(path); + err = p_func(p_udata, path, array, idx, total, enc_in_filters, enc_ex_filters, key); + + if (err != OK) { + return err; + } + + continue; + } + List<String> remaps; config->get_section_keys("remap", &remaps); @@ -1380,6 +1400,10 @@ void EditorExport::_save() { 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) { @@ -1558,6 +1582,9 @@ void EditorExport::load_config() { } 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) { diff --git a/editor/editor_export.h b/editor/editor_export.h index e6026e7aae..c96c8fdbce 100644 --- a/editor/editor_export.h +++ b/editor/editor_export.h @@ -50,6 +50,7 @@ public: EXPORT_ALL_RESOURCES, EXPORT_SELECTED_SCENES, EXPORT_SELECTED_RESOURCES, + EXCLUDE_SELECTED_RESOURCES, }; enum ScriptExportMode { diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index f78da9569f..75815fa750 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -125,6 +125,8 @@ void EditorFileDialog::_notification(int p_what) { } void EditorFileDialog::_unhandled_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventKey> k = p_event; if (k.is_valid()) { diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index dce022e86e..fb0dc57501 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -405,6 +405,10 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo memdelete(f); + if (importer_name == "keep") { + return false; //keep mode, do not reimport + } + Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name); if (importer->get_format_version() > version) { @@ -1532,6 +1536,10 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector source_file_options[p_files[i]] = Map<StringName, Variant>(); importer_name = file_importer_name; + if (importer_name == "keep") { + continue; //do nothing + } + Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name); ERR_FAIL_COND_V(!importer.is_valid(), ERR_FILE_CORRUPT); List<ResourceImporter::ImportOption> options; @@ -1555,6 +1563,10 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector base_paths[p_files[i]] = ResourceFormatImporter::get_singleton()->get_import_base_path(p_files[i]); } + if (importer_name == "keep") { + return OK; // (do nothing) + } + ERR_FAIL_COND_V(importer_name == String(), ERR_UNCONFIGURED); Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name); @@ -1668,7 +1680,7 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector return err; } -void EditorFileSystem::_reimport_file(const String &p_file) { +void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName, Variant> *p_custom_options, const String &p_custom_importer) { EditorFileSystemDirectory *fs = nullptr; int cpos = -1; bool found = _find_file(p_file, &fs, cpos); @@ -1677,23 +1689,32 @@ void EditorFileSystem::_reimport_file(const String &p_file) { //try to obtain existing params Map<StringName, Variant> params; - String importer_name; + String importer_name; //empty by default though + + if (p_custom_importer != String()) { + importer_name = p_custom_importer; + } + if (p_custom_options != nullptr) { + params = *p_custom_options; + } if (FileAccess::exists(p_file + ".import")) { //use existing - Ref<ConfigFile> cf; - cf.instance(); - Error err = cf->load(p_file + ".import"); - if (err == OK) { - if (cf->has_section("params")) { - List<String> sk; - cf->get_section_keys("params", &sk); - for (List<String>::Element *E = sk.front(); E; E = E->next()) { - params[E->get()] = cf->get_value("params", E->get()); + if (p_custom_options == nullptr) { + Ref<ConfigFile> cf; + cf.instance(); + Error err = cf->load(p_file + ".import"); + if (err == OK) { + if (cf->has_section("params")) { + List<String> sk; + cf->get_section_keys("params", &sk); + for (List<String>::Element *E = sk.front(); E; E = E->next()) { + params[E->get()] = cf->get_value("params", E->get()); + } + } + if (p_custom_importer == String() && cf->has_section("remap")) { + importer_name = cf->get_value("remap", "importer"); } - } - if (cf->has_section("remap")) { - importer_name = cf->get_value("remap", "importer"); } } @@ -1701,6 +1722,16 @@ void EditorFileSystem::_reimport_file(const String &p_file) { late_added_files.insert(p_file); //imported files do not call update_file(), but just in case.. } + if (importer_name == "keep") { + //keep files, do nothing. + fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file); + fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(p_file + ".import"); + fs->files[cpos]->deps.clear(); + fs->files[cpos]->type = ""; + fs->files[cpos]->import_valid = false; + EditorResourcePreview::get_singleton()->check_for_invalidation(p_file); + return; + } Ref<ResourceImporter> importer; bool load_default = false; //find the importer @@ -1887,6 +1918,10 @@ void EditorFileSystem::_find_group_files(EditorFileSystemDirectory *efd, Map<Str } } +void EditorFileSystem::reimport_file_with_custom_parameters(const String &p_file, const String &p_importer, const Map<StringName, Variant> &p_custom_params) { + _reimport_file(p_file, &p_custom_params, p_importer); +} + void EditorFileSystem::reimport_files(const Vector<String> &p_files) { { // Ensure that ProjectSettings::IMPORTED_FILES_PATH exists. diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index 59bde238a8..6f4f058503 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -203,7 +203,7 @@ class EditorFileSystem : public Node { void _update_extensions(); - void _reimport_file(const String &p_file); + void _reimport_file(const String &p_file, const Map<StringName, Variant> *p_custom_options = nullptr, const String &p_custom_importer = String()); Error _reimport_group(const String &p_group_file, const Vector<String> &p_files); bool _test_for_reimport(const String &p_path, bool p_only_imported_files); @@ -257,6 +257,8 @@ public: void reimport_files(const Vector<String> &p_files); + void reimport_file_with_custom_parameters(const String &p_file, const String &p_importer, const Map<StringName, Variant> &p_custom_params); + void update_script_classes(); bool is_group_file(const String &p_path) const; diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 283713cd3c..a747652a2f 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -1908,6 +1908,8 @@ void FindBar::_hide_bar() { } void FindBar::_unhandled_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventKey> k = p_event; if (k.is_valid()) { if (k->is_pressed() && (rich_text_label->has_focus() || is_a_parent_of(get_focus_owner()))) { diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 9b03731fd8..738b2f9f82 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -682,6 +682,8 @@ bool EditorProperty::is_selected() const { } void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (property == StringName()) { return; } @@ -693,7 +695,7 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) { if (is_layout_rtl()) { mpos.x = get_size().x - mpos.x; } - bool button_left = me->get_button_mask() & BUTTON_MASK_LEFT; + bool button_left = me->get_button_mask() & MOUSE_BUTTON_MASK_LEFT; bool new_keying_hover = keying_rect.has_point(mpos) && !button_left; if (new_keying_hover != keying_hover) { @@ -722,7 +724,7 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { Vector2 mpos = mb->get_position(); if (is_layout_rtl()) { mpos.x = get_size().x - mpos.x; @@ -1354,12 +1356,14 @@ void EditorInspectorSection::setup(const String &p_section, const String &p_labe } void EditorInspectorSection::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (!foldable) { return; } Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { Ref<Font> font = get_theme_font("font", "Tree"); int font_size = get_theme_font_size("font_size", "Tree"); if (mb->get_position().y > font->get_height(font_size)) { //clicked outside @@ -2566,9 +2570,9 @@ void EditorInspector::_update_script_class_properties(const Object &p_object, Li } // Script Variables -> to insert: NodeC..B..A -> bottom (insert_here) - List<PropertyInfo>::Element *script_variables = NULL; - List<PropertyInfo>::Element *bottom = NULL; - List<PropertyInfo>::Element *insert_here = NULL; + 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") { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index c3e15f2840..6a50976908 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -92,7 +92,6 @@ #include "editor/filesystem_dock.h" #include "editor/import/editor_import_collada.h" #include "editor/import/resource_importer_bitmask.h" -#include "editor/import/resource_importer_csv.h" #include "editor/import/resource_importer_csv_translation.h" #include "editor/import/resource_importer_image.h" #include "editor/import/resource_importer_layered_texture.h" @@ -102,6 +101,7 @@ #include "editor/import/resource_importer_texture.h" #include "editor/import/resource_importer_texture_atlas.h" #include "editor/import/resource_importer_wav.h" +#include "editor/import/scene_import_settings.h" #include "editor/import/scene_importer_mesh_node_3d.h" #include "editor/import_dock.h" #include "editor/multi_node_edit.h" @@ -390,6 +390,8 @@ void EditorNode::_update_title() { } void EditorNode::_unhandled_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventKey> k = p_event; if (k.is_valid() && k->is_pressed() && !k->is_echo()) { EditorPlugin *old_editor = editor_plugin_screen; @@ -592,6 +594,9 @@ void EditorNode::_notification(int p_what) { _editor_select(EDITOR_3D); } + // Save the project after opening to mark it as last modified. + ProjectSettings::get_singleton()->save(); + /* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */ } break; @@ -1374,18 +1379,18 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { // which would result in an invalid texture. if (c3d == 0 && c2d == 0) { img.instance(); - img->create(1, 1, 0, Image::FORMAT_RGB8); + img->create(1, 1, false, Image::FORMAT_RGB8); } else if (c3d < c2d) { Ref<ViewportTexture> viewport_texture = scene_root->get_texture(); if (viewport_texture->get_width() > 0 && viewport_texture->get_height() > 0) { - img = viewport_texture->get_data(); + img = viewport_texture->get_image(); } } else { // The 3D editor may be disabled as a feature, but scenes can still be opened. // This check prevents the preview from regenerating in case those scenes are then saved. Ref<EditorFeatureProfile> profile = feature_profile_manager->get_current_profile(); if (profile.is_valid() && !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D)) { - img = Node3DEditor::get_singleton()->get_editor_viewport(0)->get_viewport_node()->get_texture()->get_data(); + img = Node3DEditor::get_singleton()->get_editor_viewport(0)->get_viewport_node()->get_texture()->get_image(); } } @@ -2832,7 +2837,7 @@ void EditorNode::_save_screenshot(NodePath p_path) { ERR_FAIL_COND_MSG(!viewport, "Cannot get editor main control viewport."); Ref<ViewportTexture> texture = viewport->get_texture(); ERR_FAIL_COND_MSG(texture.is_null(), "Cannot get editor main control viewport texture."); - Ref<Image> img = texture->get_data(); + Ref<Image> img = texture->get_image(); ERR_FAIL_COND_MSG(img.is_null(), "Cannot get editor main control viewport texture image."); Error error = img->save_png(p_path); ERR_FAIL_COND_MSG(error != OK, "Cannot save screenshot to file '" + p_path + "'."); @@ -4835,15 +4840,15 @@ void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) { if (mb.is_valid()) { if (scene_tabs->get_hovered_tab() >= 0) { - if (mb->get_button_index() == BUTTON_MIDDLE && mb->is_pressed()) { + if (mb->get_button_index() == MOUSE_BUTTON_MIDDLE && mb->is_pressed()) { _scene_tab_closed(scene_tabs->get_hovered_tab()); } } else { - if ((mb->get_button_index() == BUTTON_LEFT && mb->is_doubleclick()) || (mb->get_button_index() == BUTTON_MIDDLE && mb->is_pressed())) { + if ((mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_doubleclick()) || (mb->get_button_index() == MOUSE_BUTTON_MIDDLE && mb->is_pressed())) { _menu_option_confirm(FILE_NEW_SCENE, true); } } - if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { + if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) { // context menu scene_tabs_context_menu->clear(); scene_tabs_context_menu->set_size(Size2(1, 1)); @@ -5105,8 +5110,8 @@ Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) { { //todo make proper previews - Ref<ImageTexture> pic = gui_base->get_theme_icon("FileBigThumb", "EditorIcons"); - Ref<Image> img = pic->get_data(); + Ref<ImageTexture> texture = gui_base->get_theme_icon("FileBigThumb", "EditorIcons"); + Ref<Image> img = texture->get_image(); img = img->duplicate(); img->resize(48, 48); //meh Ref<ImageTexture> resized_pic = Ref<ImageTexture>(memnew(ImageTexture)); @@ -5778,10 +5783,6 @@ EditorNode::EditorNode() { import_csv_translation.instance(); ResourceFormatImporter::get_singleton()->add_importer(import_csv_translation); - Ref<ResourceImporterCSV> import_csv; - import_csv.instance(); - ResourceFormatImporter::get_singleton()->add_importer(import_csv); - Ref<ResourceImporterWAV> import_wav; import_wav.instance(); ResourceFormatImporter::get_singleton()->add_importer(import_wav); @@ -6179,6 +6180,9 @@ EditorNode::EditorNode() { project_settings = memnew(ProjectSettingsEditor(&editor_data)); gui_base->add_child(project_settings); + scene_import_settings = memnew(SceneImportSettings); + gui_base->add_child(scene_import_settings); + export_template_manager = memnew(ExportTemplateManager); gui_base->add_child(export_template_manager); @@ -6467,8 +6471,8 @@ EditorNode::EditorNode() { video_driver->connect("item_selected", callable_mp(this, &EditorNode::_video_driver_selected)); video_driver->add_theme_font_override("font", gui_base->get_theme_font("bold", "EditorFonts")); video_driver->add_theme_font_size_override("font_size", gui_base->get_theme_font_size("bold_size", "EditorFonts")); - // TODO re-enable when GLES2 is ported - video_driver->set_disabled(true); + // TODO: Show again when OpenGL is ported. + video_driver->set_visible(false); right_menu_hb->add_child(video_driver); #ifndef _MSC_VER diff --git a/editor/editor_node.h b/editor/editor_node.h index 91d873d16f..7e16936f5d 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -88,6 +88,7 @@ class Button; class VSplitContainer; class Window; class SubViewport; +class SceneImportSettings; class EditorNode : public Node { GDCLASS(EditorNode, Node); @@ -410,6 +411,7 @@ private: EditorResourcePreview *resource_preview; EditorFolding editor_folding; + SceneImportSettings *scene_import_settings; struct BottomPanelItem { String name; Control *control = nullptr; diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index c0cecbc651..064271fce8 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -262,6 +262,10 @@ Control *EditorInterface::get_base_control() { return EditorNode::get_singleton()->get_gui_base(); } +float EditorInterface::get_editor_scale() const { + return EDSCALE; +} + void EditorInterface::set_plugin_enabled(const String &p_plugin, bool p_enabled) { EditorNode::get_singleton()->set_addon_plugin_enabled(p_plugin, p_enabled, true); } @@ -306,6 +310,7 @@ void EditorInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("get_editor_settings"), &EditorInterface::get_editor_settings); ClassDB::bind_method(D_METHOD("get_script_editor"), &EditorInterface::get_script_editor); ClassDB::bind_method(D_METHOD("get_base_control"), &EditorInterface::get_base_control); + ClassDB::bind_method(D_METHOD("get_editor_scale"), &EditorInterface::get_editor_scale); ClassDB::bind_method(D_METHOD("edit_resource", "resource"), &EditorInterface::edit_resource); ClassDB::bind_method(D_METHOD("open_scene_from_path", "scene_filepath"), &EditorInterface::open_scene_from_path); ClassDB::bind_method(D_METHOD("reload_scene_from_path", "scene_filepath"), &EditorInterface::reload_scene_from_path); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index ae9fcfb28a..b0713c641b 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -100,6 +100,7 @@ public: FileSystemDock *get_file_system_dock(); Control *get_base_control(); + float get_editor_scale() const; void set_plugin_enabled(const String &p_plugin, bool p_enabled); bool is_plugin_enabled(const String &p_plugin) const; diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 2d7235038a..fa44239e32 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -621,7 +621,7 @@ public: const Ref<InputEventMouseButton> mb = p_ev; - if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed() && hovered_index >= 0) { + if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed() && hovered_index >= 0) { // Toggle the flag. // We base our choice on the hovered flag, so that it always matches the hovered flag. if (value & (1 << hovered_index)) { @@ -649,14 +649,16 @@ public: Color color = get_theme_color("highlight_color", "Editor"); for (int i = 0; i < 2; i++) { Point2 ofs(4, vofs); - if (i == 1) + if (i == 1) { ofs.y += bsize + 1; + } ofs += rect.position; for (int j = 0; j < 10; j++) { Point2 o = ofs + Point2(j * (bsize + 1), 0); - if (j >= 5) + if (j >= 5) { o.x += 1; + } const int idx = i * 10 + j; const bool on = value & (1 << idx); @@ -927,11 +929,11 @@ EditorPropertyFloat::EditorPropertyFloat() { void EditorPropertyEasing::_drag_easing(const Ref<InputEvent> &p_ev) { const Ref<InputEventMouseButton> mb = p_ev; if (mb.is_valid()) { - if (mb->is_doubleclick() && mb->get_button_index() == BUTTON_LEFT) { + if (mb->is_doubleclick() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { _setup_spin(); } - if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { preset->set_position(easing_draw->get_screen_transform().xform(mb->get_position())); preset->popup(); @@ -940,7 +942,7 @@ void EditorPropertyEasing::_drag_easing(const Ref<InputEvent> &p_ev) { easing_draw->update(); } - if (mb->get_button_index() == BUTTON_LEFT) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { dragging = mb->is_pressed(); // Update to display the correct dragging color easing_draw->update(); @@ -949,7 +951,7 @@ void EditorPropertyEasing::_drag_easing(const Ref<InputEvent> &p_ev) { const Ref<InputEventMouseMotion> mm = p_ev; - if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) { + if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { float rel = mm->get_relative().x; if (rel == 0) { return; @@ -2814,7 +2816,7 @@ void EditorPropertyResource::_sub_inspector_object_id_selected(int p_id) { void EditorPropertyResource::_button_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { _update_menu_items(); Vector2 pos = get_screen_position() + mb->get_position(); //pos = assign->get_global_transform().xform(pos); @@ -2975,6 +2977,7 @@ void EditorPropertyResource::update_property() { if (res == RES()) { assign->set_icon(Ref<Texture2D>()); assign->set_text(TTR("[empty]")); + assign->set_custom_minimum_size(Size2(1, 1)); } else { assign->set_icon(EditorNode::get_singleton()->get_object_icon(res.operator->(), "Object")); @@ -3281,7 +3284,7 @@ void EditorInspectorDefaultPlugin::parse_begin(Object *p_object) { } bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) { - float default_float_step = EDITOR_GET("interface/inspector/default_float_step"); + double default_float_step = EDITOR_GET("interface/inspector/default_float_step"); switch (p_type) { // atomic types diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index 77288be614..138830cdc6 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -174,7 +174,7 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref< } if (!r_small_texture.is_valid() && r_texture.is_valid() && preview_generators[i]->generate_small_preview_automatically()) { - Ref<Image> small_image = r_texture->get_data(); + Ref<Image> small_image = r_texture->get_image(); small_image = small_image->duplicate(); small_image->resize(small_thumbnail_size, small_thumbnail_size, Image::INTERPOLATE_CUBIC); r_small_texture.instance(); diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp index 9b92134368..1ffa20d1ea 100644 --- a/editor/editor_run_native.cpp +++ b/editor/editor_run_native.cpp @@ -43,7 +43,7 @@ void EditorRunNative::_notification(int p_what) { } Ref<ImageTexture> icon = eep->get_run_icon(); if (!icon.is_null()) { - Ref<Image> im = icon->get_data(); + Ref<Image> im = icon->get_image(); im = im->duplicate(); im->clear_mipmaps(); if (!im->is_empty()) { diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index ef1f8030fa..4ddae7c062 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -460,7 +460,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { hints["interface/theme/custom_theme"] = PropertyInfo(Variant::STRING, "interface/theme/custom_theme", PROPERTY_HINT_GLOBAL_FILE, "*.res,*.tres,*.theme", PROPERTY_USAGE_DEFAULT); // Scene tabs - _initial_set("interface/scene_tabs/show_extension", false); _initial_set("interface/scene_tabs/show_thumbnail_on_hover", true); _initial_set("interface/scene_tabs/resize_if_many_tabs", true); _initial_set("interface/scene_tabs/minimum_width", 50); @@ -620,8 +619,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // is increased significantly more than it really should need to be. hints["editors/3d/grid_division_level_max"] = PropertyInfo(Variant::INT, "editors/3d/grid_division_level_max", PROPERTY_HINT_RANGE, "-1,3,1", PROPERTY_USAGE_DEFAULT); - // Default smallest grid size is 1cm, 10^-2. - _initial_set("editors/3d/grid_division_level_min", -2); + // Default smallest grid size is 1m, 10^0. + _initial_set("editors/3d/grid_division_level_min", 0); // Lower values produce graphical artifacts regardless of view clipping planes, so limit to -2 as a lower bound. hints["editors/3d/grid_division_level_min"] = PropertyInfo(Variant::INT, "editors/3d/grid_division_level_min", PROPERTY_HINT_RANGE, "-2,2,1", PROPERTY_USAGE_DEFAULT); diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index bbabc08ea4..8577ccb9db 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -47,13 +47,15 @@ String EditorSpinSlider::get_text_value() const { } void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (read_only) { return; } Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == BUTTON_LEFT) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->is_pressed()) { if (updown_offset != -1 && mb->get_position().x > updown_offset) { //there is an updown, so use it. @@ -84,7 +86,7 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) { grabbing_spinner_attempt = false; } } - } else if (mb->get_button_index() == BUTTON_WHEEL_UP || mb->get_button_index() == BUTTON_WHEEL_DOWN) { + } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP || mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { if (grabber->is_visible()) { call_deferred("update"); } @@ -146,17 +148,17 @@ void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) { if (grabbing_grabber) { if (mb.is_valid()) { - if (mb->get_button_index() == BUTTON_WHEEL_UP) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { set_value(get_value() + get_step()); mousewheel_over_grabber = true; - } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN) { + } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { set_value(get_value() - get_step()); mousewheel_over_grabber = true; } } } - if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->is_pressed()) { grabbing_grabber = true; if (!mousewheel_over_grabber) { diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 030d36ff78..35cf330714 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -91,7 +91,7 @@ static Ref<Texture2D> flip_icon(Ref<Texture2D> p_texture, bool p_flip_y = false, } Ref<ImageTexture> texture(memnew(ImageTexture)); - Ref<Image> img = p_texture->get_data(); + Ref<Image> img = p_texture->get_image(); img = img->duplicate(); if (p_flip_y) { @@ -241,20 +241,14 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = // Generate icons. if (!p_only_thumbs) { for (int i = 0; i < editor_icons_count; i++) { - float icon_scale = EDSCALE; float saturation = p_icon_saturation; - // Always keep the DefaultProjectIcon at the default size - if (strcmp(editor_icons_names[i], "DefaultProjectIcon") == 0) { - icon_scale = 1.0f; - } - if (strcmp(editor_icons_names[i], "DefaultProjectIcon") == 0 || strcmp(editor_icons_names[i], "Godot") == 0 || strcmp(editor_icons_names[i], "Logo") == 0) { saturation = 1.0; } const int is_exception = exceptions.has(editor_icons_names[i]); - const Ref<ImageTexture> icon = editor_generate_icon(i, !is_exception, icon_scale, saturation); + const Ref<ImageTexture> icon = editor_generate_icon(i, !is_exception, EDSCALE, saturation); p_theme->set_icon(editor_icons_names[i], "EditorIcons", icon); } @@ -567,7 +561,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { style_tab_disabled->set_border_color(disabled_color); // Editor background - theme->set_stylebox("Background", "EditorStyles", make_flat_stylebox(background_color, default_margin_size, default_margin_size, default_margin_size, default_margin_size)); + Color background_color_opaque = background_color; + background_color_opaque.a = 1.0; + theme->set_stylebox("Background", "EditorStyles", make_flat_stylebox(background_color_opaque, default_margin_size, default_margin_size, default_margin_size, default_margin_size)); // Focus Ref<StyleBoxFlat> style_focus = style_default->duplicate(); @@ -1266,6 +1262,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // FileDialog theme->set_icon("folder", "FileDialog", theme->get_icon("Folder", "EditorIcons")); theme->set_icon("parent_folder", "FileDialog", theme->get_icon("ArrowUp", "EditorIcons")); + theme->set_icon("back_folder", "FileDialog", theme->get_icon("Back", "EditorIcons")); + theme->set_icon("forward_folder", "FileDialog", theme->get_icon("Forward", "EditorIcons")); theme->set_icon("reload", "FileDialog", theme->get_icon("Reload", "EditorIcons")); theme->set_icon("toggle_hidden", "FileDialog", theme->get_icon("GuiVisibilityVisible", "EditorIcons")); // Use a different color for folder icons to make them easier to distinguish from files. @@ -1398,3 +1396,15 @@ Ref<Theme> create_custom_theme(const Ref<Theme> p_theme) { return theme; } + +Ref<ImageTexture> create_unscaled_default_project_icon() { +#ifdef MODULE_SVG_ENABLED + for (int i = 0; i < editor_icons_count; i++) { + // ESCALE should never affect size of the icon + if (strcmp(editor_icons_names[i], "DefaultProjectIcon") == 0) { + return editor_generate_icon(i, false, 1.0); + } + } +#endif + return Ref<ImageTexture>(memnew(ImageTexture)); +} diff --git a/editor/editor_themes.h b/editor/editor_themes.h index 852edf7669..c040654220 100644 --- a/editor/editor_themes.h +++ b/editor/editor_themes.h @@ -31,10 +31,13 @@ #ifndef EDITOR_THEMES_H #define EDITOR_THEMES_H +#include "scene/resources/texture.h" #include "scene/resources/theme.h" Ref<Theme> create_editor_theme(Ref<Theme> p_theme = nullptr); Ref<Theme> create_custom_theme(Ref<Theme> p_theme = nullptr); +Ref<ImageTexture> create_unscaled_default_project_icon(); + #endif diff --git a/editor/editor_translation_parser.cpp b/editor/editor_translation_parser.cpp index 51bd9b3383..fd36372dde 100644 --- a/editor/editor_translation_parser.cpp +++ b/editor/editor_translation_parser.cpp @@ -38,8 +38,9 @@ EditorTranslationParser *EditorTranslationParser::singleton = nullptr; Error EditorTranslationParserPlugin::parse_file(const String &p_path, Vector<String> *r_ids, Vector<Vector<String>> *r_ids_ctx_plural) { - if (!get_script_instance()) + if (!get_script_instance()) { return ERR_UNAVAILABLE; + } if (get_script_instance()->has_method("parse_file")) { Array ids; @@ -70,8 +71,9 @@ Error EditorTranslationParserPlugin::parse_file(const String &p_path, Vector<Str } void EditorTranslationParserPlugin::get_recognized_extensions(List<String> *r_extensions) const { - if (!get_script_instance()) + if (!get_script_instance()) { return; + } if (get_script_instance()->has_method("get_recognized_extensions")) { Array extensions = get_script_instance()->call("get_recognized_extensions"); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 43bfccc656..899070f036 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -680,17 +680,17 @@ void FileSystemDock::_sort_file_info_list(List<FileSystemDock::FileInfo> &r_file break; case FILE_SORT_TYPE_REVERSE: r_file_list.sort_custom<FileInfoTypeComparator>(); - r_file_list.invert(); + r_file_list.reverse(); break; case FILE_SORT_MODIFIED_TIME: r_file_list.sort_custom<FileInfoModifiedTimeComparator>(); break; case FILE_SORT_MODIFIED_TIME_REVERSE: r_file_list.sort_custom<FileInfoModifiedTimeComparator>(); - r_file_list.invert(); + r_file_list.reverse(); break; case FILE_SORT_NAME_REVERSE: - r_file_list.invert(); + r_file_list.reverse(); break; default: // FILE_SORT_NAME break; @@ -944,8 +944,41 @@ void FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorit fpath = fpath.substr(0, fpath.length() - 1); } } else if (fpath != "Favorites") { + if (FileAccess::exists(fpath + ".import")) { + Ref<ConfigFile> config; + config.instance(); + Error err = config->load(fpath + ".import"); + if (err == OK) { + if (config->has_section_key("remap", "importer")) { + String importer = config->get_value("remap", "importer"); + if (importer == "keep") { + EditorNode::get_singleton()->show_warning(TTR("Importing has been disabled for this file, so it can't be opened for editing.")); + return; + } + } + } + } + if (ResourceLoader::get_resource_type(fpath) == "PackedScene") { - editor->open_request(fpath); + bool is_imported = false; + + { + List<String> importer_exts; + ResourceImporterScene::get_singleton()->get_recognized_extensions(&importer_exts); + String extension = fpath.get_extension(); + for (List<String>::Element *E = importer_exts.front(); E; E = E->next()) { + if (extension.nocasecmp_to(E->get()) == 0) { + is_imported = true; + break; + } + } + } + + if (is_imported) { + ResourceImporterScene::get_singleton()->show_advanced_options(fpath); + } else { + editor->open_request(fpath); + } } else { editor->load_resource(fpath); } @@ -2588,8 +2621,9 @@ void FileSystemDock::_get_imported_files(const String &p_path, Vector<String> &f } void FileSystemDock::_update_import_dock() { - if (!import_dock_needs_update) + if (!import_dock_needs_update) { return; + } // List selected. Vector<String> selected; @@ -2600,8 +2634,9 @@ void FileSystemDock::_update_import_dock() { } else { // Use the file list. for (int i = 0; i < files->get_item_count(); i++) { - if (!files->is_selected(i)) + if (!files->is_selected(i)) { continue; + } selected.push_back(files->get_item_metadata(i)); } @@ -2626,7 +2661,10 @@ void FileSystemDock::_update_import_dock() { break; } - String type = cf->get_value("remap", "type"); + String type; + if (cf->has_section_key("remap", "type")) { + type = cf->get_value("remap", "type"); + } if (import_type == "") { import_type = type; } else if (import_type != type) { diff --git a/editor/icons/GuiScrollBg.svg b/editor/icons/GuiScrollBg.svg index dd5c60e534..7cfe647368 100644 --- a/editor/icons/GuiScrollBg.svg +++ b/editor/icons/GuiScrollBg.svg @@ -1 +1 @@ -<svg height="12" viewBox="0 0 12 11.999999" width="12" xmlns="http://www.w3.org/2000/svg"/> +<svg height="12" viewBox="0 0 12 11.999999" width="12" xmlns="http://www.w3.org/2000/svg"><circle cx="6" cy="6" fill="#fff" fill-opacity=".082353" r="2"/></svg> diff --git a/editor/icons/GuiScrollGrabber.svg b/editor/icons/GuiScrollGrabber.svg index 16edfb567c..935f9361dd 100644 --- a/editor/icons/GuiScrollGrabber.svg +++ b/editor/icons/GuiScrollGrabber.svg @@ -1 +1 @@ -<svg height="12" viewBox="0 0 12 11.999999" width="12" xmlns="http://www.w3.org/2000/svg"><circle cx="6" cy="6" fill="#fff" fill-opacity=".27451" r="2"/></svg> +<svg height="12" viewBox="0 0 12 11.999999" width="12" xmlns="http://www.w3.org/2000/svg"><circle cx="6" cy="6" fill="#fff" fill-opacity=".294118" r="3"/></svg> diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index 50b13673fa..d3183e5a8d 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -79,6 +79,9 @@ struct ColladaImport { Vector<int> valid_animated_properties; Map<String, bool> bones_with_animation; + Set<String> mesh_unique_names; + Set<String> material_unique_names; + Error _populate_skeleton(Skeleton3D *p_skeleton, Collada::Node *p_node, int &r_bone, int p_parent); Error _create_scene_skeletons(Collada::Node *p_node); Error _create_scene(Collada::Node *p_node, Node3D *p_parent); @@ -326,12 +329,25 @@ Error ColladaImport::_create_material(const String &p_target) { Ref<StandardMaterial3D> material = memnew(StandardMaterial3D); + String base_name; if (src_mat.name != "") { - material->set_name(src_mat.name); + base_name = src_mat.name; } else if (effect.name != "") { - material->set_name(effect.name); + base_name = effect.name; + } else { + base_name = "Material"; } + String name = base_name; + int counter = 2; + while (material_unique_names.has(name)) { + name = base_name + itos(counter++); + } + + material_unique_names.insert(name); + + material->set_name(name); + // DIFFUSE if (effect.diffuse.texture != "") { @@ -681,7 +697,8 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor int vertex_index = p.indices[src + vertex_ofs]; //used for index field (later used by controllers) int vertex_pos = (vertex_src->stride ? vertex_src->stride : 3) * vertex_index; - ERR_FAIL_INDEX_V(vertex_pos, vertex_src->array.size(), ERR_INVALID_DATA); + ERR_FAIL_INDEX_V(vertex_pos + 0, vertex_src->array.size(), ERR_INVALID_DATA); + ERR_FAIL_INDEX_V(vertex_pos + 2, vertex_src->array.size(), ERR_INVALID_DATA); vertex.vertex = Vector3(vertex_src->array[vertex_pos + 0], vertex_src->array[vertex_pos + 1], vertex_src->array[vertex_pos + 2]); if (pre_weights.has(vertex_index)) { @@ -690,16 +707,19 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor if (normal_src) { int normal_pos = (normal_src->stride ? normal_src->stride : 3) * p.indices[src + normal_ofs]; - ERR_FAIL_INDEX_V(normal_pos, normal_src->array.size(), ERR_INVALID_DATA); + ERR_FAIL_INDEX_V(normal_pos + 0, normal_src->array.size(), ERR_INVALID_DATA); + ERR_FAIL_INDEX_V(normal_pos + 2, normal_src->array.size(), ERR_INVALID_DATA); vertex.normal = Vector3(normal_src->array[normal_pos + 0], normal_src->array[normal_pos + 1], normal_src->array[normal_pos + 2]); if (tangent_src && binormal_src) { int binormal_pos = (binormal_src->stride ? binormal_src->stride : 3) * p.indices[src + binormal_ofs]; - ERR_FAIL_INDEX_V(binormal_pos, binormal_src->array.size(), ERR_INVALID_DATA); + ERR_FAIL_INDEX_V(binormal_pos + 0, binormal_src->array.size(), ERR_INVALID_DATA); + ERR_FAIL_INDEX_V(binormal_pos + 2, binormal_src->array.size(), ERR_INVALID_DATA); Vector3 binormal = Vector3(binormal_src->array[binormal_pos + 0], binormal_src->array[binormal_pos + 1], binormal_src->array[binormal_pos + 2]); int tangent_pos = (tangent_src->stride ? tangent_src->stride : 3) * p.indices[src + tangent_ofs]; - ERR_FAIL_INDEX_V(tangent_pos, tangent_src->array.size(), ERR_INVALID_DATA); + ERR_FAIL_INDEX_V(tangent_pos + 0, tangent_src->array.size(), ERR_INVALID_DATA); + ERR_FAIL_INDEX_V(tangent_pos + 2, tangent_src->array.size(), ERR_INVALID_DATA); Vector3 tangent = Vector3(tangent_src->array[tangent_pos + 0], tangent_src->array[tangent_pos + 1], tangent_src->array[tangent_pos + 2]); vertex.tangent.normal = tangent; @@ -709,19 +729,22 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor if (uv_src) { int uv_pos = (uv_src->stride ? uv_src->stride : 2) * p.indices[src + uv_ofs]; - ERR_FAIL_INDEX_V(uv_pos, uv_src->array.size(), ERR_INVALID_DATA); + ERR_FAIL_INDEX_V(uv_pos + 0, uv_src->array.size(), ERR_INVALID_DATA); + ERR_FAIL_INDEX_V(uv_pos + 1, uv_src->array.size(), ERR_INVALID_DATA); vertex.uv = Vector3(uv_src->array[uv_pos + 0], 1.0 - uv_src->array[uv_pos + 1], 0); } if (uv2_src) { int uv2_pos = (uv2_src->stride ? uv2_src->stride : 2) * p.indices[src + uv2_ofs]; - ERR_FAIL_INDEX_V(uv2_pos, uv2_src->array.size(), ERR_INVALID_DATA); + ERR_FAIL_INDEX_V(uv2_pos + 0, uv2_src->array.size(), ERR_INVALID_DATA); + ERR_FAIL_INDEX_V(uv2_pos + 1, uv2_src->array.size(), ERR_INVALID_DATA); vertex.uv2 = Vector3(uv2_src->array[uv2_pos + 0], 1.0 - uv2_src->array[uv2_pos + 1], 0); } if (color_src) { int color_pos = (color_src->stride ? color_src->stride : 3) * p.indices[src + color_ofs]; // colors are RGB in collada.. - ERR_FAIL_INDEX_V(color_pos, color_src->array.size(), ERR_INVALID_DATA); + ERR_FAIL_INDEX_V(color_pos + 0, color_src->array.size(), ERR_INVALID_DATA); + ERR_FAIL_INDEX_V(color_pos + ((color_src->stride > 3) ? 3 : 2), color_src->array.size(), ERR_INVALID_DATA); vertex.color = Color(color_src->array[color_pos + 0], color_src->array[color_pos + 1], color_src->array[color_pos + 2], (color_src->stride > 3) ? color_src->array[color_pos + 3] : 1.0); } @@ -1121,7 +1144,22 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres ERR_FAIL_COND_V(!collada.state.mesh_data_map.has(meshid), ERR_INVALID_DATA); mesh = Ref<EditorSceneImporterMesh>(memnew(EditorSceneImporterMesh)); const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid]; - mesh->set_name(meshdata.name); + String name = meshdata.name; + if (name == "") { + name = "Mesh"; + } + int counter = 2; + while (mesh_unique_names.has(name)) { + name = meshdata.name; + if (name == "") { + name = "Mesh"; + } + name += itos(counter++); + } + + mesh_unique_names.insert(name); + + mesh->set_name(name); Error err = _create_mesh_surfaces(morphs.size() == 0, mesh, ng2->material_map, meshdata, apply_xform, bone_remap, skin, morph, morphs, p_use_compression, use_mesh_builtin_materials); ERR_FAIL_COND_V_MSG(err, err, "Cannot create mesh surface."); @@ -1638,16 +1676,23 @@ void EditorSceneImporterCollada::get_extensions(List<String> *r_extensions) cons } Node *EditorSceneImporterCollada::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { + if (r_err) { + *r_err = OK; + } ColladaImport state; uint32_t flags = Collada::IMPORT_FLAG_SCENE; if (p_flags & IMPORT_ANIMATION) { flags |= Collada::IMPORT_FLAG_ANIMATION; } - state.use_mesh_builtin_materials = !(p_flags & IMPORT_MATERIALS_IN_INSTANCES); + state.use_mesh_builtin_materials = true; state.bake_fps = p_bake_fps; - Error err = state.load(p_path, flags, p_flags & EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS, p_flags & EditorSceneImporter::IMPORT_USE_COMPRESSION); + Error err = state.load(p_path, flags, p_flags & EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS, false); + + if (r_err) { + *r_err = err; + } ERR_FAIL_COND_V_MSG(err != OK, nullptr, "Cannot load scene from file '" + p_path + "'."); @@ -1667,7 +1712,7 @@ Node *EditorSceneImporterCollada::import_scene(const String &p_path, uint32_t p_ } if (p_flags & IMPORT_ANIMATION) { - state.create_animations(p_flags & IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS, p_flags & EditorSceneImporter::IMPORT_ANIMATION_KEEP_VALUE_TRACKS); + state.create_animations(true, true); AnimationPlayer *ap = memnew(AnimationPlayer); for (int i = 0; i < state.animations.size(); i++) { String name; @@ -1677,12 +1722,6 @@ Node *EditorSceneImporterCollada::import_scene(const String &p_path, uint32_t p_ name = state.animations[i]->get_name(); } - if (p_flags & IMPORT_ANIMATION_DETECT_LOOP) { - if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) { - state.animations.write[i]->set_loop(true); - } - } - ap->add_animation(name, state.animations[i]); } state.scene->add_child(ap); @@ -1700,7 +1739,7 @@ Ref<Animation> EditorSceneImporterCollada::import_animation(const String &p_path Error err = state.load(p_path, Collada::IMPORT_FLAG_ANIMATION, p_flags & EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS); ERR_FAIL_COND_V_MSG(err != OK, RES(), "Cannot load animation from file '" + p_path + "'."); - state.create_animations(p_flags & EditorSceneImporter::IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS, p_flags & EditorSceneImporter::IMPORT_ANIMATION_KEEP_VALUE_TRACKS); + state.create_animations(true, true); if (state.scene) { memdelete(state.scene); } @@ -1709,12 +1748,6 @@ Ref<Animation> EditorSceneImporterCollada::import_animation(const String &p_path return Ref<Animation>(); } Ref<Animation> anim = state.animations[0]; - String base = p_path.get_basename().to_lower(); - if (p_flags & IMPORT_ANIMATION_DETECT_LOOP) { - if (base.begins_with("loop") || base.ends_with("loop") || base.begins_with("cycle") || base.ends_with("cycle")) { - anim->set_loop(true); - } - } return anim; } diff --git a/editor/import/resource_importer_csv.h b/editor/import/resource_importer_csv.h deleted file mode 100644 index 0f137624b9..0000000000 --- a/editor/import/resource_importer_csv.h +++ /dev/null @@ -1,57 +0,0 @@ -/*************************************************************************/ -/* resource_importer_csv.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 RESOURCEIMPORTERCSV_H -#define RESOURCEIMPORTERCSV_H - -#include "core/io/resource_importer.h" - -class ResourceImporterCSV : public ResourceImporter { - GDCLASS(ResourceImporterCSV, ResourceImporter); - -public: - virtual String get_importer_name() const override; - virtual String get_visible_name() const override; - 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; - - virtual int get_preset_count() const override; - virtual String get_preset_name(int p_idx) const override; - - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; - - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; - - ResourceImporterCSV(); -}; - -#endif // RESOURCEIMPORTERCSV_H diff --git a/editor/import/resource_importer_csv_translation.cpp b/editor/import/resource_importer_csv_translation.cpp index 7ea39ab3ef..4a4d9d8f06 100644 --- a/editor/import/resource_importer_csv_translation.cpp +++ b/editor/import/resource_importer_csv_translation.cpp @@ -32,7 +32,7 @@ #include "core/io/resource_saver.h" #include "core/os/file_access.h" -#include "core/string/compressed_translation.h" +#include "core/string/optimized_translation.h" #include "core/string/translation.h" String ResourceImporterCSVTranslation::get_importer_name() const { @@ -126,7 +126,7 @@ Error ResourceImporterCSVTranslation::import(const String &p_source_file, const Ref<Translation> xlt = translations[i]; if (compress) { - Ref<PHashTranslation> cxl = memnew(PHashTranslation); + Ref<OptimizedTranslation> cxl = memnew(OptimizedTranslation); cxl->generate(xlt); xlt = cxl; } diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp index 9111252943..dd62c72d8a 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/resource_importer_obj.cpp @@ -427,7 +427,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { List<Ref<Mesh>> meshes; - Error err = _parse_obj(p_path, meshes, false, p_flags & IMPORT_GENERATE_TANGENT_ARRAYS, p_flags & IMPORT_USE_COMPRESSION, Vector3(1, 1, 1), Vector3(0, 0, 0), r_missing_deps); + Error err = _parse_obj(p_path, meshes, false, p_flags & IMPORT_GENERATE_TANGENT_ARRAYS, false, Vector3(1, 1, 1), Vector3(0, 0, 0), r_missing_deps); if (err != OK) { if (r_err) { diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 14ecccc13e..9041b815ca 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -32,7 +32,9 @@ #include "core/io/resource_saver.h" #include "editor/editor_node.h" +#include "editor/import/scene_import_settings.h" #include "editor/import/scene_importer_mesh_node_3d.h" +#include "scene/3d/area_3d.h" #include "scene/3d/collision_shape_3d.h" #include "scene/3d/mesh_instance_3d.h" #include "scene/3d/navigation_region_3d.h" @@ -111,20 +113,14 @@ void EditorSceneImporter::_bind_methods() { BIND_CONSTANT(IMPORT_SCENE); BIND_CONSTANT(IMPORT_ANIMATION); - BIND_CONSTANT(IMPORT_ANIMATION_DETECT_LOOP); - BIND_CONSTANT(IMPORT_ANIMATION_OPTIMIZE); - BIND_CONSTANT(IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS); - BIND_CONSTANT(IMPORT_ANIMATION_KEEP_VALUE_TRACKS); - BIND_CONSTANT(IMPORT_GENERATE_TANGENT_ARRAYS); BIND_CONSTANT(IMPORT_FAIL_ON_MISSING_DEPENDENCIES); - BIND_CONSTANT(IMPORT_MATERIALS_IN_INSTANCES); - BIND_CONSTANT(IMPORT_USE_COMPRESSION); + BIND_CONSTANT(IMPORT_GENERATE_TANGENT_ARRAYS); + BIND_CONSTANT(IMPORT_USE_NAMED_SKIN_BINDS); } ///////////////////////////////// void EditorScenePostImport::_bind_methods() { BIND_VMETHOD(MethodInfo(Variant::OBJECT, "post_import", PropertyInfo(Variant::OBJECT, "scene"))); - ClassDB::bind_method(D_METHOD("get_source_folder"), &EditorScenePostImport::get_source_folder); ClassDB::bind_method(D_METHOD("get_source_file"), &EditorScenePostImport::get_source_file); } @@ -136,16 +132,11 @@ Node *EditorScenePostImport::post_import(Node *p_scene) { return p_scene; } -String EditorScenePostImport::get_source_folder() const { - return source_folder; -} - String EditorScenePostImport::get_source_file() const { return source_file; } -void EditorScenePostImport::init(const String &p_source_folder, const String &p_source_file) { - source_folder = p_source_folder; +void EditorScenePostImport::init(const String &p_source_file) { source_file = p_source_file; } @@ -183,29 +174,9 @@ bool ResourceImporterScene::get_option_visibility(const String &p_option, const if (p_option != "animation/import" && !bool(p_options["animation/import"])) { return false; } - - if (p_option == "animation/keep_custom_tracks" && int(p_options["animation/storage"]) == 0) { - return false; - } - - if (p_option.begins_with("animation/optimizer/") && p_option != "animation/optimizer/enabled" && !bool(p_options["animation/optimizer/enabled"])) { - return false; - } - - if (p_option.begins_with("animation/clip_")) { - int max_clip = p_options["animation/clips/amount"]; - int clip = p_option.get_slice("/", 1).get_slice("_", 1).to_int() - 1; - if (clip >= max_clip) { - return false; - } - } - } - - if (p_option == "materials/keep_on_reimport" && int(p_options["materials/storage"]) == 0) { - return false; } - if (p_option == "meshes/lightmap_texel_size" && int(p_options["meshes/light_baking"]) < 2) { + if (p_option == "meshes/lightmap_texel_size" && int(p_options["meshes/light_baking"]) < 3) { return false; } @@ -213,34 +184,11 @@ bool ResourceImporterScene::get_option_visibility(const String &p_option, const } int ResourceImporterScene::get_preset_count() const { - return PRESET_MAX; + return 0; } String ResourceImporterScene::get_preset_name(int p_idx) const { - switch (p_idx) { - case PRESET_SINGLE_SCENE: - return TTR("Import as Single Scene"); - case PRESET_SEPARATE_ANIMATIONS: - return TTR("Import with Separate Animations"); - case PRESET_SEPARATE_MATERIALS: - return TTR("Import with Separate Materials"); - case PRESET_SEPARATE_MESHES: - return TTR("Import with Separate Objects"); - case PRESET_SEPARATE_MESHES_AND_MATERIALS: - return TTR("Import with Separate Objects+Materials"); - case PRESET_SEPARATE_MESHES_AND_ANIMATIONS: - return TTR("Import with Separate Objects+Animations"); - case PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS: - return TTR("Import with Separate Materials+Animations"); - case PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS: - return TTR("Import with Separate Objects+Materials+Animations"); - case PRESET_MULTIPLE_SCENES: - return TTR("Import as Multiple Scenes"); - case PRESET_MULTIPLE_SCENES_AND_MATERIALS: - return TTR("Import as Multiple Scenes+Materials"); - } - - return ""; + return String(); } static bool _teststr(const String &p_what, const String &p_str) { @@ -286,6 +234,7 @@ static String _fixstr(const String &p_what, const String &p_str) { } static void _gen_shape_list(const Ref<Mesh> &mesh, List<Ref<Shape3D>> &r_shape_list, bool p_convex) { + ERR_FAIL_NULL_MSG(mesh, "Cannot generate shape list with null mesh value"); if (!p_convex) { Ref<Shape3D> shape = mesh->create_trimesh_shape(); r_shape_list.push_back(shape); @@ -299,10 +248,25 @@ static void _gen_shape_list(const Ref<Mesh> &mesh, List<Ref<Shape3D>> &r_shape_l } } -Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape3D>>> &collision_map, LightBakeMode p_light_bake_mode) { +static void _pre_gen_shape_list(const Ref<EditorSceneImporterMesh> &mesh, List<Ref<Shape3D>> &r_shape_list, bool p_convex) { + ERR_FAIL_NULL_MSG(mesh, "Cannot generate shape list with null mesh value"); + if (!p_convex) { + Ref<Shape3D> shape = mesh->create_trimesh_shape(); + r_shape_list.push_back(shape); + } else { + Vector<Ref<Shape3D>> cd = mesh->convex_decompose(); + if (cd.size()) { + for (int i = 0; i < cd.size(); i++) { + r_shape_list.push_back(cd[i]); + } + } + } +} + +Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map) { // children first for (int i = 0; i < p_node->get_child_count(); i++) { - Node *r = _fix_node(p_node->get_child(i), p_root, collision_map, p_light_bake_mode); + Node *r = _pre_fix_node(p_node->get_child(i), p_root, collision_map); if (!r) { i--; //was erased } @@ -317,33 +281,29 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> return nullptr; } - if (Object::cast_to<MeshInstance3D>(p_node)) { - MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node); + if (Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { + EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); - Ref<ArrayMesh> m = mi->get_mesh(); + Ref<EditorSceneImporterMesh> m = mi->get_mesh(); if (m.is_valid()) { for (int i = 0; i < m->get_surface_count(); i++) { - Ref<StandardMaterial3D> mat = m->surface_get_material(i); + Ref<BaseMaterial3D> mat = m->get_surface_material(i); if (!mat.is_valid()) { continue; } if (_teststr(mat->get_name(), "alpha")) { - mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); + mat->set_transparency(BaseMaterial3D::TRANSPARENCY_ALPHA); mat->set_name(_fixstr(mat->get_name(), "alpha")); } if (_teststr(mat->get_name(), "vcol")) { - mat->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - mat->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); + mat->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + mat->set_flag(BaseMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); mat->set_name(_fixstr(mat->get_name(), "vcol")); } } } - - if (p_light_bake_mode != LIGHT_BAKE_DISABLED) { - mi->set_gi_mode(GeometryInstance3D::GI_MODE_BAKED); - } } if (Object::cast_to<AnimationPlayer>(p_node)) { @@ -367,6 +327,17 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> } } } + + String animname = E->get(); + const int loop_string_count = 3; + static const char *loop_strings[loop_string_count] = { "loops", "loop", "cycle" }; + for (int i = 0; i < loop_string_count; i++) { + if (_teststr(animname, loop_strings[i])) { + anim->set_loop(true); + animname = _fixstr(animname, loop_strings[i]); + ap->rename_animation(E->get(), animname); + } + } } } @@ -374,9 +345,9 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> if (isroot) { return p_node; } - MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node); + EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); if (mi) { - Ref<Mesh> mesh = mi->get_mesh(); + Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { List<Ref<Shape3D>> shapes; @@ -384,10 +355,10 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> if (collision_map.has(mesh)) { shapes = collision_map[mesh]; } else if (_teststr(name, "colonly")) { - _gen_shape_list(mesh, shapes, false); + _pre_gen_shape_list(mesh, shapes, false); collision_map[mesh] = shapes; } else if (_teststr(name, "convcolonly")) { - _gen_shape_list(mesh, shapes, true); + _pre_gen_shape_list(mesh, shapes, true); collision_map[mesh] = shapes; } @@ -407,16 +378,7 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> memdelete(p_node); p_node = col; - int idx = 0; - for (List<Ref<Shape3D>>::Element *E = shapes.front(); E; E = E->next()) { - CollisionShape3D *cshape = memnew(CollisionShape3D); - cshape->set_shape(E->get()); - col->add_child(cshape); - - cshape->set_name("shape" + itos(idx)); - cshape->set_owner(col->get_owner()); - idx++; - } + _add_shapes(col, shapes); } } @@ -433,34 +395,30 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> BoxShape3D *boxShape = memnew(BoxShape3D); boxShape->set_size(Vector3(2, 2, 2)); colshape->set_shape(boxShape); - colshape->set_name("BoxShape3D"); } else if (empty_draw_type == "SINGLE_ARROW") { RayShape3D *rayShape = memnew(RayShape3D); rayShape->set_length(1); colshape->set_shape(rayShape); - colshape->set_name("RayShape3D"); Object::cast_to<Node3D>(sb)->rotate_x(Math_PI / 2); } else if (empty_draw_type == "IMAGE") { WorldMarginShape3D *world_margin_shape = memnew(WorldMarginShape3D); colshape->set_shape(world_margin_shape); - colshape->set_name("WorldMarginShape3D"); } else { SphereShape3D *sphereShape = memnew(SphereShape3D); sphereShape->set_radius(1); colshape->set_shape(sphereShape); - colshape->set_name("SphereShape3D"); } sb->add_child(colshape); colshape->set_owner(sb->get_owner()); } - } else if (_teststr(name, "rigid") && Object::cast_to<MeshInstance3D>(p_node)) { + } else if (_teststr(name, "rigid") && Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { if (isroot) { return p_node; } - MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node); - Ref<Mesh> mesh = mi->get_mesh(); + EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); + Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { List<Ref<Shape3D>> shapes; @@ -475,27 +433,17 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> p_node->replace_by(rigid_body); rigid_body->set_transform(mi->get_transform()); p_node = rigid_body; - mi->set_name("mesh"); mi->set_transform(Transform()); rigid_body->add_child(mi); mi->set_owner(rigid_body->get_owner()); - int idx = 0; - for (List<Ref<Shape3D>>::Element *E = shapes.front(); E; E = E->next()) { - CollisionShape3D *cshape = memnew(CollisionShape3D); - cshape->set_shape(E->get()); - rigid_body->add_child(cshape); - - cshape->set_name("shape" + itos(idx)); - cshape->set_owner(p_node->get_owner()); - idx++; - } + _add_shapes(rigid_body, shapes); } - } else if ((_teststr(name, "col") || (_teststr(name, "convcol"))) && Object::cast_to<MeshInstance3D>(p_node)) { - MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node); + } else if ((_teststr(name, "col") || (_teststr(name, "convcol"))) && Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { + EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); - Ref<Mesh> mesh = mi->get_mesh(); + Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { List<Ref<Shape3D>> shapes; @@ -524,89 +472,38 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> if (shapes.size()) { StaticBody3D *col = memnew(StaticBody3D); - col->set_name("static_collision"); mi->add_child(col); col->set_owner(mi->get_owner()); - int idx = 0; - for (List<Ref<Shape3D>>::Element *E = shapes.front(); E; E = E->next()) { - CollisionShape3D *cshape = memnew(CollisionShape3D); - cshape->set_shape(E->get()); - col->add_child(cshape); - - cshape->set_name("shape" + itos(idx)); - cshape->set_owner(p_node->get_owner()); - - idx++; - } + _add_shapes(col, shapes); } } - } else if (_teststr(name, "navmesh") && Object::cast_to<MeshInstance3D>(p_node)) { + } else if (_teststr(name, "navmesh") && Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { if (isroot) { return p_node; } - MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node); + EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); - Ref<ArrayMesh> mesh = mi->get_mesh(); + Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); ERR_FAIL_COND_V(mesh.is_null(), nullptr); NavigationRegion3D *nmi = memnew(NavigationRegion3D); nmi->set_name(_fixstr(name, "navmesh")); - Ref<NavigationMesh> nmesh = memnew(NavigationMesh); - nmesh->create_from_mesh(mesh); + Ref<NavigationMesh> nmesh = mesh->create_navigation_mesh(); nmi->set_navigation_mesh(nmesh); Object::cast_to<Node3D>(nmi)->set_transform(mi->get_transform()); p_node->replace_by(nmi); memdelete(p_node); p_node = nmi; - } else if (_teststr(name, "vehicle")) { - if (isroot) { - return p_node; - } - - Node *owner = p_node->get_owner(); - Node3D *s = Object::cast_to<Node3D>(p_node); - VehicleBody3D *bv = memnew(VehicleBody3D); - String n = _fixstr(p_node->get_name(), "vehicle"); - bv->set_name(n); - p_node->replace_by(bv); - p_node->set_name(n); - bv->add_child(p_node); - bv->set_owner(owner); - p_node->set_owner(owner); - bv->set_transform(s->get_transform()); - s->set_transform(Transform()); - - p_node = bv; - - } else if (_teststr(name, "wheel")) { - if (isroot) { - return p_node; - } - Node *owner = p_node->get_owner(); - Node3D *s = Object::cast_to<Node3D>(p_node); - VehicleWheel3D *bv = memnew(VehicleWheel3D); - String n = _fixstr(p_node->get_name(), "wheel"); - bv->set_name(n); - p_node->replace_by(bv); - p_node->set_name(n); - bv->add_child(p_node); - bv->set_owner(owner); - p_node->set_owner(owner); - bv->set_transform(s->get_transform()); - s->set_transform(Transform()); - - p_node = bv; - - } else if (Object::cast_to<MeshInstance3D>(p_node)) { + } else if (Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { //last attempt, maybe collision inside the mesh data - MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node); + EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); - Ref<ArrayMesh> mesh = mi->get_mesh(); + Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); if (!mesh.is_null()) { List<Ref<Shape3D>> shapes; if (collision_map.has(mesh)) { @@ -623,19 +520,268 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> if (shapes.size()) { StaticBody3D *col = memnew(StaticBody3D); - col->set_name("static_collision"); p_node->add_child(col); col->set_owner(p_node->get_owner()); - int idx = 0; - for (List<Ref<Shape3D>>::Element *E = shapes.front(); E; E = E->next()) { - CollisionShape3D *cshape = memnew(CollisionShape3D); - cshape->set_shape(E->get()); - col->add_child(cshape); + _add_shapes(col, shapes); + } + } + } + + return p_node; +} + +Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &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++) { + Node *r = _post_fix_node(p_node->get_child(i), p_root, collision_map, r_scanned_meshes, p_node_data, p_material_data, p_animation_data, p_animation_fps); + if (!r) { + i--; //was erased + } + } + + bool isroot = p_node == p_root; + + String import_id; + + if (p_node->has_meta("import_id")) { + import_id = p_node->get_meta("import_id"); + } else { + 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]; + } + + if (!isroot && (node_settings.has("import/skip_import") && bool(node_settings["import/skip_import"]))) { + memdelete(p_node); + return nullptr; + } + + if (Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { + EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); + + Ref<EditorSceneImporterMesh> m = mi->get_mesh(); + + if (m.is_valid()) { + if (!r_scanned_meshes.has(m)) { + for (int i = 0; i < m->get_surface_count(); i++) { + Ref<Material> mat = m->get_surface_material(i); + if (mat.is_valid()) { + String mat_id; + if (mat->has_meta("import_id")) { + mat_id = mat->get_meta("import_id"); + } else { + mat_id = mat->get_name(); + } + + if (mat_id != String() && p_material_data.has(mat_id)) { + Dictionary matdata = p_material_data[mat_id]; + if (matdata.has("use_external/enabled") && bool(matdata["use_external/enabled"]) && matdata.has("use_external/path")) { + String path = matdata["use_external/path"]; + Ref<Material> external_mat = ResourceLoader::load(path); + if (external_mat.is_valid()) { + m->set_surface_material(i, external_mat); + } + } + } + } + } + + r_scanned_meshes.insert(m); + } + + if (node_settings.has("generate/physics")) { + int mesh_physics_mode = node_settings["generate/physics"]; + + if (mesh_physics_mode != MESH_PHYSICS_DISABLED) { + List<Ref<Shape3D>> shapes; + + if (collision_map.has(m)) { + shapes = collision_map[m]; + } else { + switch (mesh_physics_mode) { + case MESH_PHYSICS_MESH_AND_STATIC_COLLIDER: { + _pre_gen_shape_list(m, shapes, false); + } break; + case MESH_PHYSICS_RIGID_BODY_AND_MESH: { + _pre_gen_shape_list(m, shapes, true); + } break; + case MESH_PHYSICS_STATIC_COLLIDER_ONLY: { + _pre_gen_shape_list(m, shapes, false); + } break; + case MESH_PHYSICS_AREA_ONLY: { + _pre_gen_shape_list(m, shapes, true); + } break; + } + } + + if (shapes.size()) { + CollisionObject3D *base = nullptr; + switch (mesh_physics_mode) { + case MESH_PHYSICS_MESH_AND_STATIC_COLLIDER: { + StaticBody3D *col = memnew(StaticBody3D); + p_node->add_child(col); + base = col; + } break; + case MESH_PHYSICS_RIGID_BODY_AND_MESH: { + RigidBody3D *rigid_body = memnew(RigidBody3D); + rigid_body->set_name(p_node->get_name()); + p_node->replace_by(rigid_body); + rigid_body->set_transform(mi->get_transform()); + p_node = rigid_body; + mi->set_transform(Transform()); + rigid_body->add_child(mi); + mi->set_owner(rigid_body->get_owner()); + base = rigid_body; + } break; + case MESH_PHYSICS_STATIC_COLLIDER_ONLY: { + StaticBody3D *col = memnew(StaticBody3D); + col->set_transform(mi->get_transform()); + col->set_name(p_node->get_name()); + p_node->replace_by(col); + memdelete(p_node); + p_node = col; + base = col; + } break; + case MESH_PHYSICS_AREA_ONLY: { + Area3D *area = memnew(Area3D); + area->set_transform(mi->get_transform()); + area->set_name(p_node->get_name()); + p_node->replace_by(area); + memdelete(p_node); + p_node = area; + base = area; + + } break; + } + + int idx = 0; + for (List<Ref<Shape3D>>::Element *E = shapes.front(); E; E = E->next()) { + CollisionShape3D *cshape = memnew(CollisionShape3D); + cshape->set_shape(E->get()); + base->add_child(cshape); + + cshape->set_owner(base->get_owner()); + idx++; + } + } + } + } + } + } + + //navmesh (node may have changed type above) + if (Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { + EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); - cshape->set_name("shape" + itos(idx)); - cshape->set_owner(p_node->get_owner()); - idx++; + Ref<EditorSceneImporterMesh> m = mi->get_mesh(); + + if (m.is_valid()) { + if (node_settings.has("generate/navmesh")) { + int navmesh_mode = node_settings["generate/navmesh"]; + + if (navmesh_mode != NAVMESH_DISABLED) { + NavigationRegion3D *nmi = memnew(NavigationRegion3D); + + Ref<NavigationMesh> nmesh = m->create_navigation_mesh(); + nmi->set_navigation_mesh(nmesh); + + if (navmesh_mode == NAVMESH_NAVMESH_ONLY) { + nmi->set_transform(mi->get_transform()); + p_node->replace_by(nmi); + memdelete(p_node); + p_node = nmi; + } else { + mi->add_child(nmi); + nmi->set_owner(mi->get_owner()); + } + } + } + } + } + + if (Object::cast_to<AnimationPlayer>(p_node)) { + AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node); + + { + //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 (List<ImportOption>::Element *E = iopts.front(); E; E = E->next()) { + if (!node_settings.has(E->get().option.name)) { + node_settings[E->get().option.name] = E->get().default_value; + } + } + } + + 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"]; + bool loop = node_settings["clip_" + itos(i + 1) + "/loops"]; + 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); + 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 (List<StringName>::Element *E = anims.front(); E; E = E->next()) { + String name = E->get(); + 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 (List<ImportOption>::Element *F = iopts.front(); F; F = F->next()) { + if (!anim_settings.has(F->get().option.name)) { + anim_settings[F->get().option.name] = F->get().default_value; + } + } + } + + anim->set_loop(anim_settings["settings/loops"]); + 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) { + ap->add_animation(name, saved_anim); //replace + } } } } @@ -644,27 +790,52 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> return p_node; } -void ResourceImporterScene::_create_clips(Node *scene, const Array &p_clips, bool p_bake_all) { - if (!scene->has_node(String("AnimationPlayer"))) { - return; +Ref<Animation> ResourceImporterScene::_save_animation_to_file(Ref<Animation> anim, bool p_save_to_file, String p_save_to_path, bool p_keep_custom_tracks) { + if (!p_save_to_file || !p_save_to_path.is_resource_file()) { + return anim; } - Node *n = scene->get_node(String("AnimationPlayer")); - ERR_FAIL_COND(!n); - AnimationPlayer *anim = Object::cast_to<AnimationPlayer>(n); - ERR_FAIL_COND(!anim); + if (FileAccess::exists(p_save_to_path) && p_keep_custom_tracks) { + // Copy custom animation tracks from previously imported files. + Ref<Animation> old_anim = ResourceLoader::load(p_save_to_path, "Animation", ResourceFormatLoader::CACHE_MODE_IGNORE); + if (old_anim.is_valid()) { + for (int i = 0; i < old_anim->get_track_count(); i++) { + if (!old_anim->track_is_imported(i)) { + old_anim->copy_track(i, anim); + } + } + anim->set_loop(old_anim->has_loop()); + } + } + if (ResourceCache::has(p_save_to_path)) { + Ref<Animation> old_anim = Ref<Resource>(ResourceCache::get(p_save_to_path)); + if (old_anim.is_valid()) { + old_anim->copy_from(anim); + anim = old_anim; + } + } + 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); + ERR_FAIL_COND_V_MSG(err != OK, anim, "Saving of animation failed: " + p_save_to_path); + return anim; +} + +void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_clips, bool p_bake_all) { if (!anim->has_animation("default")) { return; } Ref<Animation> default_anim = anim->get_animation("default"); - for (int i = 0; i < p_clips.size(); i += 4) { + for (int i = 0; i < p_clips.size(); i += 7) { String name = p_clips[i]; float from = p_clips[i + 1]; float to = p_clips[i + 2]; bool loop = p_clips[i + 3]; + bool save_to_file = p_clips[i + 4]; + String save_to_path = p_clips[i + 5]; + bool keep_current = p_clips[i + 6]; if (from >= to) { continue; } @@ -752,141 +923,17 @@ void ResourceImporterScene::_create_clips(Node *scene, const Array &p_clips, boo new_anim->set_loop(loop); new_anim->set_length(to - from); anim->add_animation(name, new_anim); - } - - anim->remove_animation("default"); //remove default (no longer needed) -} - -void ResourceImporterScene::_filter_anim_tracks(Ref<Animation> anim, Set<String> &keep) { - Ref<Animation> a = anim; - ERR_FAIL_COND(!a.is_valid()); - - for (int j = 0; j < a->get_track_count(); j++) { - String path = a->track_get_path(j); - if (!keep.has(path)) { - a->remove_track(j); - j--; + Ref<Animation> saved_anim = _save_animation_to_file(new_anim, save_to_file, save_to_path, keep_current); + if (saved_anim != new_anim) { + anim->add_animation(name, saved_anim); } } -} - -void ResourceImporterScene::_filter_tracks(Node *scene, const String &p_text) { - if (!scene->has_node(String("AnimationPlayer"))) { - return; - } - Node *n = scene->get_node(String("AnimationPlayer")); - ERR_FAIL_COND(!n); - AnimationPlayer *anim = Object::cast_to<AnimationPlayer>(n); - ERR_FAIL_COND(!anim); - - Vector<String> strings = p_text.split("\n"); - for (int i = 0; i < strings.size(); i++) { - strings.write[i] = strings[i].strip_edges(); - } - - List<StringName> anim_names; - anim->get_animation_list(&anim_names); - for (List<StringName>::Element *E = anim_names.front(); E; E = E->next()) { - String name = E->get(); - bool valid_for_this = false; - bool valid = false; - - Set<String> keep; - Set<String> keep_local; - - for (int i = 0; i < strings.size(); i++) { - if (strings[i].begins_with("@")) { - valid_for_this = false; - for (Set<String>::Element *F = keep_local.front(); F; F = F->next()) { - keep.insert(F->get()); - } - keep_local.clear(); - - Vector<String> filters = strings[i].substr(1, strings[i].length()).split(","); - for (int j = 0; j < filters.size(); j++) { - String fname = filters[j].strip_edges(); - if (fname == "") { - continue; - } - int fc = fname[0]; - bool plus; - if (fc == '+') { - plus = true; - } else if (fc == '-') { - plus = false; - } else { - continue; - } - String filter = fname.substr(1, fname.length()).strip_edges(); - - if (!name.matchn(filter)) { - continue; - } - valid_for_this = plus; - } - - if (valid_for_this) { - valid = true; - } - - } else if (valid_for_this) { - Ref<Animation> a = anim->get_animation(name); - if (!a.is_valid()) { - continue; - } - - for (int j = 0; j < a->get_track_count(); j++) { - String path = a->track_get_path(j); - - String tname = strings[i]; - if (tname == "") { - continue; - } - int fc = tname[0]; - bool plus; - if (fc == '+') { - plus = true; - } else if (fc == '-') { - plus = false; - } else { - continue; - } - - String filter = tname.substr(1, tname.length()).strip_edges(); - - if (!path.matchn(filter)) { - continue; - } - - if (plus) { - keep_local.insert(path); - } else if (!keep.has(path)) { - keep_local.erase(path); - } - } - } - } - - if (valid) { - for (Set<String>::Element *F = keep_local.front(); F; F = F->next()) { - keep.insert(F->get()); - } - _filter_anim_tracks(anim->get_animation(name), keep); - } - } + anim->remove_animation("default"); //remove default (no longer needed) } -void ResourceImporterScene::_optimize_animations(Node *scene, float p_max_lin_error, float p_max_ang_error, float p_max_angle) { - if (!scene->has_node(String("AnimationPlayer"))) { - return; - } - Node *n = scene->get_node(String("AnimationPlayer")); - ERR_FAIL_COND(!n); - AnimationPlayer *anim = Object::cast_to<AnimationPlayer>(n); - ERR_FAIL_COND(!anim); - +void ResourceImporterScene::_optimize_animations(AnimationPlayer *anim, float p_max_lin_error, float p_max_ang_error, float p_max_angle) { List<StringName> anim_names; anim->get_animation_list(&anim_names); for (List<StringName>::Element *E = anim_names.front(); E; E = E->next()) { @@ -895,208 +942,99 @@ void ResourceImporterScene::_optimize_animations(Node *scene, float p_max_lin_er } } -static String _make_extname(const String &p_str) { - String ext_name = p_str.replace(".", "_"); - ext_name = ext_name.replace(":", "_"); - ext_name = ext_name.replace("\"", "_"); - ext_name = ext_name.replace("<", "_"); - ext_name = ext_name.replace(">", "_"); - ext_name = ext_name.replace("/", "_"); - ext_name = ext_name.replace("|", "_"); - ext_name = ext_name.replace("\\", "_"); - ext_name = ext_name.replace("?", "_"); - ext_name = ext_name.replace("*", "_"); - - return ext_name; -} - -void ResourceImporterScene::_find_meshes(Node *p_node, Map<Ref<ArrayMesh>, Transform> &meshes) { - List<PropertyInfo> pi; - p_node->get_property_list(&pi); - - MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node); - - if (mi) { - Ref<ArrayMesh> mesh = mi->get_mesh(); - - if (mesh.is_valid() && !meshes.has(mesh)) { - Node3D *s = mi; - Transform transform; - while (s) { - transform = transform * s->get_transform(); - s = Object::cast_to<Node3D>(s->get_parent()); +void ResourceImporterScene::get_internal_import_options(InternalImportCategory p_category, List<ImportOption> *r_options) const { + switch (p_category) { + case INTERNAL_IMPORT_CATEGORY_NODE: { + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/skip_import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); + } break; + case INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE: { + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/skip_import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/physics", PROPERTY_HINT_ENUM, "Disabled,Mesh + Static Collider,Rigid Body + Mesh,Static Collider Only,Area Only"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/navmesh", PROPERTY_HINT_ENUM, "Disabled,Mesh + NavMesh,NavMesh Only"), 0)); + } break; + case INTERNAL_IMPORT_CATEGORY_MESH: { + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "save_to_file/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "save_to_file/path", PROPERTY_HINT_SAVE_FILE, "*.res,*.tres"), "")); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "save_to_file/make_streamable"), "")); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/shadow_meshes", PROPERTY_HINT_ENUM, "Default,Enable,Disable"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/lightmap_uv", PROPERTY_HINT_ENUM, "Default,Enable,Disable"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/lods", PROPERTY_HINT_ENUM, "Default,Enable,Disable"), 0)); + } break; + case INTERNAL_IMPORT_CATEGORY_MATERIAL: { + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "use_external/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "use_external/path", PROPERTY_HINT_FILE, "*.material,*.res,*.tres"), "")); + } break; + case INTERNAL_IMPORT_CATEGORY_ANIMATION: { + r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "settings/loops"), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "save_to_file/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "save_to_file/path", PROPERTY_HINT_SAVE_FILE, "*.res,*.tres"), "")); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "save_to_file/keep_custom_tracks"), "")); + } break; + case INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE: { + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/skip_import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "optimizer/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "optimizer/max_linear_error"), 0.05)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "optimizer/max_angular_error"), 0.01)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "optimizer/max_angle"), 22)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slices/amount", PROPERTY_HINT_RANGE, "0,256,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0)); + + for (int i = 0; i < 256; i++) { + r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "slice_" + itos(i + 1) + "/name"), "")); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slice_" + itos(i + 1) + "/start_frame"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slice_" + itos(i + 1) + "/end_frame"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "slice_" + itos(i + 1) + "/loops"), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "slice_" + itos(i + 1) + "/save_to_file/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "slice_" + itos(i + 1) + "/save_to_file/path", PROPERTY_HINT_SAVE_FILE, ".res,*.tres"), "")); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "slice_" + itos(i + 1) + "/save_to_file/keep_custom_tracks"), false)); } - - meshes[mesh] = transform; + } break; + default: { } } - for (int i = 0; i < p_node->get_child_count(); i++) { - _find_meshes(p_node->get_child(i), meshes); - } } -void ResourceImporterScene::_make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_animations_as_text, bool p_keep_animations, bool p_make_materials, bool p_materials_as_text, bool p_keep_materials, bool p_make_meshes, bool p_meshes_as_text, Map<Ref<Animation>, Ref<Animation>> &p_animations, Map<Ref<Material>, Ref<Material>> &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh>> &p_meshes) { - List<PropertyInfo> pi; - - if (p_make_animations) { - if (Object::cast_to<AnimationPlayer>(p_node)) { - AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node); - - List<StringName> anims; - ap->get_animation_list(&anims); - for (List<StringName>::Element *E = anims.front(); E; E = E->next()) { - Ref<Animation> anim = ap->get_animation(E->get()); - ERR_CONTINUE(anim.is_null()); - - if (!p_animations.has(anim)) { - // Tracks from source file should be set as imported, anything else is a custom track. - for (int i = 0; i < anim->get_track_count(); i++) { - anim->track_set_imported(i, true); - } - - String ext_name; - - if (p_animations_as_text) { - ext_name = p_base_path.plus_file(_make_extname(E->get()) + ".tres"); - } else { - ext_name = p_base_path.plus_file(_make_extname(E->get()) + ".anim"); - } - - if (FileAccess::exists(ext_name) && p_keep_animations) { - // Copy custom animation tracks from previously imported files. - Ref<Animation> old_anim = ResourceLoader::load(ext_name, "Animation", ResourceFormatLoader::CACHE_MODE_IGNORE); - if (old_anim.is_valid()) { - for (int i = 0; i < old_anim->get_track_count(); i++) { - if (!old_anim->track_is_imported(i)) { - old_anim->copy_track(i, anim); - } - } - anim->set_loop(old_anim->has_loop()); - } - } - - anim->set_path(ext_name, true); // Set path to save externally. - ResourceSaver::save(ext_name, anim, ResourceSaver::FLAG_CHANGE_PATH); - p_animations[anim] = anim; - } +bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const { + if (p_options.has("import/skip_import") && p_option != "import/skip_import" && bool(p_options["import/skip_import"])) { + return false; //if skip import + } + switch (p_category) { + case INTERNAL_IMPORT_CATEGORY_NODE: { + } break; + case INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE: { + } break; + case INTERNAL_IMPORT_CATEGORY_MESH: { + if (p_option == "save_to_file/path" || p_option == "save_to_file/make_streamable") { + return p_options["save_to_file/enabled"]; + } + } break; + case INTERNAL_IMPORT_CATEGORY_MATERIAL: { + if (p_option == "use_external/path") { + return p_options["use_external/enabled"]; + } + } break; + case INTERNAL_IMPORT_CATEGORY_ANIMATION: { + if (p_option == "save_to_file/path" || p_option == "save_to_file/keep_custom_tracks") { + return p_options["save_to_file/enabled"]; + } + } break; + case INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE: { + if (p_option.begins_with("animation/optimizer/") && p_option != "animation/optimizer/enabled" && !bool(p_options["animation/optimizer/enabled"])) { + return false; } - } - } - - p_node->get_property_list(&pi); - - for (List<PropertyInfo>::Element *E = pi.front(); E; E = E->next()) { - if (E->get().type == Variant::OBJECT) { - Ref<Material> mat = p_node->get(E->get().name); - - if (p_make_materials && mat.is_valid() && mat->get_name() != "") { - if (!p_materials.has(mat)) { - String ext_name; - - if (p_materials_as_text) { - ext_name = p_base_path.plus_file(_make_extname(mat->get_name()) + ".tres"); - } else { - ext_name = p_base_path.plus_file(_make_extname(mat->get_name()) + ".material"); - } - - if (p_keep_materials && FileAccess::exists(ext_name)) { - //if exists, use it - p_materials[mat] = ResourceLoader::load(ext_name); - } else { - ResourceSaver::save(ext_name, mat, ResourceSaver::FLAG_CHANGE_PATH); - p_materials[mat] = ResourceLoader::load(ext_name, "", ResourceFormatLoader::CACHE_MODE_IGNORE); // disable loading from the cache. - } - } - - if (p_materials[mat] != mat) { - p_node->set(E->get().name, p_materials[mat]); - } - } else { - Ref<ArrayMesh> mesh = p_node->get(E->get().name); - - if (mesh.is_valid()) { - bool mesh_just_added = false; - - if (p_make_meshes) { - if (!p_meshes.has(mesh)) { - //meshes are always overwritten, keeping them is not practical - String ext_name; - - if (p_meshes_as_text) { - ext_name = p_base_path.plus_file(_make_extname(mesh->get_name()) + ".tres"); - } else { - ext_name = p_base_path.plus_file(_make_extname(mesh->get_name()) + ".mesh"); - } - - ResourceSaver::save(ext_name, mesh, ResourceSaver::FLAG_CHANGE_PATH); - p_meshes[mesh] = ResourceLoader::load(ext_name); - p_node->set(E->get().name, p_meshes[mesh]); - mesh_just_added = true; - } - } - - if (p_make_materials) { - if (mesh_just_added || !p_meshes.has(mesh)) { - for (int i = 0; i < mesh->get_surface_count(); i++) { - mat = mesh->surface_get_material(i); - - if (!mat.is_valid()) { - continue; - } - if (mat->get_name() == "") { - continue; - } - - if (!p_materials.has(mat)) { - String ext_name; - - if (p_materials_as_text) { - ext_name = p_base_path.plus_file(_make_extname(mat->get_name()) + ".tres"); - } else { - ext_name = p_base_path.plus_file(_make_extname(mat->get_name()) + ".material"); - } - - if (p_keep_materials && FileAccess::exists(ext_name)) { - //if exists, use it - p_materials[mat] = ResourceLoader::load(ext_name); - } else { - ResourceSaver::save(ext_name, mat, ResourceSaver::FLAG_CHANGE_PATH); - p_materials[mat] = ResourceLoader::load(ext_name, "", ResourceFormatLoader::CACHE_MODE_IGNORE); // disable loading from the cache. - } - } - - if (p_materials[mat] != mat) { - mesh->surface_set_material(i, p_materials[mat]); - - //re-save the mesh since a material is now assigned - if (p_make_meshes) { - String ext_name; - - if (p_meshes_as_text) { - ext_name = p_base_path.plus_file(_make_extname(mesh->get_name()) + ".tres"); - } else { - ext_name = p_base_path.plus_file(_make_extname(mesh->get_name()) + ".mesh"); - } - - ResourceSaver::save(ext_name, mesh, ResourceSaver::FLAG_CHANGE_PATH); - p_meshes[mesh] = ResourceLoader::load(ext_name); - } - } - } - if (!p_make_meshes) { - p_meshes[mesh] = Ref<ArrayMesh>(); //save it anyway, so it won't be checked again - } - } - } + if (p_option.begins_with("animation/slice_")) { + int max_slice = p_options["animation/slices/amount"]; + int slice = p_option.get_slice("/", 1).get_slice("_", 1).to_int() - 1; + if (slice >= max_slice) { + return false; } } + } break; + default: { } } - for (int i = 0; i < p_node->get_child_count(); i++) { - _make_external_resources(p_node->get_child(i), p_base_path, p_make_animations, p_animations_as_text, p_keep_animations, p_make_materials, p_materials_as_text, p_keep_materials, p_make_meshes, p_meshes_as_text, p_animations, p_materials, p_meshes); - } + return true; } void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, int p_preset) const { @@ -1115,42 +1053,18 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in script_ext_hint += "*." + E->get(); } - bool materials_out = p_preset == PRESET_SEPARATE_MATERIALS || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || p_preset == PRESET_MULTIPLE_SCENES_AND_MATERIALS || p_preset == PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS; - bool meshes_out = p_preset == PRESET_SEPARATE_MESHES || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || p_preset == PRESET_SEPARATE_MESHES_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS; - bool scenes_out = p_preset == PRESET_MULTIPLE_SCENES || p_preset == PRESET_MULTIPLE_SCENES_AND_MATERIALS; - bool animations_out = p_preset == PRESET_SEPARATE_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS; - r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "nodes/root_scale", PROPERTY_HINT_RANGE, "0.001,1000,0.001"), 1.0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/custom_script", PROPERTY_HINT_FILE, script_ext_hint), "")); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "nodes/storage", PROPERTY_HINT_ENUM, "Single Scene,Instanced Sub-Scenes"), scenes_out ? 1 : 0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "materials/location", PROPERTY_HINT_ENUM, "Node,Mesh"), (meshes_out || materials_out) ? 1 : 0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "materials/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.material),Files (.tres)", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), materials_out ? 1 : 0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "materials/keep_on_reimport"), materials_out)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/ensure_tangents"), true)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.mesh),Files (.tres)"), meshes_out ? 1 : 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/generate_lods"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/create_shadow_meshes"), true)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Enable,Gen Lightmaps", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Dynamic,Static,Static Lightmaps", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 2)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.1)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "skins/use_named_skins"), true)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "external_files/store_in_subdir"), false)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 15)); - r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "animation/filter_script", PROPERTY_HINT_MULTILINE_TEXT), "")); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "animation/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.anim),Files (.tres)", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), animations_out)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/keep_custom_tracks"), animations_out)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/optimizer/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true)); - r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/optimizer/max_linear_error"), 0.05)); - r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/optimizer/max_angular_error"), 0.01)); - r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/optimizer/max_angle"), 22)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/optimizer/remove_unused_tracks"), true)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "animation/clips/amount", PROPERTY_HINT_RANGE, "0,256,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0)); - for (int i = 0; i < 256; i++) { - r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "animation/clip_" + itos(i + 1) + "/name"), "")); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "animation/clip_" + itos(i + 1) + "/start_frame"), 0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "animation/clip_" + itos(i + 1) + "/end_frame"), 0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/clip_" + itos(i + 1) + "/loops"), false)); - } + r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "import_script/path", PROPERTY_HINT_FILE, script_ext_hint), "")); + + r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "_subresources", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), Dictionary())); } void ResourceImporterScene::_replace_owner(Node *p_node, Node *p_scene, Node *p_new_owner) { @@ -1222,7 +1136,7 @@ Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(Edito return importer->import_animation(p_path, p_flags, p_bake_fps); } -void ResourceImporterScene::_generate_meshes(Node *p_node, bool p_generate_lods, bool p_create_shadow_meshes) { +void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_mesh_data, bool p_generate_lods, bool p_create_shadow_meshes, LightBakeMode p_light_bake_mode, float p_lightmap_texel_size, const Vector<uint8_t> &p_src_lightmap_cache, Vector<uint8_t> &r_dst_lightmap_cache) { EditorSceneImporterMeshNode3D *src_mesh_node = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); if (src_mesh_node) { //is mesh @@ -1235,14 +1149,94 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, bool p_generate_lods, Ref<ArrayMesh> mesh; if (!src_mesh_node->get_mesh()->has_mesh()) { //do mesh processing - if (p_generate_lods) { + + bool generate_lods = p_generate_lods; + bool create_shadow_meshes = p_create_shadow_meshes; + bool bake_lightmaps = p_light_bake_mode == LIGHT_BAKE_STATIC_LIGHTMAPS; + String save_to_file; + + String mesh_id; + + if (src_mesh_node->get_mesh()->has_meta("import_id")) { + mesh_id = src_mesh_node->get_mesh()->get_meta("import_id"); + } else { + mesh_id = src_mesh_node->get_mesh()->get_name(); + } + + if (mesh_id != String() && p_mesh_data.has(mesh_id)) { + Dictionary mesh_settings = p_mesh_data[mesh_id]; + + if (mesh_settings.has("generate/shadow_meshes")) { + int shadow_meshes = mesh_settings["generate/shadow_meshes"]; + if (shadow_meshes == MESH_OVERRIDE_ENABLE) { + create_shadow_meshes = true; + } else if (shadow_meshes == MESH_OVERRIDE_DISABLE) { + create_shadow_meshes = false; + } + } + + if (mesh_settings.has("generate/lightmap_uv")) { + int lightmap_uv = mesh_settings["generate/lightmap_uv"]; + if (lightmap_uv == MESH_OVERRIDE_ENABLE) { + bake_lightmaps = true; + } else if (lightmap_uv == MESH_OVERRIDE_DISABLE) { + bake_lightmaps = false; + } + } + + if (mesh_settings.has("generate/lods")) { + int lods = mesh_settings["generate/lods"]; + if (lods == MESH_OVERRIDE_ENABLE) { + generate_lods = true; + } else if (lods == MESH_OVERRIDE_DISABLE) { + generate_lods = false; + } + } + + if (mesh_settings.has("save_to_file/enabled") && bool(mesh_settings["save_to_file/enabled"]) && mesh_settings.has("save_to_file/path")) { + save_to_file = mesh_settings["save_to_file/path"]; + if (!save_to_file.is_resource_file()) { + save_to_file = ""; + } + } + } + + if (generate_lods) { src_mesh_node->get_mesh()->generate_lods(); } - if (p_create_shadow_meshes) { + if (create_shadow_meshes) { src_mesh_node->get_mesh()->create_shadow_mesh(); } + + if (bake_lightmaps) { + Transform xf; + Node3D *n = src_mesh_node; + while (n) { + xf = n->get_transform() * xf; + n = n->get_parent_spatial(); + } + + //use xf as transform for mesh, and bake it + } + + if (save_to_file != String()) { + Ref<Mesh> existing = Ref<Resource>(ResourceCache::get(save_to_file)); + if (existing.is_valid()) { + //if somehow an existing one is useful, create + existing->reset_state(); + } + mesh = src_mesh_node->get_mesh()->get_mesh(existing); + + ResourceSaver::save(save_to_file, mesh); //override + + mesh->set_path(save_to_file, true); //takeover existing, if needed + + } else { + mesh = src_mesh_node->get_mesh()->get_mesh(); + } + } else { + mesh = src_mesh_node->get_mesh()->get_mesh(); } - mesh = src_mesh_node->get_mesh()->get_mesh(); if (mesh.is_valid()) { mesh_node->set_mesh(mesh); @@ -1251,15 +1245,78 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, bool p_generate_lods, } } } + + switch (p_light_bake_mode) { + case LIGHT_BAKE_DISABLED: { + mesh_node->set_gi_mode(GeometryInstance3D::GI_MODE_DISABLED); + } break; + case LIGHT_BAKE_DYNAMIC: { + mesh_node->set_gi_mode(GeometryInstance3D::GI_MODE_DYNAMIC); + } break; + case LIGHT_BAKE_STATIC: + case LIGHT_BAKE_STATIC_LIGHTMAPS: { + mesh_node->set_gi_mode(GeometryInstance3D::GI_MODE_BAKED); + } break; + } + p_node->replace_by(mesh_node); memdelete(p_node); p_node = mesh_node; } for (int i = 0; i < p_node->get_child_count(); i++) { - _generate_meshes(p_node->get_child(i), p_generate_lods, p_create_shadow_meshes); + _generate_meshes(p_node->get_child(i), p_mesh_data, p_generate_lods, p_create_shadow_meshes, p_light_bake_mode, p_lightmap_texel_size, p_src_lightmap_cache, r_dst_lightmap_cache); + } +} + +void ResourceImporterScene::_add_shapes(Node *p_node, const List<Ref<Shape3D>> &p_shapes) { + for (const List<Ref<Shape3D>>::Element *E = p_shapes.front(); E; E = E->next()) { + CollisionShape3D *cshape = memnew(CollisionShape3D); + cshape->set_shape(E->get()); + p_node->add_child(cshape); + + cshape->set_owner(p_node->get_owner()); } } + +Node *ResourceImporterScene::pre_import(const String &p_source_file) { + Ref<EditorSceneImporter> importer; + String ext = p_source_file.get_extension().to_lower(); + + EditorProgress progress("pre-import", TTR("Pre-Import Scene"), 0); + progress.step(TTR("Importing Scene..."), 0); + + for (Set<Ref<EditorSceneImporter>>::Element *E = importers.front(); E; E = E->next()) { + List<String> extensions; + E->get()->get_extensions(&extensions); + + for (List<String>::Element *F = extensions.front(); F; F = F->next()) { + if (F->get().to_lower() == ext) { + importer = E->get(); + break; + } + } + + if (importer.is_valid()) { + break; + } + } + + ERR_FAIL_COND_V(!importer.is_valid(), nullptr); + + Error err = OK; + Node *scene = importer->import_scene(p_source_file, EditorSceneImporter::IMPORT_ANIMATION | EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS, 15, nullptr, &err); + if (!scene || err != OK) { + return nullptr; + } + + Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> collision_map; + + _pre_fix_node(scene, scene, collision_map); + + return scene; +} + Error ResourceImporterScene::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { const String &src_path = p_source_file; @@ -1289,27 +1346,21 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p float fps = p_options["animation/fps"]; - int import_flags = EditorSceneImporter::IMPORT_ANIMATION_DETECT_LOOP; - if (!bool(p_options["animation/optimizer/remove_unused_tracks"])) { - import_flags |= EditorSceneImporter::IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS; - } + int import_flags = 0; if (bool(p_options["animation/import"])) { import_flags |= EditorSceneImporter::IMPORT_ANIMATION; } - if (bool(p_options["meshes/ensure_tangents"])) { - import_flags |= EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS; - } - - if (int(p_options["materials/location"]) == 0) { - import_flags |= EditorSceneImporter::IMPORT_MATERIALS_IN_INSTANCES; - } - if (bool(p_options["skins/use_named_skins"])) { import_flags |= EditorSceneImporter::IMPORT_USE_NAMED_SKIN_BINDS; } + bool ensure_tangents = p_options["meshes/ensure_tangents"]; + if (ensure_tangents) { + import_flags |= EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS; + } + Error err = OK; List<String> missing_deps; // for now, not much will be done with this Node *scene = importer->import_scene(src_path, import_flags, fps, &missing_deps, &err); @@ -1317,6 +1368,29 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p return err; } + Dictionary subresources = p_options["_subresources"]; + + Dictionary node_data; + if (subresources.has("nodes")) { + node_data = subresources["nodes"]; + } + + Dictionary material_data; + if (subresources.has("materials")) { + material_data = subresources["materials"]; + } + + Dictionary animation_data; + if (subresources.has("animations")) { + animation_data = subresources["animations"]; + } + + Set<Ref<EditorSceneImporterMesh>> scanned_meshes; + Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> collision_map; + + _pre_fix_node(scene, scene, collision_map); + _post_fix_node(scene, scene, collision_map, scanned_meshes, node_data, material_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. @@ -1354,73 +1428,35 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p bool gen_lods = bool(p_options["meshes/generate_lods"]); bool create_shadow_meshes = bool(p_options["meshes/create_shadow_meshes"]); - - _generate_meshes(scene, gen_lods, create_shadow_meshes); - - err = OK; - - String animation_filter = String(p_options["animation/filter_script"]).strip_edges(); - - bool use_optimizer = p_options["animation/optimizer/enabled"]; - float anim_optimizer_linerr = p_options["animation/optimizer/max_linear_error"]; - float anim_optimizer_angerr = p_options["animation/optimizer/max_angular_error"]; - float anim_optimizer_maxang = p_options["animation/optimizer/max_angle"]; int light_bake_mode = p_options["meshes/light_baking"]; + float texel_size = p_options["meshes/lightmap_texel_size"]; + float lightmap_texel_size = MAX(0.001, texel_size); - Map<Ref<Mesh>, List<Ref<Shape3D>>> collision_map; - - scene = _fix_node(scene, scene, collision_map, LightBakeMode(light_bake_mode)); - - if (use_optimizer) { - _optimize_animations(scene, anim_optimizer_linerr, anim_optimizer_angerr, anim_optimizer_maxang); - } + Vector<uint8_t> src_lightmap_cache; + Vector<uint8_t> dst_lightmap_cache; - Array animation_clips; { - int clip_count = p_options["animation/clips/amount"]; - - for (int i = 0; i < clip_count; i++) { - String name = p_options["animation/clip_" + itos(i + 1) + "/name"]; - int from_frame = p_options["animation/clip_" + itos(i + 1) + "/start_frame"]; - int end_frame = p_options["animation/clip_" + itos(i + 1) + "/end_frame"]; - bool loop = p_options["animation/clip_" + itos(i + 1) + "/loops"]; - - animation_clips.push_back(name); - animation_clips.push_back(from_frame / fps); - animation_clips.push_back(end_frame / fps); - animation_clips.push_back(loop); + src_lightmap_cache = FileAccess::get_file_as_array(p_source_file + ".unwrap_cache", &err); + if (err != OK) { + src_lightmap_cache.clear(); } } - if (animation_clips.size()) { - _create_clips(scene, animation_clips, !bool(p_options["animation/optimizer/remove_unused_tracks"])); - } - if (animation_filter != "") { - _filter_tracks(scene, animation_filter); + Dictionary mesh_data; + if (subresources.has("meshes")) { + mesh_data = subresources["meshes"]; } + _generate_meshes(scene, mesh_data, gen_lods, create_shadow_meshes, LightBakeMode(light_bake_mode), lightmap_texel_size, src_lightmap_cache, dst_lightmap_cache); - bool external_animations = int(p_options["animation/storage"]) == 1 || int(p_options["animation/storage"]) == 2; - bool external_animations_as_text = int(p_options["animation/storage"]) == 2; - bool keep_custom_tracks = p_options["animation/keep_custom_tracks"]; - bool external_materials = int(p_options["materials/storage"]) == 1 || int(p_options["materials/storage"]) == 2; - bool external_materials_as_text = int(p_options["materials/storage"]) == 2; - bool external_meshes = int(p_options["meshes/storage"]) == 1 || int(p_options["meshes/storage"]) == 2; - bool external_meshes_as_text = int(p_options["meshes/storage"]) == 2; - bool external_scenes = int(p_options["nodes/storage"]) == 1; - - String base_path = p_source_file.get_base_dir(); - - if (external_animations || external_materials || external_meshes || external_scenes) { - if (bool(p_options["external_files/store_in_subdir"])) { - String subdir_name = p_source_file.get_file().get_basename(); - DirAccess *da = DirAccess::open(base_path); - Error err2 = da->make_dir(subdir_name); - memdelete(da); - ERR_FAIL_COND_V_MSG(err2 != OK && err2 != ERR_ALREADY_EXISTS, err2, "Cannot make directory '" + subdir_name + "'."); - base_path = base_path.plus_file(subdir_name); + if (dst_lightmap_cache.size()) { + FileAccessRef f = FileAccess::open(p_source_file + ".unwrap_cache", FileAccess::WRITE); + if (f) { + f->store_buffer(dst_lightmap_cache.ptr(), dst_lightmap_cache.size()); } } + err = OK; +#if 0 if (light_bake_mode == 2 /* || generate LOD */) { Map<Ref<ArrayMesh>, Transform> meshes; _find_meshes(scene, meshes); @@ -1445,9 +1481,6 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p } } - float texel_size = p_options["meshes/lightmap_texel_size"]; - texel_size = MAX(0.001, texel_size); - Map<String, unsigned int> used_unwraps; EditorProgress progress2("gen_lightmaps", TTR("Generating Lightmaps"), meshes.size()); @@ -1469,7 +1502,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p if (err2 != OK) { EditorNode::add_io_error("Mesh '" + name + "' failed lightmap generation. Please fix geometry."); } else { - String hash = String::md5((unsigned char *)ret_cache_data); +` String hash = String::md5((unsigned char *)ret_cache_data); used_unwraps.insert(hash, ret_cache_size); if (!ret_used_cache) { @@ -1482,7 +1515,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p } else { int current_size = cache_data.size(); cache_data.resize(cache_data.size() + ret_cache_size); - unsigned char *ptrw = cache_data.ptrw(); + unsigned char *ptrw = cache_data.ptrw(); memcpy(&ptrw[current_size], ret_cache_data, ret_cache_size); int *data = (int *)ptrw; data[0] += 1; @@ -1530,20 +1563,11 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p file->close(); } } - - if (external_animations || external_materials || external_meshes) { - Map<Ref<Animation>, Ref<Animation>> anim_map; - Map<Ref<Material>, Ref<Material>> mat_map; - Map<Ref<ArrayMesh>, Ref<ArrayMesh>> mesh_map; - - bool keep_materials = bool(p_options["materials/keep_on_reimport"]); - - _make_external_resources(scene, base_path, external_animations, external_animations_as_text, keep_custom_tracks, external_materials, external_materials_as_text, keep_materials, external_meshes, external_meshes_as_text, anim_map, mat_map, mesh_map); - } +#endif progress.step(TTR("Running Custom Script..."), 2); - String post_import_script_path = p_options["nodes/custom_script"]; + String post_import_script_path = p_options["import_script/path"]; Ref<EditorScenePostImport> post_import_script; if (post_import_script_path != "") { @@ -1562,7 +1586,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p } if (post_import_script.is_valid()) { - post_import_script->init(base_path, p_source_file); + post_import_script->init(p_source_file); scene = post_import_script->post_import(scene); if (!scene) { EditorNode::add_io_error( @@ -1574,29 +1598,6 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p progress.step(TTR("Saving..."), 104); - if (external_scenes) { - //save sub-scenes as instances! - for (int i = 0; i < scene->get_child_count(); i++) { - Node *child = scene->get_child(i); - if (child->get_owner() != scene) { - continue; //not a real child probably created by scene type (ig, a scrollbar) - } - _replace_owner(child, scene, child); - - String cn = String(child->get_name()).strip_edges().replace(".", "_").replace(":", "_"); - if (cn == String()) { - cn = "ChildNode" + itos(i); - } - String path = base_path.plus_file(cn + ".scn"); - child->set_filename(path); - - Ref<PackedScene> packer = memnew(PackedScene); - packer->pack(child); - err = ResourceSaver::save(path, packer); //do not take over, let the changed files reload themselves - ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save scene to file '" + path + "'."); - } - } - Ref<PackedScene> packer = memnew(PackedScene); packer->pack(scene); print_verbose("Saving scene to: " + p_save_path + ".scn"); @@ -1613,6 +1614,13 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p ResourceImporterScene *ResourceImporterScene::singleton = nullptr; +bool ResourceImporterScene::ResourceImporterScene::has_advanced_options() const { + return true; +} +void ResourceImporterScene::ResourceImporterScene::show_advanced_options(const String &p_path) { + SceneImportSettings::get_singleton()->open_settings(p_path); +} + ResourceImporterScene::ResourceImporterScene() { singleton = this; } diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index aced0226ff..6c6af57c4c 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -39,7 +39,9 @@ #include "scene/resources/skin.h" class Material; +class AnimationPlayer; +class EditorSceneImporterMesh; class EditorSceneImporter : public Reference { GDCLASS(EditorSceneImporter, Reference); @@ -53,15 +55,9 @@ public: enum ImportFlags { IMPORT_SCENE = 1, IMPORT_ANIMATION = 2, - IMPORT_ANIMATION_DETECT_LOOP = 4, - IMPORT_ANIMATION_OPTIMIZE = 8, - IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS = 16, - IMPORT_ANIMATION_KEEP_VALUE_TRACKS = 32, - IMPORT_GENERATE_TANGENT_ARRAYS = 256, - IMPORT_FAIL_ON_MISSING_DEPENDENCIES = 512, - IMPORT_MATERIALS_IN_INSTANCES = 1024, - IMPORT_USE_COMPRESSION = 2048, - IMPORT_USE_NAMED_SKIN_BINDS = 4096, + IMPORT_FAIL_ON_MISSING_DEPENDENCIES = 4, + IMPORT_GENERATE_TANGENT_ARRAYS = 8, + IMPORT_USE_NAMED_SKIN_BINDS = 16, }; @@ -76,17 +72,15 @@ public: class EditorScenePostImport : public Reference { GDCLASS(EditorScenePostImport, Reference); - String source_folder; String source_file; protected: static void _bind_methods(); public: - String get_source_folder() const; String get_source_file() const; virtual Node *post_import(Node *p_scene); - virtual void init(const String &p_source_folder, const String &p_source_file); + virtual void init(const String &p_source_file); EditorScenePostImport(); }; @@ -97,31 +91,36 @@ class ResourceImporterScene : public ResourceImporter { static ResourceImporterScene *singleton; - enum Presets { - PRESET_SEPARATE_MATERIALS, - PRESET_SEPARATE_MESHES, - PRESET_SEPARATE_ANIMATIONS, - - PRESET_SINGLE_SCENE, + enum LightBakeMode { + LIGHT_BAKE_DISABLED, + LIGHT_BAKE_DYNAMIC, + LIGHT_BAKE_STATIC, + LIGHT_BAKE_STATIC_LIGHTMAPS + }; - PRESET_SEPARATE_MESHES_AND_MATERIALS, - PRESET_SEPARATE_MESHES_AND_ANIMATIONS, - PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS, - PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS, + enum MeshPhysicsMode { + MESH_PHYSICS_DISABLED, + MESH_PHYSICS_MESH_AND_STATIC_COLLIDER, + MESH_PHYSICS_RIGID_BODY_AND_MESH, + MESH_PHYSICS_STATIC_COLLIDER_ONLY, + MESH_PHYSICS_AREA_ONLY, + }; - PRESET_MULTIPLE_SCENES, - PRESET_MULTIPLE_SCENES_AND_MATERIALS, - PRESET_MAX + enum NavMeshMode { + NAVMESH_DISABLED, + NAVMESH_MESH_AND_NAVMESH, + NAVMESH_NAVMESH_ONLY, }; - enum LightBakeMode { - LIGHT_BAKE_DISABLED, - LIGHT_BAKE_ENABLE, - LIGHT_BAKE_LIGHTMAPS + enum MeshOverride { + MESH_OVERRIDE_DEFAULT, + MESH_OVERRIDE_ENABLE, + MESH_OVERRIDE_DISABLE, }; void _replace_owner(Node *p_node, Node *p_scene, Node *p_new_owner); - void _generate_meshes(Node *p_node, bool p_generate_lods, bool p_create_shadow_meshes); + void _generate_meshes(Node *p_node, const Dictionary &p_mesh_data, bool p_generate_lods, bool p_create_shadow_meshes, LightBakeMode p_light_bake_mode, float p_lightmap_texel_size, const Vector<uint8_t> &p_src_lightmap_cache, Vector<uint8_t> &r_dst_lightmap_cache); + void _add_shapes(Node *p_node, const List<Ref<Shape3D>> &p_shapes); public: static ResourceImporterScene *get_singleton() { return singleton; } @@ -141,26 +140,39 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; + enum InternalImportCategory { + INTERNAL_IMPORT_CATEGORY_NODE, + INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE, + INTERNAL_IMPORT_CATEGORY_MESH, + INTERNAL_IMPORT_CATEGORY_MATERIAL, + INTERNAL_IMPORT_CATEGORY_ANIMATION, + INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, + INTERNAL_IMPORT_CATEGORY_MAX + }; + + void get_internal_import_options(InternalImportCategory p_category, List<ImportOption> *r_options) const; + bool get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const; + virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual int get_import_order() const override { return 100; } //after everything - void _find_meshes(Node *p_node, Map<Ref<ArrayMesh>, Transform> &meshes); + Node *_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map); + Node *_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps); - void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_animations_as_text, bool p_keep_animations, bool p_make_materials, bool p_materials_as_text, bool p_keep_materials, bool p_make_meshes, bool p_meshes_as_text, Map<Ref<Animation>, Ref<Animation>> &p_animations, Map<Ref<Material>, Ref<Material>> &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh>> &p_meshes); - - Node *_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape3D>>> &collision_map, LightBakeMode p_light_bake_mode); - - void _create_clips(Node *scene, const Array &p_clips, bool p_bake_all); - void _filter_anim_tracks(Ref<Animation> anim, Set<String> &keep); - void _filter_tracks(Node *scene, const String &p_text); - void _optimize_animations(Node *scene, float p_max_lin_error, float p_max_ang_error, float p_max_angle); + 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); + void _optimize_animations(AnimationPlayer *anim, float p_max_lin_error, float p_max_ang_error, float p_max_angle); + Node *pre_import(const String &p_source_file); virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; Node *import_scene_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps); Ref<Animation> import_animation_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps); + virtual bool has_advanced_options() const override; + virtual void show_advanced_options(const String &p_path) override; + ResourceImporterScene(); }; diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp new file mode 100644 index 0000000000..48340ac242 --- /dev/null +++ b/editor/import/scene_import_settings.cpp @@ -0,0 +1,1199 @@ +/*************************************************************************/ +/* scene_import_settings.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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_import_settings.h" +#include "editor/editor_node.h" +#include "editor/editor_scale.h" +#include "editor/import/scene_importer_mesh_node_3d.h" +#include "scene/resources/surface_tool.h" + +class SceneImportSettingsData : public Object { + GDCLASS(SceneImportSettingsData, Object) + friend class SceneImportSettings; + Map<StringName, Variant> *settings = nullptr; + Map<StringName, Variant> current; + Map<StringName, Variant> defaults; + List<ResourceImporter::ImportOption> options; + + ResourceImporterScene::InternalImportCategory category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX; + + bool _set(const StringName &p_name, const Variant &p_value) { + if (settings) { + if (defaults.has(p_name) && defaults[p_name] == p_value) { + settings->erase(p_name); + } else { + (*settings)[p_name] = p_value; + } + + current[p_name] = p_value; + return true; + } + return false; + } + bool _get(const StringName &p_name, Variant &r_ret) const { + if (settings) { + if (settings->has(p_name)) { + r_ret = (*settings)[p_name]; + return true; + } + } + if (defaults.has(p_name)) { + r_ret = defaults[p_name]; + return true; + } + return false; + } + void _get_property_list(List<PropertyInfo> *p_list) const { + for (const List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) { + if (ResourceImporterScene::get_singleton()->get_internal_option_visibility(category, E->get().option.name, current)) { + p_list->push_back(E->get().option); + } + } + } +}; + +void SceneImportSettings::_fill_material(Tree *p_tree, const Ref<Material> &p_material, TreeItem *p_parent) { + String import_id; + bool has_import_id = false; + + if (p_material->has_meta("import_id")) { + import_id = p_material->get_meta("import_id"); + has_import_id = true; + } else if (p_material->get_name() != "") { + import_id = p_material->get_name(); + has_import_id = true; + } else { + import_id = "@MATERIAL:" + itos(material_set.size()); + } + + if (!material_map.has(import_id)) { + MaterialData md; + md.has_import_id = has_import_id; + md.material = p_material; + + _load_default_subresource_settings(md.settings, "materials", import_id, ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MATERIAL); + + material_map[import_id] = md; + } + + MaterialData &material_data = material_map[import_id]; + + Ref<Texture2D> icon = get_theme_icon("StandardMaterial3D", "EditorIcons"); + + TreeItem *item = p_tree->create_item(p_parent); + item->set_text(0, p_material->get_name()); + item->set_icon(0, icon); + + bool created = false; + if (!material_set.has(p_material)) { + material_set.insert(p_material); + created = true; + } + + item->set_meta("type", "Material"); + item->set_meta("import_id", import_id); + item->set_tooltip(0, vformat(TTR("Import ID: %s"), import_id)); + item->set_selectable(0, true); + + if (p_tree == scene_tree) { + material_data.scene_node = item; + } else if (p_tree == mesh_tree) { + material_data.mesh_node = item; + } else { + material_data.material_node = item; + } + + if (created) { + _fill_material(material_tree, p_material, material_tree->get_root()); + } +} + +void SceneImportSettings::_fill_mesh(Tree *p_tree, const Ref<Mesh> &p_mesh, TreeItem *p_parent) { + String import_id; + + bool has_import_id = false; + if (p_mesh->has_meta("import_id")) { + import_id = p_mesh->get_meta("import_id"); + has_import_id = true; + } else if (p_mesh->get_name() != String()) { + import_id = p_mesh->get_name(); + has_import_id = true; + } else { + import_id = "@MESH:" + itos(mesh_set.size()); + } + + if (!mesh_map.has(import_id)) { + MeshData md; + md.has_import_id = has_import_id; + md.mesh = p_mesh; + + _load_default_subresource_settings(md.settings, "meshes", import_id, ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MESH); + + mesh_map[import_id] = md; + } + + MeshData &mesh_data = mesh_map[import_id]; + + Ref<Texture2D> icon = get_theme_icon("Mesh", "EditorIcons"); + + TreeItem *item = p_tree->create_item(p_parent); + item->set_text(0, p_mesh->get_name()); + item->set_icon(0, icon); + + bool created = false; + if (!mesh_set.has(p_mesh)) { + mesh_set.insert(p_mesh); + created = true; + } + + item->set_meta("type", "Mesh"); + item->set_meta("import_id", import_id); + item->set_tooltip(0, vformat(TTR("Import ID: %s"), import_id)); + + item->set_selectable(0, true); + + if (p_tree == scene_tree) { + mesh_data.scene_node = item; + } else { + mesh_data.mesh_node = item; + } + + item->set_collapsed(true); + + for (int i = 0; i < p_mesh->get_surface_count(); i++) { + Ref<Material> mat = p_mesh->surface_get_material(i); + if (mat.is_valid()) { + _fill_material(p_tree, mat, item); + } + } + + if (created) { + _fill_mesh(mesh_tree, p_mesh, mesh_tree->get_root()); + } +} + +void SceneImportSettings::_fill_animation(Tree *p_tree, const Ref<Animation> &p_anim, const String &p_name, TreeItem *p_parent) { + if (!animation_map.has(p_name)) { + AnimationData ad; + ad.animation = p_anim; + + _load_default_subresource_settings(ad.settings, "animations", p_name, ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION); + + animation_map[p_name] = ad; + } + + AnimationData &animation_data = animation_map[p_name]; + + Ref<Texture2D> icon = get_theme_icon("Animation", "EditorIcons"); + + TreeItem *item = p_tree->create_item(p_parent); + item->set_text(0, p_name); + item->set_icon(0, icon); + + item->set_meta("type", "Animation"); + item->set_meta("import_id", p_name); + + item->set_selectable(0, true); + + animation_data.scene_node = item; +} + +void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) { + String import_id; + + if (p_node->has_meta("import_id")) { + import_id = p_node->get_meta("import_id"); + } else { + import_id = "PATH:" + String(scene->get_path_to(p_node)); + p_node->set_meta("import_id", import_id); + } + + EditorSceneImporterMeshNode3D *src_mesh_node = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); + + if (src_mesh_node) { + MeshInstance3D *mesh_node = memnew(MeshInstance3D); + mesh_node->set_name(src_mesh_node->get_name()); + mesh_node->set_transform(src_mesh_node->get_transform()); + mesh_node->set_skin(src_mesh_node->get_skin()); + mesh_node->set_skeleton_path(src_mesh_node->get_skeleton_path()); + if (src_mesh_node->get_mesh().is_valid()) { + Ref<EditorSceneImporterMesh> editor_mesh = src_mesh_node->get_mesh(); + mesh_node->set_mesh(editor_mesh->get_mesh()); + } + + p_node->replace_by(mesh_node); + memdelete(p_node); + p_node = mesh_node; + } + + String type = p_node->get_class(); + + if (!has_theme_icon(type, "EditorIcons")) { + type = "Node3D"; + } + + Ref<Texture2D> icon = get_theme_icon(type, "EditorIcons"); + + TreeItem *item = scene_tree->create_item(p_parent_item); + item->set_text(0, p_node->get_name()); + + if (p_node == scene) { + icon = get_theme_icon("PackedScene", "EditorIcons"); + item->set_text(0, "Scene"); + } + + item->set_icon(0, icon); + + item->set_meta("type", "Node"); + item->set_meta("class", type); + item->set_meta("import_id", import_id); + item->set_tooltip(0, vformat(TTR("Type: %s\nImport ID: %s"), type, import_id)); + + item->set_selectable(0, true); + + if (!node_map.has(import_id)) { + NodeData nd; + + if (p_node != scene) { + ResourceImporterScene::InternalImportCategory category; + if (src_mesh_node) { + category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE; + } else if (Object::cast_to<AnimationPlayer>(p_node)) { + category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE; + } else { + category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_NODE; + } + + _load_default_subresource_settings(nd.settings, "nodes", import_id, category); + } + + node_map[import_id] = nd; + } + NodeData &node_data = node_map[import_id]; + + node_data.node = p_node; + node_data.scene_node = item; + + AnimationPlayer *anim_node = Object::cast_to<AnimationPlayer>(p_node); + if (anim_node) { + List<StringName> animations; + anim_node->get_animation_list(&animations); + for (List<StringName>::Element *E = animations.front(); E; E = E->next()) { + _fill_animation(scene_tree, anim_node->get_animation(E->get()), E->get(), item); + } + } + + for (int i = 0; i < p_node->get_child_count(); i++) { + _fill_scene(p_node->get_child(i), item); + } + MeshInstance3D *mesh_node = Object::cast_to<MeshInstance3D>(p_node); + if (mesh_node && mesh_node->get_mesh().is_valid()) { + _fill_mesh(scene_tree, mesh_node->get_mesh(), item); + + Transform accum_xform; + Node3D *base = mesh_node; + while (base) { + accum_xform = base->get_transform() * accum_xform; + base = Object::cast_to<Node3D>(base->get_parent()); + } + + AABB aabb = accum_xform.xform(mesh_node->get_mesh()->get_aabb()); + if (first_aabb) { + contents_aabb = aabb; + first_aabb = false; + } else { + contents_aabb.merge_with(aabb); + } + } +} + +void SceneImportSettings::_update_scene() { + scene_tree->clear(); + material_tree->clear(); + mesh_tree->clear(); + + //hiden roots + material_tree->create_item(); + mesh_tree->create_item(); + + _fill_scene(scene, nullptr); +} + +void SceneImportSettings::_update_camera() { + AABB camera_aabb; + + float rot_x = cam_rot_x; + float rot_y = cam_rot_y; + float zoom = cam_zoom; + + if (selected_type == "Node" || selected_type == "") { + camera_aabb = contents_aabb; + } else { + if (mesh_preview->get_mesh().is_valid()) { + camera_aabb = mesh_preview->get_transform().xform(mesh_preview->get_mesh()->get_aabb()); + } else { + camera_aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); + } + if (selected_type == "Mesh" && mesh_map.has(selected_id)) { + const MeshData &md = mesh_map[selected_id]; + rot_x = md.cam_rot_x; + rot_y = md.cam_rot_y; + zoom = md.cam_zoom; + } else if (selected_type == "Material" && material_map.has(selected_id)) { + const MaterialData &md = material_map[selected_id]; + rot_x = md.cam_rot_x; + rot_y = md.cam_rot_y; + zoom = md.cam_zoom; + } + } + + Vector3 center = camera_aabb.position + camera_aabb.size * 0.5; + float camera_size = camera_aabb.get_longest_axis_size(); + + camera->set_orthogonal(camera_size * zoom, 0.0001, camera_size * 2); + + Transform xf; + xf.basis = Basis(Vector3(0, 1, 0), rot_y) * Basis(Vector3(1, 0, 0), rot_x); + xf.origin = center; + xf.translate(0, 0, camera_size); + + camera->set_transform(xf); +} + +void SceneImportSettings::_load_default_subresource_settings(Map<StringName, Variant> &settings, const String &p_type, const String &p_import_id, ResourceImporterScene::InternalImportCategory p_category) { + if (base_subresource_settings.has(p_type)) { + Dictionary d = base_subresource_settings[p_type]; + if (d.has(p_import_id)) { + d = d[p_import_id]; + List<ResourceImporterScene::ImportOption> options; + ResourceImporterScene::get_singleton()->get_internal_import_options(p_category, &options); + for (List<ResourceImporterScene::ImportOption>::Element *E = options.front(); E; E = E->next()) { + String key = E->get().option.name; + if (d.has(key)) { + settings[key] = d[key]; + } + } + } + } +} + +void SceneImportSettings::open_settings(const String &p_path) { + if (scene) { + memdelete(scene); + scene = nullptr; + } + scene = ResourceImporterScene::get_singleton()->pre_import(p_path); + if (scene == nullptr) { + EditorNode::get_singleton()->show_warning(TTR("Error opening scene")); + return; + } + + base_path = p_path; + + material_set.clear(); + mesh_set.clear(); + material_map.clear(); + mesh_map.clear(); + node_map.clear(); + defaults.clear(); + + selected_id = ""; + selected_type = ""; + + cam_rot_x = -Math_PI / 4; + cam_rot_y = -Math_PI / 4; + cam_zoom = 1; + + { + base_subresource_settings.clear(); + + Ref<ConfigFile> config; + config.instance(); + Error err = config->load(p_path + ".import"); + if (err == OK) { + List<String> keys; + config->get_section_keys("params", &keys); + for (List<String>::Element *E = keys.front(); E; E = E->next()) { + Variant value = config->get_value("params", E->get()); + if (E->get() == "_subresources") { + base_subresource_settings = value; + } else { + defaults[E->get()] = value; + } + } + } + } + + first_aabb = true; + + _update_scene(); + + base_viewport->add_child(scene); + + if (first_aabb) { + contents_aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); + first_aabb = false; + } + + popup_centered_ratio(); + _update_camera(); + + set_title(vformat(TTR("Advanced Import Settings for '%s'"), base_path.get_file())); +} + +SceneImportSettings *SceneImportSettings::singleton = nullptr; + +SceneImportSettings *SceneImportSettings::get_singleton() { + return singleton; +} + +void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) { + selecting = true; + + if (p_type == "Node") { + node_selected->hide(); //always hide just in case + mesh_preview->hide(); + if (Object::cast_to<Node3D>(scene)) { + Object::cast_to<Node3D>(scene)->show(); + } + //NodeData &nd=node_map[p_id]; + material_tree->deselect_all(); + mesh_tree->deselect_all(); + NodeData &nd = node_map[p_id]; + + MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(nd.node); + if (mi) { + Ref<Mesh> base_mesh = mi->get_mesh(); + if (base_mesh.is_valid()) { + AABB aabb = base_mesh->get_aabb(); + Transform aabb_xf; + aabb_xf.basis.scale(aabb.size); + aabb_xf.origin = aabb.position; + + aabb_xf = mi->get_global_transform() * aabb_xf; + node_selected->set_transform(aabb_xf); + node_selected->show(); + } + } + + if (nd.node == scene) { + scene_import_settings_data->settings = &defaults; + scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX; + } else { + scene_import_settings_data->settings = &nd.settings; + if (mi) { + scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE; + } else if (Object::cast_to<AnimationPlayer>(nd.node)) { + scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE; + } else { + scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_NODE; + } + } + } else if (p_type == "Animation") { + node_selected->hide(); //always hide just in case + mesh_preview->hide(); + if (Object::cast_to<Node3D>(scene)) { + Object::cast_to<Node3D>(scene)->show(); + } + //NodeData &nd=node_map[p_id]; + material_tree->deselect_all(); + mesh_tree->deselect_all(); + AnimationData &ad = animation_map[p_id]; + + scene_import_settings_data->settings = &ad.settings; + scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION; + } else if (p_type == "Mesh") { + node_selected->hide(); + if (Object::cast_to<Node3D>(scene)) { + Object::cast_to<Node3D>(scene)->hide(); + } + + MeshData &md = mesh_map[p_id]; + if (p_from != mesh_tree) { + md.mesh_node->uncollapse_tree(); + md.mesh_node->select(0); + mesh_tree->ensure_cursor_is_visible(); + } + if (p_from != scene_tree) { + md.scene_node->uncollapse_tree(); + md.scene_node->select(0); + scene_tree->ensure_cursor_is_visible(); + } + + mesh_preview->set_mesh(md.mesh); + mesh_preview->show(); + + material_tree->deselect_all(); + + scene_import_settings_data->settings = &md.settings; + scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MESH; + } else if (p_type == "Material") { + node_selected->hide(); + if (Object::cast_to<Node3D>(scene)) { + Object::cast_to<Node3D>(scene)->hide(); + } + + mesh_preview->show(); + + MaterialData &md = material_map[p_id]; + + material_preview->set_material(md.material); + mesh_preview->set_mesh(material_preview); + + if (p_from != mesh_tree) { + md.mesh_node->uncollapse_tree(); + md.mesh_node->select(0); + mesh_tree->ensure_cursor_is_visible(); + } + if (p_from != scene_tree) { + md.scene_node->uncollapse_tree(); + md.scene_node->select(0); + scene_tree->ensure_cursor_is_visible(); + } + if (p_from != material_tree) { + md.material_node->uncollapse_tree(); + md.material_node->select(0); + material_tree->ensure_cursor_is_visible(); + } + + scene_import_settings_data->settings = &md.settings; + scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MATERIAL; + } + + selected_type = p_type; + selected_id = p_id; + + selecting = false; + + _update_camera(); + + List<ResourceImporter::ImportOption> options; + + if (scene_import_settings_data->category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) { + ResourceImporterScene::get_singleton()->get_import_options(&options); + } else { + ResourceImporterScene::get_singleton()->get_internal_import_options(scene_import_settings_data->category, &options); + } + + scene_import_settings_data->defaults.clear(); + scene_import_settings_data->current.clear(); + + for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) { + scene_import_settings_data->defaults[E->get().option.name] = E->get().default_value; + //needed for visibility toggling (fails if something is missing) + if (scene_import_settings_data->settings->has(E->get().option.name)) { + scene_import_settings_data->current[E->get().option.name] = (*scene_import_settings_data->settings)[E->get().option.name]; + } else { + scene_import_settings_data->current[E->get().option.name] = E->get().default_value; + } + } + scene_import_settings_data->options = options; + inspector->edit(scene_import_settings_data); + scene_import_settings_data->notify_property_list_changed(); +} + +void SceneImportSettings::_material_tree_selected() { + if (selecting) { + return; + } + TreeItem *item = material_tree->get_selected(); + String type = item->get_meta("type"); + String import_id = item->get_meta("import_id"); + + _select(material_tree, type, import_id); +} +void SceneImportSettings::_mesh_tree_selected() { + if (selecting) { + return; + } + + TreeItem *item = mesh_tree->get_selected(); + String type = item->get_meta("type"); + String import_id = item->get_meta("import_id"); + + _select(mesh_tree, type, import_id); +} +void SceneImportSettings::_scene_tree_selected() { + if (selecting) { + return; + } + TreeItem *item = scene_tree->get_selected(); + String type = item->get_meta("type"); + String import_id = item->get_meta("import_id"); + + _select(scene_tree, type, import_id); +} + +void SceneImportSettings::_viewport_input(const Ref<InputEvent> &p_input) { + float *rot_x = &cam_rot_x; + float *rot_y = &cam_rot_y; + float *zoom = &cam_zoom; + + if (selected_type == "Mesh" && mesh_map.has(selected_id)) { + MeshData &md = mesh_map[selected_id]; + rot_x = &md.cam_rot_x; + rot_y = &md.cam_rot_y; + zoom = &md.cam_zoom; + } else if (selected_type == "Material" && material_map.has(selected_id)) { + MaterialData &md = material_map[selected_id]; + rot_x = &md.cam_rot_x; + rot_y = &md.cam_rot_y; + zoom = &md.cam_zoom; + } + Ref<InputEventMouseMotion> mm = p_input; + if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + (*rot_x) -= mm->get_relative().y * 0.01 * EDSCALE; + (*rot_y) -= mm->get_relative().x * 0.01 * EDSCALE; + (*rot_x) = CLAMP((*rot_x), -Math_PI / 2, Math_PI / 2); + _update_camera(); + } + Ref<InputEventMouseButton> mb = p_input; + if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { + (*zoom) *= 1.1; + if ((*zoom) > 10.0) { + (*zoom) = 10.0; + } + _update_camera(); + } + if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { + (*zoom) /= 1.1; + if ((*zoom) < 0.1) { + (*zoom) = 0.1; + } + _update_camera(); + } +} + +void SceneImportSettings::_re_import() { + Map<StringName, Variant> main_settings; + + main_settings = defaults; + main_settings.erase("_subresources"); + Dictionary nodes; + Dictionary materials; + Dictionary meshes; + Dictionary animations; + + Dictionary subresources; + + for (Map<String, NodeData>::Element *E = node_map.front(); E; E = E->next()) { + if (E->get().settings.size()) { + Dictionary d; + for (Map<StringName, Variant>::Element *F = E->get().settings.front(); F; F = F->next()) { + d[String(F->key())] = F->get(); + } + nodes[E->key()] = d; + } + } + if (nodes.size()) { + subresources["nodes"] = nodes; + } + + for (Map<String, MaterialData>::Element *E = material_map.front(); E; E = E->next()) { + if (E->get().settings.size()) { + Dictionary d; + for (Map<StringName, Variant>::Element *F = E->get().settings.front(); F; F = F->next()) { + d[String(F->key())] = F->get(); + } + materials[E->key()] = d; + } + } + if (materials.size()) { + subresources["materials"] = materials; + } + + for (Map<String, MeshData>::Element *E = mesh_map.front(); E; E = E->next()) { + if (E->get().settings.size()) { + Dictionary d; + for (Map<StringName, Variant>::Element *F = E->get().settings.front(); F; F = F->next()) { + d[String(F->key())] = F->get(); + } + meshes[E->key()] = d; + } + } + if (meshes.size()) { + subresources["meshes"] = meshes; + } + + for (Map<String, AnimationData>::Element *E = animation_map.front(); E; E = E->next()) { + if (E->get().settings.size()) { + Dictionary d; + for (Map<StringName, Variant>::Element *F = E->get().settings.front(); F; F = F->next()) { + d[String(F->key())] = F->get(); + } + animations[E->key()] = d; + } + } + if (animations.size()) { + subresources["animations"] = animations; + } + + if (subresources.size()) { + main_settings["_subresources"] = subresources; + } + + EditorFileSystem::get_singleton()->reimport_file_with_custom_parameters(base_path, "scene", main_settings); +} + +void SceneImportSettings::_notification(int p_what) { + if (p_what == NOTIFICATION_READY) { + connect("confirmed", callable_mp(this, &SceneImportSettings::_re_import)); + } +} + +void SceneImportSettings::_menu_callback(int p_id) { + switch (p_id) { + case ACTION_EXTRACT_MATERIALS: { + save_path->set_text(TTR("Select folder to extract material resources")); + external_extension_type->select(0); + } break; + case ACTION_CHOOSE_MESH_SAVE_PATHS: { + save_path->set_text(TTR("Select folder where mesh resources will save on import")); + external_extension_type->select(1); + } break; + case ACTION_CHOOSE_ANIMATION_SAVE_PATHS: { + save_path->set_text(TTR("Select folder where animations will save on import")); + external_extension_type->select(1); + } break; + } + + save_path->set_current_dir(base_path.get_base_dir()); + current_action = p_id; + save_path->popup_centered_ratio(); +} + +void SceneImportSettings::_save_path_changed(const String &p_path) { + save_path_item->set_text(1, p_path); + + if (FileAccess::exists(p_path)) { + save_path_item->set_text(2, "Warning: File exists"); + save_path_item->set_tooltip(2, TTR("Existing file with the same name will be replaced.")); + save_path_item->set_icon(2, get_theme_icon("StatusWarning", "EditorIcons")); + + } else { + save_path_item->set_text(2, "Will create new File"); + save_path_item->set_icon(2, get_theme_icon("StatusSuccess", "EditorIcons")); + } +} + +void SceneImportSettings::_browse_save_callback(Object *p_item, int p_column, int p_id) { + TreeItem *item = Object::cast_to<TreeItem>(p_item); + + String path = item->get_text(1); + + item_save_path->set_current_file(path); + save_path_item = item; + + item_save_path->popup_centered_ratio(); +} + +void SceneImportSettings::_save_dir_callback(const String &p_path) { + external_path_tree->clear(); + TreeItem *root = external_path_tree->create_item(); + save_path_items.clear(); + + switch (current_action) { + case ACTION_EXTRACT_MATERIALS: { + for (Map<String, MaterialData>::Element *E = material_map.front(); E; E = E->next()) { + MaterialData &md = material_map[E->key()]; + + TreeItem *item = external_path_tree->create_item(root); + + String name = md.material_node->get_text(0); + + item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); + item->set_icon(0, get_theme_icon("StandardMaterial3D", "EditorIcons")); + item->set_text(0, name); + + if (md.has_import_id) { + if (md.settings.has("use_external/enabled") && bool(md.settings["use_external/enabled"])) { + item->set_text(2, "Already External"); + item->set_tooltip(2, TTR("This material already references an external file, no action will be taken.\nDisable the external property for it to be extracted again.")); + } else { + item->set_metadata(0, E->key()); + item->set_editable(0, true); + item->set_checked(0, true); + String path = p_path.plus_file(name); + if (external_extension_type->get_selected() == 0) { + path += ".tres"; + } else { + path += ".res"; + } + + item->set_text(1, path); + if (FileAccess::exists(path)) { + item->set_text(2, "Warning: File exists"); + item->set_tooltip(2, TTR("Existing file with the same name will be replaced.")); + item->set_icon(2, get_theme_icon("StatusWarning", "EditorIcons")); + + } else { + item->set_text(2, "Will create new File"); + item->set_icon(2, get_theme_icon("StatusSuccess", "EditorIcons")); + } + + item->add_button(1, get_theme_icon("Folder", "EditorIcons")); + } + + } else { + item->set_text(2, "No import ID"); + item->set_tooltip(2, TTR("Material has no name nor any other way to identify on re-import.\nPlease name it or ensure it is exported with an unique ID.")); + item->set_icon(2, get_theme_icon("StatusError", "EditorIcons")); + } + + save_path_items.push_back(item); + } + + external_paths->set_title(TTR("Extract Materials to Resource Files")); + external_paths->get_ok_button()->set_text(TTR("Extract")); + } break; + case ACTION_CHOOSE_MESH_SAVE_PATHS: { + for (Map<String, MeshData>::Element *E = mesh_map.front(); E; E = E->next()) { + MeshData &md = mesh_map[E->key()]; + + TreeItem *item = external_path_tree->create_item(root); + + String name = md.mesh_node->get_text(0); + + item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); + item->set_icon(0, get_theme_icon("Mesh", "EditorIcons")); + item->set_text(0, name); + + if (md.has_import_id) { + if (md.settings.has("save_to_file/enabled") && bool(md.settings["save_to_file/enabled"])) { + item->set_text(2, "Already Saving"); + item->set_tooltip(2, TTR("This mesh already saves to an external resource, no action will be taken.")); + } else { + item->set_metadata(0, E->key()); + item->set_editable(0, true); + item->set_checked(0, true); + String path = p_path.plus_file(name); + if (external_extension_type->get_selected() == 0) { + path += ".tres"; + } else { + path += ".res"; + } + + item->set_text(1, path); + if (FileAccess::exists(path)) { + item->set_text(2, "Warning: File exists"); + item->set_tooltip(2, TTR("Existing file with the same name will be replaced on import.")); + item->set_icon(2, get_theme_icon("StatusWarning", "EditorIcons")); + + } else { + item->set_text(2, "Will save to new File"); + item->set_icon(2, get_theme_icon("StatusSuccess", "EditorIcons")); + } + + item->add_button(1, get_theme_icon("Folder", "EditorIcons")); + } + + } else { + item->set_text(2, "No import ID"); + item->set_tooltip(2, TTR("Mesh has no name nor any other way to identify on re-import.\nPlease name it or ensure it is exported with an unique ID.")); + item->set_icon(2, get_theme_icon("StatusError", "EditorIcons")); + } + + save_path_items.push_back(item); + } + + external_paths->set_title(TTR("Set paths to save meshes as resource files on Reimport")); + external_paths->get_ok_button()->set_text(TTR("Set Paths")); + } break; + case ACTION_CHOOSE_ANIMATION_SAVE_PATHS: { + for (Map<String, AnimationData>::Element *E = animation_map.front(); E; E = E->next()) { + AnimationData &ad = animation_map[E->key()]; + + TreeItem *item = external_path_tree->create_item(root); + + String name = ad.scene_node->get_text(0); + + item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); + item->set_icon(0, get_theme_icon("Animation", "EditorIcons")); + item->set_text(0, name); + + if (ad.settings.has("save_to_file/enabled") && bool(ad.settings["save_to_file/enabled"])) { + item->set_text(2, "Already Saving"); + item->set_tooltip(2, TTR("This animation already saves to an external resource, no action will be taken.")); + } else { + item->set_metadata(0, E->key()); + item->set_editable(0, true); + item->set_checked(0, true); + String path = p_path.plus_file(name); + if (external_extension_type->get_selected() == 0) { + path += ".tres"; + } else { + path += ".res"; + } + + item->set_text(1, path); + if (FileAccess::exists(path)) { + item->set_text(2, "Warning: File exists"); + item->set_tooltip(2, TTR("Existing file with the same name will be replaced on import.")); + item->set_icon(2, get_theme_icon("StatusWarning", "EditorIcons")); + + } else { + item->set_text(2, "Will save to new File"); + item->set_icon(2, get_theme_icon("StatusSuccess", "EditorIcons")); + } + + item->add_button(1, get_theme_icon("Folder", "EditorIcons")); + } + + save_path_items.push_back(item); + } + + external_paths->set_title(TTR("Set paths to save animations as resource files on Reimport")); + external_paths->get_ok_button()->set_text(TTR("Set Paths")); + + } break; + } + + external_paths->popup_centered_ratio(); +} + +void SceneImportSettings::_save_dir_confirm() { + for (int i = 0; i < save_path_items.size(); i++) { + TreeItem *item = save_path_items[i]; + if (!item->is_checked(0)) { + continue; //ignore + } + String path = item->get_text(1); + if (!path.is_resource_file()) { + continue; + } + + String id = item->get_metadata(0); + + switch (current_action) { + case ACTION_EXTRACT_MATERIALS: { + ERR_CONTINUE(!material_map.has(id)); + MaterialData &md = material_map[id]; + + Error err = ResourceSaver::save(path, md.material); + if (err != OK) { + EditorNode::get_singleton()->add_io_error(TTR("Can't make material external to file, write error:") + "\n\t" + path); + continue; + } + + md.settings["use_external/enabled"] = true; + md.settings["use_external/path"] = path; + + } break; + case ACTION_CHOOSE_MESH_SAVE_PATHS: { + ERR_CONTINUE(!mesh_map.has(id)); + MeshData &md = mesh_map[id]; + + md.settings["save_to_file/enabled"] = true; + md.settings["save_to_file/path"] = path; + } break; + case ACTION_CHOOSE_ANIMATION_SAVE_PATHS: { + ERR_CONTINUE(!animation_map.has(id)); + AnimationData &ad = animation_map[id]; + + ad.settings["save_to_file/enabled"] = true; + ad.settings["save_to_file/path"] = path; + + } break; + } + } + + if (current_action == ACTION_EXTRACT_MATERIALS) { + //as this happens right now, the scene needs to be saved and reimported. + _re_import(); + open_settings(base_path); + } else { + scene_import_settings_data->notify_property_list_changed(); + } +} + +SceneImportSettings::SceneImportSettings() { + singleton = this; + + VBoxContainer *main_vb = memnew(VBoxContainer); + add_child(main_vb); + HBoxContainer *menu_hb = memnew(HBoxContainer); + main_vb->add_child(menu_hb); + + action_menu = memnew(MenuButton); + action_menu->set_text(TTR("Actions...")); + menu_hb->add_child(action_menu); + + action_menu->get_popup()->add_item(TTR("Extract Materials"), ACTION_EXTRACT_MATERIALS); + action_menu->get_popup()->add_separator(); + action_menu->get_popup()->add_item(TTR("Set Animation Save Paths"), ACTION_CHOOSE_ANIMATION_SAVE_PATHS); + action_menu->get_popup()->add_item(TTR("Set Mesh Save Paths"), ACTION_CHOOSE_MESH_SAVE_PATHS); + + action_menu->get_popup()->connect("id_pressed", callable_mp(this, &SceneImportSettings::_menu_callback)); + + tree_split = memnew(HSplitContainer); + main_vb->add_child(tree_split); + tree_split->set_v_size_flags(Control::SIZE_EXPAND_FILL); + + data_mode = memnew(TabContainer); + tree_split->add_child(data_mode); + data_mode->set_custom_minimum_size(Size2(300 * EDSCALE, 0)); + + property_split = memnew(HSplitContainer); + tree_split->add_child(property_split); + property_split->set_h_size_flags(Control::SIZE_EXPAND_FILL); + + scene_tree = memnew(Tree); + scene_tree->set_name(TTR("Scene")); + data_mode->add_child(scene_tree); + scene_tree->connect("cell_selected", callable_mp(this, &SceneImportSettings::_scene_tree_selected)); + + mesh_tree = memnew(Tree); + mesh_tree->set_name(TTR("Meshes")); + data_mode->add_child(mesh_tree); + mesh_tree->set_hide_root(true); + mesh_tree->connect("cell_selected", callable_mp(this, &SceneImportSettings::_mesh_tree_selected)); + + material_tree = memnew(Tree); + material_tree->set_name(TTR("Materials")); + data_mode->add_child(material_tree); + material_tree->connect("cell_selected", callable_mp(this, &SceneImportSettings::_material_tree_selected)); + + material_tree->set_hide_root(true); + + SubViewportContainer *vp_container = memnew(SubViewportContainer); + vp_container->set_h_size_flags(Control::SIZE_EXPAND_FILL); + vp_container->set_custom_minimum_size(Size2(10, 10)); + vp_container->set_stretch(true); + vp_container->connect("gui_input", callable_mp(this, &SceneImportSettings::_viewport_input)); + property_split->add_child(vp_container); + + base_viewport = memnew(SubViewport); + vp_container->add_child(base_viewport); + + base_viewport->set_use_own_world_3d(true); + + camera = memnew(Camera3D); + base_viewport->add_child(camera); + camera->make_current(); + + light = memnew(DirectionalLight3D); + light->set_transform(Transform().looking_at(Vector3(-1, -2, -0.6), Vector3(0, 1, 0))); + base_viewport->add_child(light); + light->set_shadow(true); + + { + Ref<StandardMaterial3D> selection_mat; + selection_mat.instance(); + selection_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + selection_mat->set_albedo(Color(1, 0.8, 1.0)); + + Ref<SurfaceTool> st; + st.instance(); + st->begin(Mesh::PRIMITIVE_LINES); + + AABB base_aabb; + base_aabb.size = Vector3(1, 1, 1); + + for (int i = 0; i < 12; i++) { + Vector3 a, b; + base_aabb.get_edge(i, a, b); + + st->add_vertex(a); + st->add_vertex(a.lerp(b, 0.2)); + st->add_vertex(b); + st->add_vertex(b.lerp(a, 0.2)); + } + + selection_mesh.instance(); + st->commit(selection_mesh); + selection_mesh->surface_set_material(0, selection_mat); + + node_selected = memnew(MeshInstance3D); + node_selected->set_mesh(selection_mesh); + base_viewport->add_child(node_selected); + node_selected->hide(); + } + + { + mesh_preview = memnew(MeshInstance3D); + base_viewport->add_child(mesh_preview); + mesh_preview->hide(); + + material_preview.instance(); + } + + inspector = memnew(EditorInspector); + inspector->set_custom_minimum_size(Size2(300 * EDSCALE, 0)); + + property_split->add_child(inspector); + + scene_import_settings_data = memnew(SceneImportSettingsData); + + get_ok_button()->set_text(TTR("Reimport")); + get_cancel_button()->set_text(TTR("Close")); + + external_paths = memnew(ConfirmationDialog); + add_child(external_paths); + external_path_tree = memnew(Tree); + external_paths->add_child(external_path_tree); + external_path_tree->connect("button_pressed", callable_mp(this, &SceneImportSettings::_browse_save_callback)); + external_paths->connect("confirmed", callable_mp(this, &SceneImportSettings::_save_dir_confirm)); + external_path_tree->set_columns(3); + external_path_tree->set_column_titles_visible(true); + external_path_tree->set_column_expand(0, true); + external_path_tree->set_column_min_width(0, 100 * EDSCALE); + external_path_tree->set_column_title(0, TTR("Resource")); + external_path_tree->set_column_expand(1, true); + external_path_tree->set_column_min_width(1, 100 * EDSCALE); + external_path_tree->set_column_title(1, TTR("Path")); + external_path_tree->set_column_expand(2, false); + external_path_tree->set_column_min_width(2, 200 * EDSCALE); + external_path_tree->set_column_title(2, TTR("Status")); + save_path = memnew(EditorFileDialog); + save_path->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_DIR); + HBoxContainer *extension_hb = memnew(HBoxContainer); + save_path->get_vbox()->add_child(extension_hb); + extension_hb->add_spacer(); + extension_hb->add_child(memnew(Label(TTR("Save Extension: ")))); + external_extension_type = memnew(OptionButton); + extension_hb->add_child(external_extension_type); + external_extension_type->add_item(TTR("Text: *.tres")); + external_extension_type->add_item(TTR("Binary: *.res")); + external_path_tree->set_hide_root(true); + add_child(save_path); + + item_save_path = memnew(EditorFileDialog); + item_save_path->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); + item_save_path->add_filter("*.tres;Text Resource"); + item_save_path->add_filter("*.res;Binary Resource"); + add_child(item_save_path); + item_save_path->connect("file_selected", callable_mp(this, &SceneImportSettings::_save_path_changed)); + + save_path->connect("dir_selected", callable_mp(this, &SceneImportSettings::_save_dir_callback)); +} + +SceneImportSettings::~SceneImportSettings() { + memdelete(scene_import_settings_data); +} diff --git a/editor/import/scene_import_settings.h b/editor/import/scene_import_settings.h new file mode 100644 index 0000000000..ddcf4a6d5d --- /dev/null +++ b/editor/import/scene_import_settings.h @@ -0,0 +1,199 @@ +/*************************************************************************/ +/* scene_import_settings.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 SCENEIMPORTSETTINGS_H +#define SCENEIMPORTSETTINGS_H + +#include "editor/editor_file_dialog.h" +#include "editor/editor_inspector.h" +#include "editor/import/resource_importer_scene.h" +#include "scene/3d/camera_3d.h" +#include "scene/3d/light_3d.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/gui/dialogs.h" +#include "scene/gui/item_list.h" +#include "scene/gui/menu_button.h" +#include "scene/gui/option_button.h" +#include "scene/gui/split_container.h" +#include "scene/gui/subviewport_container.h" +#include "scene/gui/tab_container.h" +#include "scene/gui/tree.h" +#include "scene/resources/primitive_meshes.h" + +class SceneImportSettingsData; + +class SceneImportSettings : public ConfirmationDialog { + GDCLASS(SceneImportSettings, ConfirmationDialog) + + static SceneImportSettings *singleton; + + enum Actions { + ACTION_EXTRACT_MATERIALS, + ACTION_CHOOSE_MESH_SAVE_PATHS, + ACTION_CHOOSE_ANIMATION_SAVE_PATHS, + }; + + Node *scene = nullptr; + + HSplitContainer *tree_split; + HSplitContainer *property_split; + TabContainer *data_mode; + Tree *scene_tree; + Tree *mesh_tree; + Tree *material_tree; + + EditorInspector *inspector; + + SubViewport *base_viewport; + + Camera3D *camera; + bool first_aabb = false; + AABB contents_aabb; + + DirectionalLight3D *light; + Ref<ArrayMesh> selection_mesh; + MeshInstance3D *node_selected; + + MeshInstance3D *mesh_preview; + Ref<SphereMesh> material_preview; + + float cam_rot_x; + float cam_rot_y; + float cam_zoom; + + void _update_scene(); + + struct MaterialData { + bool has_import_id; + Ref<Material> material; + TreeItem *scene_node; + TreeItem *mesh_node; + TreeItem *material_node; + + float cam_rot_x = -Math_PI / 4; + float cam_rot_y = -Math_PI / 4; + float cam_zoom = 1; + + Map<StringName, Variant> settings; + }; + Map<String, MaterialData> material_map; + + struct MeshData { + bool has_import_id; + Ref<Mesh> mesh; + TreeItem *scene_node; + TreeItem *mesh_node; + + float cam_rot_x = -Math_PI / 4; + float cam_rot_y = -Math_PI / 4; + float cam_zoom = 1; + Map<StringName, Variant> settings; + }; + Map<String, MeshData> mesh_map; + + struct AnimationData { + Ref<Animation> animation; + TreeItem *scene_node; + Map<StringName, Variant> settings; + }; + Map<String, AnimationData> animation_map; + + struct NodeData { + Node *node; + TreeItem *scene_node; + Map<StringName, Variant> settings; + }; + Map<String, NodeData> node_map; + + void _fill_material(Tree *p_tree, const Ref<Material> &p_material, TreeItem *p_parent); + void _fill_mesh(Tree *p_tree, const Ref<Mesh> &p_mesh, TreeItem *p_parent); + void _fill_animation(Tree *p_tree, const Ref<Animation> &p_anim, const String &p_name, TreeItem *p_parent); + void _fill_scene(Node *p_node, TreeItem *p_parent_item); + + Set<Ref<Mesh>> mesh_set; + Set<Ref<Material>> material_set; + + String selected_type; + String selected_id; + + bool selecting = false; + + void _update_camera(); + void _select(Tree *p_from, String p_type, String p_id); + void _material_tree_selected(); + void _mesh_tree_selected(); + void _scene_tree_selected(); + + void _viewport_input(const Ref<InputEvent> &p_input); + + Map<StringName, Variant> defaults; + + SceneImportSettingsData *scene_import_settings_data; + + void _re_import(); + + String base_path; + + MenuButton *action_menu; + + ConfirmationDialog *external_paths; + Tree *external_path_tree; + EditorFileDialog *save_path; + OptionButton *external_extension_type; + + EditorFileDialog *item_save_path; + + void _menu_callback(int p_id); + void _save_dir_callback(const String &p_path); + + int current_action; + + Vector<TreeItem *> save_path_items; + + TreeItem *save_path_item = nullptr; + void _save_path_changed(const String &p_path); + void _browse_save_callback(Object *p_item, int p_column, int p_id); + void _save_dir_confirm(); + + Dictionary base_subresource_settings; + + void _load_default_subresource_settings(Map<StringName, Variant> &settings, const String &p_type, const String &p_import_id, ResourceImporterScene::InternalImportCategory p_category); + +protected: + void _notification(int p_what); + +public: + void open_settings(const String &p_path); + static SceneImportSettings *get_singleton(); + SceneImportSettings(); + ~SceneImportSettings(); +}; + +#endif // SCENEIMPORTSETTINGS_H diff --git a/editor/import/scene_importer_mesh.cpp b/editor/import/scene_importer_mesh.cpp index 46eb4e4fdc..28fdd4ddbd 100644 --- a/editor/import/scene_importer_mesh.cpp +++ b/editor/import/scene_importer_mesh.cpp @@ -136,6 +136,11 @@ Ref<Material> EditorSceneImporterMesh::get_surface_material(int p_surface) const return surfaces[p_surface].material; } +void EditorSceneImporterMesh::set_surface_material(int p_surface, const Ref<Material> &p_material) { + ERR_FAIL_INDEX(p_surface, surfaces.size()); + surfaces.write[p_surface].material = p_material; +} + void EditorSceneImporterMesh::generate_lods() { if (!SurfaceTool::simplify_func) { return; @@ -219,11 +224,20 @@ bool EditorSceneImporterMesh::has_mesh() const { return mesh.is_valid(); } -Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh() { +Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh(const Ref<Mesh> &p_base) { ERR_FAIL_COND_V(surfaces.size() == 0, Ref<ArrayMesh>()); if (mesh.is_null()) { - mesh.instance(); + if (p_base.is_valid()) { + mesh = p_base; + } + if (mesh.is_null()) { + mesh.instance(); + } + mesh->set_name(get_name()); + if (has_meta("import_id")) { + mesh->set_meta("import_id", get_meta("import_id")); + } for (int i = 0; i < blend_shapes.size(); i++) { mesh->add_blend_shape(blend_shapes[i]); } @@ -251,6 +265,8 @@ Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh() { } } + mesh->set_lightmap_size_hint(lightmap_size_hint); + if (shadow_mesh.is_valid()) { Ref<ArrayMesh> shadow = shadow_mesh->get_mesh(); mesh->set_shadow_mesh(shadow); @@ -436,6 +452,338 @@ Dictionary EditorSceneImporterMesh::_get_data() const { return data; } +Vector<Face3> EditorSceneImporterMesh::get_faces() const { + Vector<Face3> faces; + for (int i = 0; i < surfaces.size(); i++) { + if (surfaces[i].primitive == Mesh::PRIMITIVE_TRIANGLES) { + Vector<Vector3> vertices = surfaces[i].arrays[Mesh::ARRAY_VERTEX]; + Vector<int> indices = surfaces[i].arrays[Mesh::ARRAY_INDEX]; + if (indices.size()) { + for (int j = 0; j < indices.size(); j += 3) { + Face3 f; + f.vertex[0] = vertices[indices[j + 0]]; + f.vertex[1] = vertices[indices[j + 1]]; + f.vertex[2] = vertices[indices[j + 2]]; + faces.push_back(f); + } + } else { + for (int j = 0; j < vertices.size(); j += 3) { + Face3 f; + f.vertex[0] = vertices[j + 0]; + f.vertex[1] = vertices[j + 1]; + f.vertex[2] = vertices[j + 2]; + faces.push_back(f); + } + } + } + } + + return faces; +} + +Vector<Ref<Shape3D>> EditorSceneImporterMesh::convex_decompose() const { + ERR_FAIL_COND_V(!Mesh::convex_composition_function, Vector<Ref<Shape3D>>()); + + const Vector<Face3> faces = get_faces(); + + Vector<Vector<Face3>> decomposed = Mesh::convex_composition_function(faces); + + Vector<Ref<Shape3D>> ret; + + for (int i = 0; i < decomposed.size(); i++) { + Set<Vector3> points; + for (int j = 0; j < decomposed[i].size(); j++) { + points.insert(decomposed[i][j].vertex[0]); + points.insert(decomposed[i][j].vertex[1]); + points.insert(decomposed[i][j].vertex[2]); + } + + Vector<Vector3> convex_points; + convex_points.resize(points.size()); + { + Vector3 *w = convex_points.ptrw(); + int idx = 0; + for (Set<Vector3>::Element *E = points.front(); E; E = E->next()) { + w[idx++] = E->get(); + } + } + + Ref<ConvexPolygonShape3D> shape; + shape.instance(); + shape->set_points(convex_points); + ret.push_back(shape); + } + + return ret; +} + +Ref<Shape3D> EditorSceneImporterMesh::create_trimesh_shape() const { + Vector<Face3> faces = get_faces(); + if (faces.size() == 0) { + return Ref<Shape3D>(); + } + + Vector<Vector3> face_points; + face_points.resize(faces.size() * 3); + + for (int i = 0; i < face_points.size(); i += 3) { + Face3 f = faces.get(i / 3); + face_points.set(i, f.vertex[0]); + face_points.set(i + 1, f.vertex[1]); + face_points.set(i + 2, f.vertex[2]); + } + + Ref<ConcavePolygonShape3D> shape = memnew(ConcavePolygonShape3D); + shape->set_faces(face_points); + return shape; +} + +Ref<NavigationMesh> EditorSceneImporterMesh::create_navigation_mesh() { + Vector<Face3> faces = get_faces(); + if (faces.size() == 0) { + return Ref<NavigationMesh>(); + } + + Map<Vector3, int> unique_vertices; + LocalVector<int> face_indices; + + for (int i = 0; i < faces.size(); i++) { + for (int j = 0; j < 3; j++) { + Vector3 v = faces[i].vertex[j]; + int idx; + if (unique_vertices.has(v)) { + idx = unique_vertices[v]; + } else { + idx = unique_vertices.size(); + unique_vertices[v] = idx; + } + face_indices.push_back(idx); + } + } + + Vector<Vector3> vertices; + vertices.resize(unique_vertices.size()); + for (Map<Vector3, int>::Element *E = unique_vertices.front(); E; E = E->next()) { + vertices.write[E->get()] = E->key(); + } + + Ref<NavigationMesh> nm; + nm.instance(); + nm->set_vertices(vertices); + + Vector<int> v3; + v3.resize(3); + for (uint32_t i = 0; i < face_indices.size(); i += 3) { + v3.write[0] = face_indices[i + 0]; + v3.write[1] = face_indices[i + 1]; + v3.write[2] = face_indices[i + 2]; + nm->add_polygon(v3); + } + + return nm; +} + +extern bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y, int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache); + +struct EditorSceneImporterMeshLightmapSurface { + Ref<Material> material; + LocalVector<SurfaceTool::Vertex> vertices; + Mesh::PrimitiveType primitive = Mesh::PrimitiveType::PRIMITIVE_MAX; + uint32_t format = 0; + String name; +}; + +Error EditorSceneImporterMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache, const Transform &p_base_transform, float p_texel_size) { + ERR_FAIL_COND_V(!array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED); + ERR_FAIL_COND_V_MSG(blend_shapes.size() != 0, ERR_UNAVAILABLE, "Can't unwrap mesh with blend shapes."); + + Vector<float> vertices; + Vector<float> normals; + Vector<int> indices; + Vector<float> uv; + Vector<Pair<int, int>> uv_indices; + + Vector<EditorSceneImporterMeshLightmapSurface> lightmap_surfaces; + + // Keep only the scale + Transform transform = p_base_transform; + transform.origin = Vector3(); + transform.looking_at(Vector3(1, 0, 0), Vector3(0, 1, 0)); + + Basis normal_basis = transform.basis.inverse().transposed(); + + for (int i = 0; i < get_surface_count(); i++) { + EditorSceneImporterMeshLightmapSurface s; + s.primitive = get_surface_primitive_type(i); + + ERR_FAIL_COND_V_MSG(s.primitive != Mesh::PRIMITIVE_TRIANGLES, ERR_UNAVAILABLE, "Only triangles are supported for lightmap unwrap."); + Array arrays = get_surface_arrays(i); + s.material = get_surface_material(i); + s.name = get_surface_name(i); + + SurfaceTool::create_vertex_array_from_triangle_arrays(arrays, s.vertices, &s.format); + + Vector<Vector3> rvertices = arrays[Mesh::ARRAY_VERTEX]; + int vc = rvertices.size(); + const Vector3 *r = rvertices.ptr(); + + Vector<Vector3> rnormals = arrays[Mesh::ARRAY_NORMAL]; + + ERR_FAIL_COND_V_MSG(rnormals.size() == 0, ERR_UNAVAILABLE, "Normals are required for lightmap unwrap."); + + const Vector3 *rn = rnormals.ptr(); + + int vertex_ofs = vertices.size() / 3; + + vertices.resize((vertex_ofs + vc) * 3); + normals.resize((vertex_ofs + vc) * 3); + uv_indices.resize(vertex_ofs + vc); + + for (int j = 0; j < vc; j++) { + Vector3 v = transform.xform(r[j]); + Vector3 n = normal_basis.xform(rn[j]).normalized(); + + vertices.write[(j + vertex_ofs) * 3 + 0] = v.x; + vertices.write[(j + vertex_ofs) * 3 + 1] = v.y; + vertices.write[(j + vertex_ofs) * 3 + 2] = v.z; + normals.write[(j + vertex_ofs) * 3 + 0] = n.x; + normals.write[(j + vertex_ofs) * 3 + 1] = n.y; + normals.write[(j + vertex_ofs) * 3 + 2] = n.z; + uv_indices.write[j + vertex_ofs] = Pair<int, int>(i, j); + } + + Vector<int> rindices = arrays[Mesh::ARRAY_INDEX]; + int ic = rindices.size(); + + if (ic == 0) { + for (int j = 0; j < vc / 3; j++) { + if (Face3(r[j * 3 + 0], r[j * 3 + 1], r[j * 3 + 2]).is_degenerate()) { + continue; + } + + indices.push_back(vertex_ofs + j * 3 + 0); + indices.push_back(vertex_ofs + j * 3 + 1); + indices.push_back(vertex_ofs + j * 3 + 2); + } + + } else { + const int *ri = rindices.ptr(); + + for (int j = 0; j < ic / 3; j++) { + if (Face3(r[ri[j * 3 + 0]], r[ri[j * 3 + 1]], r[ri[j * 3 + 2]]).is_degenerate()) { + continue; + } + indices.push_back(vertex_ofs + ri[j * 3 + 0]); + indices.push_back(vertex_ofs + ri[j * 3 + 1]); + indices.push_back(vertex_ofs + ri[j * 3 + 2]); + } + } + + lightmap_surfaces.push_back(s); + } + + //unwrap + + float *gen_uvs; + int *gen_vertices; + int *gen_indices; + int gen_vertex_count; + int gen_index_count; + int size_x; + int size_y; + + bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), indices.size(), &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y, r_cache_data, r_cache_size, r_used_cache); + + if (!ok) { + return ERR_CANT_CREATE; + } + + //remove surfaces + clear(); + + //create surfacetools for each surface.. + Vector<Ref<SurfaceTool>> surfaces_tools; + + for (int i = 0; i < lightmap_surfaces.size(); i++) { + Ref<SurfaceTool> st; + st.instance(); + st->begin(Mesh::PRIMITIVE_TRIANGLES); + st->set_material(lightmap_surfaces[i].material); + st->set_meta("name", lightmap_surfaces[i].name); + surfaces_tools.push_back(st); //stay there + } + + print_verbose("Mesh: Gen indices: " + itos(gen_index_count)); + //go through all indices + for (int i = 0; i < gen_index_count; i += 3) { + ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], uv_indices.size(), ERR_BUG); + ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], uv_indices.size(), ERR_BUG); + ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], uv_indices.size(), ERR_BUG); + + ERR_FAIL_COND_V(uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 1]]].first || uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 2]]].first, ERR_BUG); + + int surface = uv_indices[gen_vertices[gen_indices[i + 0]]].first; + + for (int j = 0; j < 3; j++) { + SurfaceTool::Vertex v = lightmap_surfaces[surface].vertices[uv_indices[gen_vertices[gen_indices[i + j]]].second]; + + if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_COLOR) { + surfaces_tools.write[surface]->set_color(v.color); + } + if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_TEX_UV) { + surfaces_tools.write[surface]->set_uv(v.uv); + } + if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_NORMAL) { + surfaces_tools.write[surface]->set_normal(v.normal); + } + if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_TANGENT) { + Plane t; + t.normal = v.tangent; + t.d = v.binormal.dot(v.normal.cross(v.tangent)) < 0 ? -1 : 1; + surfaces_tools.write[surface]->set_tangent(t); + } + if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_BONES) { + surfaces_tools.write[surface]->set_bones(v.bones); + } + if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_WEIGHTS) { + surfaces_tools.write[surface]->set_weights(v.weights); + } + + Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]); + surfaces_tools.write[surface]->set_uv2(uv2); + + surfaces_tools.write[surface]->add_vertex(v.vertex); + } + } + + //generate surfaces + + for (int i = 0; i < surfaces_tools.size(); i++) { + surfaces_tools.write[i]->index(); + Array arrays = surfaces_tools.write[i]->commit_to_arrays(); + add_surface(surfaces_tools.write[i]->get_primitive(), arrays, Array(), Dictionary(), surfaces_tools.write[i]->get_material(), surfaces_tools.write[i]->get_meta("name")); + } + + set_lightmap_size_hint(Size2(size_x, size_y)); + + if (!r_used_cache) { + //free stuff + ::free(gen_vertices); + ::free(gen_indices); + ::free(gen_uvs); + } + + return OK; +} + +void EditorSceneImporterMesh::set_lightmap_size_hint(const Size2i &p_size) { + lightmap_size_hint = p_size; +} + +Size2i EditorSceneImporterMesh::get_lightmap_size_hint() const { + return lightmap_size_hint; +} + void EditorSceneImporterMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &EditorSceneImporterMesh::add_blend_shape); ClassDB::bind_method(D_METHOD("get_blend_shape_count"), &EditorSceneImporterMesh::get_blend_shape_count); @@ -462,5 +810,8 @@ void EditorSceneImporterMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_data", "data"), &EditorSceneImporterMesh::_set_data); ClassDB::bind_method(D_METHOD("_get_data"), &EditorSceneImporterMesh::_get_data); + ClassDB::bind_method(D_METHOD("set_lightmap_size_hint", "size"), &EditorSceneImporterMesh::set_lightmap_size_hint); + ClassDB::bind_method(D_METHOD("get_lightmap_size_hint"), &EditorSceneImporterMesh::get_lightmap_size_hint); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_data", "_get_data"); } diff --git a/editor/import/scene_importer_mesh.h b/editor/import/scene_importer_mesh.h index 42507cbe8c..3326fab55d 100644 --- a/editor/import/scene_importer_mesh.h +++ b/editor/import/scene_importer_mesh.h @@ -32,7 +32,10 @@ #define EDITOR_SCENE_IMPORTER_MESH_H #include "core/io/resource.h" +#include "scene/resources/concave_polygon_shape_3d.h" +#include "scene/resources/convex_polygon_shape_3d.h" #include "scene/resources/mesh.h" +#include "scene/resources/navigation_mesh.h" // The following classes are used by importers instead of ArrayMesh and MeshInstance3D // so the data is not registered (hence, quality loss), importing happens faster and // its easier to modify before saving @@ -63,6 +66,8 @@ class EditorSceneImporterMesh : public Resource { Ref<EditorSceneImporterMesh> shadow_mesh; + Size2i lightmap_size_hint; + protected: void _set_data(const Dictionary &p_data); Dictionary _get_data() const; @@ -89,13 +94,24 @@ public: float get_surface_lod_size(int p_surface, int p_lod) const; Ref<Material> get_surface_material(int p_surface) const; + void set_surface_material(int p_surface, const Ref<Material> &p_material); + void generate_lods(); void create_shadow_mesh(); Ref<EditorSceneImporterMesh> get_shadow_mesh() const; + Vector<Face3> get_faces() const; + Vector<Ref<Shape3D>> convex_decompose() const; + Ref<Shape3D> create_trimesh_shape() const; + Ref<NavigationMesh> create_navigation_mesh(); + Error lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache, const Transform &p_base_transform, float p_texel_size); + + void set_lightmap_size_hint(const Size2i &p_size); + Size2i get_lightmap_size_hint() const; + bool has_mesh() const; - Ref<ArrayMesh> get_mesh(); + Ref<ArrayMesh> get_mesh(const Ref<Mesh> &p_base = Ref<Mesh>()); void clear(); }; #endif // EDITOR_SCENE_IMPORTER_MESH_H diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index 97a04e6557..17c51f0f85 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -98,11 +98,9 @@ void ImportDock::set_edit_path(const String &p_path) { return; } - params->importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(config->get_value("remap", "importer")); - if (params->importer.is_null()) { - clear(); - return; - } + String importer_name = config->get_value("remap", "importer"); + + params->importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name); params->paths.clear(); params->paths.push_back(p_path); @@ -124,11 +122,18 @@ void ImportDock::set_edit_path(const String &p_path) { for (List<Pair<String, String>>::Element *E = importer_names.front(); E; E = E->next()) { import_as->add_item(E->get().first); import_as->set_item_metadata(import_as->get_item_count() - 1, E->get().second); - if (E->get().second == params->importer->get_importer_name()) { + if (E->get().second == importer_name) { import_as->select(import_as->get_item_count() - 1); } } + import_as->add_separator(); + import_as->add_item(TTR("Keep File (No Import)")); + import_as->set_item_metadata(import_as->get_item_count() - 1, "keep"); + if (importer_name == "keep") { + import_as->select(import_as->get_item_count() - 1); + } + import->set_disabled(false); import_as->set_disabled(false); preset->set_disabled(false); @@ -138,7 +143,10 @@ void ImportDock::set_edit_path(const String &p_path) { void ImportDock::_update_options(const Ref<ConfigFile> &p_config) { List<ResourceImporter::ImportOption> options; - params->importer->get_import_options(&options); + + if (params->importer.is_valid()) { + params->importer->get_import_options(&options); + } params->properties.clear(); params->values.clear(); @@ -156,6 +164,14 @@ void ImportDock::_update_options(const Ref<ConfigFile> &p_config) { params->update(); _update_preset_menu(); + + if (params->importer.is_valid() && params->paths.size() == 1 && params->importer->has_advanced_options()) { + advanced->show(); + advanced_spacer->show(); + } else { + advanced->hide(); + advanced_spacer->hide(); + } } void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) { @@ -178,6 +194,10 @@ void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) { } } + if (!config->has_section("params")) { + continue; + } + List<String> keys; config->get_section_keys("params", &keys); @@ -258,11 +278,26 @@ void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) { preset->set_disabled(false); imported->set_text(vformat(TTR("%d Files"), p_paths.size())); + + if (params->paths.size() == 1 && params->importer->has_advanced_options()) { + advanced->show(); + advanced_spacer->show(); + } else { + advanced->hide(); + advanced_spacer->hide(); + } } void ImportDock::_update_preset_menu() { preset->get_popup()->clear(); + if (params->importer.is_null()) { + preset->get_popup()->add_item(TTR("Default")); + preset->hide(); + return; + } + preset->show(); + if (params->importer->get_preset_count() == 0) { preset->get_popup()->add_item(TTR("Default")); } else { @@ -282,20 +317,25 @@ void ImportDock::_update_preset_menu() { void ImportDock::_importer_selected(int i_idx) { String name = import_as->get_selected_metadata(); - Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(name); - ERR_FAIL_COND(importer.is_null()); + if (name == "keep") { + params->importer.unref(); + _update_options(Ref<ConfigFile>()); + } else { + Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(name); + ERR_FAIL_COND(importer.is_null()); - params->importer = importer; + params->importer = importer; - Ref<ConfigFile> config; - if (params->paths.size()) { - config.instance(); - Error err = config->load(params->paths[0] + ".import"); - if (err != OK) { - config.unref(); + Ref<ConfigFile> config; + if (params->paths.size()) { + config.instance(); + Error err = config->load(params->paths[0] + ".import"); + if (err != OK) { + config.unref(); + } } + _update_options(config); } - _update_options(config); } void ImportDock::_preset_selected(int p_idx) { @@ -391,6 +431,13 @@ static bool _find_owners(EditorFileSystemDirectory *efsd, const String &p_path) void ImportDock::_reimport_attempt() { bool need_restart = false; bool used_in_resources = false; + + String importer_name; + if (params->importer.is_valid()) { + importer_name = params->importer->get_importer_name(); + } else { + importer_name = "keep"; + } for (int i = 0; i < params->paths.size(); i++) { Ref<ConfigFile> config; config.instance(); @@ -398,7 +445,7 @@ void ImportDock::_reimport_attempt() { ERR_CONTINUE(err != OK); String imported_with = config->get_value("remap", "importer"); - if (imported_with != params->importer->get_importer_name()) { + if (imported_with != importer_name) { need_restart = true; if (_find_owners(EditorFileSystem::get_singleton()->get_filesystem(), params->paths[i])) { used_in_resources = true; @@ -422,6 +469,11 @@ void ImportDock::_reimport_and_restart() { EditorNode::get_singleton()->restart_editor(); } +void ImportDock::_advanced_options() { + if (params->paths.size() == 1 && params->importer.is_valid()) { + params->importer->show_advanced_options(params->paths[0]); + } +} void ImportDock::_reimport() { for (int i = 0; i < params->paths.size(); i++) { Ref<ConfigFile> config; @@ -429,38 +481,45 @@ void ImportDock::_reimport() { Error err = config->load(params->paths[i] + ".import"); ERR_CONTINUE(err != OK); - String importer_name = params->importer->get_importer_name(); + if (params->importer.is_valid()) { + String importer_name = params->importer->get_importer_name(); - if (params->checking && config->get_value("remap", "importer") == params->importer->get_importer_name()) { - //update only what is edited (checkboxes) if the importer is the same - for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) { - if (params->checked.has(E->get().name)) { + if (params->checking && config->get_value("remap", "importer") == params->importer->get_importer_name()) { + //update only what is edited (checkboxes) if the importer is the same + for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) { + if (params->checked.has(E->get().name)) { + config->set_value("params", E->get().name, params->values[E->get().name]); + } + } + } else { + //override entirely + config->set_value("remap", "importer", importer_name); + if (config->has_section("params")) { + config->erase_section("params"); + } + + for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) { config->set_value("params", E->get().name, params->values[E->get().name]); } } - } else { - //override entirely - config->set_value("remap", "importer", importer_name); - if (config->has_section("params")) { - config->erase_section("params"); - } - for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) { - config->set_value("params", E->get().name, params->values[E->get().name]); + //handle group file + Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name); + ERR_CONTINUE(!importer.is_valid()); + String group_file_property = importer->get_option_group_file(); + if (group_file_property != String()) { + //can import from a group (as in, atlas) + ERR_CONTINUE(!params->values.has(group_file_property)); + String group_file = params->values[group_file_property]; + config->set_value("remap", "group_file", group_file); + } else { + config->set_value("remap", "group_file", Variant()); //clear group file if unused } - } - //handle group file - Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name); - ERR_CONTINUE(!importer.is_valid()); - String group_file_property = importer->get_option_group_file(); - if (group_file_property != String()) { - //can import from a group (as in, atlas) - ERR_CONTINUE(!params->values.has(group_file_property)); - String group_file = params->values[group_file_property]; - config->set_value("remap", "group_file", group_file); } else { - config->set_value("remap", "group_file", Variant()); //clear group file if unused + //set to no import + config->clear(); + config->set_value("remap", "importer", "keep"); } config->save(params->paths[i] + ".import"); @@ -531,10 +590,27 @@ ImportDock::ImportDock() { import->set_text(TTR("Reimport")); import->set_disabled(true); import->connect("pressed", callable_mp(this, &ImportDock::_reimport_attempt)); + if (!DisplayServer::get_singleton()->get_swap_cancel_ok()) { + advanced_spacer = hb->add_spacer(); + advanced = memnew(Button); + advanced->set_text(TTR("Advanced...")); + hb->add_child(advanced); + } hb->add_spacer(); hb->add_child(import); hb->add_spacer(); + if (DisplayServer::get_singleton()->get_swap_cancel_ok()) { + advanced = memnew(Button); + advanced->set_text(TTR("Advanced...")); + hb->add_child(advanced); + advanced_spacer = hb->add_spacer(); + } + + advanced->hide(); + advanced_spacer->hide(); + advanced->connect("pressed", callable_mp(this, &ImportDock::_advanced_options)); + reimport_confirm = memnew(ConfirmationDialog); reimport_confirm->get_ok_button()->set_text(TTR("Save Scenes, Re-Import, and Restart")); add_child(reimport_confirm); diff --git a/editor/import_dock.h b/editor/import_dock.h index 6c5779ddce..2be48dd505 100644 --- a/editor/import_dock.h +++ b/editor/import_dock.h @@ -57,6 +57,9 @@ class ImportDock : public VBoxContainer { Label *label_warning; Button *import; + Control *advanced_spacer; + Button *advanced; + ImportDockParameters *params; void _preset_selected(int p_idx); @@ -69,6 +72,7 @@ class ImportDock : public VBoxContainer { void _reimport_and_restart(); void _reimport(); + void _advanced_options(); enum { ITEM_SET_AS_DEFAULT = 100, ITEM_LOAD_DEFAULT, diff --git a/editor/node_3d_editor_gizmos.cpp b/editor/node_3d_editor_gizmos.cpp index 64cf9a7bb7..7dcabafece 100644 --- a/editor/node_3d_editor_gizmos.cpp +++ b/editor/node_3d_editor_gizmos.cpp @@ -3531,7 +3531,7 @@ String CollisionObject3DGizmoPlugin::get_gizmo_name() const { } int CollisionObject3DGizmoPlugin::get_priority() const { - return -1; + return -2; } void CollisionObject3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index c90f87de56..80d0a7db60 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -264,7 +264,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); if (mode == MODE_EDIT || (_is_line() && mode == MODE_CREATE)) { - if (mb->get_button_index() == BUTTON_LEFT) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->is_pressed()) { if (mb->get_control() || mb->get_shift() || mb->get_alt()) { return false; @@ -326,7 +326,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) return true; } } - } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && !edited_point.valid()) { + } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed() && !edited_point.valid()) { const PosVertex closest = closest_point(gpoint); if (closest.valid()) { @@ -335,7 +335,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) } } } else if (mode == MODE_DELETE) { - if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) { const PosVertex closest = closest_point(gpoint); if (closest.valid()) { @@ -346,7 +346,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) } if (mode == MODE_CREATE) { - if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) { if (_is_line()) { // for lines, we don't have a wip mode, and we can undo each single add point. Vector<Vector2> vertices = _get_polygon(0); @@ -384,7 +384,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) return true; } } - } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) { + } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed() && wip_active) { _wip_cancel(); } } @@ -395,7 +395,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) if (mm.is_valid()) { Vector2 gpoint = mm->get_position(); - if (edited_point.valid() && (wip_active || (mm->get_button_mask() & BUTTON_MASK_LEFT))) { + if (edited_point.valid() && (wip_active || (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT))) { Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint))); //Move the point in a single axis. Should only work when editing a polygon and while holding shift. diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp index d69913cc46..025fcaf818 100644 --- a/editor/plugins/animation_blend_space_1d_editor.cpp +++ b/editor/plugins/animation_blend_space_1d_editor.cpp @@ -51,7 +51,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) || (mb->get_button_index() == BUTTON_LEFT && tool_create->is_pressed()))) { + if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) || (mb->get_button_index() == MOUSE_BUTTON_LEFT && tool_create->is_pressed()))) { menu->clear(); animations_menu->clear(); animations_to_add.clear(); @@ -110,7 +110,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven } } - if (mb.is_valid() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { blend_space_draw->update(); // why not // try to see if a point can be selected @@ -132,7 +132,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven } } - if (mb.is_valid() && !mb->is_pressed() && dragging_selected_attempt && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && !mb->is_pressed() && dragging_selected_attempt && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (dragging_selected) { // move float point = blend_space->get_blend_point_position(selected_point); @@ -161,7 +161,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven } // *set* the blend - if (mb.is_valid() && !mb->is_pressed() && tool_blend->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && !mb->is_pressed() && tool_blend->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { float blend_pos = mb->get_position().x / blend_space_draw->get_size().x; blend_pos *= blend_space->get_max_space() - blend_space->get_min_space(); blend_pos += blend_space->get_min_space(); @@ -184,7 +184,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven _update_edited_point_pos(); } - if (mm.is_valid() && tool_blend->is_pressed() && mm->get_button_mask() & BUTTON_MASK_LEFT) { + if (mm.is_valid() && tool_blend->is_pressed() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { float blend_pos = mm->get_position().x / blend_space_draw->get_size().x; blend_pos *= blend_space->get_max_space() - blend_space->get_min_space(); blend_pos += blend_space->get_min_space(); diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp index 6a57463dbc..af9c391174 100644 --- a/editor/plugins/animation_blend_space_2d_editor.cpp +++ b/editor/plugins/animation_blend_space_2d_editor.cpp @@ -79,7 +79,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) || (mb->get_button_index() == BUTTON_LEFT && tool_create->is_pressed()))) { + if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) || (mb->get_button_index() == MOUSE_BUTTON_LEFT && tool_create->is_pressed()))) { menu->clear(); animations_menu->clear(); animations_to_add.clear(); @@ -134,7 +134,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven } } - if (mb.is_valid() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { blend_space_draw->update(); //update anyway //try to see if a point can be selected selected_point = -1; @@ -174,7 +174,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven } } - if (mb.is_valid() && mb->is_pressed() && tool_triangle->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && tool_triangle->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { blend_space_draw->update(); //update anyway //try to see if a point can be selected selected_point = -1; @@ -209,7 +209,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven } } - if (mb.is_valid() && !mb->is_pressed() && dragging_selected_attempt && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && !mb->is_pressed() && dragging_selected_attempt && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (dragging_selected) { //move Vector2 point = blend_space->get_blend_point_position(selected_point); @@ -236,7 +236,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven blend_space_draw->update(); } - if (mb.is_valid() && mb->is_pressed() && tool_blend->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && tool_blend->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { Vector2 blend_pos = (mb->get_position() / blend_space_draw->get_size()); blend_pos.y = 1.0 - blend_pos.y; blend_pos *= (blend_space->get_max_space() - blend_space->get_min_space()); @@ -270,7 +270,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven blend_space_draw->update(); } - if (mm.is_valid() && tool_blend->is_pressed() && mm->get_button_mask() & BUTTON_MASK_LEFT) { + if (mm.is_valid() && tool_blend->is_pressed() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { Vector2 blend_pos = (mm->get_position() / blend_space_draw->get_size()); blend_pos.y = 1.0 - blend_pos.y; blend_pos *= (blend_space->get_max_space() - blend_space->get_min_space()); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 7c623505b5..612a8f30a4 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -117,8 +117,8 @@ void AnimationPlayerEditor::_notification(int p_what) { autoplay_icon = get_theme_icon("AutoPlay", "EditorIcons"); reset_icon = get_theme_icon("Reload", "EditorIcons"); { - Ref<Image> autoplay_img = autoplay_icon->get_data(); - Ref<Image> reset_img = reset_icon->get_data(); + Ref<Image> autoplay_img = autoplay_icon->get_image(); + Ref<Image> reset_img = reset_icon->get_image(); Ref<Image> autoplay_reset_img; Size2 icon_size = Size2(autoplay_img->get_width(), autoplay_img->get_height()); autoplay_reset_img.instance(); @@ -1219,6 +1219,8 @@ void AnimationPlayerEditor::_onion_skinning_menu(int p_option) { } void AnimationPlayerEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) { + ERR_FAIL_COND(p_ev.is_null()); + Ref<InputEventKey> k = p_ev; if (is_visible_in_tree() && k.is_valid() && k->is_pressed() && !k->is_echo() && !k->get_alt() && !k->get_control() && !k->get_metakey()) { switch (k->get_keycode()) { diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index c6d2faf849..a9709bbb16 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -76,7 +76,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv Ref<InputEventMouseButton> mb = p_event; //Add new node - if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) || (tool_create->is_pressed() && mb->get_button_index() == BUTTON_LEFT))) { + if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) || (tool_create->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT))) { menu->clear(); animations_menu->clear(); animations_to_add.clear(); @@ -124,7 +124,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv } // select node or push a field inside - if (mb.is_valid() && !mb->get_shift() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && !mb->get_shift() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { selected_transition_from = StringName(); selected_transition_to = StringName(); selected_node = StringName(); @@ -216,7 +216,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv } //end moving node - if (mb.is_valid() && dragging_selected_attempt && mb->get_button_index() == BUTTON_LEFT && !mb->is_pressed()) { + if (mb.is_valid() && dragging_selected_attempt && mb->get_button_index() == MOUSE_BUTTON_LEFT && !mb->is_pressed()) { if (dragging_selected) { Ref<AnimationNode> an = state_machine->get_node(selected_node); updating = true; @@ -237,7 +237,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv } //connect nodes - if (mb.is_valid() && ((tool_select->is_pressed() && mb->get_shift()) || tool_connect->is_pressed()) && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) { + if (mb.is_valid() && ((tool_select->is_pressed() && mb->get_shift()) || tool_connect->is_pressed()) && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) { for (int i = node_rects.size() - 1; i >= 0; i--) { //inverse to draw order if (node_rects[i].node.has_point(mb->get_position())) { //select node since nothing else was selected connecting = true; @@ -250,7 +250,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv } //end connecting nodes - if (mb.is_valid() && connecting && mb->get_button_index() == BUTTON_LEFT && !mb->is_pressed()) { + if (mb.is_valid() && connecting && mb->get_button_index() == MOUSE_BUTTON_LEFT && !mb->is_pressed()) { if (connecting_to_node != StringName()) { if (state_machine->has_transition(connecting_from, connecting_to_node)) { EditorNode::get_singleton()->show_warning(TTR("Transition exists!")); @@ -284,7 +284,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv Ref<InputEventMouseMotion> mm = p_event; //pan window - if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_MIDDLE) { + if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) { h_scroll->set_value(h_scroll->get_value() - mm->get_relative().x); v_scroll->set_value(v_scroll->get_value() - mm->get_relative().y); } diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index b7484aa748..fd47d9964e 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -144,8 +144,8 @@ void EditorAssetLibraryItemDescription::set_image(int p_type, int p_index, const for (int i = 0; i < preview_images.size(); i++) { if (preview_images[i].id == p_index) { if (preview_images[i].is_video) { - Ref<Image> overlay = previews->get_theme_icon("PlayOverlay", "EditorIcons")->get_data(); - Ref<Image> thumbnail = p_image->get_data(); + Ref<Image> overlay = previews->get_theme_icon("PlayOverlay", "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); @@ -557,8 +557,15 @@ void EditorAssetLibrary::_notification(int p_what) { error_label->raise(); } break; case NOTIFICATION_VISIBILITY_CHANGED: { - if (is_visible() && initial_loading) { - _repository_changed(0); // Update when shown for the first time. + if (is_visible()) { + // Focus the search box automatically when switching to the Templates tab (in the Project Manager) + // or switching to the AssetLib tab (in the editor). + // The Project Manager's project filter box is automatically focused in the project manager code. + filter->grab_focus(); + + if (initial_loading) { + _repository_changed(0); // Update when shown for the first time. + } } } break; case NOTIFICATION_PROCESS: { @@ -606,6 +613,8 @@ void EditorAssetLibrary::_update_repository_options() { } void EditorAssetLibrary::_unhandled_key_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + const Ref<InputEventKey> key = p_event; if (key.is_valid() && key->is_pressed()) { @@ -1332,6 +1341,11 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { library_main->add_theme_constant_override("separation", 10 * EDSCALE); filter = memnew(LineEdit); + if (templates_only) { + filter->set_placeholder(TTR("Search templates, projects, and demos")); + } else { + filter->set_placeholder(TTR("Search assets (excluding templates, projects, and demos)")); + } search_hb->add_child(filter); filter->set_h_size_flags(Control::SIZE_EXPAND_FILL); filter->connect("text_changed", callable_mp(this, &EditorAssetLibrary::_search_text_changed)); diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp index 5963092860..3553450672 100644 --- a/editor/plugins/audio_stream_editor_plugin.cpp +++ b/editor/plugins/audio_stream_editor_plugin.cpp @@ -105,6 +105,8 @@ void AudioStreamEditor::_audio_changed() { 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("MainPlay", "EditorIcons")); set_process(false); @@ -125,10 +127,13 @@ void AudioStreamEditor::_stop() { void AudioStreamEditor::_on_finished() { _play_button->set_icon(get_theme_icon("MainPlay", "EditorIcons")); - if (_current == _player->get_stream()->get_length()) { + if (!_pausing) { _current = 0; _indicator->update(); + } else { + _pausing = false; } + set_process(false); } void AudioStreamEditor::_draw_indicator() { @@ -194,8 +199,6 @@ void AudioStreamEditor::_bind_methods() { AudioStreamEditor::AudioStreamEditor() { set_custom_minimum_size(Size2(1, 100) * EDSCALE); - _current = 0; - _dragging = false; _player = memnew(AudioStreamPlayer); _player->connect("finished", callable_mp(this, &AudioStreamEditor::_on_finished)); diff --git a/editor/plugins/audio_stream_editor_plugin.h b/editor/plugins/audio_stream_editor_plugin.h index aa906a6a05..14e829d025 100644 --- a/editor/plugins/audio_stream_editor_plugin.h +++ b/editor/plugins/audio_stream_editor_plugin.h @@ -41,17 +41,18 @@ class AudioStreamEditor : public ColorRect { GDCLASS(AudioStreamEditor, ColorRect); Ref<AudioStream> stream; - AudioStreamPlayer *_player; - ColorRect *_preview; - Control *_indicator; - Label *_current_label; - Label *_duration_label; + AudioStreamPlayer *_player = nullptr; + ColorRect *_preview = nullptr; + Control *_indicator = nullptr; + Label *_current_label = nullptr; + Label *_duration_label = nullptr; - Button *_play_button; - Button *_stop_button; + Button *_play_button = nullptr; + Button *_stop_button = nullptr; - float _current; - bool _dragging; + float _current = 0; + bool _dragging = false; + bool _pausing = false; void _audio_changed(); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 23467c8377..b678197037 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -472,6 +472,8 @@ float CanvasItemEditor::snap_angle(float p_target, float p_start) const { } void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) { + ERR_FAIL_COND(p_ev.is_null()); + Ref<InputEventKey> k = p_ev; if (!is_visible_in_tree()) { @@ -1095,7 +1097,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve } // Start dragging a guide - if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed()) { // Press button if (b->get_position().x < RULER_WIDTH && b->get_position().y < RULER_WIDTH) { // Drag a new double guide @@ -1154,7 +1156,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve } // Release confirms the guide move - if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed()) { if (show_guides && EditorNode::get_singleton()->get_edited_scene()) { Transform2D xform = viewport_scrollable->get_transform() * transform; @@ -1268,7 +1270,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo if (pan_on_scroll) { // Perform horizontal scrolling first so we can check for Shift being held. if (b->is_pressed() && - (b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_shift() && b->get_button_index() == BUTTON_WHEEL_UP))) { + (b->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT || (b->get_shift() && b->get_button_index() == MOUSE_BUTTON_WHEEL_UP))) { // Pan left view_offset.x -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); update_viewport(); @@ -1276,7 +1278,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo } if (b->is_pressed() && - (b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_shift() && b->get_button_index() == BUTTON_WHEEL_DOWN))) { + (b->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT || (b->get_shift() && b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN))) { // Pan right view_offset.x += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); update_viewport(); @@ -1284,7 +1286,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo } } - if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_DOWN) { + if (b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { // Scroll or pan down if (pan_on_scroll) { view_offset.y += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); @@ -1299,7 +1301,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo return true; } - if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_UP) { + if (b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { // Scroll or pan up if (pan_on_scroll) { view_offset.y -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); @@ -1316,17 +1318,17 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo if (!panning) { if (b->is_pressed() && - (b->get_button_index() == BUTTON_MIDDLE || - b->get_button_index() == BUTTON_RIGHT || - (b->get_button_index() == BUTTON_LEFT && tool == TOOL_PAN) || - (b->get_button_index() == BUTTON_LEFT && !EditorSettings::get_singleton()->get("editors/2d/simple_panning") && pan_pressed))) { + (b->get_button_index() == MOUSE_BUTTON_MIDDLE || + b->get_button_index() == MOUSE_BUTTON_RIGHT || + (b->get_button_index() == MOUSE_BUTTON_LEFT && tool == TOOL_PAN) || + (b->get_button_index() == MOUSE_BUTTON_LEFT && !EditorSettings::get_singleton()->get("editors/2d/simple_panning") && pan_pressed))) { // Pan the viewport panning = true; } } if (panning) { - if (!b->is_pressed() && (pan_on_scroll || (b->get_button_index() != BUTTON_WHEEL_DOWN && b->get_button_index() != BUTTON_WHEEL_UP))) { + if (!b->is_pressed() && (pan_on_scroll || (b->get_button_index() != MOUSE_BUTTON_WHEEL_DOWN && b->get_button_index() != MOUSE_BUTTON_WHEEL_UP))) { // Stop panning the viewport (for any mouse button press except zooming) panning = false; } @@ -1412,7 +1414,7 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) { // Drag the pivot (in pivot mode / with V key) if (drag_type == DRAG_NONE) { - if ((b.is_valid() && b->is_pressed() && b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) || + if ((b.is_valid() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) || (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == KEY_V)) { List<CanvasItem *> selection = _get_edited_canvas_items(); @@ -1466,7 +1468,7 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) { // Confirm the pivot move if (drag_selection.size() >= 1 && - ((b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) || + ((b.is_valid() && !b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) || (k.is_valid() && !k->is_pressed() && k->get_keycode() == KEY_V))) { _commit_canvas_item_state( drag_selection, @@ -1480,7 +1482,7 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) { } // Cancel a drag - if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) { _restore_canvas_item_state(drag_selection); drag_type = DRAG_NONE; viewport->update(); @@ -1566,7 +1568,7 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) { // Start rotation if (drag_type == DRAG_NONE) { - if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed()) { if ((b->get_command() && !b->get_alt() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) { List<CanvasItem *> selection = _get_edited_canvas_items(); @@ -1610,7 +1612,7 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) { } // Confirms the node rotation - if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed()) { if (drag_selection.size() != 1) { _commit_canvas_item_state( drag_selection, @@ -1634,7 +1636,7 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) { } // Cancel a drag - if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) { _restore_canvas_item_state(drag_selection); drag_type = DRAG_NONE; viewport->update(); @@ -1648,7 +1650,7 @@ bool CanvasItemEditor::_gui_input_open_scene_on_double_click(const Ref<InputEven Ref<InputEventMouseButton> b = p_event; // Open a sub-scene on double-click - if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && b->is_doubleclick() && tool == TOOL_SELECT) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && b->is_doubleclick() && tool == TOOL_SELECT) { List<CanvasItem *> selection = _get_edited_canvas_items(); if (selection.size() == 1) { CanvasItem *canvas_item = selection[0]; @@ -1667,7 +1669,7 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) { // Starts anchor dragging if needed if (drag_type == DRAG_NONE) { - if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) { List<CanvasItem *> selection = _get_edited_canvas_items(); if (selection.size() == 1) { Control *control = Object::cast_to<Control>(selection[0]); @@ -1787,7 +1789,7 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) { } // Confirms new anchor position - if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) { + if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed()) { _commit_canvas_item_state( drag_selection, vformat(TTR("Move CanvasItem \"%s\" Anchor"), drag_selection[0]->get_name())); @@ -1796,7 +1798,7 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) { } // Cancel a drag - if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) { _restore_canvas_item_state(drag_selection); drag_type = DRAG_NONE; viewport->update(); @@ -1812,7 +1814,7 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) { // Drag resize handles if (drag_type == DRAG_NONE) { - if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) { List<CanvasItem *> selection = _get_edited_canvas_items(); if (selection.size() == 1) { CanvasItem *canvas_item = selection[0]; @@ -1966,7 +1968,7 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) { } // Confirm resize - if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) { + if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed()) { const Node2D *node2d = Object::cast_to<Node2D>(drag_selection[0]); if (node2d) { // Extends from Node2D. @@ -2003,7 +2005,7 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) { } // Cancel a drag - if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) { _restore_canvas_item_state(drag_selection); snap_target[0] = SNAP_TARGET_NONE; snap_target[1] = SNAP_TARGET_NONE; @@ -2021,7 +2023,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { // Drag resize handles if (drag_type == DRAG_NONE) { - if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && ((b->get_alt() && b->get_control()) || tool == TOOL_SCALE)) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && ((b->get_alt() && b->get_control()) || tool == TOOL_SCALE)) { List<CanvasItem *> selection = _get_edited_canvas_items(); if (selection.size() == 1) { CanvasItem *canvas_item = selection[0]; @@ -2117,7 +2119,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { } // Confirm resize - if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed()) { if (drag_selection.size() != 1) { _commit_canvas_item_state( drag_selection, @@ -2142,7 +2144,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { } // Cancel a drag - if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) { _restore_canvas_item_state(drag_selection); drag_type = DRAG_NONE; viewport->update(); @@ -2159,7 +2161,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { if (drag_type == DRAG_NONE) { //Start moving the nodes - if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed()) { if ((b->get_alt() && !b->get_control()) || tool == TOOL_MOVE) { List<CanvasItem *> selection = _get_edited_canvas_items(); @@ -2262,7 +2264,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { } // Confirm the move (only if it was moved) - if (b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT) { + if (b.is_valid() && !b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_LEFT) { if (transform.affine_inverse().xform(b->get_position()) != drag_from) { if (drag_selection.size() != 1) { _commit_canvas_item_state( @@ -2295,7 +2297,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { } // Cancel a drag - if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) { _restore_canvas_item_state(drag_selection, true); snap_target[0] = SNAP_TARGET_NONE; snap_target[1] = SNAP_TARGET_NONE; @@ -2435,8 +2437,8 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { if (drag_type == DRAG_NONE) { if (b.is_valid() && - ((b->get_button_index() == BUTTON_RIGHT && b->get_alt() && tool == TOOL_SELECT) || - (b->get_button_index() == BUTTON_LEFT && tool == TOOL_LIST_SELECT))) { + ((b->get_button_index() == MOUSE_BUTTON_RIGHT && b->get_alt() && tool == TOOL_SELECT) || + (b->get_button_index() == MOUSE_BUTTON_LEFT && tool == TOOL_LIST_SELECT))) { // Popup the selection menu list Point2 click = transform.affine_inverse().xform(b->get_position()); @@ -2497,7 +2499,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { } } - if (b.is_valid() && b->is_pressed() && b->get_button_index() == BUTTON_RIGHT && b->get_control()) { + if (b.is_valid() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->get_control()) { add_node_menu->set_position(get_global_transform().xform(get_local_mouse_position())); add_node_menu->set_size(Vector2(1, 1)); add_node_menu->popup(); @@ -2505,7 +2507,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { return true; } - if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) { // Single item selection Point2 click = transform.affine_inverse().xform(b->get_position()); @@ -2571,7 +2573,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { } if (drag_type == DRAG_BOX_SELECTION) { - if (b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT) { + if (b.is_valid() && !b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_LEFT) { // Confirms box selection Node *scene = editor->get_edited_scene(); if (scene) { @@ -2597,7 +2599,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { return true; } - if (b.is_valid() && b->is_pressed() && b->get_button_index() == BUTTON_RIGHT) { + if (b.is_valid() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_RIGHT) { // Cancel box selection drag_type = DRAG_NONE; viewport->update(); @@ -2634,7 +2636,7 @@ bool CanvasItemEditor::_gui_input_ruler_tool(const Ref<InputEvent> &p_event) { ruler_tool_origin = snap_point(viewport->get_local_mouse_position() / zoom + view_offset); } - if (b.is_valid() && b->get_button_index() == BUTTON_LEFT) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT) { if (b->is_pressed()) { ruler_tool_active = true; } else { diff --git a/editor/plugins/collision_polygon_3d_editor_plugin.cpp b/editor/plugins/collision_polygon_3d_editor_plugin.cpp index 0c18975258..b50a497ccf 100644 --- a/editor/plugins/collision_polygon_3d_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_3d_editor_plugin.cpp @@ -142,7 +142,7 @@ bool CollisionPolygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, con switch (mode) { case MODE_CREATE: { - if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) { if (!wip_active) { wip.clear(); wip.push_back(cpoint); @@ -166,14 +166,14 @@ bool CollisionPolygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, con return true; } } - } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) { + } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed() && wip_active) { _wip_close(); } } break; case MODE_EDIT: { - if (mb->get_button_index() == BUTTON_LEFT) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->is_pressed()) { if (mb->get_control()) { if (poly.size() < 3) { @@ -267,7 +267,7 @@ bool CollisionPolygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, con } } } - if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) { + if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) { int closest_idx = -1; Vector2 closest_pos; real_t closest_dist = 1e10; @@ -301,7 +301,7 @@ bool CollisionPolygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, con Ref<InputEventMouseMotion> mm = p_event; if (mm.is_valid()) { - if (edited_point != -1 && (wip_active || mm->get_button_mask() & BUTTON_MASK_LEFT)) { + if (edited_point != -1 && (wip_active || mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT)) { Vector2 gpoint = mm->get_position(); Vector3 ray_from = p_camera->project_ray_origin(gpoint); diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index 141ee35cdb..c38458c37f 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -325,7 +325,7 @@ bool CollisionShape2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_e if (mb.is_valid()) { Vector2 gpoint = mb->get_position(); - if (mb->get_button_index() == BUTTON_LEFT) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->is_pressed()) { for (int i = 0; i < handles.size(); i++) { if (xform.xform(handles[i]).distance_to(gpoint) < 8) { diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index bff5cb8d2a..db999f50ab 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -115,22 +115,22 @@ void CurveEditor::on_gui_input(const Ref<InputEvent> &p_event) { } switch (mb.get_button_index()) { - case BUTTON_RIGHT: + case MOUSE_BUTTON_RIGHT: _context_click_pos = mpos; open_context_menu(get_global_transform().xform(mpos)); break; - case BUTTON_MIDDLE: + case MOUSE_BUTTON_MIDDLE: remove_point(_hover_point); break; - case BUTTON_LEFT: + case MOUSE_BUTTON_LEFT: _dragging = true; break; } } - if (!mb.is_pressed() && _dragging && mb.get_button_index() == BUTTON_LEFT) { + if (!mb.is_pressed() && _dragging && mb.get_button_index() == MOUSE_BUTTON_LEFT) { _dragging = false; if (_has_undo_data) { UndoRedo &ur = *EditorNode::get_singleton()->get_undo_redo(); diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index eb3c06fba1..d3e5854786 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -88,7 +88,7 @@ Ref<Texture2D> EditorTexturePreviewPlugin::generate(const RES &p_from, const Siz return Ref<Texture2D>(); } - Ref<Image> atlas = tex->get_data(); + Ref<Image> atlas = tex->get_image(); if (!atlas.is_valid()) { return Ref<Texture2D>(); } @@ -99,7 +99,7 @@ Ref<Texture2D> EditorTexturePreviewPlugin::generate(const RES &p_from, const Siz } else { Ref<Texture2D> tex = p_from; if (tex.is_valid()) { - img = tex->get_data(); + img = tex->get_image(); if (img.is_valid()) { img = img->duplicate(); } diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp index 1e4553a967..9d29c31522 100644 --- a/editor/plugins/mesh_editor_plugin.cpp +++ b/editor/plugins/mesh_editor_plugin.cpp @@ -33,8 +33,10 @@ #include "editor/editor_scale.h" void MeshEditor::_gui_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) { + if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { rot_x -= mm->get_relative().y * 0.01; rot_y -= mm->get_relative().x * 0.01; if (rot_x < -Math_PI / 2) { diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 1d08a7821d..cbe0133034 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -185,8 +185,10 @@ void ViewportRotationControl::_get_sorted_axis(Vector<Axis2D> &r_axis) { } void ViewportRotationControl::_gui_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + const Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { Vector2 pos = mb->get_position(); if (mb->is_pressed()) { if (pos.distance_to(get_size() / 2.0) < get_size().x / 2.0) { @@ -1123,23 +1125,21 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { float zoom_factor = 1 + (ZOOM_FREELOOK_MULTIPLIER - 1) * b->get_factor(); switch (b->get_button_index()) { - case BUTTON_WHEEL_UP: { + case MOUSE_BUTTON_WHEEL_UP: { if (is_freelook_active()) { scale_freelook_speed(zoom_factor); } else { scale_cursor_distance(1.0 / zoom_factor); } } break; - - case BUTTON_WHEEL_DOWN: { + case MOUSE_BUTTON_WHEEL_DOWN: { if (is_freelook_active()) { scale_freelook_speed(1.0 / zoom_factor); } else { scale_cursor_distance(zoom_factor); } } break; - - case BUTTON_RIGHT: { + case MOUSE_BUTTON_RIGHT: { NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); if (b->is_pressed() && _edit.gizmo.is_valid()) { @@ -1200,7 +1200,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } } break; - case BUTTON_MIDDLE: { + case MOUSE_BUTTON_MIDDLE: { if (b->is_pressed() && _edit.mode != TRANSFORM_NONE) { switch (_edit.plane) { case TRANSFORM_VIEW: { @@ -1231,7 +1231,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } } } break; - case BUTTON_LEFT: { + case MOUSE_BUTTON_LEFT: { if (b->is_pressed()) { NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); if ((nav_scheme == NAVIGATION_MAYA || nav_scheme == NAVIGATION_MODO) && b->get_alt()) { @@ -1440,7 +1440,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { String n = _edit.gizmo->get_handle_name(_edit.gizmo_handle); set_message(n + ": " + String(v)); - } else if (m->get_button_mask() & BUTTON_MASK_LEFT) { + } else if (m->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { if (nav_scheme == NAVIGATION_MAYA && m->get_alt()) { nav_mode = NAVIGATION_ORBIT; } else if (nav_scheme == NAVIGATION_MODO && m->get_alt() && m->get_shift()) { @@ -1474,7 +1474,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { Vector3 ray_pos = _get_ray_pos(m->get_position()); Vector3 ray = _get_ray(m->get_position()); - float snap = EDITOR_GET("interface/inspector/default_float_step"); + double snap = EDITOR_GET("interface/inspector/default_float_step"); int snap_step_decimals = Math::range_step_decimals(snap); switch (_edit.mode) { @@ -1768,7 +1768,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { Vector3 y_axis = (click - _edit.center).normalized(); Vector3 x_axis = plane.normal.cross(y_axis).normalized(); - float angle = Math::atan2(x_axis.dot(intersection - _edit.center), y_axis.dot(intersection - _edit.center)); + double angle = Math::atan2(x_axis.dot(intersection - _edit.center), y_axis.dot(intersection - _edit.center)); if (_edit.snap || spatial_editor->is_snap_enabled()) { snap = spatial_editor->get_rotate_snap(); @@ -1830,8 +1830,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } } } - - } else if ((m->get_button_mask() & BUTTON_MASK_RIGHT) || freelook_active) { + } else if ((m->get_button_mask() & MOUSE_BUTTON_MASK_RIGHT) || freelook_active) { if (nav_scheme == NAVIGATION_MAYA && m->get_alt()) { nav_mode = NAVIGATION_ZOOM; } else if (freelook_active) { @@ -1840,7 +1839,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { nav_mode = NAVIGATION_PAN; } - } else if (m->get_button_mask() & BUTTON_MASK_MIDDLE) { + } else if (m->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) { const int mod = _get_key_modifier(m); if (nav_scheme == NAVIGATION_GODOT) { if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) { @@ -1851,13 +1850,11 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { // Always allow Alt as a modifier to better support graphic tablets. nav_mode = NAVIGATION_ORBIT; } - } else if (nav_scheme == NAVIGATION_MAYA) { if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) { nav_mode = NAVIGATION_PAN; } } - } else if (EditorSettings::get_singleton()->get("editors/3d/navigation/emulate_3_button_mouse")) { // Handle trackpad (no external mouse) use case const int mod = _get_key_modifier(m); @@ -4197,9 +4194,11 @@ Node3DEditorViewport::~Node3DEditorViewport() { ////////////////////////////////////////////////////////////// void Node3DEditorViewportContainer::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->is_pressed()) { Vector2 size = get_size(); @@ -4582,7 +4581,12 @@ void _update_all_gizmos(Node *p_node) { void Node3DEditor::update_all_gizmos(Node *p_node) { if (!p_node) { - p_node = SceneTree::get_singleton()->get_root(); + if (SceneTree::get_singleton()) { + p_node = SceneTree::get_singleton()->get_root(); + } else { + // No scene tree, so nothing to update. + return; + } } _update_all_gizmos(p_node); } @@ -5820,7 +5824,7 @@ void Node3DEditor::_init_grid() { // Offsets division_level for bigger or smaller grids. // Default value is -0.2. -1.0 gives Blender-like behavior, 0.5 gives huge grids. real_t division_level_bias = EditorSettings::get_singleton()->get("editors/3d/grid_division_level_bias"); - // Default largest grid size is 100m, 10^2 (default value is 2). + // Default largest grid size is 8^2 when primary_grid_steps is 8 (64m apart, so primary grid lines are 512m apart). int division_level_max = EditorSettings::get_singleton()->get("editors/3d/grid_division_level_max"); // Default smallest grid size is 1cm, 10^-2 (default value is -2). int division_level_min = EditorSettings::get_singleton()->get("editors/3d/grid_division_level_min"); @@ -6159,6 +6163,8 @@ void Node3DEditor::snap_selected_nodes_to_floor() { } void Node3DEditor::_unhandled_key_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (!is_visible_in_tree()) { return; } @@ -6611,7 +6617,7 @@ void Node3DEditor::_update_preview_environment() { void Node3DEditor::_sun_direction_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) { + if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { float x = -mm->get_relative().y * 0.02 * EDSCALE; float y = mm->get_relative().x * 0.02 * EDSCALE; diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index 908235f89f..84b4516452 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -88,7 +88,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { real_t dist_to_p_in = gpoint.distance_to(xform.xform(curve->get_point_position(i) + curve->get_point_in(i))); // Check for point movement start (for point + in/out controls). - if (mb->get_button_index() == BUTTON_LEFT) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mode == MODE_EDIT && !mb->get_shift() && dist_to_p < grab_threshold) { // Points can only be moved in edit mode. @@ -118,7 +118,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } // Check for point deletion. - if ((mb->get_button_index() == BUTTON_RIGHT && mode == MODE_EDIT) || (mb->get_button_index() == BUTTON_LEFT && mode == MODE_DELETE)) { + if ((mb->get_button_index() == MOUSE_BUTTON_RIGHT && mode == MODE_EDIT) || (mb->get_button_index() == MOUSE_BUTTON_LEFT && mode == MODE_DELETE)) { if (dist_to_p < grab_threshold) { undo_redo->create_action(TTR("Remove Point from Curve")); undo_redo->add_do_method(curve.ptr(), "remove_point", i); @@ -149,7 +149,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } // Check for point creation. - if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && ((mb->get_command() && mode == MODE_EDIT) || mode == MODE_CREATE)) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && ((mb->get_command() && mode == MODE_EDIT) || mode == MODE_CREATE)) { Ref<Curve2D> curve = node->get_curve(); undo_redo->create_action(TTR("Add Point to Curve")); @@ -170,7 +170,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } // Check for segment split. - if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && mode == MODE_EDIT && on_edge) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mode == MODE_EDIT && on_edge) { Vector2 gpoint2 = mb->get_position(); Ref<Curve2D> curve = node->get_curve(); @@ -207,7 +207,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } // Check for point movement completion. - if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && action != ACTION_NONE) { + if (!mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && action != ACTION_NONE) { Ref<Curve2D> curve = node->get_curve(); Vector2 new_pos = moving_from + xform.affine_inverse().basis_xform(gpoint - moving_screen_from); diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp index 3783af8fc6..47bd1114d2 100644 --- a/editor/plugins/path_3d_editor_plugin.cpp +++ b/editor/plugins/path_3d_editor_plugin.cpp @@ -316,7 +316,7 @@ bool Path3DEditorPlugin::forward_spatial_gui_input(Camera3D *p_camera, const Ref set_handle_clicked(false); } - if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb->get_control()))) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb->get_control()))) { //click into curve, break it down Vector<Vector3> v3a = c->tessellate(); int idx = 0; @@ -411,7 +411,7 @@ bool Path3DEditorPlugin::forward_spatial_gui_input(Camera3D *p_camera, const Ref //add new at pos } - } else if (mb->is_pressed() && ((mb->get_button_index() == BUTTON_LEFT && curve_del->is_pressed()) || (mb->get_button_index() == BUTTON_RIGHT && curve_edit->is_pressed()))) { + } else if (mb->is_pressed() && ((mb->get_button_index() == MOUSE_BUTTON_LEFT && curve_del->is_pressed()) || (mb->get_button_index() == MOUSE_BUTTON_RIGHT && curve_edit->is_pressed()))) { for (int i = 0; i < c->get_point_count(); i++) { real_t dist_to_p = p_camera->unproject_position(gt.xform(c->get_point_position(i))).distance_to(mbpos); real_t dist_to_p_out = p_camera->unproject_position(gt.xform(c->get_point_position(i) + c->get_point_out(i))).distance_to(mbpos); diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 3d7b01c149..470d897dcc 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -447,7 +447,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { Ref<InputEventMouseButton> mb = p_input; if (mb.is_valid()) { - if (mb->get_button_index() == BUTTON_LEFT) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->is_pressed()) { uv_drag_from = snap_point(Vector2(mb->get_position().x, mb->get_position().y)); uv_drag = true; @@ -759,7 +759,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { bone_painting = false; } } - } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { + } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) { _cancel_editing(); if (bone_painting) { @@ -768,9 +768,9 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_edit_draw->update(); - } else if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) { + } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed()) { uv_zoom->set_value(uv_zoom->get_value() / (1 - (0.1 * mb->get_factor()))); - } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed()) { + } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed()) { uv_zoom->set_value(uv_zoom->get_value() * (1 - (0.1 * mb->get_factor()))); } } @@ -778,7 +778,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { Ref<InputEventMouseMotion> mm = p_input; if (mm.is_valid()) { - if ((mm->get_button_mask() & BUTTON_MASK_MIDDLE) || Input::get_singleton()->is_key_pressed(KEY_SPACE)) { + if ((mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) || Input::get_singleton()->is_key_pressed(KEY_SPACE)) { Vector2 drag(mm->get_relative().x, mm->get_relative().y); uv_hscroll->set_value(uv_hscroll->get_value() - drag.x); uv_vscroll->set_value(uv_vscroll->get_value() - drag.y); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 8bf5d0611d..58e6717a3d 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -2706,6 +2706,8 @@ void ScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Co } void ScriptEditor::_unhandled_key_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (!is_visible_in_tree() || !p_event->is_pressed() || p_event->is_echo()) { return; } @@ -2737,7 +2739,7 @@ void ScriptEditor::_script_list_gui_input(const Ref<InputEvent> &ev) { Ref<InputEventMouseButton> mb = ev; if (mb.is_valid() && mb->is_pressed()) { switch (mb->get_button_index()) { - case BUTTON_MIDDLE: { + case MOUSE_BUTTON_MIDDLE: { // Right-click selects automatically; middle-click does not. int idx = script_list->get_item_at_position(mb->get_position(), true); if (idx >= 0) { @@ -2747,7 +2749,7 @@ void ScriptEditor::_script_list_gui_input(const Ref<InputEvent> &ev) { } } break; - case BUTTON_RIGHT: { + case MOUSE_BUTTON_RIGHT: { _make_script_list_context_menu(); } break; } diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index b6df66b8af..3534809891 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -601,8 +601,7 @@ void ScriptTextEditor::_bookmark_item_pressed(int p_idx) { if (p_idx < 4) { // Any item before the separator. _edit_option(bookmarks_menu->get_item_id(p_idx)); } else { - code_editor->goto_line(bookmarks_menu->get_item_metadata(p_idx)); - code_editor->get_text_editor()->call_deferred("center_viewport_to_cursor"); //Need to be deferred, because goto uses call_deferred(). + code_editor->goto_line_centered(bookmarks_menu->get_item_metadata(p_idx)); } } @@ -791,7 +790,7 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c emit_signal("request_open_script_at_line", result.script, result.location - 1); } else { emit_signal("request_save_history"); - _goto_line(result.location - 1); + goto_line_centered(result.location - 1); } } break; case ScriptLanguage::LookupResult::RESULT_CLASS: { @@ -1517,7 +1516,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { bool create_menu = false; CodeEdit *tx = code_editor->get_text_editor(); - if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) { local_pos = mb->get_global_position() - tx->get_global_position(); create_menu = true; } else if (k.is_valid() && k->get_keycode() == KEY_MENU) { diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index c8a46715ad..8f8a4b3054 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -460,7 +460,7 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { Ref<InputEventMouseButton> mb = ev; if (mb.is_valid()) { - if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { + if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) { int col, row; CodeEdit *tx = shader_editor->get_text_editor(); tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col); diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 121ccfa417..ad60984ad1 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -167,16 +167,18 @@ void BoneTransformEditor::_notification(int p_what) { } void BoneTransformEditor::_value_changed(const double p_value) { - if (updating) + if (updating) { return; + } Transform tform = compute_transform_from_vector3s(); _change_transform(tform); } void BoneTransformEditor::_value_changed_vector3(const String p_property_name, const Vector3 p_vector, const StringName p_edited_property_name, const bool p_boolean) { - if (updating) + if (updating) { return; + } Transform tform = compute_transform_from_vector3s(); _change_transform(tform); } @@ -194,8 +196,9 @@ Transform BoneTransformEditor::compute_transform_from_vector3s() const { } void BoneTransformEditor::_value_changed_transform(const String p_property_name, const Transform p_transform, const StringName p_edited_property_name, const bool p_boolean) { - if (updating) + if (updating) { return; + } _change_transform(p_transform); } @@ -222,11 +225,13 @@ void BoneTransformEditor::update_enabled_checkbox() { } void BoneTransformEditor::_update_properties() { - if (updating) + if (updating) { return; + } - if (skeleton == nullptr) + if (skeleton == nullptr) { return; + } updating = true; @@ -235,11 +240,13 @@ void BoneTransformEditor::_update_properties() { } void BoneTransformEditor::_update_custom_pose_properties() { - if (updating) + if (updating) { return; + } - if (skeleton == nullptr) + if (skeleton == nullptr) { return; + } updating = true; @@ -287,14 +294,16 @@ void BoneTransformEditor::set_toggle_enabled(const bool p_enabled) { } void BoneTransformEditor::_key_button_pressed() { - if (skeleton == nullptr) + if (skeleton == nullptr) { return; + } const BoneId bone_id = property.get_slicec('/', 1).to_int(); const String name = skeleton->get_bone_name(bone_id); - if (name.is_empty()) + if (name.is_empty()) { return; + } // Need to normalize the basis before you key it Transform tform = compute_transform_from_vector3s(); @@ -405,8 +414,9 @@ PhysicalBone3D *Skeleton3DEditor::create_physical_bone(int bone_id, int bone_chi Variant Skeleton3DEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) { TreeItem *selected = joint_tree->get_selected(); - if (!selected) + if (!selected) { return Variant(); + } Ref<Texture> icon = selected->get_icon(0); @@ -431,27 +441,32 @@ Variant Skeleton3DEditor::get_drag_data_fw(const Point2 &p_point, Control *p_fro bool Skeleton3DEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { TreeItem *target = joint_tree->get_item_at_position(p_point); - if (!target) + if (!target) { return false; + } const String path = target->get_metadata(0); - if (!path.begins_with("bones/")) + if (!path.begins_with("bones/")) { return false; + } TreeItem *selected = Object::cast_to<TreeItem>(Dictionary(p_data)["node"]); - if (target == selected) + if (target == selected) { return false; + } const String path2 = target->get_metadata(0); - if (!path2.begins_with("bones/")) + if (!path2.begins_with("bones/")) { return false; + } return true; } void Skeleton3DEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { - if (!can_drop_data_fw(p_point, p_data, p_from)) + if (!can_drop_data_fw(p_point, p_data, p_from)) { return; + } TreeItem *target = joint_tree->get_item_at_position(p_point); TreeItem *selected = Object::cast_to<TreeItem>(Dictionary(p_data)["node"]); @@ -510,19 +525,23 @@ void Skeleton3DEditor::_joint_tree_rmb_select(const Vector2 &p_pos) { } void Skeleton3DEditor::_update_properties() { - if (rest_editor) + if (rest_editor) { rest_editor->_update_properties(); - if (pose_editor) + } + if (pose_editor) { pose_editor->_update_properties(); - if (custom_pose_editor) + } + if (custom_pose_editor) { custom_pose_editor->_update_custom_pose_properties(); + } } void Skeleton3DEditor::update_joint_tree() { joint_tree->clear(); - if (skeleton == nullptr) + if (skeleton == nullptr) { return; + } TreeItem *root = joint_tree->create_item(); diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp index 4949d2b9b7..4a7f6c0f7e 100644 --- a/editor/plugins/sprite_2d_editor_plugin.cpp +++ b/editor/plugins/sprite_2d_editor_plugin.cpp @@ -171,7 +171,7 @@ void Sprite2DEditor::_update_mesh_data() { return; } - Ref<Image> image = texture->get_data(); + Ref<Image> image = texture->get_image(); ERR_FAIL_COND(image.is_null()); if (image->is_compressed()) { @@ -179,7 +179,7 @@ void Sprite2DEditor::_update_mesh_data() { } Rect2 rect; - if (node->is_region()) { + if (node->is_region_enabled()) { rect = node->get_region_rect(); } else { rect.size = Size2(image->get_width(), image->get_height()); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index a6949c873e..bd6dac7490 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -105,7 +105,7 @@ void SpriteFramesEditor::_sheet_preview_draw() { void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { Size2i size = split_sheet_preview->get_size(); int h = split_sheet_h->get_value(); int v = split_sheet_v->get_value(); @@ -150,11 +150,11 @@ void SpriteFramesEditor::_sheet_scroll_input(const Ref<InputEvent> &p_event) { // Zoom in/out using Ctrl + mouse wheel. This is done on the ScrollContainer // to allow performing this action anywhere, even if the cursor isn't // hovering the texture in the workspace. - if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) { _sheet_zoom_in(); // Don't scroll up after zooming in. accept_event(); - } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) { + } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) { _sheet_zoom_out(); // Don't scroll down after zooming out. accept_event(); @@ -694,11 +694,11 @@ void SpriteFramesEditor::_tree_input(const Ref<InputEvent> &p_event) { const Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) { _zoom_in(); // Don't scroll up after zooming in. accept_event(); - } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) { + } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) { _zoom_out(); // Don't scroll down after zooming out. accept_event(); diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index b88f1c91e6..2b8bfe067d 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -469,7 +469,7 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { Ref<InputEventMouseButton> mb = ev; if (mb.is_valid()) { - if (mb->get_button_index() == BUTTON_RIGHT) { + if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) { int col, row; CodeEdit *tx = code_editor->get_text_editor(); tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col); diff --git a/editor/plugins/texture_layered_editor_plugin.cpp b/editor/plugins/texture_layered_editor_plugin.cpp index 254ad3d56e..89ed98d53e 100644 --- a/editor/plugins/texture_layered_editor_plugin.cpp +++ b/editor/plugins/texture_layered_editor_plugin.cpp @@ -35,8 +35,10 @@ #include "editor/editor_settings.h" void TextureLayeredEditor::_gui_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) { + if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { y_rot += -mm->get_relative().x * 0.01; x_rot += mm->get_relative().y * 0.01; _update_material(); diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 63255e6547..7b927ad98b 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -285,7 +285,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { Ref<InputEventMouseButton> mb = p_input; if (mb.is_valid()) { - if (mb->get_button_index() == BUTTON_LEFT) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->is_pressed()) { if (node_ninepatch || obj_styleBox.is_valid()) { edited_margin = -1; @@ -447,7 +447,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { creating = false; } - } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { + } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) { if (drag) { drag = false; if (edited_margin >= 0) { @@ -466,9 +466,9 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { drag_index = -1; } } - } else if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) { + } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed()) { _zoom_on_position(draw_zoom * ((0.95 + (0.05 * mb->get_factor())) / 0.95), mb->get_position()); - } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed()) { + } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed()) { _zoom_on_position(draw_zoom * (1 - (0.05 * mb->get_factor())), mb->get_position()); } } @@ -476,7 +476,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { Ref<InputEventMouseMotion> mm = p_input; if (mm.is_valid()) { - if (mm->get_button_mask() & BUTTON_MASK_MIDDLE || Input::get_singleton()->is_key_pressed(KEY_SPACE)) { + if (mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE || Input::get_singleton()->is_key_pressed(KEY_SPACE)) { Vector2 dragged(mm->get_relative().x / draw_zoom, mm->get_relative().y / draw_zoom); hscroll->set_value(hscroll->get_value() - dragged.x); vscroll->set_value(vscroll->get_value() - dragged.y); @@ -897,7 +897,7 @@ void TextureRegionEditor::edit(Object *p_obj) { atlas_tex = Ref<AtlasTexture>(nullptr); } edit_draw->update(); - if ((node_sprite && !node_sprite->is_region()) || (node_sprite_3d && !node_sprite_3d->is_region())) { + if ((node_sprite && !node_sprite->is_region_enabled()) || (node_sprite_3d && !node_sprite_3d->is_region_enabled())) { set_process(true); } if (!p_obj) { @@ -1115,7 +1115,7 @@ void TextureRegionEditorPlugin::_editor_visiblity_changed() { void TextureRegionEditorPlugin::make_visible(bool p_visible) { if (p_visible) { texture_region_button->show(); - bool is_node_configured = region_editor->is_stylebox() || region_editor->is_atlas_texture() || region_editor->is_ninepatch() || (region_editor->get_sprite() && region_editor->get_sprite()->is_region()) || (region_editor->get_sprite_3d() && region_editor->get_sprite_3d()->is_region()); + bool is_node_configured = region_editor->is_stylebox() || region_editor->is_atlas_texture() || region_editor->is_ninepatch() || (region_editor->get_sprite() && region_editor->get_sprite()->is_region_enabled()) || (region_editor->get_sprite_3d() && region_editor->get_sprite_3d()->is_region_enabled()); if ((is_node_configured && !manually_hidden) || texture_region_button->is_pressed()) { editor->make_bottom_panel_item_visible(region_editor); } diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 74b01b3c36..bd721244ea 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -233,11 +233,11 @@ void TileMapEditor::_palette_input(const Ref<InputEvent> &p_event) { // Zoom in/out using Ctrl + mouse wheel. if (mb.is_valid() && mb->is_pressed() && mb->get_command()) { - if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { size_slider->set_value(size_slider->get_value() + 0.2); } - if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_DOWN) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { size_slider->set_value(size_slider->get_value() - 0.2); } } @@ -966,9 +966,9 @@ void TileMapEditor::_update_copydata() { tcd.flip_v = node->is_cell_y_flipped(j, i); tcd.transpose = node->is_cell_transposed(j, i); tcd.autotile_coord = node->get_cell_autotile_coord(j, i); - } - copydata.push_back(tcd); + copydata.push_back(tcd); + } } } } @@ -1027,7 +1027,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == BUTTON_LEFT) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->is_pressed()) { if (Input::get_singleton()->is_key_pressed(KEY_SPACE)) { return false; // Drag. @@ -1177,7 +1177,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return true; } } - } else if (mb->get_button_index() == BUTTON_RIGHT) { + } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) { if (mb->is_pressed()) { if (tool == TOOL_SELECTING || selection_active) { tool = TOOL_NONE; @@ -1462,7 +1462,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return true; } - if (tool == TOOL_PICKING && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) { + if (tool == TOOL_PICKING && Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT)) { _pick_tile(over_tile); return true; diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index c628fe8367..feaf609557 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -80,7 +80,7 @@ void TileSetEditor::_import_node(Node *p_node, Ref<TileSet> p_library) { Vector2 phys_offset; Size2 s; - if (mi->is_region()) { + if (mi->is_region_enabled()) { s = mi->get_region_rect().size; p_library->tile_set_region(id, mi->get_region_rect()); } else { @@ -1246,12 +1246,12 @@ void TileSetEditor::_on_scroll_container_input(const Ref<InputEvent> &p_event) { // Zoom in/out using Ctrl + mouse wheel. This is done on the ScrollContainer // to allow performing this action anywhere, even if the cursor isn't // hovering the texture in the workspace. - if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) { print_line("zooming in"); _zoom_in(); // Don't scroll up after zooming in. accept_event(); - } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) { + } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) { print_line("zooming out"); _zoom_out(); // Don't scroll down after zooming out. @@ -1280,7 +1280,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { const Ref<InputEventMouseMotion> mm = p_ie; if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && !creating_shape) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && !creating_shape) { if (!current_tile_region.has_point(mb->get_position())) { List<int> *tiles = new List<int>(); tileset->get_tile_list(tiles); @@ -1304,7 +1304,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } // Drag Middle Mouse if (mm.is_valid()) { - if (mm->get_button_mask() & BUTTON_MASK_MIDDLE) { + if (mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) { Vector2 dragged(mm->get_relative().x, mm->get_relative().y); scroll->set_h_scroll(scroll->get_h_scroll() - dragged.x * workspace->get_scale().x); scroll->set_v_scroll(scroll->get_v_scroll() - dragged.y * workspace->get_scale().x); @@ -1313,7 +1313,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { if (edit_mode == EDITMODE_REGION) { if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (get_current_tile() >= 0 || workspace_mode != WORKSPACE_EDIT) { dragging = true; region_from = mb->get_position(); @@ -1322,13 +1322,13 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { workspace_overlay->update(); return; } - } else if (dragging && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) { + } else if (dragging && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { dragging = false; edited_region = Rect2(); workspace->update(); workspace_overlay->update(); return; - } else if (dragging && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + } else if (dragging && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { dragging = false; update_edited_region(mb->get_position()); edited_region.position -= WORKSPACE_MARGIN; @@ -1428,7 +1428,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { switch (edit_mode) { case EDITMODE_ICON: { if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && current_tile_region.has_point(mb->get_position())) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && current_tile_region.has_point(mb->get_position())) { Vector2 coord((int)((mb->get_position().x - current_tile_region.position.x) / (spacing + size.x)), (int)((mb->get_position().y - current_tile_region.position.y) / (spacing + size.y))); undo_redo->create_action(TTR("Set Tile Icon")); undo_redo->add_do_method(tileset.ptr(), "autotile_set_icon_coordinate", get_current_tile(), coord); @@ -1445,9 +1445,9 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { if (dragging) { return; } - if ((mb->get_button_index() == BUTTON_RIGHT || mb->get_button_index() == BUTTON_LEFT) && current_tile_region.has_point(mb->get_position())) { + if ((mb->get_button_index() == MOUSE_BUTTON_RIGHT || mb->get_button_index() == MOUSE_BUTTON_LEFT) && current_tile_region.has_point(mb->get_position())) { dragging = true; - erasing = (mb->get_button_index() == BUTTON_RIGHT); + erasing = (mb->get_button_index() == MOUSE_BUTTON_RIGHT); alternative = Input::get_singleton()->is_key_pressed(KEY_SHIFT); Vector2 coord((int)((mb->get_position().x - current_tile_region.position.x) / (spacing + size.x)), (int)((mb->get_position().y - current_tile_region.position.y) / (spacing + size.y))); Vector2 pos(coord.x * (spacing + size.x), coord.y * (spacing + size.y)); @@ -1518,7 +1518,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } } } else { - if ((erasing && mb->get_button_index() == BUTTON_RIGHT) || (!erasing && mb->get_button_index() == BUTTON_LEFT)) { + if ((erasing && mb->get_button_index() == MOUSE_BUTTON_RIGHT) || (!erasing && mb->get_button_index() == MOUSE_BUTTON_LEFT)) { dragging = false; erasing = false; alternative = false; @@ -1612,7 +1612,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { shape_anchor += current_tile_region.position; if (tools[TOOL_SELECT]->is_pressed()) { if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (edit_mode != EDITMODE_PRIORITY && current_shape.size() > 0) { int grabbed_point = get_grabbed_point(mb->get_position(), grab_threshold); @@ -1630,7 +1630,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } } workspace->update(); - } else if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + } else if (!mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (edit_mode == EDITMODE_COLLISION) { if (dragging_point >= 0) { dragging_point = -1; @@ -1705,7 +1705,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } } else if (tools[SHAPE_NEW_POLYGON]->is_pressed()) { if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { Vector2 pos = mb->get_position(); pos = snap_point(pos); if (creating_shape) { @@ -1725,7 +1725,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { current_shape.push_back(snap_point(pos)); workspace->update(); } - } else if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) { + } else if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { if (creating_shape) { creating_shape = false; _select_edited_shape_coord(); @@ -1739,7 +1739,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } } else if (tools[SHAPE_NEW_RECTANGLE]->is_pressed()) { if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { _set_edited_collision_shape(Ref<ConvexPolygonShape2D>()); current_shape.resize(0); Vector2 pos = mb->get_position(); @@ -1751,13 +1751,13 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { creating_shape = true; workspace->update(); return; - } else if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) { + } else if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { if (creating_shape) { creating_shape = false; _select_edited_shape_coord(); workspace->update(); } - } else if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + } else if (!mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (creating_shape) { // if the first two corners are within grabbing distance of one another, expand the rect to fill the tile if (is_within_grabbing_distance_of_first_point(current_shape[1], grab_threshold)) { @@ -2928,7 +2928,7 @@ void TileSetEditor::close_shape(const Vector2 &shape_anchor) { } if (p_total < 0) { - points.invert(); + points.reverse(); } shape->set_points(points); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index a63e641c2b..b2fa9c540e 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -384,6 +384,20 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { port_offset += 2; } + if (is_resizable) { + Ref<VisualShaderNodeComment> comment_node = Object::cast_to<VisualShaderNodeComment>(vsnode.ptr()); + if (comment_node.is_valid()) { + node->set_comment(true); + + Label *comment_label = memnew(Label); + node->add_child(comment_label); + comment_label->set_h_size_flags(Control::SIZE_EXPAND_FILL); + comment_label->set_v_size_flags(Control::SIZE_EXPAND_FILL); + comment_label->set_mouse_filter(Control::MouseFilter::MOUSE_FILTER_STOP); + comment_label->set_text(comment_node->get_description()); + } + } + Ref<VisualShaderNodeUniform> uniform = vsnode; if (uniform.is_valid()) { VisualShaderEditor::get_singleton()->graph->add_child(node); @@ -1624,6 +1638,92 @@ void VisualShaderEditor::_preview_select_port(int p_node, int p_port) { undo_redo->commit_action(); } +void VisualShaderEditor::_comment_title_popup_show(const Point2 &p_position, int p_node_id) { + VisualShader::Type type = get_current_shader_type(); + Ref<VisualShaderNodeComment> node = visual_shader->get_node(type, p_node_id); + if (node.is_null()) { + return; + } + comment_title_change_edit->set_text(node->get_title()); + comment_title_change_popup->set_meta("id", p_node_id); + comment_title_change_popup->popup(); + comment_title_change_popup->set_position(p_position); +} + +void VisualShaderEditor::_comment_title_text_changed(const String &p_new_text) { + comment_title_change_edit->set_size(Size2(-1, -1)); + comment_title_change_popup->set_size(Size2(-1, -1)); +} + +void VisualShaderEditor::_comment_title_text_entered(const String &p_new_text) { + comment_title_change_popup->hide(); +} + +void VisualShaderEditor::_comment_title_popup_focus_out() { + comment_title_change_popup->hide(); +} + +void VisualShaderEditor::_comment_title_popup_hide() { + ERR_FAIL_COND(!comment_title_change_popup->has_meta("id")); + int node_id = (int)comment_title_change_popup->get_meta("id"); + + VisualShader::Type type = get_current_shader_type(); + Ref<VisualShaderNodeComment> node = visual_shader->get_node(type, node_id); + + ERR_FAIL_COND(node.is_null()); + + if (node->get_title() == comment_title_change_edit->get_text()) { + return; // nothing changed - ignored + } + undo_redo->create_action(TTR("Set Comment Node Title")); + undo_redo->add_do_method(node.ptr(), "set_title", comment_title_change_edit->get_text()); + undo_redo->add_undo_method(node.ptr(), "set_title", node->get_title()); + undo_redo->add_do_method(graph_plugin.ptr(), "update_node", (int)type, node_id); + undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", (int)type, node_id); + undo_redo->commit_action(); +} + +void VisualShaderEditor::_comment_desc_popup_show(const Point2 &p_position, int p_node_id) { + VisualShader::Type type = get_current_shader_type(); + Ref<VisualShaderNodeComment> node = visual_shader->get_node(type, p_node_id); + if (node.is_null()) { + return; + } + comment_desc_change_edit->set_text(node->get_description()); + comment_desc_change_popup->set_meta("id", p_node_id); + comment_desc_change_popup->popup(); + comment_desc_change_popup->set_position(p_position); +} + +void VisualShaderEditor::_comment_desc_text_changed() { + comment_desc_change_edit->set_size(Size2(-1, -1)); + comment_desc_change_popup->set_size(Size2(-1, -1)); +} + +void VisualShaderEditor::_comment_desc_confirm() { + comment_desc_change_popup->hide(); +} + +void VisualShaderEditor::_comment_desc_popup_hide() { + ERR_FAIL_COND(!comment_desc_change_popup->has_meta("id")); + int node_id = (int)comment_desc_change_popup->get_meta("id"); + + VisualShader::Type type = get_current_shader_type(); + Ref<VisualShaderNodeComment> node = visual_shader->get_node(type, node_id); + + ERR_FAIL_COND(node.is_null()); + + if (node->get_description() == comment_desc_change_edit->get_text()) { + return; // nothing changed - ignored + } + undo_redo->create_action(TTR("Set Comment Node Description")); + undo_redo->add_do_method(node.ptr(), "set_description", comment_desc_change_edit->get_text()); + undo_redo->add_undo_method(node.ptr(), "set_description", node->get_title()); + undo_redo->add_do_method(graph_plugin.ptr(), "update_node", (int)type, node_id); + undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", (int)type, node_id); + undo_redo->commit_action(); +} + void VisualShaderEditor::_uniform_line_edit_changed(const String &p_text, int p_node_id) { VisualShader::Type type = get_current_shader_type(); @@ -2504,9 +2604,10 @@ void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; VisualShader::Type type = get_current_shader_type(); - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { selected_constants.clear(); selected_uniforms.clear(); + selected_comment = -1; List<int> to_change; for (int i = 0; i < graph->get_child_count(); i++) { @@ -2517,17 +2618,27 @@ void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { to_change.push_back(id); Ref<VisualShaderNode> node = visual_shader->get_node(type, id); - VisualShaderNodeConstant *cnode = Object::cast_to<VisualShaderNodeConstant>(node.ptr()); - if (cnode != nullptr) { + + VisualShaderNodeComment *comment_node = Object::cast_to<VisualShaderNodeComment>(node.ptr()); + if (comment_node != nullptr) { + selected_comment = id; + } + VisualShaderNodeConstant *constant_node = Object::cast_to<VisualShaderNodeConstant>(node.ptr()); + if (constant_node != nullptr) { selected_constants.insert(id); } - VisualShaderNodeUniform *unode = Object::cast_to<VisualShaderNodeUniform>(node.ptr()); - if (unode != nullptr) { + VisualShaderNodeUniform *uniform_node = Object::cast_to<VisualShaderNodeUniform>(node.ptr()); + if (uniform_node != nullptr && uniform_node->is_convertible_to_constant()) { selected_uniforms.insert(id); } } } } + + if (to_change.size() > 1) { + selected_comment = -1; + } + if (to_change.is_empty() && copy_nodes_buffer.is_empty()) { _show_members_dialog(true); } else { @@ -2548,16 +2659,34 @@ void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { if (temp != -1) { popup_menu->remove_item(temp); } + temp = popup_menu->get_item_index(NodeMenuOptions::SEPARATOR3); + if (temp != -1) { + popup_menu->remove_item(temp); + } + temp = popup_menu->get_item_index(NodeMenuOptions::SET_COMMENT_TITLE); + if (temp != -1) { + popup_menu->remove_item(temp); + } + temp = popup_menu->get_item_index(NodeMenuOptions::SET_COMMENT_DESCRIPTION); + if (temp != -1) { + popup_menu->remove_item(temp); + } - if (selected_constants.size() > 0 || selected_uniforms.size() > 0) { + if (selected_comment != -1) { popup_menu->add_separator("", NodeMenuOptions::SEPARATOR2); + popup_menu->add_item(TTR("Set Comment Title"), NodeMenuOptions::SET_COMMENT_TITLE); + popup_menu->add_item(TTR("Set Comment Description"), NodeMenuOptions::SET_COMMENT_DESCRIPTION); + } + + if (selected_constants.size() > 0 || selected_uniforms.size() > 0) { + popup_menu->add_separator("", NodeMenuOptions::SEPARATOR3); if (selected_constants.size() > 0) { popup_menu->add_item(TTR("Convert Constant(s) to Uniform(s)"), NodeMenuOptions::CONVERT_CONSTANTS_TO_UNIFORMS); } if (selected_uniforms.size() > 0) { - popup_menu->add_item(TTR("Convert Uniforms(s) to Constant(s)"), NodeMenuOptions::CONVERT_UNIFORMS_TO_CONSTANTS); + popup_menu->add_item(TTR("Convert Uniform(s) to Constant(s)"), NodeMenuOptions::CONVERT_UNIFORMS_TO_CONSTANTS); } } @@ -3111,6 +3240,12 @@ void VisualShaderEditor::_node_menu_id_pressed(int p_idx) { case NodeMenuOptions::CONVERT_UNIFORMS_TO_CONSTANTS: _convert_constants_to_uniforms(true); break; + case NodeMenuOptions::SET_COMMENT_TITLE: + _comment_title_popup_show(get_global_mouse_position(), selected_comment); + break; + case NodeMenuOptions::SET_COMMENT_DESCRIPTION: + _comment_desc_popup_show(get_global_mouse_position(), selected_comment); + break; default: break; } @@ -3534,6 +3669,35 @@ VisualShaderEditor::VisualShaderEditor() { alert->get_label()->set_custom_minimum_size(Size2(400, 60) * EDSCALE); add_child(alert); + comment_title_change_popup = memnew(PopupPanel); + comment_title_change_edit = memnew(LineEdit); + comment_title_change_edit->set_expand_to_text_length(true); + comment_title_change_edit->connect("text_changed", callable_mp(this, &VisualShaderEditor::_comment_title_text_changed)); + comment_title_change_edit->connect("text_entered", callable_mp(this, &VisualShaderEditor::_comment_title_text_entered)); + comment_title_change_popup->add_child(comment_title_change_edit); + comment_title_change_edit->set_size(Size2(-1, -1)); + comment_title_change_popup->set_size(Size2(-1, -1)); + comment_title_change_popup->connect("focus_exited", callable_mp(this, &VisualShaderEditor::_comment_title_popup_focus_out)); + comment_title_change_popup->connect("popup_hide", callable_mp(this, &VisualShaderEditor::_comment_title_popup_hide)); + add_child(comment_title_change_popup); + + comment_desc_change_popup = memnew(PopupPanel); + VBoxContainer *comment_desc_vbox = memnew(VBoxContainer); + comment_desc_change_popup->add_child(comment_desc_vbox); + comment_desc_change_edit = memnew(TextEdit); + comment_desc_change_edit->connect("text_changed", callable_mp(this, &VisualShaderEditor::_comment_desc_text_changed)); + comment_desc_vbox->add_child(comment_desc_change_edit); + comment_desc_change_edit->set_custom_minimum_size(Size2(300 * EDSCALE, 150 * EDSCALE)); + comment_desc_change_edit->set_size(Size2(-1, -1)); + comment_desc_change_popup->set_size(Size2(-1, -1)); + comment_desc_change_popup->connect("focus_exited", callable_mp(this, &VisualShaderEditor::_comment_desc_confirm)); + comment_desc_change_popup->connect("popup_hide", callable_mp(this, &VisualShaderEditor::_comment_desc_popup_hide)); + Button *comment_desc_confirm_button = memnew(Button); + comment_desc_confirm_button->set_text(TTR("OK")); + comment_desc_vbox->add_child(comment_desc_confirm_button); + comment_desc_confirm_button->connect("pressed", callable_mp(this, &VisualShaderEditor::_comment_desc_confirm)); + add_child(comment_desc_change_popup); + /////////////////////////////////////// // SHADER NODES TREE OPTIONS /////////////////////////////////////// @@ -3971,6 +4135,7 @@ VisualShaderEditor::VisualShaderEditor() { // SPECIAL + add_options.push_back(AddOption("Comment", "Special", "", "VisualShaderNodeComment", TTR("A rectangular area with a description string for better graph organization."))); add_options.push_back(AddOption("Expression", "Special", "", "VisualShaderNodeExpression", TTR("Custom Godot Shader Language expression, with custom amount of input and output ports. This is a direct injection of code into the vertex/fragment/light function, do not use it to write the function declarations inside."))); add_options.push_back(AddOption("Fresnel", "Special", "", "VisualShaderNodeFresnel", TTR("Returns falloff based on the dot product of surface normal and view direction of camera (pass associated inputs to it)."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); add_options.push_back(AddOption("GlobalExpression", "Special", "", "VisualShaderNodeGlobalExpression", TTR("Custom Godot Shader Language expression, which is placed on top of the resulted shader. You can place various function definitions inside and call it later in the Expressions. You can also declare varyings, uniforms and constants."))); diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index 182bed6ba6..517dc6056f 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -67,7 +67,7 @@ private: VisualShader::Type type = VisualShader::Type::TYPE_MAX; VisualShaderNode *visual_node = nullptr; GraphNode *graph_node = nullptr; - bool preview_visible = 0; + bool preview_visible = false; int preview_pos = 0; Map<int, InputPort> input_ports; Map<int, Port> output_ports; @@ -161,6 +161,12 @@ class VisualShaderEditor : public VBoxContainer { PopupMenu *popup_menu; MenuButton *tools; + PopupPanel *comment_title_change_popup = nullptr; + LineEdit *comment_title_change_edit = nullptr; + + PopupPanel *comment_desc_change_popup = nullptr; + TextEdit *comment_desc_change_edit = nullptr; + bool preview_first = true; bool preview_showed = false; bool particles_mode; @@ -192,6 +198,9 @@ class VisualShaderEditor : public VBoxContainer { SEPARATOR2, // ignore CONVERT_CONSTANTS_TO_UNIFORMS, CONVERT_UNIFORMS_TO_CONSTANTS, + SEPARATOR3, // ignore + SET_COMMENT_TITLE, + SET_COMMENT_DESCRIPTION, }; Tree *members; @@ -325,6 +334,7 @@ class VisualShaderEditor : public VBoxContainer { Set<int> selected_constants; Set<int> selected_uniforms; + int selected_comment = -1; void _convert_constants_to_uniforms(bool p_vice_versa); void _replace_node(VisualShader::Type p_type_id, int p_node_id, const StringName &p_from, const StringName &p_to); @@ -334,6 +344,17 @@ class VisualShaderEditor : public VBoxContainer { void _connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position); void _connection_from_empty(const String &p_to, int p_to_slot, const Vector2 &p_release_position); + void _comment_title_popup_show(const Point2 &p_position, int p_node_id); + void _comment_title_popup_hide(); + void _comment_title_popup_focus_out(); + void _comment_title_text_changed(const String &p_new_text); + void _comment_title_text_entered(const String &p_new_text); + + void _comment_desc_popup_show(const Point2 &p_position, int p_node_id); + void _comment_desc_popup_hide(); + void _comment_desc_confirm(); + void _comment_desc_text_changed(); + void _uniform_line_edit_changed(const String &p_text, int p_node_id); void _uniform_line_edit_focus_out(Object *line_edit, int p_node_id); diff --git a/editor/project_export.cpp b/editor/project_export.cpp index 4bcb616fbd..3ede50320a 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -37,7 +37,7 @@ #include "core/os/dir_access.h" #include "core/os/file_access.h" #include "core/os/os.h" -#include "core/string/compressed_translation.h" +#include "core/string/optimized_translation.h" #include "editor_data.h" #include "editor_node.h" #include "editor_scale.h" @@ -1082,6 +1082,7 @@ ProjectExportDialog::ProjectExportDialog() { export_filter->add_item(TTR("Export all resources in the project")); export_filter->add_item(TTR("Export selected scenes (and dependencies)")); export_filter->add_item(TTR("Export selected resources (and dependencies)")); + export_filter->add_item(TTR("Export all resources in the project except resources checked below")); resources_vb->add_margin_child(TTR("Export Mode:"), export_filter); export_filter->connect("item_selected", callable_mp(this, &ProjectExportDialog::_export_type_changed)); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index d57491533d..d3def86bd1 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -100,6 +100,7 @@ private: FileDialog *fdialog_install; String zip_path; String zip_title; + String zip_root; AcceptDialog *dialog_error; String fav_dir; @@ -200,7 +201,9 @@ private: char fname[16384]; ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0); - if (String(fname).ends_with("project.godot")) { + String fname_str = String(fname); + if (fname_str.ends_with("project.godot")) { + zip_root = fname_str.substr(0, fname_str.rfind("project.godot")); break; } @@ -487,7 +490,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"), msg->get_theme_icon("DefaultProjectIcon", "EditorIcons")); + ResourceSaver::save(dir.plus_file("icon.png"), create_unscaled_default_project_icon()); FileAccess *f = FileAccess::open(dir.plus_file("default_env.tres"), FileAccess::WRITE); if (!f) { @@ -533,44 +536,34 @@ private: String path = fname; - int depth = 1; //stuff from github comes with tag - bool skip = false; - while (depth > 0) { - int pp = path.find("/"); - if (pp == -1) { - skip = true; - break; - } - path = path.substr(pp + 1, path.length()); - depth--; - } - - if (skip || path == String()) { + if (path == String() || path == zip_root || !zip_root.is_subsequence_of(path)) { // } else if (path.ends_with("/")) { // a dir path = path.substr(0, path.length() - 1); + String rel_path = path.substr(zip_root.length()); DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - da->make_dir(dir.plus_file(path)); + da->make_dir(dir.plus_file(rel_path)); memdelete(da); } else { Vector<uint8_t> data; data.resize(info.uncompressed_size); + String rel_path = path.substr(zip_root.length()); //read unzOpenCurrentFile(pkg); unzReadCurrentFile(pkg, data.ptrw(), data.size()); unzCloseCurrentFile(pkg); - FileAccess *f = FileAccess::open(dir.plus_file(path), FileAccess::WRITE); + FileAccess *f = FileAccess::open(dir.plus_file(rel_path), FileAccess::WRITE); if (f) { f->store_buffer(data.ptr(), data.size()); memdelete(f); } else { - failed_files.push_back(path); + failed_files.push_back(rel_path); } } @@ -1745,7 +1738,7 @@ void ProjectList::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) { int clicked_index = p_hb->get_index(); const Item &clicked_project = _projects[clicked_index]; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->get_shift() && _selected_project_keys.size() > 0 && _last_clicked != "" && clicked_project.project_key != _last_clicked) { int anchor_index = -1; for (int i = 0; i < _projects.size(); ++i) { @@ -1893,6 +1886,8 @@ void ProjectManager::_update_project_buttons() { } void ProjectManager::_unhandled_key_input(const Ref<InputEvent> &p_ev) { + ERR_FAIL_COND(p_ev.is_null()); + Ref<InputEventKey> k = p_ev; if (k.is_valid()) { @@ -2343,6 +2338,17 @@ void ProjectManager::_on_order_option_changed(int p_idx) { } } +void ProjectManager::_on_tab_changed(int p_tab) { + if (p_tab == 0) { // Projects + // Automatically grab focus when the user moves from the Templates tab + // back to the Projects tab. + search_box->grab_focus(); + } + + // The Templates tab's search field is focused on display in the asset + // library editor plugin code. +} + void ProjectManager::_on_search_term_changed(const String &p_term) { _project_list->set_search_term(p_term); _project_list->sort_projects(); @@ -2430,8 +2436,10 @@ ProjectManager::ProjectManager() { // Define a minimum window size to prevent UI elements from overlapping or being cut off DisplayServer::get_singleton()->window_set_min_size(Size2(750, 420) * EDSCALE); - // TODO: Resize windows on hiDPI displays on Windows and Linux and remove the line below - DisplayServer::get_singleton()->window_set_size(DisplayServer::get_singleton()->window_get_size() * MAX(1, EDSCALE)); + // TODO: Resize windows on hiDPI displays on Windows and Linux and remove the lines below + float scale_factor = MAX(1, EDSCALE); + Vector2i window_size = DisplayServer::get_singleton()->window_get_size(); + DisplayServer::get_singleton()->window_set_size(Vector2i(window_size.x * scale_factor, window_size.y * scale_factor)); } // TRANSLATORS: This refers to the application where users manage their Godot projects. @@ -2466,6 +2474,7 @@ ProjectManager::ProjectManager() { center_box->add_child(tabs); tabs->set_anchors_and_offsets_preset(Control::PRESET_WIDE); tabs->set_tab_align(TabContainer::ALIGN_LEFT); + tabs->connect("tab_changed", callable_mp(this, &ProjectManager::_on_tab_changed)); HBoxContainer *projects_hb = memnew(HBoxContainer); projects_hb->set_name(TTR("Projects")); @@ -2482,8 +2491,8 @@ ProjectManager::ProjectManager() { search_tree_vb->add_child(hb); search_box = memnew(LineEdit); - search_box->set_placeholder(TTR("Search")); - search_box->set_tooltip(TTR("The search box filters projects by name and last path component.\nTo filter projects by name and full path, the query must contain at least one `/` character.")); + search_box->set_placeholder(TTR("Filter projects")); + search_box->set_tooltip(TTR("This field filters projects by name and last path component.\nTo filter projects by name and full path, the query must contain at least one `/` character.")); search_box->connect("text_changed", callable_mp(this, &ProjectManager::_on_search_term_changed)); search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); hb->add_child(search_box); diff --git a/editor/project_manager.h b/editor/project_manager.h index d659f38076..d13315c022 100644 --- a/editor/project_manager.h +++ b/editor/project_manager.h @@ -120,6 +120,7 @@ class ProjectManager : public Control { void _files_dropped(PackedStringArray p_files, int p_screen); void _on_order_option_changed(int p_idx); + void _on_tab_changed(int p_tab); void _on_search_term_changed(const String &p_term); protected: diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 8ce7153355..0a4f432e4a 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -1353,7 +1353,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) { void CustomPropertyEditor::_drag_easing(const Ref<InputEvent> &p_ev) { Ref<InputEventMouseMotion> mm = p_ev; - if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) { + if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { float rel = mm->get_relative().x; if (rel == 0) { return; diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp index 48aa0471c9..b51524b299 100644 --- a/editor/rename_dialog.cpp +++ b/editor/rename_dialog.cpp @@ -434,7 +434,10 @@ String RenameDialog::_substitute(const String &subject, const Node *node, int co } int current = EditorNode::get_singleton()->get_editor_data().get_edited_scene(); - result = result.replace("${SCENE}", EditorNode::get_singleton()->get_editor_data().get_scene_title(current)); + // Always request the scene title with the extension stripped. + // Otherwise, the result could vary depending on whether a scene with the same name + // (but different extension) is currently open. + result = result.replace("${SCENE}", EditorNode::get_singleton()->get_editor_data().get_scene_title(current, true)); Node *root_node = SceneTree::get_singleton()->get_edited_scene_root(); if (root_node) { diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 2cdab83d90..c62e9cbe5f 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -61,14 +61,18 @@ void SceneTreeDock::_quick_open() { } void SceneTreeDock::_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { restore_script_editor_on_drag = false; //lost chance } } void SceneTreeDock::_unhandled_key_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (get_focus_owner() && get_focus_owner()->is_text_field()) { return; } @@ -608,7 +612,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { List<Node *> selection = editor_selection->get_selected_node_list(); selection.sort_custom<Node::Comparator>(); // sort by index if (MOVING_DOWN) { - selection.invert(); + selection.reverse(); } int lowest_id = common_parent->get_child_count() - 1; @@ -897,7 +901,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { Node *scene = editor_data->get_edited_scene_root(); if (!scene) { - accept->set_text(TTR("This operation can't be done without a scene.")); + accept->set_text(TTR("Saving the branch as a scene requires having a scene open in the editor.")); accept->popup_centered(); break; } @@ -905,7 +909,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { List<Node *> selection = editor_selection->get_selected_node_list(); if (selection.size() != 1) { - accept->set_text(TTR("This operation requires a single selected node.")); + accept->set_text(vformat(TTR("Saving the branch as a scene requires selecting only one node, but you have selected %d nodes."), selection.size())); accept->popup_centered(); break; } @@ -913,13 +917,13 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { Node *tocopy = selection.front()->get(); if (tocopy == scene) { - accept->set_text(TTR("Can not perform with the root node.")); + accept->set_text(TTR("Can't save the root node branch as an instanced scene.\nTo create an editable copy of the current scene, duplicate it using the FileSystem dock context menu\nor create an inherited scene using Scene > New Inherited Scene... instead.")); accept->popup_centered(); break; } if (tocopy != editor_data->get_edited_scene_root() && tocopy->get_filename() != "") { - accept->set_text(TTR("This operation can't be done on instanced scenes.")); + accept->set_text(TTR("Can't save the branch of an already instanced scene.\nTo create a variation of a scene, you can make an inherited scene based on the instanced scene using Scene > New Inherited Scene... instead.")); accept->popup_centered(); break; } @@ -1384,7 +1388,7 @@ void SceneTreeDock::fill_path_renames(Node *p_node, Node *p_new_parent, List<Pai base_path.push_back(n->get_name()); n = n->get_parent(); } - base_path.invert(); + base_path.reverse(); Vector<StringName> new_base_path; if (p_new_parent) { @@ -1394,7 +1398,7 @@ void SceneTreeDock::fill_path_renames(Node *p_node, Node *p_new_parent, List<Pai n = n->get_parent(); } - new_base_path.invert(); + new_base_path.reverse(); } _fill_path_renames(base_path, new_base_path, p_node, p_renames); @@ -1580,7 +1584,7 @@ void SceneTreeDock::_node_prerenamed(Node *p_node, const String &p_new_name) { base_path.push_back(n->get_name()); n = n->get_parent(); } - base_path.invert(); + base_path.reverse(); Vector<StringName> new_base_path = base_path; base_path.push_back(p_node->get_name()); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index e9de91f851..b5e9aec854 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -994,9 +994,6 @@ bool SceneTreeEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_d if (!can_rename) { return false; //not editable tree } - if (filter != String()) { - return false; //can't rearrange tree with filter turned on - } Dictionary d = p_data; if (!d.has("type")) { @@ -1049,7 +1046,7 @@ bool SceneTreeEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_d } } - return String(d["type"]) == "nodes"; + return String(d["type"]) == "nodes" && filter == String(); } void SceneTreeEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h index 6b505a6784..fd5157f04f 100644 --- a/editor/scene_tree_editor.h +++ b/editor/scene_tree_editor.h @@ -181,6 +181,7 @@ protected: public: void popup_scenetree_dialog(); SceneTreeEditor *get_scene_tree() { return tree; } + LineEdit *get_filter_line_edit() { return filter; } SceneTreeDialog(); ~SceneTreeDialog(); }; diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp index 3852c389c7..3be2136a20 100644 --- a/editor/settings_config_dialog.cpp +++ b/editor/settings_config_dialog.cpp @@ -139,6 +139,8 @@ void EditorSettingsDialog::_notification(int p_what) { } void EditorSettingsDialog::_unhandled_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + const Ref<InputEventKey> k = p_event; if (k.is_valid() && k->is_pressed()) { diff --git a/editor/translations/af.po b/editor/translations/af.po index bda0eed750..a60466f417 100644 --- a/editor/translations/af.po +++ b/editor/translations/af.po @@ -6,12 +6,13 @@ # Julius Stopforth <jjstopforth@gmail.com>, 2018. # Isa Tippens <isatippens2@gmail.com>, 2019. # Henry Geyser <thegoat187@gmail.com>, 2020. +# Henry LeRoux <henry.leroux@ocsbstudent.ca>, 2021. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-12-01 20:29+0000\n" -"Last-Translator: Henry Geyser <thegoat187@gmail.com>\n" +"PO-Revision-Date: 2021-04-05 14:28+0000\n" +"Last-Translator: Henry LeRoux <henry.leroux@ocsbstudent.ca>\n" "Language-Team: Afrikaans <https://hosted.weblate.org/projects/godot-engine/" "godot/af/>\n" "Language: af\n" @@ -19,7 +20,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.4-dev\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -216,14 +217,12 @@ msgid "Animation Playback Track" msgstr "" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Animation length (frames)" -msgstr "Animasie lengte (in sekondes)." +msgstr "Animasie lengte (in rame)." #: editor/animation_track_editor.cpp -#, fuzzy msgid "Animation length (seconds)" -msgstr "Animasie lengte (in sekondes)." +msgstr "Animasie lengte (in sekondes)" #: editor/animation_track_editor.cpp #, fuzzy @@ -3667,6 +3666,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -4095,6 +4099,10 @@ msgid "Reset to Defaults" msgstr "Laai Verstek" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp #, fuzzy msgid "%d Files" msgstr "Vind" diff --git a/editor/translations/ar.po b/editor/translations/ar.po index 5c03984e01..f4b65c0065 100644 --- a/editor/translations/ar.po +++ b/editor/translations/ar.po @@ -3691,6 +3691,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "الØالة: إستيراد المل٠Ùشل. من Ùضلك Ø£ØµÙ„Ø Ø§Ù„Ù…Ù„Ù Ùˆ أعد إستيراده يدوياً." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "لا يمكن مسØ/إعادة تسمية جذر الموارد." @@ -4092,6 +4097,10 @@ msgid "Reset to Defaults" msgstr "تØميل الإÙتراضي" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d ملÙات" diff --git a/editor/translations/bg.po b/editor/translations/bg.po index 848574a1f1..cb2b9e1bd2 100644 --- a/editor/translations/bg.po +++ b/editor/translations/bg.po @@ -3537,6 +3537,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3927,6 +3932,10 @@ msgid "Reset to Defaults" msgstr "Връщане на Ñтандартните наÑтройки" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d файла" diff --git a/editor/translations/bn.po b/editor/translations/bn.po index ca8fff0724..c8d082fbd5 100644 --- a/editor/translations/bn.po +++ b/editor/translations/bn.po @@ -3872,6 +3872,11 @@ msgstr "" "ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨à¥¤" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp #, fuzzy msgid "Cannot move/rename resources root." msgstr "ফনà§à¦Ÿà§‡à¦° উৎস লোড/পà§à¦°à¦¸à§‡à¦¸ করা সমà§à¦à¦¬ হচà§à¦›à§‡ না।" @@ -4323,6 +4328,10 @@ msgid "Reset to Defaults" msgstr "পà§à¦°à¦¾à¦¥à¦®à¦¿à¦• sRGB বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp #, fuzzy msgid "%d Files" msgstr "ফাইল" diff --git a/editor/translations/br.po b/editor/translations/br.po index 7600dd4eb1..29f9cd2d79 100644 --- a/editor/translations/br.po +++ b/editor/translations/br.po @@ -3512,6 +3512,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3902,6 +3907,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/ca.po b/editor/translations/ca.po index 141f2cd58f..ca28ea5eaf 100644 --- a/editor/translations/ca.po +++ b/editor/translations/ca.po @@ -3714,6 +3714,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "Estat: No s'ha pogut importar. Corregiu el fitxer i torneu a importar." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "No es pot moure/reanomenar l'arrel dels recursos." @@ -4121,6 +4126,10 @@ msgid "Reset to Defaults" msgstr "Carrega Valors predeterminats" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d Fitxers" diff --git a/editor/translations/cs.po b/editor/translations/cs.po index 2c21fc0e63..17e44a4863 100644 --- a/editor/translations/cs.po +++ b/editor/translations/cs.po @@ -19,17 +19,18 @@ # Emil Jiřà Tywoniak <emil.tywoniak@gmail.com>, 2020, 2021. # Filip Vincůrek <vincurek.f@gmail.com>, 2020. # Ondrej Pavelka <ondrej.pavelka@outlook.com>, 2020. -# ZbynÄ›k <zbynek.fiala@gmail.com>, 2020. +# ZbynÄ›k <zbynek.fiala@gmail.com>, 2020, 2021. # Daniel KřÞ <Daniel.kriz@protonmail.com>, 2020. # VladimirBlazek <vblazek042@gmail.com>, 2020. # kubajz22 <til.jakubesko@seznam.cz>, 2020. # Václav Blažej <vaclavblazej@seznam.cz>, 2020, 2021. +# ProfJack <profjackcz@gmail.com>, 2021. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-08 15:33+0000\n" -"Last-Translator: Václav Blažej <vaclavblazej@seznam.cz>\n" +"PO-Revision-Date: 2021-04-05 14:28+0000\n" +"Last-Translator: ProfJack <profjackcz@gmail.com>\n" "Language-Team: Czech <https://hosted.weblate.org/projects/godot-engine/godot/" "cs/>\n" "Language: cs\n" @@ -37,7 +38,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -"X-Generator: Weblate 4.5.1\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -354,7 +355,7 @@ msgstr "ZmÄ›nit režim interpolace animace" #: editor/animation_track_editor.cpp msgid "Change Animation Loop Mode" -msgstr "ZmÄ›nit režim smyÄky animace" +msgstr "ZmÄ›nit mód smyÄky animace" #: editor/animation_track_editor.cpp msgid "Remove Anim Track" @@ -3674,6 +3675,12 @@ msgstr "" "znovu ruÄnÄ›." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" +"Importovánà tohoto souboru bylo zakázáno, takže jej nelze otevÅ™Ãt pro úpravy." + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Nelze pÅ™esunout/pÅ™ejmenovat koÅ™en zdrojů." @@ -4062,19 +4069,20 @@ msgid "Saving..." msgstr "UkládánÃ..." #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Select Importer" -msgstr "Režim výbÄ›ru" +msgstr "Vybrat Importér" #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Importer:" -msgstr "Import" +msgstr "Importér:" #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Reset to Defaults" -msgstr "NaÄÃst výchozÃ" +msgstr "Obnovit výchozÃ" + +#: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "Zachovat soubor (bez importu)" #: editor/import_dock.cpp msgid "%d Files" @@ -5083,11 +5091,11 @@ msgstr "Stahovánà tohoto assetu právÄ› probÃhá!" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Recently Updated" -msgstr "Naposledy upravené" +msgstr "Nedávno aktualizované" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Least Recently Updated" -msgstr "Naposledy neupravené" +msgstr "Dlouho neaktualizované" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Name (A-Z)" @@ -5175,7 +5183,7 @@ msgid "" "Can't determine a save path for lightmap images.\n" "Save your scene and try again." msgstr "" -"Nelze urÄit cestu uloženà pro svÄ›telnou mapu obrázku.\n" +"Nelze urÄit cestu pro uloženà obrázků svÄ›telné mapy.\n" "Uložte scénu (obrázky se uložà do stejného adresáře) nebo vyberte cestu pro " "uloženà z vlastnosti BakedLightmap." @@ -7340,9 +7348,8 @@ msgid "Yaw" msgstr "Náklon" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Size" -msgstr "Velikost: " +msgstr "Velikost" #: editor/plugins/spatial_editor_plugin.cpp msgid "Objects Drawn" @@ -10390,7 +10397,6 @@ msgid "Plugins" msgstr "Pluginy" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Import Defaults" msgstr "NaÄÃst výchozÃ" @@ -10642,9 +10648,8 @@ msgid "Instance Child Scene" msgstr "PÅ™idat instanci scény" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Can't paste root node into the same scene." -msgstr "Nelze manipulovat s uzly z cizà scény!" +msgstr "Nelze vložit koÅ™enový uzel do stejné scény." #: editor/scene_tree_dock.cpp msgid "Paste Node(s)" @@ -11612,7 +11617,7 @@ msgstr "Následné zpracovánÃ" #: modules/lightmapper_cpu/lightmapper_cpu.cpp #, fuzzy msgid "Plotting lightmaps" -msgstr "Vykreslenà svÄ›tel:" +msgstr "Vykreslovánà svÄ›telných map" #: modules/mono/csharp_script.cpp msgid "Class name can't be a reserved keyword" @@ -12427,11 +12432,11 @@ msgstr "Prázdný CollisionPolygon2D nemá pÅ™i kolizi žádný efekt." #: scene/2d/collision_polygon_2d.cpp msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode." -msgstr "" +msgstr "Chybný polygon. Alespoň 3 body jsou potÅ™eba v 'Solids' build módu." #: scene/2d/collision_polygon_2d.cpp msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode." -msgstr "" +msgstr "Chybný polygon. Alespoň 2 body jsou potÅ™eba v 'Segments' build módu." #: scene/2d/collision_shape_2d.cpp msgid "" @@ -13050,6 +13055,8 @@ msgid "" "The sampler port is connected but not used. Consider changing the source to " "'SamplerPort'." msgstr "" +"Sampler port je pÅ™ipojen, ale nenà použitý. Zvažte zmÄ›nu zdroje na " +"'SamplerPort'." #: scene/resources/visual_shader_nodes.cpp msgid "Invalid source for preview." diff --git a/editor/translations/da.po b/editor/translations/da.po index 72b2bf0e81..7de7e428c5 100644 --- a/editor/translations/da.po +++ b/editor/translations/da.po @@ -22,7 +22,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-16 10:40+0000\n" +"PO-Revision-Date: 2021-03-20 04:18+0000\n" "Last-Translator: snakatk <snaqii@live.dk>\n" "Language-Team: Danish <https://hosted.weblate.org/projects/godot-engine/" "godot/da/>\n" @@ -406,7 +406,7 @@ msgstr "Anim Indsæt Nøgle" #: editor/animation_track_editor.cpp #, fuzzy msgid "Change Animation Step" -msgstr "Ændre Animation Navn:" +msgstr "Ændre animationsskridt" #: editor/animation_track_editor.cpp #, fuzzy @@ -549,7 +549,7 @@ msgstr "Grupper spor efter node eller vis dem som almindelig liste." #: editor/animation_track_editor.cpp #, fuzzy msgid "Snap:" -msgstr "Trin: " +msgstr "Trin:" #: editor/animation_track_editor.cpp msgid "Animation step value." @@ -595,8 +595,9 @@ msgid "Duplicate Selection" msgstr "Duplikér Valgte" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Duplicate Transposed" -msgstr "Duplicate transposed" +msgstr "Duplikér Transposed" #: editor/animation_track_editor.cpp msgid "Delete Selection" @@ -673,7 +674,7 @@ msgstr "Skalaforhold:" #: editor/animation_track_editor.cpp #, fuzzy msgid "Select Tracks to Copy" -msgstr "Vælg spor til kopiering:" +msgstr "Vælg spor til kopiering" #: editor/animation_track_editor.cpp editor/editor_log.cpp #: editor/editor_properties.cpp @@ -690,9 +691,8 @@ msgid "Select All/None" msgstr "Vælg Node" #: editor/animation_track_editor_plugins.cpp -#, fuzzy msgid "Add Audio Track Clip" -msgstr "Lydklip:" +msgstr "Tilføj lydspor klip" #: editor/animation_track_editor_plugins.cpp msgid "Change Audio Track Clip Start Offset" @@ -798,7 +798,7 @@ msgstr "Metode i target Node skal angives!" #: editor/connections_dialog.cpp #, fuzzy msgid "Method name must be a valid identifier." -msgstr "Navnet er ikke et gyldigt id:" +msgstr "Metodenavnet er ikke et gyldigt id." #: editor/connections_dialog.cpp #, fuzzy @@ -856,7 +856,7 @@ msgstr "Ekstra Call Argumenter:" #: editor/connections_dialog.cpp #, fuzzy msgid "Receiver Method:" -msgstr "Vælg Method" +msgstr "Modtager Metode:" #: editor/connections_dialog.cpp #, fuzzy @@ -936,9 +936,8 @@ msgid "Connect a Signal to a Method" msgstr "Forbind Signal: " #: editor/connections_dialog.cpp -#, fuzzy msgid "Edit Connection:" -msgstr "Redigere Forbindelse: " +msgstr "Redigér Forbindelse:" #: editor/connections_dialog.cpp msgid "Are you sure you want to remove all connections from the \"%s\" signal?" @@ -1082,14 +1081,15 @@ msgid "Owners Of:" msgstr "Ejere af:" #: editor/dependency_editor.cpp -#, fuzzy msgid "" "Remove selected files from the project? (no undo)\n" "You can find the removed files in the system trash to restore them." -msgstr "Fjern de valgte filer fra projektet? (ej fortrydes)" +msgstr "" +"Fjern de valgte filer fra projektet? (ej fortrydes)\n" +"Du kan finde de fjernede filer i systemets skraldespand for at genoprette " +"dem." #: editor/dependency_editor.cpp -#, fuzzy msgid "" "The files being removed are required by other resources in order for them to " "work.\n" @@ -1097,7 +1097,9 @@ msgid "" "You can find the removed files in the system trash to restore them." msgstr "" "De filer der fjernes er nødvendige for, at andre ressourcer kan fungere.\n" -"Fjern dem alligevel? (ej fortrydes)" +"Fjern dem alligevel? (ej fortrydes)\n" +"Du kan finde de fjernede filer i systemets skraldespand for at genoprette " +"dem." #: editor/dependency_editor.cpp msgid "Cannot remove:" @@ -1129,7 +1131,7 @@ msgstr "Fejl ved indlæsning!" #: editor/dependency_editor.cpp msgid "Permanently delete %d item(s)? (No undo!)" -msgstr "Slette %d styk(s) permanent? (ej fortryd)" +msgstr "Slet %d styk(s) permanent? (ej fortrydes)" #: editor/dependency_editor.cpp #, fuzzy @@ -1204,14 +1206,12 @@ msgid "Gold Sponsors" msgstr "Guld Sponsorer" #: editor/editor_about.cpp -#, fuzzy msgid "Silver Sponsors" -msgstr "Sølv Donorer" +msgstr "Sølv Sponsorer" #: editor/editor_about.cpp -#, fuzzy msgid "Bronze Sponsors" -msgstr "Bronze Donorer" +msgstr "Bronze Sponsorer" #: editor/editor_about.cpp msgid "Mini Sponsors" @@ -1238,22 +1238,21 @@ msgid "License" msgstr "Licens" #: editor/editor_about.cpp -#, fuzzy msgid "Third-party Licenses" -msgstr "Tredjeparts Licens" +msgstr "Tredjepartslicenser" #: editor/editor_about.cpp -#, fuzzy msgid "" "Godot Engine relies on a number of third-party free and open source " "libraries, all compatible with the terms of its MIT license. The following " "is an exhaustive list of all such third-party components with their " "respective copyright statements and license terms." msgstr "" -"Godot Engine er afhængig af en række tredjeparts biblioteker som er gratis " +"Godot Engine er afhængig af en række tredjepartsbiblioteker, som er gratis " "og open source. Alle bibliotekerne er kompatible med vilkÃ¥rene i MIT-" -"licensen. Følgende er en udtømmende liste over alle sÃ¥danne tredjeparts " -"komponenter med deres respektive ophavsretlige udsagn og licensbetingelser." +"licensen. Følgende er en udtømmende liste over alle sÃ¥danne " +"tredjepartskomponenter med deres respektive ophavsretlige udsagn og " +"licensbetingelser." #: editor/editor_about.cpp msgid "All Components" @@ -1268,9 +1267,8 @@ msgid "Licenses" msgstr "Licenser" #: editor/editor_asset_installer.cpp editor/project_manager.cpp -#, fuzzy msgid "Error opening package file, not in ZIP format." -msgstr "Fejl ved Ã¥bning af pakke fil, ikke i zip format." +msgstr "Fejl ved Ã¥bning af pakkefil, ikke i ZIP-format." #: editor/editor_asset_installer.cpp #, fuzzy @@ -1286,9 +1284,8 @@ msgid "The following files failed extraction from package:" msgstr "De følgende filer kunne ikke trækkes ud af pakken:" #: editor/editor_asset_installer.cpp -#, fuzzy msgid "And %s more files." -msgstr "%d flere filer" +msgstr "Og %s flere filer." #: editor/editor_asset_installer.cpp editor/project_manager.cpp msgid "Package installed successfully!" @@ -1380,7 +1377,7 @@ msgstr "Bus muligheder" #: editor/editor_audio_buses.cpp editor/filesystem_dock.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "Duplicate" -msgstr "Duplikere" +msgstr "Duplikér" #: editor/editor_audio_buses.cpp msgid "Reset Volume" @@ -1431,12 +1428,10 @@ msgid "Open Audio Bus Layout" msgstr "Ã…ben Audio Bus Layout" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "There is no '%s' file." msgstr "Der er ingen '%s' fil." #: editor/editor_audio_buses.cpp editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Layout" msgstr "Layout" @@ -1454,9 +1449,8 @@ msgid "Add Bus" msgstr "Tilføj Bus" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Add a new Audio Bus to this layout." -msgstr "Gem Audio Bus Layout Som..." +msgstr "Tilføj en ny Audio Bus til dette layout." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1550,9 +1544,8 @@ msgid "Rearrange Autoloads" msgstr "Flytte om pÃ¥ Autoloads" #: editor/editor_autoload_settings.cpp -#, fuzzy msgid "Can't add autoload:" -msgstr "Kan ikke tilføje autoload:" +msgstr "Autoload kan ikke tilføjes:" #: editor/editor_autoload_settings.cpp msgid "Add AutoLoad" @@ -1604,9 +1597,8 @@ msgid "[unsaved]" msgstr "[ikke gemt]" #: editor/editor_dir_dialog.cpp -#, fuzzy msgid "Please select a base directory first." -msgstr "Vælg en basis mappe først" +msgstr "Vælg en basismappe først." #: editor/editor_dir_dialog.cpp msgid "Choose a Directory" @@ -1639,16 +1631,14 @@ msgid "Storing File:" msgstr "Lagrings Fil:" #: editor/editor_export.cpp -#, fuzzy msgid "No export template found at the expected path:" -msgstr "Ingen eksporterings-skabelon fundet ved den forventede sti:" +msgstr "Ingen eksporterings-skabelon fundet pÃ¥ den forventede sti:" #: editor/editor_export.cpp msgid "Packing" msgstr "Pakker" #: editor/editor_export.cpp -#, fuzzy msgid "" "Target platform requires 'ETC' texture compression for GLES2. Enable 'Import " "Etc' in Project Settings." @@ -1657,7 +1647,6 @@ msgstr "" "i Projektindstillingerne." #: editor/editor_export.cpp -#, fuzzy msgid "" "Target platform requires 'ETC2' texture compression for GLES3. Enable " "'Import Etc 2' in Project Settings." @@ -1672,18 +1661,25 @@ msgid "" "Enable 'Import Etc' in Project Settings, or disable 'Driver Fallback " "Enabled'." msgstr "" +"MÃ¥lplatform kræver 'ETC' teksturkomprimering for driver fallback til GLES2.\n" +"Aktivér 'Import Etc' i Projektindstillingerne, eller deaktivér 'Driver " +"Fallback Aktiveret'." #: editor/editor_export.cpp msgid "" "Target platform requires 'PVRTC' texture compression for GLES2. Enable " "'Import Pvrtc' in Project Settings." msgstr "" +"MÃ¥lplatform kræver 'PVRTC' teksturkomprimering for GLES2. Aktivér 'Import " +"Pvrtc' i Projektindstillingerne." #: editor/editor_export.cpp msgid "" "Target platform requires 'ETC2' or 'PVRTC' texture compression for GLES3. " "Enable 'Import Etc 2' or 'Import Pvrtc' in Project Settings." msgstr "" +"MÃ¥lplatformen kræver 'ETC2' eller 'PVRTC' teksturkomprimering for GLES3. " +"Aktivér 'Import Etc 2' eller 'Import Pvrtc' i Projektindstillingerne." #: editor/editor_export.cpp msgid "" @@ -1692,12 +1688,16 @@ msgid "" "Enable 'Import Pvrtc' in Project Settings, or disable 'Driver Fallback " "Enabled'." msgstr "" +"MÃ¥lplatform kræver 'PVRTC' teksturkomprimering for driver fallback til " +"GLES2.\n" +"Aktivér 'Import Pvrtc' i Projektindstillingerne, eller deaktivér 'Driver " +"Fallback Aktiveret'." #: editor/editor_export.cpp platform/android/export/export.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp #: platform/osx/export/export.cpp platform/uwp/export/export.cpp msgid "Custom debug template not found." -msgstr "Brugerdefineret debug skabelonfil ikke fundet:" +msgstr "Brugerdefineret debug skabelonfil ikke fundet." #: editor/editor_export.cpp platform/android/export/export.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp @@ -1711,7 +1711,7 @@ msgstr "Skabelonfil ikke fundet:" #: editor/editor_export.cpp msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB." -msgstr "" +msgstr "Den indlejrede PCK kan ikke overstige 4 GiB ved 32-bit eksport." #: editor/editor_feature_profile.cpp #, fuzzy @@ -1797,7 +1797,7 @@ msgstr "Funktions Liste:" #: editor/editor_feature_profile.cpp #, fuzzy msgid "Enabled Classes:" -msgstr "Søg Classes" +msgstr "Aktiverede Classes:" #: editor/editor_feature_profile.cpp msgid "File '%s' format is invalid, import aborted." @@ -2074,14 +2074,13 @@ msgid "Inherited by:" msgstr "Arvet af:" #: editor/editor_help.cpp -#, fuzzy msgid "Description" -msgstr "Beskrivelse:" +msgstr "Beskrivelse" #: editor/editor_help.cpp #, fuzzy msgid "Online Tutorials" -msgstr "Online Undervisning:" +msgstr "Online Vejledninger" #: editor/editor_help.cpp msgid "Properties" @@ -2092,9 +2091,8 @@ msgid "override:" msgstr "" #: editor/editor_help.cpp -#, fuzzy msgid "default:" -msgstr "Standard" +msgstr "standardindstilling:" #: editor/editor_help.cpp msgid "Methods" @@ -2117,9 +2115,8 @@ msgid "Property Descriptions" msgstr "Egenskab beskrivelser" #: editor/editor_help.cpp -#, fuzzy msgid "(value)" -msgstr "Værdi:" +msgstr "(værdi)" #: editor/editor_help.cpp msgid "" @@ -2880,7 +2877,7 @@ msgstr "Projekt Indstillinger" #: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp #, fuzzy msgid "Version Control" -msgstr "Version:" +msgstr "Versionskontrol" #: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp msgid "Set Up Version Control" @@ -3773,14 +3770,17 @@ msgid "Favorites" msgstr "Favoritter" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" -"\n" "Status: Import af filen fejlede. Venligst reparer filen og genimporter " "manuelt." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Kan ikke flytte/omdøbe resourcen root." @@ -4219,6 +4219,10 @@ msgid "Reset to Defaults" msgstr "Indlæs Default" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d Filer" @@ -9994,9 +9998,8 @@ msgid "Export All" msgstr "Eksporter" #: editor/project_export.cpp editor/project_manager.cpp -#, fuzzy msgid "ZIP File" -msgstr " Filer" +msgstr "ZIP-Fil" #: editor/project_export.cpp msgid "Godot Game Pack" diff --git a/editor/translations/de.po b/editor/translations/de.po index ffd8a8874e..f70522a365 100644 --- a/editor/translations/de.po +++ b/editor/translations/de.po @@ -71,7 +71,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-09 04:13+0000\n" +"PO-Revision-Date: 2021-03-31 03:53+0000\n" "Last-Translator: So Wieso <sowieso@dukun.de>\n" "Language-Team: German <https://hosted.weblate.org/projects/godot-engine/" "godot/de/>\n" @@ -80,7 +80,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.5.1\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -3758,6 +3758,13 @@ msgstr "" "Status: Dateiimport fehlgeschlagen. Manuelle Reparatur und Neuimport nötig." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" +"Für diese Datei wurde die Import-Funktion deaktiviert, sie kann folglich " +"nicht zum Bearbeiten geöffnet werden." + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Ressourcen-Wurzel kann nicht verschoben oder umbenannt werden." @@ -4160,6 +4167,10 @@ msgid "Reset to Defaults" msgstr "Auf Standardwerte zurücksetzen" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "Datei behalten (kein Import)" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d Dateien" diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot index d11d4f42ac..2c0294e8b8 100644 --- a/editor/translations/editor.pot +++ b/editor/translations/editor.pot @@ -3490,6 +3490,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3880,6 +3885,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/el.po b/editor/translations/el.po index 8cd3397399..2aa33c39aa 100644 --- a/editor/translations/el.po +++ b/editor/translations/el.po @@ -11,12 +11,13 @@ # KostasMSC <kargyris@athtech.gr>, 2020. # lawfulRobot <czavantias@gmail.com>, 2020. # Michalis <michalisntovas@yahoo.gr>, 2021. +# leriaz <leriaz@live.com>, 2021. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-03 15:50+0000\n" -"Last-Translator: Michalis <michalisntovas@yahoo.gr>\n" +"PO-Revision-Date: 2021-03-29 21:57+0000\n" +"Last-Translator: leriaz <leriaz@live.com>\n" "Language-Team: Greek <https://hosted.weblate.org/projects/godot-engine/godot/" "el/>\n" "Language: el\n" @@ -24,7 +25,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.5.1-dev\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -825,7 +826,7 @@ msgstr "ÎœÎθοδος ΔÎκτη:" #: editor/connections_dialog.cpp msgid "Advanced" -msgstr "Για Î ÏοχωÏημÎνους" +msgstr "Για Ï€ÏοχωÏημÎνους" #: editor/connections_dialog.cpp msgid "Deferred" @@ -1041,11 +1042,13 @@ msgid "Owners Of:" msgstr "Ιδιοκτήτες του:" #: editor/dependency_editor.cpp -#, fuzzy msgid "" "Remove selected files from the project? (no undo)\n" "You can find the removed files in the system trash to restore them." -msgstr "ΑφαίÏεση επιλεγμÎνων αÏχείων από το ÎÏγο; (Αδυναμία αναίÏεσης)" +msgstr "" +"ΑφαίÏεση επιλεγμÎνων αÏχείων από το ÎÏγο; (Αδυναμία αναίÏεσης)\n" +"ΜποÏείτε να βÏείτε τα διεγÏαμμÎνα αÏχεία στον κάδο ανακÏκλωσης για να τα " +"επαναφÎÏετε." #: editor/dependency_editor.cpp #, fuzzy @@ -3700,6 +3703,11 @@ msgstr "" "επανεισάγετε το χειÏοκίνητα." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Δεν ήταν δυνατή η μετακίνηση/μετονομασία του πηγαίου καταλόγου." @@ -4104,6 +4112,10 @@ msgid "Reset to Defaults" msgstr "ΧÏήση Ï€ÏοεπιλεγμÎνου sRGB" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d αÏχεία" diff --git a/editor/translations/eo.po b/editor/translations/eo.po index 46e3a6b28d..3cb57c4089 100644 --- a/editor/translations/eo.po +++ b/editor/translations/eo.po @@ -3593,6 +3593,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3994,6 +3999,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp #, fuzzy msgid "%d Files" msgstr "Trovi en dosierojn" diff --git a/editor/translations/es.po b/editor/translations/es.po index 4f8441fbfc..7fc20c2f14 100644 --- a/editor/translations/es.po +++ b/editor/translations/es.po @@ -63,7 +63,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-10 22:14+0000\n" +"PO-Revision-Date: 2021-03-31 03:53+0000\n" "Last-Translator: Javier Ocampos <xavier.ocampos@gmail.com>\n" "Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/" "godot/es/>\n" @@ -72,7 +72,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.5.2-dev\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -211,7 +211,7 @@ msgstr "Cambiar Transformación de la Animación" #: editor/animation_track_editor.cpp msgid "Anim Change Keyframe Value" -msgstr "Cambiar Valor de la Clave de Animación" +msgstr "Cambiar Valor de Fotogramas Clave de Animación" #: editor/animation_track_editor.cpp msgid "Anim Change Call" @@ -219,7 +219,7 @@ msgstr "Cambiar Llamada de Animación" #: editor/animation_track_editor.cpp msgid "Anim Multi Change Keyframe Time" -msgstr "Cambiar Tiempo de Múltiples Keyframes de Animación" +msgstr "Cambiar Tiempo de Múltiples Fotogramas Clave de Animación" #: editor/animation_track_editor.cpp msgid "Anim Multi Change Transition" @@ -231,7 +231,7 @@ msgstr "Cambiar Múltiples Transforms de Animación" #: editor/animation_track_editor.cpp msgid "Anim Multi Change Keyframe Value" -msgstr "Cambiar Valor de Múltiples Keyframes de Animación" +msgstr "Cambiar Valor de Múltiples Fotogramas Clave de Animación" #: editor/animation_track_editor.cpp msgid "Anim Multi Change Call" @@ -272,7 +272,7 @@ msgstr "Pista de Reproducción de Animación" #: editor/animation_track_editor.cpp msgid "Animation length (frames)" -msgstr "Duración de la animación (frames)" +msgstr "Duración de la animación (fotogramas)" #: editor/animation_track_editor.cpp msgid "Animation length (seconds)" @@ -3314,7 +3314,7 @@ msgstr "Medida:" #: editor/editor_profiler.cpp msgid "Frame Time (sec)" -msgstr "Duración de Frame (seg)" +msgstr "Duración de Fotogramas (seg)" #: editor/editor_profiler.cpp msgid "Average Time (sec)" @@ -3322,11 +3322,11 @@ msgstr "Tiempo Promedio (seg)" #: editor/editor_profiler.cpp msgid "Frame %" -msgstr "Frame %" +msgstr "Fotograma %" #: editor/editor_profiler.cpp msgid "Physics Frame %" -msgstr "Frames de FÃsica %" +msgstr "Fotogramas de FÃsica %" #: editor/editor_profiler.cpp msgid "Inclusive" @@ -3338,7 +3338,7 @@ msgstr "Propio" #: editor/editor_profiler.cpp msgid "Frame #:" -msgstr "Frame #:" +msgstr "Fotograma #:" #: editor/editor_profiler.cpp msgid "Time" @@ -3756,6 +3756,13 @@ msgstr "" "reimpórtalo manualmente." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" +"Se ha desactivado la importación de este archivo, por lo que no se puede " +"abrir para editarlo." + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "No se puede mover/renombrar la raÃz de los recursos." @@ -4157,6 +4164,10 @@ msgid "Reset to Defaults" msgstr "Restablecer Valores por Defecto" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "Mantener Archivo (No Importar)" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d archivos" @@ -5796,7 +5807,7 @@ msgstr "Centrar Selección" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Frame Selection" -msgstr "Encuadrar Selección" +msgstr "Seleccionar Fotogramas" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Preview Canvas Scale" @@ -7945,15 +7956,15 @@ msgstr "Configuración:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "No Frames Selected" -msgstr "No hay Frames Seleccionados" +msgstr "No hay Fotogramas Seleccionados" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Add %d Frame(s)" -msgstr "Añadir %d Frame(s)" +msgstr "Añadir %d Fotograma(s)" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Add Frame" -msgstr "Añadir Frame" +msgstr "Añadir Fotograma" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Unable to load images" @@ -7961,7 +7972,7 @@ msgstr "No se pueden cargar las imágenes" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "ERROR: Couldn't load frame resource!" -msgstr "ERROR: ¡No se pudo cargar el recurso de frames!" +msgstr "ERROR: ¡No se pudo cargar el recurso de fotogramas!" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Resource clipboard is empty or not a texture!" @@ -7969,7 +7980,7 @@ msgstr "¡El portapapeles de recursos esta vacÃo o no es una textura!" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Paste Frame" -msgstr "Pegar Frame" +msgstr "Pegar Fotograma" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Add Empty" @@ -7985,7 +7996,7 @@ msgstr "(vacÃo)" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Move Frame" -msgstr "Mover Frame" +msgstr "Mover Fotograma" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Animations:" @@ -8005,7 +8016,7 @@ msgstr "Loop" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Animation Frames:" -msgstr "Frames de Animación:" +msgstr "Fotogramas de Animación:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Add a Texture from File" @@ -8013,7 +8024,7 @@ msgstr "Añadir Textura desde Archivo" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Add Frames from a Sprite Sheet" -msgstr "Añadir Frames desde un Sprite Sheet" +msgstr "Añadir Fotogramas desde un Sprite Sheet" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -8033,7 +8044,7 @@ msgstr "Mover (Después)" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Select Frames" -msgstr "Seleccionar Frames" +msgstr "Seleccionar Fotogramas" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Horizontal:" @@ -8045,11 +8056,11 @@ msgstr "Vertical:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Select/Clear All Frames" -msgstr "Seleccionar/Limpiar Todos los Frames" +msgstr "Seleccionar/Limpiar Todos los Fotogramas" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Create Frames from Sprite Sheet" -msgstr "Crear Frames a partir de Sprite Sheet" +msgstr "Crear Fotogramas a partir de un Sprite Sheet" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "SpriteFrames" @@ -11324,7 +11335,7 @@ msgstr "Inspeccionar Instancia Siguiente" #: editor/script_editor_debugger.cpp msgid "Stack Frames" -msgstr "Frames del Stack" +msgstr "Fotogramas Apilados" #: editor/script_editor_debugger.cpp msgid "Profiler" @@ -12561,7 +12572,7 @@ msgid "" "order for AnimatedSprite to display frames." msgstr "" "Se debe crear o establecer un recurso SpriteFrames en la propiedad \"Frames" -"\" para que AnimatedSprite pueda mostrar frames." +"\" para que AnimatedSprite pueda mostrar los fotogramas." #: scene/2d/canvas_modulate.cpp msgid "" @@ -13046,7 +13057,7 @@ msgid "" "order for AnimatedSprite3D to display frames." msgstr "" "Se debe crear o establecer un recurso SpriteFrames en la propiedad \"Frames" -"\" para que AnimatedSprite3D pueda mostrar frames." +"\" para que AnimatedSprite3D pueda mostrar los fotogramas." #: scene/3d/vehicle_body.cpp msgid "" diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po index 11e55b2dfa..ef65c1d220 100644 --- a/editor/translations/es_AR.po +++ b/editor/translations/es_AR.po @@ -21,7 +21,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-09 04:13+0000\n" +"PO-Revision-Date: 2021-03-31 03:53+0000\n" "Last-Translator: Lisandro Lorea <lisandrolorea@gmail.com>\n" "Language-Team: Spanish (Argentina) <https://hosted.weblate.org/projects/" "godot-engine/godot/es_AR/>\n" @@ -30,7 +30,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.5.1\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -3708,6 +3708,13 @@ msgstr "" "reimportá manualmente." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" +"Se ha desactivado la importación de este archivo, por lo que no se puede " +"abrir para editarlo." + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "No se puede mover/renombrar la raiz de recursos." @@ -4108,6 +4115,10 @@ msgid "Reset to Defaults" msgstr "Restablecer Valores Por Defecto" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "Mantener Archivo (No Importar)" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d Archivos" diff --git a/editor/translations/et.po b/editor/translations/et.po index ba7272db84..d1f68d4402 100644 --- a/editor/translations/et.po +++ b/editor/translations/et.po @@ -3545,6 +3545,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3938,6 +3943,10 @@ msgid "Reset to Defaults" msgstr "Laadi vaikimisi" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/eu.po b/editor/translations/eu.po index 95e87167e5..0fda17a8d5 100644 --- a/editor/translations/eu.po +++ b/editor/translations/eu.po @@ -3507,6 +3507,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3901,6 +3906,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d fitxategi" diff --git a/editor/translations/fa.po b/editor/translations/fa.po index 1ac27a6fd6..4b2ad80f34 100644 --- a/editor/translations/fa.po +++ b/editor/translations/fa.po @@ -3585,6 +3585,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -4017,6 +4022,10 @@ msgid "Reset to Defaults" msgstr "بارگیری پیش Ùرض" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp #, fuzzy msgid "%d Files" msgstr " پوشه ها" diff --git a/editor/translations/fi.po b/editor/translations/fi.po index 4d690bd29d..c60ab24d1d 100644 --- a/editor/translations/fi.po +++ b/editor/translations/fi.po @@ -11,12 +11,13 @@ # Tapani Niemi <tapani.niemi@kapsi.fi>, 2018, 2019, 2020, 2021. # Tuomas Lähteenmäki <lahtis@gmail.com>, 2019. # Matti Niskanen <matti.t.niskanen@gmail.com>, 2020. +# Severi Vidnäs <severi.vidnas@gmail.com>, 2021. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-10 22:14+0000\n" -"Last-Translator: Tapani Niemi <tapani.niemi@kapsi.fi>\n" +"PO-Revision-Date: 2021-04-05 14:28+0000\n" +"Last-Translator: Severi Vidnäs <severi.vidnas@gmail.com>\n" "Language-Team: Finnish <https://hosted.weblate.org/projects/godot-engine/" "godot/fi/>\n" "Language: fi\n" @@ -24,7 +25,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.5.2-dev\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -1760,7 +1761,7 @@ msgstr "Uusi" #: editor/editor_feature_profile.cpp editor/editor_node.cpp #: editor/project_manager.cpp msgid "Import" -msgstr "Tuonti" +msgstr "Tuo" #: editor/editor_feature_profile.cpp editor/project_export.cpp msgid "Export" @@ -3666,6 +3667,13 @@ msgstr "" "Tila: Tuonti epäonnistui. Ole hyvä, korjaa tiedosto ja tuo se uudelleen." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" +"Tuonti on poistettu käytöstä tälle tiedostolle, joten sitä ei voi avata " +"muokkausta varten." + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Ei voitu siirtää/nimetä uudelleen resurssien päätasoa." @@ -4068,6 +4076,10 @@ msgid "Reset to Defaults" msgstr "Palauta oletusarvoihin" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "Pidä tiedosto (ei tuontia)" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d tiedostoa" diff --git a/editor/translations/fil.po b/editor/translations/fil.po index e9c24cf0f2..ef48d8b143 100644 --- a/editor/translations/fil.po +++ b/editor/translations/fil.po @@ -3507,6 +3507,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3897,6 +3902,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/fr.po b/editor/translations/fr.po index 7b9d411e6d..3e6dc5fb35 100644 --- a/editor/translations/fr.po +++ b/editor/translations/fr.po @@ -82,7 +82,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-01-22 10:21+0000\n" +"PO-Revision-Date: 2021-03-21 12:25+0000\n" "Last-Translator: Pierre Caye <pierrecaye@laposte.net>\n" "Language-Team: French <https://hosted.weblate.org/projects/godot-engine/" "godot/fr/>\n" @@ -91,7 +91,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.5-dev\n" +"X-Generator: Weblate 4.5.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -3779,6 +3779,13 @@ msgstr "" "le réimporter manuellement." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" +"L'importation a été désactivée pour ce fichier, il ne peut donc pas être " +"ouvert dans l'éditeur." + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Impossible de déplacer / renommer les ressources root." @@ -4180,6 +4187,10 @@ msgid "Reset to Defaults" msgstr "Réinitialiser" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "Conserver le fichier (non importé)" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d fichiers" @@ -12648,10 +12659,14 @@ msgstr "Un CollisionPolygon2D vide n'a pas d'effet sur les collisions." #: scene/2d/collision_polygon_2d.cpp msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode." msgstr "" +"Polygone non valide. Il doit avoir au moins trois points en mode de " +"construction 'Solide'." #: scene/2d/collision_polygon_2d.cpp msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode." msgstr "" +"Polygone non valide. Il doit y avoir au moins 2 points en mode de " +"construction 'Segments'." #: scene/2d/collision_shape_2d.cpp msgid "" diff --git a/editor/translations/ga.po b/editor/translations/ga.po index 4e537d9882..3bedee8314 100644 --- a/editor/translations/ga.po +++ b/editor/translations/ga.po @@ -3500,6 +3500,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3892,6 +3897,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp #, fuzzy msgid "%d Files" msgstr "Amharc ar Chomhaid" diff --git a/editor/translations/gl.po b/editor/translations/gl.po index 5559444f0c..519fc06c8d 100644 --- a/editor/translations/gl.po +++ b/editor/translations/gl.po @@ -3657,6 +3657,11 @@ msgstr "" "impórtao manualmente." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -4060,6 +4065,10 @@ msgid "Reset to Defaults" msgstr "Cargar Valores por Defecto" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d Arquivos" diff --git a/editor/translations/he.po b/editor/translations/he.po index ab97d97c0a..30a3212661 100644 --- a/editor/translations/he.po +++ b/editor/translations/he.po @@ -3646,6 +3646,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "מצב: ×™×™×‘×•× ×”×§×•×‘×¥ × ×›×©×œ. × × ×œ×ª×§×Ÿ ×ת הקובץ ×•×œ×™×™×‘× ×ž×—×“×© ×™×“× ×™×ª." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "×œ× × ×™×ª×Ÿ להעביר/×œ×©× ×•×ª ×©× ×œ×ž×§×•×¨ של מש×בי×." @@ -4071,6 +4076,10 @@ msgid "Reset to Defaults" msgstr "×˜×¢×™× ×ª בררת המחדל" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d קבצי×" diff --git a/editor/translations/hi.po b/editor/translations/hi.po index 034451542b..8425dd284f 100644 --- a/editor/translations/hi.po +++ b/editor/translations/hi.po @@ -3646,6 +3646,11 @@ msgstr "" "सà¥à¤¥à¤¿à¤¤à¤¿: फाइल का आयात विफल रहा। कृपया फाइल को ठीक करें और मैनà¥à¤¯à¥à¤…ल रूप से पà¥à¤¨à¤°à¥à¤†à¤¯à¤¾à¤¤ करें।" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "संसाधनों की जड़ को सà¥à¤¥à¤¾à¤¨à¤¾à¤‚तरित/नाम नहीं दे सकते ।" @@ -4051,6 +4056,10 @@ msgid "Reset to Defaults" msgstr "पà¥à¤°à¤¾à¤¯à¤¿à¤• लोड कीजिये" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/hr.po b/editor/translations/hr.po index 047363db63..861f3e6c1c 100644 --- a/editor/translations/hr.po +++ b/editor/translations/hr.po @@ -3512,6 +3512,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3909,6 +3914,10 @@ msgid "Reset to Defaults" msgstr "UÄitaj Zadano" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d Fajlovi" diff --git a/editor/translations/hu.po b/editor/translations/hu.po index 3966959f91..448c79c7f1 100644 --- a/editor/translations/hu.po +++ b/editor/translations/hu.po @@ -15,12 +15,13 @@ # thekeymethod <csokan.andras87@protonmail.ch>, 2020. # Czmorek Dávid <czmdav.soft@gmail.com>, 2020. # Újvári Marcell <mmarci72@gmail.com>, 2021. +# GergÅ‘ Pistai <gergopistai@gmail.com>, 2021. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-01-22 10:21+0000\n" -"Last-Translator: Újvári Marcell <mmarci72@gmail.com>\n" +"PO-Revision-Date: 2021-03-31 03:53+0000\n" +"Last-Translator: GergÅ‘ Pistai <gergopistai@gmail.com>\n" "Language-Team: Hungarian <https://hosted.weblate.org/projects/godot-engine/" "godot/hu/>\n" "Language: hu\n" @@ -28,7 +29,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.5-dev\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -673,15 +674,15 @@ msgstr "Összes/semmi kijelölése" #: editor/animation_track_editor_plugins.cpp msgid "Add Audio Track Clip" -msgstr "" +msgstr "Hangsávklip hozzáadása" #: editor/animation_track_editor_plugins.cpp msgid "Change Audio Track Clip Start Offset" -msgstr "" +msgstr "Hangsáv klip eltolt kezdési idejének módosÃtása" #: editor/animation_track_editor_plugins.cpp msgid "Change Audio Track Clip End Offset" -msgstr "" +msgstr "Hangsáv klip eltolt befejezési idejének módosÃtása" #: editor/array_property_edit.cpp msgid "Resize Array" @@ -732,9 +733,8 @@ msgid "Replace All" msgstr "Összes cseréje" #: editor/code_editor.cpp -#, fuzzy msgid "Selection Only" -msgstr "Csak a kijelölés" +msgstr "Csak kijelölés" #: editor/code_editor.cpp editor/plugins/script_text_editor.cpp #: editor/plugins/text_editor.cpp @@ -771,7 +771,7 @@ msgstr "Sor és oszlopszámok." #: editor/connections_dialog.cpp msgid "Method in target node must be specified." -msgstr "" +msgstr "Nevezze el a metódust a cél node-ban." #: editor/connections_dialog.cpp msgid "Method name must be a valid identifier." @@ -915,9 +915,8 @@ msgid "Signals" msgstr "Jelzések" #: editor/connections_dialog.cpp -#, fuzzy msgid "Filter signals" -msgstr "Csempék szűrése" +msgstr "Jelek szűrése" #: editor/connections_dialog.cpp msgid "Are you sure you want to remove all connections from this signal?" @@ -1045,14 +1044,14 @@ msgid "Owners Of:" msgstr "Tulajdonosai:" #: editor/dependency_editor.cpp -#, fuzzy msgid "" "Remove selected files from the project? (no undo)\n" "You can find the removed files in the system trash to restore them." -msgstr "EltávolÃtja a kiválasztott fájlokat a projektbÅ‘l? (nem visszavonható)" +msgstr "" +"EltávolÃtja a kiválasztott fájlokat a projektbÅ‘l? (nem visszavonható)\n" +"Az eltávolÃtott fájlokat a lomtárban találja, ha visszaállÃtaná Å‘ket." #: editor/dependency_editor.cpp -#, fuzzy msgid "" "The files being removed are required by other resources in order for them to " "work.\n" @@ -1060,7 +1059,8 @@ msgid "" "You can find the removed files in the system trash to restore them." msgstr "" "Az eltávolÃtandó fájlokat szükségelik más források a működésükhöz.\n" -"EltávolÃtja Å‘ket ennek ellenére? (nem visszavonható)" +"EltávolÃtja Å‘ket ennek ellenére? (nem visszavonható)\n" +"Az eltávolÃtott fájlokat a lomtárban találja, ha visszaállÃtaná Å‘ket." #: editor/dependency_editor.cpp msgid "Cannot remove:" @@ -1202,7 +1202,6 @@ msgid "Third-party Licenses" msgstr "Harmadik féltÅ‘l származó licencek" #: editor/editor_about.cpp -#, fuzzy msgid "" "Godot Engine relies on a number of third-party free and open source " "libraries, all compatible with the terms of its MIT license. The following " @@ -1591,12 +1590,16 @@ msgid "" "Target platform requires 'ETC' texture compression for GLES2. Enable 'Import " "Etc' in Project Settings." msgstr "" +"A célplatformnak 'ETC' textúra tömörÃtésre van szüksége GLES2-höz. " +"Engedélyezze az 'Import Etc' beállÃtást a Projekt BeállÃtásokban." #: editor/editor_export.cpp msgid "" "Target platform requires 'ETC2' texture compression for GLES3. Enable " "'Import Etc 2' in Project Settings." msgstr "" +"A célplatformnak 'ETC2' textúra tömörÃtésre van szüksége GLES3-höz. " +"Engedélyezze az 'Import Etc 2' beállÃtást a Projekt BeállÃtásokban." #: editor/editor_export.cpp msgid "" @@ -1605,18 +1608,27 @@ msgid "" "Enable 'Import Etc' in Project Settings, or disable 'Driver Fallback " "Enabled'." msgstr "" +"A célplatformnak 'ETC' textúra tömörÃtésre van szüksége a tartalék driverhez " +"GLES2-höz.\n" +"Engedélyezze az 'Import Etc' beállÃtást a Projekt BeállÃtásokban, vagy " +"kapcsolja ki a 'Driver Fallback Enabled' beállÃtást." #: editor/editor_export.cpp msgid "" "Target platform requires 'PVRTC' texture compression for GLES2. Enable " "'Import Pvrtc' in Project Settings." msgstr "" +"A célplatformnak 'PVRTC' textúra tömörÃtésre van szüksége GLES2-höz. " +"Engedélyezze az 'Import Pvrtc' beállÃtást a Projekt BeállÃtásokban." #: editor/editor_export.cpp msgid "" "Target platform requires 'ETC2' or 'PVRTC' texture compression for GLES3. " "Enable 'Import Etc 2' or 'Import Pvrtc' in Project Settings." msgstr "" +"A célplatformnak 'ETC2' vagy 'PVRTC' textúra tömörÃtésre van szüksége GLES3-" +"hoz. Engedélyezze az 'Import Etc 2' vagy 'Import Pvrtc' beállÃtást a Projekt " +"BeállÃtásokban." #: editor/editor_export.cpp msgid "" @@ -1625,6 +1637,9 @@ msgid "" "Enable 'Import Pvrtc' in Project Settings, or disable 'Driver Fallback " "Enabled'." msgstr "" +"A célplatformnak 'PVRTC' textúra tömörÃtésre van szüksége GLES2-höz.\n" +"Engedélyezze az 'Import Pvrtc' beállÃtást a Projekt BeállÃtásokban, vagy " +"kapcsolja ki a 'Driver Fallback Enabled' beállÃtást." #: editor/editor_export.cpp platform/android/export/export.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp @@ -1644,7 +1659,7 @@ msgstr "Sablon fájl nem található:" #: editor/editor_export.cpp msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB." -msgstr "" +msgstr "32-bites exportokon a beágyazott PCK nem lehet nagyobb mint 4 GiB." #: editor/editor_feature_profile.cpp msgid "3D Editor" @@ -1664,12 +1679,11 @@ msgstr "Jelenetfa szerkesztése" #: editor/editor_feature_profile.cpp msgid "Node Dock" -msgstr "" +msgstr "Node dokk" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "FileSystem Dock" -msgstr "Fájlrendszer" +msgstr "Fájlrendszer dokk" #: editor/editor_feature_profile.cpp msgid "Import Dock" @@ -1810,7 +1824,7 @@ msgstr "Válassza ezt a mappát" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "Copy Path" -msgstr "Útvonal másolása" +msgstr "Útvonal Másolása" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "Open in File Manager" @@ -1879,11 +1893,11 @@ msgstr "Ugrás Fel" #: editor/editor_file_dialog.cpp msgid "Toggle Hidden Files" -msgstr "" +msgstr "Rejtett fálok megjelenÃtése/elrejtése" #: editor/editor_file_dialog.cpp msgid "Toggle Favorite" -msgstr "" +msgstr "Kedvencek Mutatása/Elrejtése" #: editor/editor_file_dialog.cpp msgid "Toggle Mode" @@ -1891,7 +1905,7 @@ msgstr "Mód váltása" #: editor/editor_file_dialog.cpp msgid "Focus Path" -msgstr "" +msgstr "Elérési Út Fókuszálása" #: editor/editor_file_dialog.cpp msgid "Move Favorite Up" @@ -1926,7 +1940,6 @@ msgid "Toggle the visibility of hidden files." msgstr "A rejtett fájlok láthatóságának ki- és bekapcsolása." #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp -#, fuzzy msgid "View items as a grid of thumbnails." msgstr "Az elemek megtekintése bélyegkép-rácsként." @@ -2117,9 +2130,8 @@ msgid "Property:" msgstr "Tulajdonság:" #: editor/editor_inspector.cpp -#, fuzzy msgid "Set" -msgstr "BeállÃtás" +msgstr "BeállÃt" #: editor/editor_inspector.cpp msgid "Set Multiple:" @@ -2272,6 +2284,9 @@ 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 "" +"Ezt a jelenetet nem lehet elmenteni, mivel ciklikus peldányosÃtást " +"tartalmaz.\n" +"Kérem oldja meg a problémát, aztán próbáljon meg ismét menteni." #: editor/editor_node.cpp msgid "" @@ -2306,6 +2321,9 @@ msgid "" "An error occurred while trying to save the editor layout.\n" "Make sure the editor's user data path is writable." msgstr "" +"Hiba történt a szerkesztÅ‘ elrendezésének mentése közben.\n" +"Bizonyosodjon meg róla, hogy a szerkesztÅ‘ felhasználói elérési útján " +"engedélyezve van az Ãrás." #: editor/editor_node.cpp msgid "" @@ -2313,16 +2331,19 @@ msgid "" "To restore the Default layout to its base settings, use the Delete Layout " "option and delete the Default layout." msgstr "" +"Alapértelmezett szerkesztÅ‘ elrendezés felülÃrva.\n" +"Hogy visszaállÃtsa az alapértelmezett elrendezést az eredeti beállÃtásokra, " +"használja az Elrendezés Törlése opciót és törölje az alapértelmezett " +"elrendezést." #: editor/editor_node.cpp msgid "Layout name not found!" msgstr "Elrendezés neve nem található!" #: editor/editor_node.cpp -#, fuzzy msgid "Restored the Default layout to its base settings." msgstr "" -"Az alapértelmezett elrendezés vissza lett állÃtva az alap beállÃtásokra." +"Az alapértelmezett elrendezés vissza lett állÃtva az eredeti beállÃtásokra." #: editor/editor_node.cpp msgid "" @@ -2382,7 +2403,7 @@ msgstr "Nincs meghatározva Scene a futtatáshoz." #: editor/editor_node.cpp msgid "Save scene before running..." -msgstr "" +msgstr "Futtatás elÅ‘tt mentse a jelenetet..." #: editor/editor_node.cpp msgid "Could not start subprocess!" @@ -2390,23 +2411,23 @@ msgstr "Az alprocesszt nem lehetett elindÃtani!" #: editor/editor_node.cpp editor/filesystem_dock.cpp msgid "Open Scene" -msgstr "Scene megnyitás" +msgstr "Jelenet megnyitása" #: editor/editor_node.cpp msgid "Open Base Scene" -msgstr "Alap Scene megnyitás" +msgstr "Alap Jelenet Megnyitása" #: editor/editor_node.cpp msgid "Quick Open..." -msgstr "Gyors megnyitás..." +msgstr "Gyors Megnyitás..." #: editor/editor_node.cpp msgid "Quick Open Scene..." -msgstr "Jelenet gyors megnyitása..." +msgstr "Jelenet Gyors Megnyitása..." #: editor/editor_node.cpp msgid "Quick Open Script..." -msgstr "Szkript gyors megnyitás..." +msgstr "Szkript Gyors Megnyitás..." #: editor/editor_node.cpp msgid "Save & Close" @@ -2422,11 +2443,11 @@ msgstr "%s módosÃtott erÅ‘forrás mentve." #: editor/editor_node.cpp msgid "A root node is required to save the scene." -msgstr "" +msgstr "Egy gyökér node szükséges a jelenet mentéséhez." #: editor/editor_node.cpp msgid "Save Scene As..." -msgstr "Scene mentés másként..." +msgstr "Scene Mentése Másként..." #: editor/editor_node.cpp editor/scene_tree_dock.cpp msgid "This operation can't be done without a scene." @@ -2530,7 +2551,6 @@ msgstr "" "megbukott." #: editor/editor_node.cpp -#, fuzzy msgid "Unable to find script field for addon plugin at: '%s'." msgstr "" "Nem található szkript mezÅ‘ az addon pluginnak a következÅ‘ helyen: 'res://" @@ -2737,7 +2757,7 @@ msgstr "Legutóbbi Megnyitása" #: editor/editor_node.cpp msgid "Save Scene" -msgstr "Scene mentés" +msgstr "Jelenet Mentése" #: editor/editor_node.cpp msgid "Save All Scenes" @@ -2763,7 +2783,7 @@ msgstr "Visszavonás" #: editor/editor_node.cpp editor/plugins/script_text_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Redo" -msgstr "Mégis" +msgstr "Újra" #: editor/editor_node.cpp msgid "Miscellaneous project or scene-wide tools." @@ -2834,12 +2854,10 @@ msgid "" msgstr "" #: editor/editor_node.cpp -#, fuzzy msgid "Small Deploy with Network Filesystem" -msgstr "Kis TelepÃtés Hálózati FS-sel" +msgstr "Kis TelepÃtés Hálózati Fájlrendszerrel" #: editor/editor_node.cpp -#, fuzzy msgid "" "When this option is enabled, using one-click deploy for Android will only " "export an executable without the project data.\n" @@ -2860,52 +2878,46 @@ msgid "Visible Collision Shapes" msgstr "Látható Ãœtközési Alakzatok" #: editor/editor_node.cpp -#, fuzzy msgid "" "When this option is enabled, collision shapes and raycast nodes (for 2D and " "3D) will be visible in the running project." msgstr "" -"Az ütközési alakzatok és a fénysugárkövetÅ‘ Node-ok (mind 2D-hez és 3D-hez) " -"láthatóak lesznek a játék futásakor, ha ez az opció be van kapcsolva." +"Ha ez az opció be van kapcsolva, az ütközési alakzatok és a sugárkövetÅ‘ Node-" +"ok (mind 2D-hez és 3D-hez) láthatóak lesznek a játék futásakor." #: editor/editor_node.cpp msgid "Visible Navigation" msgstr "Látható Navigáció" #: editor/editor_node.cpp -#, fuzzy msgid "" "When this option is enabled, navigation meshes and polygons will be visible " "in the running project." msgstr "" -"A navigációs hálók és sokszögek láthatóak lesznek a játék futásakor, ha ez " -"az opció be van kapcsolva." +"Ha ez az opció be van kapcsolva, a navigációs hálók és sokszögek láthatóak " +"lesznek a játék futásakor." #: editor/editor_node.cpp -#, fuzzy msgid "Synchronize Scene Changes" -msgstr "Jelenet változtatások szinkronizálása" +msgstr "Jelenet Változások Szinkronizálása" #: editor/editor_node.cpp -#, fuzzy msgid "" "When this option is enabled, any changes made to the scene in the editor " "will be replicated in the running project.\n" "When used remotely on a device, this is more efficient when the network " "filesystem option is enabled." msgstr "" -"Ha ez a beállÃtás be van kapcsolva, bármilyen változtatás a jeleneten a " -"szerkesztÅ‘ben le lesz másolva a futó játékba.\n" -"Ha egy távoli eszközön használja, sokkal hatékonyabb a hálózati " -"fájlrendszerrel együtt." +"Ha ez a beállÃtás be van kapcsolva, bármely a jeleneten való változtatás a " +"szerkesztbÅ‘l, a futó projekre is alkalmazva lesz.\n" +"Távoli eszköz használatakor hatékonyabb, ha a hálózati fájlrendszer opció " +"engedélyezve van." #: editor/editor_node.cpp -#, fuzzy msgid "Synchronize Script Changes" msgstr "Szkript Változtatások Szinkronizálása" #: editor/editor_node.cpp -#, fuzzy msgid "" "When this option is enabled, any script that is saved will be reloaded in " "the running project.\n" @@ -2914,8 +2926,8 @@ msgid "" msgstr "" "Ha ez a beállÃtás be van kapcsolva, bármilyen szkript, amit elment, újra " "betöltÅ‘dik a futó játékba.\n" -"Ha egy távoli eszközön használja, sokkal hatékonyabb a hálózati " -"fájlrendszerrel együtt." +"Távoli eszköz használatakor hatékonyabb, ha a hálózati fájlrendszer opció " +"engedélyezve van." #: editor/editor_node.cpp editor/script_create_dialog.cpp msgid "Editor" @@ -2950,9 +2962,8 @@ msgid "Open Editor Data/Settings Folder" msgstr "SzerkesztÅ‘ adatok/beállÃtások mappa megnyitása" #: editor/editor_node.cpp -#, fuzzy msgid "Open Editor Data Folder" -msgstr "A szerkesztÅ‘ adatmappájának megnyitása" +msgstr "SzerkesztÅ‘ Adatmappájának Megnyitása" #: editor/editor_node.cpp msgid "Open Editor Settings Folder" @@ -2984,9 +2995,8 @@ msgid "Report a Bug" msgstr "Hiba bejelentése" #: editor/editor_node.cpp -#, fuzzy msgid "Send Docs Feedback" -msgstr "Visszajelzés a Dokumentumokról" +msgstr "Visszajelzé Küldése s A Dokumentumokról" #: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp msgid "Community" @@ -3022,7 +3032,7 @@ msgstr "Szerkesztett Scene futtatása." #: editor/editor_node.cpp msgid "Play Scene" -msgstr "Scene futtatás" +msgstr "Scene Futtatása" #: editor/editor_node.cpp msgid "Play custom scene" @@ -3081,6 +3091,7 @@ msgstr "Nincs Mentés" #: editor/editor_node.cpp msgid "Android build template is missing, please install relevant templates." msgstr "" +"Hiányzó Android épÃtési-sablon, kérem telepÃtse az ide tartozó sablonokat." #: editor/editor_node.cpp msgid "Manage Templates" @@ -3104,6 +3115,10 @@ msgid "" "Remove the \"res://android/build\" directory manually before attempting this " "operation again." msgstr "" +"Az Android épÃtési-sablon már telepÃtve van a projektbe és nem lesz " +"felülÃrva.\n" +"TávolÃtsa el a(z) \"res://android/build\" könyvtárat manuálisan, mivelÅ‘tt " +"újra megkÃsérelné a műveletet." #: editor/editor_node.cpp msgid "Import Templates From ZIP File" @@ -3126,13 +3141,12 @@ msgid "Open & Run a Script" msgstr "Szkriptet Megnyit és Futtat" #: editor/editor_node.cpp -#, fuzzy msgid "" "The following files are newer on disk.\n" "What action should be taken?" msgstr "" "A alábbi fájlok újabbak a lemezen.\n" -"Mit szeretne lépni?:" +"Mit szeretne tenni?" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp #: editor/plugins/shader_editor_plugin.cpp @@ -3154,7 +3168,7 @@ msgstr "Betöltési Hibák" #: editor/editor_node.cpp editor/plugins/tile_map_editor_plugin.cpp msgid "Select" -msgstr "Kiválaszt" +msgstr "Kiválasztás" #: editor/editor_node.cpp msgid "Open 2D Editor" @@ -3385,14 +3399,13 @@ msgid "Add Key/Value Pair" msgstr "Kulcs/érték pár hozzáadása" #: editor/editor_run_native.cpp -#, fuzzy msgid "" "No runnable export preset found for this platform.\n" "Please add a runnable preset in the Export menu or define an existing preset " "as runnable." msgstr "" "Nem található futtatható exportállomány ehhez a platformhoz.\n" -"Adjon hozzá egy futtatható exportállományt az export menüben." +"Kérem adjon hozzá egy futtatható exportállományt az export menüben." #: editor/editor_run_script.cpp msgid "Write your logic in the _run() method." @@ -3553,12 +3566,11 @@ msgid "Cannot remove temporary file:" msgstr "Az ideiglenes fájl nem távolÃtható el:" #: editor/export_template_manager.cpp -#, fuzzy msgid "" "Templates installation failed.\n" "The problematic templates archives can be found at '%s'." msgstr "" -"A sablonok telepÃtése nem sikerült.\n" +"A sablonok telepÃtése sikertelen.\n" "A problémás sablonok archÃvuma megtalálható a következÅ‘ helyen: '%s'." #: editor/export_template_manager.cpp @@ -3663,6 +3675,11 @@ msgstr "" "újra manuálisan." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Az erÅ‘források gyökere nem mozgatható vagy átnevezhetÅ‘." @@ -3787,9 +3804,8 @@ msgid "Duplicate..." msgstr "MegkettÅ‘zés..." #: editor/filesystem_dock.cpp -#, fuzzy msgid "Move to Trash" -msgstr "AutoLoad Ãthelyezése" +msgstr "Lomtárba Helyezés" #: editor/filesystem_dock.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Rename..." @@ -3898,19 +3914,16 @@ msgid "Searching..." msgstr "Keresés…" #: editor/find_in_files.cpp -#, fuzzy msgid "%d match in %d file." -msgstr "%d egyezés." +msgstr "%d egyezés %d fájlban." #: editor/find_in_files.cpp -#, fuzzy msgid "%d matches in %d file." -msgstr "%d egyezés." +msgstr "%d egyezés %d fájlban." #: editor/find_in_files.cpp -#, fuzzy msgid "%d matches in %d files." -msgstr "%d egyezés." +msgstr "%d egyezések %d fájlban." #: editor/groups_editor.cpp msgid "Add to Group" @@ -4048,19 +4061,20 @@ msgid "Saving..." msgstr "Mentés..." #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Select Importer" -msgstr "Kiválasztó Mód" +msgstr "Importer Kiválasztása" #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Importer:" -msgstr "Importálás" +msgstr "Importáló:" #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Reset to Defaults" -msgstr "Alapértelmezett Betöltése" +msgstr "VisszaállÃtás Alapértelmezettre" + +#: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" #: editor/import_dock.cpp msgid "%d Files" @@ -4096,7 +4110,6 @@ msgstr "" "Az importált fájl tÃpusának módosÃtásához a szerkesztÅ‘t újra kell indÃtani." #: editor/import_dock.cpp -#, fuzzy msgid "" "WARNING: Assets exist that use this resource, they may stop loading properly." msgstr "" @@ -4381,7 +4394,6 @@ msgid "BlendSpace2D does not belong to an AnimationTree node." msgstr "" #: editor/plugins/animation_blend_space_2d_editor.cpp -#, fuzzy msgid "No triangles exist, so no blending can take place." msgstr "Nincsenek háromszögek, Ãgy nem történhet keverés." @@ -4811,7 +4823,7 @@ msgstr "Lejátszási mód:" #: editor/plugins/animation_tree_editor_plugin.cpp #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "AnimationTree" -msgstr "" +msgstr "AnimációFa" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "New name:" @@ -5020,9 +5032,8 @@ msgid "Got:" msgstr "Kapott:" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Failed SHA-256 hash check" -msgstr "sha256 hash ellenÅ‘rzés megbukott" +msgstr "SHA-256 hash ellenÅ‘rzés megbukot" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Asset Download Error:" @@ -5200,7 +5211,7 @@ msgstr "Fény Besütése" #: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "Select lightmap bake file:" -msgstr "Válasszon sablonfájlt" +msgstr "Válasszon fénytérkép sablonfájlt:" #: editor/plugins/camera_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -5272,19 +5283,17 @@ msgid "Set CanvasItem \"%s\" Pivot Offset to (%d, %d)" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Rotate %d CanvasItems" -msgstr "CanvasItem forgatása" +msgstr "%d CanvasItem Forgatása" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Rotate CanvasItem \"%s\" to %d degrees" -msgstr "CanvasItem forgatása" +msgstr "\"%s\" CanvasItem Forgatása %d fokra" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy msgid "Move CanvasItem \"%s\" Anchor" -msgstr "CanvasItem áthelyezése" +msgstr "CanvasItem \"%s\" Horgony Mozgatása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Scale Node2D \"%s\" to (%s, %s)" @@ -5295,24 +5304,20 @@ msgid "Resize Control \"%s\" to (%d, %d)" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Scale %d CanvasItems" -msgstr "CanvasItem méretezése" +msgstr "%d CanvasItem Méretezése" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Scale CanvasItem \"%s\" to (%s, %s)" -msgstr "CanvasItem méretezése" +msgstr "\"%s\" CanvasItem Méretezése (%s, %s)-ra/re" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Move %d CanvasItems" -msgstr "CanvasItem áthelyezése" +msgstr "%d CanvasItem Ãthelyezése" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Move CanvasItem \"%s\" to (%d, %d)" -msgstr "CanvasItem áthelyezése" +msgstr "%s CanvasItem mozgatása (%d, %d)-ra/re" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "" @@ -5391,9 +5396,8 @@ msgid "HCenter Wide" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Full Rect" -msgstr "Teljes téglalap" +msgstr "Teljes Téglalap" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Keep Ratio" @@ -5413,10 +5417,13 @@ msgstr "Horgonyok MódosÃtása" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp +#, fuzzy msgid "" "Game Camera Override\n" "Overrides game camera with editor viewport camera." msgstr "" +"Játék Kamera FelülÃrás.\n" +"FelülÃrja a játék kamerát szerkesztÅ‘i nézetablak kamerával." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -5507,12 +5514,12 @@ msgstr "Alt + Jobb Egérgomb: Mélységi lista választás" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Move Mode" -msgstr "" +msgstr "Mozgató Mód" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotate Mode" -msgstr "Forgató mód" +msgstr "Forgató Mód" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -5855,7 +5862,6 @@ msgid "Emission Colors" msgstr "Kibocsátási szÃnek" #: editor/plugins/cpu_particles_editor_plugin.cpp -#, fuzzy msgid "CPUParticles" msgstr "CPU-részecskék" @@ -5870,7 +5876,6 @@ msgid "Create Emission Points From Node" msgstr "Kibocsátási pontok létrehozása a Node alapján" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Flat 0" msgstr "Lapos 0" @@ -5919,9 +5924,8 @@ msgid "Right Linear" msgstr "Jobb lineáris" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Load Preset" -msgstr "ElÅ‘re beállÃtott betöltése" +msgstr "BeállÃtás Betöltése" #: editor/plugins/curve_editor_plugin.cpp msgid "Remove Curve Point" @@ -6262,7 +6266,6 @@ msgstr "Navigációs Sokszög Létrehozása" #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp -#, fuzzy msgid "Convert to CPUParticles" msgstr "Konvertálás CPU-részecskékké" @@ -6279,9 +6282,8 @@ msgid "Can only set point into a ParticlesMaterial process material" msgstr "Csak egy ParticlesMaterial feldolgozó anyagba állÃthat pontot" #: editor/plugins/particles_2d_editor_plugin.cpp -#, fuzzy msgid "Convert to CPUParticles2D" -msgstr "Konvertálás CPU-részecskékké" +msgstr "Konvertálás CPUParticles2D-re" #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp @@ -6566,18 +6568,16 @@ msgid "Move Points" msgstr "Pontok mozgatása" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Command: Rotate" -msgstr "Húzás: Forgatás" +msgstr "Command: Forgatás" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Shift: Move All" msgstr "Shift: Mind Mozgatása" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Shift+Command: Scale" -msgstr "Shift + Ctrl: Skálázás" +msgstr "Shif+Command: Méretezés" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Ctrl: Rotate" @@ -6622,14 +6622,12 @@ msgid "Radius:" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Copy Polygon to UV" -msgstr "Sokszög és UV létrehozása" +msgstr "Sokszög UV-ba másolása" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Copy UV to Polygon" -msgstr "Csontok szinkronizálása a sokszöggel" +msgstr "UV Másolása Sokszögbe" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Clear UV" @@ -6676,9 +6674,8 @@ msgid "Grid Step Y:" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Sync Bones to Polygon" -msgstr "Csontok szinkronizálása a sokszöggel" +msgstr "Csontok Szinkronizálása Sokszögre" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "ERROR: Couldn't load resource!" @@ -6838,7 +6835,6 @@ msgid "Filter scripts" msgstr "Szkriptek szűrése" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Toggle alphabetical sorting of the method list." msgstr "Ãbécészerinti rendezés változtatása a metóduslistában." @@ -7112,7 +7108,7 @@ msgstr "Ãtváltás Megjegyzésre" #: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" -msgstr "Sor Összezárása / Kibontása" +msgstr "Sor Összezárása/Kibontása" #: editor/plugins/script_text_editor.cpp msgid "Fold All Lines" @@ -7132,7 +7128,7 @@ msgstr "Szimbólum Befejezése" #: editor/plugins/script_text_editor.cpp msgid "Evaluate Selection" -msgstr "" +msgstr "Kijelölés Kiértékelése" #: editor/plugins/script_text_editor.cpp msgid "Trim Trailing Whitespace" @@ -7222,7 +7218,6 @@ msgid "Set Rest Pose to Bones" msgstr "" #: editor/plugins/skeleton_2d_editor_plugin.cpp -#, fuzzy msgid "Skeleton2D" msgstr "Csontváz2D" @@ -7252,27 +7247,27 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Orthogonal" -msgstr "" +msgstr "Ortogonális" #: editor/plugins/spatial_editor_plugin.cpp msgid "Perspective" -msgstr "" +msgstr "PerspektÃva" #: editor/plugins/spatial_editor_plugin.cpp msgid "Transform Aborted." -msgstr "" +msgstr "ÃtalakÃtás MegszakÃtva." #: editor/plugins/spatial_editor_plugin.cpp msgid "X-Axis Transform." -msgstr "" +msgstr "X-Tengely Transzformáció." #: editor/plugins/spatial_editor_plugin.cpp msgid "Y-Axis Transform." -msgstr "" +msgstr "Y-tengely Transzformáció." #: editor/plugins/spatial_editor_plugin.cpp msgid "Z-Axis Transform." -msgstr "Z-Tengely transzformáció" +msgstr "Z-Tengely Transzformáció." #: editor/plugins/spatial_editor_plugin.cpp msgid "View Plane Transform." @@ -7307,9 +7302,8 @@ msgid "Yaw" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Size" -msgstr "Méret: " +msgstr "Méret" #: editor/plugins/spatial_editor_plugin.cpp msgid "Objects Drawn" @@ -7563,7 +7557,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Insert Animation Key" -msgstr "" +msgstr "Animációs Kulcs Beszúrása" #: editor/plugins/spatial_editor_plugin.cpp msgid "Focus Origin" @@ -7852,9 +7846,8 @@ msgid "Loop" msgstr "Ciklus" #: editor/plugins/sprite_frames_editor_plugin.cpp -#, fuzzy msgid "Animation Frames:" -msgstr "Animációs képkockák:" +msgstr "Animációs Képkockák:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Add a Texture from File" @@ -7909,9 +7902,8 @@ msgid "Set Region Rect" msgstr "" #: editor/plugins/texture_region_editor_plugin.cpp -#, fuzzy msgid "Set Margin" -msgstr "Margó beállÃtása" +msgstr "Margó BeállÃtása" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Snap Mode:" @@ -8035,12 +8027,10 @@ msgid "Submenu" msgstr "" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Subitem 1" msgstr "Alelem 1" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Subitem 2" msgstr "Alelem 2" @@ -8116,7 +8106,7 @@ msgstr "Érvénytelen csempék javÃtása" #: editor/plugins/tile_map_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Cut Selection" -msgstr "Kijelölés kivágása" +msgstr "Kijelölés Kivágása" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Paint TileMap" @@ -8144,16 +8134,15 @@ msgstr "Csempe keresése" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Transpose" -msgstr "" +msgstr "Transzpozálás" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Disable Autotile" msgstr "" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Enable Priority" -msgstr "Prioritás engedélyezése" +msgstr "Prioritás Engedélyezése" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Filter tiles" @@ -8208,9 +8197,8 @@ msgid "Add Texture(s) to TileSet." msgstr "" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Remove selected Texture from TileSet." -msgstr "TávolÃtsa el a kijelölt textúrát a csempekészletbÅ‘l." +msgstr "Kijelölj textúra eltávolÃtása TileSet-bÅ‘l." #: editor/plugins/tile_set_editor_plugin.cpp msgid "Create from Scene" @@ -8249,7 +8237,6 @@ msgid "Select the previous shape, subtile, or Tile." msgstr "" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Region" msgstr "Régió" @@ -8266,7 +8253,6 @@ msgid "Navigation" msgstr "Navigáció" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Bitmask" msgstr "Bitmaszk" @@ -8327,23 +8313,20 @@ msgid "Create a new rectangle." msgstr "Új téglalap létrehozása." #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "New Rectangle" -msgstr "Új Scene" +msgstr "Új Négyszög" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Create a new polygon." msgstr "Új sokszög létrehozása." #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "New Polygon" -msgstr "Sokszög Mozgatása" +msgstr "Új Sokszög" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Delete Selected Shape" -msgstr "Kijelöltek törlése" +msgstr "Kijelölt Alakzat Törlése" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Keep polygon inside region Rect." @@ -8667,7 +8650,6 @@ msgid "Remove output port" msgstr "Kimeneti port eltávolÃtása" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Set expression" msgstr "Kifejezés beállÃtása" @@ -8688,9 +8670,8 @@ msgid "Add Node to Visual Shader" msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Node(s) Moved" -msgstr "Node eltávolÃtva" +msgstr "Node(ok) Ãthelyezve" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Duplicate Nodes" @@ -8710,9 +8691,8 @@ msgid "Visual Shader Input Type Changed" msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "UniformRef Name Changed" -msgstr "A paraméter megváltozott" +msgstr "UniformRef Név Megváltozott" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Vertex" @@ -8735,7 +8715,6 @@ msgid "Create Shader Node" msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Color function." msgstr "SzÃn függvény." @@ -8796,7 +8775,6 @@ msgid "SoftLight operator." msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Color constant." msgstr "SzÃnállandó." @@ -8871,7 +8849,6 @@ msgid "" msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Boolean constant." msgstr "Logikai állandó." @@ -8884,7 +8861,6 @@ msgid "'%s' input parameter for all shader modes." msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Input parameter." msgstr "Bemeneti paraméter." @@ -8913,12 +8889,10 @@ msgid "'%s' input parameter for vertex and fragment shader mode." msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Scalar function." msgstr "Skalárfüggvény." #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Scalar operator." msgstr "Skalár operátor." @@ -9145,9 +9119,8 @@ msgid "Subtracts scalar from scalar." msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Scalar constant." -msgstr "Skaláris állandó." +msgstr "Skalár állandó." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Scalar uniform." @@ -9225,12 +9198,10 @@ msgid "Transform uniform." msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Vector function." -msgstr "Vektor függvény." +msgstr "Vektorfüggvény." #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Vector operator." msgstr "Vektor operátor." @@ -9349,7 +9320,6 @@ msgid "Subtracts vector from vector." msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Vector constant." msgstr "Vektor állandó." @@ -9490,9 +9460,8 @@ msgid "" msgstr "" #: editor/project_export.cpp -#, fuzzy msgid "Export Path" -msgstr "Exportálási útvonal" +msgstr "Exportálási Útvonal" #: editor/project_export.cpp msgid "Resources" @@ -9532,7 +9501,7 @@ msgstr "" #: editor/project_export.cpp msgid "Features" -msgstr "" +msgstr "Funkciók" #: editor/project_export.cpp msgid "Custom (comma-separated):" @@ -9547,9 +9516,8 @@ msgid "Script" msgstr "Szkript" #: editor/project_export.cpp -#, fuzzy msgid "Script Export Mode:" -msgstr "Szkript exportálás módja:" +msgstr "Szkript Exportálás Mód:" #: editor/project_export.cpp msgid "Text" @@ -9612,9 +9580,8 @@ msgid "The path specified doesn't exist." msgstr "A megadott útvonal nem létezik." #: editor/project_manager.cpp -#, fuzzy msgid "Error opening package file (it's not in ZIP format)." -msgstr "Hiba a csomagfájl megnyitása során (az nem ZIP formátumú)." +msgstr "Hiba a csomagfájl megnyitása során (nem ZIP formátumú)." #: editor/project_manager.cpp msgid "" @@ -9764,12 +9731,10 @@ msgid "Error: Project is missing on the filesystem." msgstr "" #: editor/project_manager.cpp -#, fuzzy msgid "Can't open project at '%s'." msgstr "A projekt nem nyitható meg a(z) %s helyen." #: editor/project_manager.cpp -#, fuzzy msgid "Are you sure to open more than one project?" msgstr "Biztos, hogy egynél több projektet nyit meg?" @@ -9861,9 +9826,8 @@ msgid "Projects" msgstr "Projektek" #: editor/project_manager.cpp -#, fuzzy msgid "Loading, please wait..." -msgstr "Tükrök letöltése, kérjük várjon..." +msgstr "Betöltés, kérem várjon..." #: editor/project_manager.cpp msgid "Last Modified" @@ -9958,10 +9922,9 @@ msgstr "Eszköz" #: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp msgid "Press a Key..." -msgstr "Nyomjon le egy billentyűt" +msgstr "Nyomjon meg egy billentyűt..." #: editor/project_settings_editor.cpp -#, fuzzy msgid "Mouse Button Index:" msgstr "Egérgomb index:" @@ -10042,9 +10005,8 @@ msgid "Middle Button." msgstr "KözépsÅ‘ Egérgomb." #: editor/project_settings_editor.cpp -#, fuzzy msgid "Wheel Up." -msgstr "Felfelé görgetés." +msgstr "Felfelé Görgetés." #: editor/project_settings_editor.cpp msgid "Wheel Down." @@ -10173,7 +10135,6 @@ msgid "Index:" msgstr "Index:" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Localization" msgstr "Lokalizáció" @@ -10391,8 +10352,9 @@ msgid "snake_case to PascalCase" msgstr "" #: editor/rename_dialog.cpp +#, fuzzy msgid "Case" -msgstr "" +msgstr "Eset" #: editor/rename_dialog.cpp msgid "To Lowercase" @@ -10411,45 +10373,46 @@ msgid "Regular Expression Error:" msgstr "Reguláris Kifejezési Hiba:" #: editor/rename_dialog.cpp -#, fuzzy msgid "At character %s" msgstr "A(z) %s karakternél" #: editor/reparent_dialog.cpp editor/scene_tree_dock.cpp msgid "Reparent Node" -msgstr "" +msgstr "Node új szülÅ‘höz rendelése" #: editor/reparent_dialog.cpp msgid "Reparent Location (Select new Parent):" -msgstr "" +msgstr "HelyszÃn új szülÅ‘höz rendelése (Új szülÅ‘ kiválasztása):" #: editor/reparent_dialog.cpp msgid "Keep Global Transform" -msgstr "" +msgstr "Globális Transzformáció Megtartása" #: editor/reparent_dialog.cpp editor/scene_tree_dock.cpp msgid "Reparent" -msgstr "" +msgstr "Új szülÅ‘ hozzárendelése" #: editor/run_settings_dialog.cpp msgid "Run Mode:" -msgstr "" +msgstr "Futás Mód:" #: editor/run_settings_dialog.cpp +#, fuzzy msgid "Current Scene" -msgstr "" +msgstr "Jelenlegi Jelenet" #: editor/run_settings_dialog.cpp msgid "Main Scene" -msgstr "" +msgstr "FÅ‘ Jelenet" #: editor/run_settings_dialog.cpp msgid "Main Scene Arguments:" -msgstr "" +msgstr "FÅ‘ Jelenet Argumentumok:" #: editor/run_settings_dialog.cpp +#, fuzzy msgid "Scene Run Settings" -msgstr "" +msgstr "Jelenet IndÃtási BeállÃtások" #: editor/scene_tree_dock.cpp msgid "No parent to instance the scenes at." @@ -10467,24 +10430,24 @@ msgstr "" #: editor/scene_tree_dock.cpp msgid "Instance Scene(s)" -msgstr "" +msgstr "Jelenet(ek) PéldányosÃtása" #: editor/scene_tree_dock.cpp +#, fuzzy msgid "Replace with Branch Scene" -msgstr "" +msgstr "Kicserélés Ãg Jelenettel" #: editor/scene_tree_dock.cpp msgid "Instance Child Scene" -msgstr "" +msgstr "Gyermek Jelenet PeldányosÃtása" #: editor/scene_tree_dock.cpp msgid "Can't paste root node into the same scene." -msgstr "" +msgstr "Gyökér node nem illeszthetÅ‘ be azonos jelenetbe." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Paste Node(s)" -msgstr "Node-ok beillesztése" +msgstr "Node(ok) beillesztése" #: editor/scene_tree_dock.cpp msgid "Detach Script" @@ -10504,7 +10467,7 @@ msgstr "" #: editor/scene_tree_dock.cpp msgid "Duplicate Node(s)" -msgstr "" +msgstr "Node(ok) MegkettÅ‘zése" #: editor/scene_tree_dock.cpp msgid "Can't reparent nodes in inherited scenes, order of nodes can't change." @@ -10532,7 +10495,7 @@ msgstr "" #: editor/scene_tree_dock.cpp msgid "Delete the root node \"%s\"?" -msgstr "" +msgstr "Gyökér node törlése \"%s\"?" #: editor/scene_tree_dock.cpp msgid "Delete node \"%s\" and its children?" @@ -10576,23 +10539,23 @@ msgstr "" #: editor/scene_tree_dock.cpp msgid "Create Root Node:" -msgstr "Gyökér node létrehozása:" +msgstr "Gyökér Node Létrehozása:" #: editor/scene_tree_dock.cpp msgid "2D Scene" -msgstr "2D jelenet" +msgstr "2D Jelenet" #: editor/scene_tree_dock.cpp msgid "3D Scene" -msgstr "3D jelenet" +msgstr "3D Jelenet" #: editor/scene_tree_dock.cpp msgid "User Interface" -msgstr "" +msgstr "Felhasználói Felület" #: editor/scene_tree_dock.cpp msgid "Other Node" -msgstr "" +msgstr "Másik Node" #: editor/scene_tree_dock.cpp msgid "Can't operate on nodes from a foreign scene!" @@ -10607,9 +10570,8 @@ msgid "Attach Script" msgstr "" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Cut Node(s)" -msgstr "Node-ok kivágása" +msgstr "Node(ok) Kivágása" #: editor/scene_tree_dock.cpp msgid "Remove Node(s)" @@ -10735,14 +10697,12 @@ msgid "Unlock Node" msgstr "Node feloldása" #: editor/scene_tree_editor.cpp -#, fuzzy msgid "Button Group" msgstr "Gombcsoport" #: editor/scene_tree_editor.cpp -#, fuzzy msgid "(Connecting From)" -msgstr "(Csatlakozás innen)" +msgstr "(Csatlakozás Innen)" #: editor/scene_tree_editor.cpp msgid "Node configuration warning:" @@ -10825,9 +10785,8 @@ msgid "Path is not local." msgstr "Az útvonal nem helyi." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Invalid base path." -msgstr "Érvénytelen alapútvonal." +msgstr "Érvénytelen Alapútvonal." #: editor/script_create_dialog.cpp msgid "A directory with the same name exists." @@ -11085,7 +11044,7 @@ msgstr "" #: editor/settings_config_dialog.cpp msgid "Erase Shortcut" -msgstr "" +msgstr "Gyorsbillentyű törlése" #: editor/settings_config_dialog.cpp msgid "Restore Shortcut" @@ -11410,29 +11369,24 @@ msgid "Preparing data structures" msgstr "" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Generate buffers" -msgstr "AABB Generálása" +msgstr "Bufferek Generálása" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Direct lighting" -msgstr "Irányok" +msgstr "Közvetlen megvilágÃtás" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Indirect lighting" -msgstr "Behúzás Jobbra" +msgstr "Közvetett megvilágÃtás" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Post processing" -msgstr "Kifejezés beállÃtása" +msgstr "Utófeldolgozás" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Plotting lightmaps" -msgstr "Fénytérképek Létrehozása" +msgstr "Fénytérképek Ãbrázolása" #: modules/mono/csharp_script.cpp msgid "Class name can't be a reserved keyword" @@ -11644,7 +11598,7 @@ msgstr "" #: modules/visual_script/visual_script_editor.cpp msgid "Duplicate VisualScript Nodes" -msgstr "" +msgstr "VisualScript Node-ok MegkettÅ‘zése" #: modules/visual_script/visual_script_editor.cpp msgid "Hold %s to drop a Getter. Hold Shift to drop a generic signature." @@ -12121,7 +12075,6 @@ msgid "Using default boot splash image." msgstr "" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid package short name." msgstr "Érvénytelen rövid csomagnév." @@ -12130,19 +12083,16 @@ msgid "Invalid package unique name." msgstr "Érvénytelen egyedi csomagnév." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid package publisher display name." msgstr "Érvénytelen csomagközzétevÅ‘ megjelenÃtendÅ‘ neve." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid product GUID." -msgstr "Érvénytelen termékazonosÃtó." +msgstr "Érvénytelen termék GUID." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid publisher GUID." -msgstr "Érvénytelen közzétevÅ‘i GUID." +msgstr "Érvénytelen kiadó GUID." #: platform/uwp/export/export.cpp msgid "Invalid background color." @@ -12384,14 +12334,12 @@ msgid "Finding meshes and lights" msgstr "" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Preparing geometry (%d/%d)" -msgstr "Geometria Elemzése…" +msgstr "Geometria ElÅ‘készÃtése (%d/%d)" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Preparing environment" -msgstr "Geometria Elemzése…" +msgstr "Környezet elÅ‘készÃtése" #: scene/3d/baked_lightmap.cpp #, fuzzy @@ -12404,9 +12352,8 @@ msgid "Saving lightmaps" msgstr "Fénytérképek Létrehozása" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Done" -msgstr "Kész!" +msgstr "Kész" #: scene/3d/collision_object.cpp msgid "" @@ -12682,9 +12629,8 @@ msgid "Must use a valid extension." msgstr "Használjon érvényes kiterjesztést." #: scene/gui/graph_edit.cpp -#, fuzzy msgid "Enable grid minimap." -msgstr "Illesztés Engedélyezése" +msgstr "Rács kistérkép engedélyezése." #: scene/gui/popup.cpp msgid "" @@ -12737,7 +12683,6 @@ msgid "" msgstr "" #: scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Invalid source for preview." msgstr "Érvénytelen forrás az elÅ‘nézethez." diff --git a/editor/translations/id.po b/editor/translations/id.po index 5dc5b9751a..6657101598 100644 --- a/editor/translations/id.po +++ b/editor/translations/id.po @@ -11,7 +11,7 @@ # Khairul Hidayat <khairulcyber4rt@gmail.com>, 2016. # Reza Hidayat Bayu Prabowo <rh.bayu.prabowo@gmail.com>, 2018, 2019. # Romi Kusuma Bakti <romikusumab@gmail.com>, 2017, 2018. -# Sofyan Sugianto <sofyanartem@gmail.com>, 2017-2018, 2019, 2020. +# Sofyan Sugianto <sofyanartem@gmail.com>, 2017-2018, 2019, 2020, 2021. # Tito <ijavadroid@gmail.com>, 2018. # Tom My <tom.asadinawan@gmail.com>, 2017. # yursan9 <rizal.sagi@gmail.com>, 2016. @@ -24,17 +24,19 @@ # Modeus Darksono <garuga17@gmail.com>, 2019. # Akhmad Zulfikar <azuldegratz@gmail.com>, 2020. # Ade Fikri Malihuddin <ade.fm97@gmail.com>, 2020. -# zephyroths <ridho.hikaru@gmail.com>, 2020. +# zephyroths <ridho.hikaru@gmail.com>, 2020, 2021. # Richard Urban <redasuio1@gmail.com>, 2020. # yusuf afandi <afandi.yusuf.04@gmail.com>, 2020. # Habib Rohman <revolusi147id@gmail.com>, 2020. # Hanz <hanzhaxors@gmail.com>, 2021. +# Reza Almanda <rezaalmanda27@gmail.com>, 2021. +# Naufal Adriansyah <naufaladrn90@gmail.com>, 2021. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-08 15:33+0000\n" -"Last-Translator: Hanz <hanzhaxors@gmail.com>\n" +"PO-Revision-Date: 2021-04-05 14:28+0000\n" +"Last-Translator: Naufal Adriansyah <naufaladrn90@gmail.com>\n" "Language-Team: Indonesian <https://hosted.weblate.org/projects/godot-engine/" "godot/id/>\n" "Language: id\n" @@ -42,13 +44,12 @@ 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.5.1\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Invalid type argument to convert(), use TYPE_* constants." -msgstr "" -"Tipe argumen salah dalam menggunakan convert(), gunakan konstanta TYPE_*." +msgstr "Tipe argumen salah dalam penggunaan convert(), gunakan konstan TYPE_*." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp msgid "Expected a string of length 1 (a character)." @@ -59,7 +60,8 @@ msgstr "String dengan panjang 1 (karakter) yang diharapkan." #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Not enough bytes for decoding bytes, or invalid format." msgstr "" -"Tidak cukup bytes untuk merubah bytes ke nilai asal, atau format tidak valid." +"Tidak memiliki bytes yang cukup untuk merubah bytes ke nilai asal, atau " +"format tidak valid." #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" @@ -534,7 +536,7 @@ msgstr "" #: editor/animation_track_editor.cpp msgid "Only show tracks from nodes selected in tree." -msgstr "Hanya tampilkan track dari node terpilih dalam tree." +msgstr "Hanya tampilkan track dari node terpilih dalam tree." #: editor/animation_track_editor.cpp msgid "Group tracks by node or display them as plain list." @@ -597,11 +599,11 @@ msgstr "Hapus Pilihan" #: editor/animation_track_editor.cpp msgid "Go to Next Step" -msgstr "Menuju Langkah Berikutnya" +msgstr "Pergi ke Langkah Berikutnya" #: editor/animation_track_editor.cpp msgid "Go to Previous Step" -msgstr "Menuju Langkah Sebelumnya" +msgstr "Pergi ke Langkah Sebelumnya" #: editor/animation_track_editor.cpp msgid "Optimize Animation" @@ -1751,7 +1753,7 @@ msgid "" "Profile '%s' already exists. Remove it first before importing, import " "aborted." msgstr "" -"Sudah ada profil '%s'. Hapus profil ini terlebih dahulu sebelum mengimpor, " +"Sudah ada profil '%s'. Hapus profil ini terlebih dahulu sebelum mengimpor, " "impor dibatalkan." #: editor/editor_feature_profile.cpp @@ -2851,7 +2853,7 @@ msgstr "" "file yang bisa dieksekusi mencoba untuk terhubung ke IP komputer ini, " "sehingga proyek yang sedang berajalan dapat didebug.\n" "Pilihan ini dimaksudkan untuk digunakan sebagai cara men-debug jarak jauh " -"(biasanya menggunakan perangkat selular).\n" +"(biasanya menggunakan perangkat selular).\n" "Kamu tidak perlu mengaktifkan ini jika menggunakan GDScript debugger secara " "lokal." @@ -3689,6 +3691,13 @@ msgstr "" "manual." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" +"Mengimpor telah didisable untuk berkas ini, jadi itu tidak bisa dibuka untuk " +"disunting." + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Tidak bisa memindah/mengubah nama resource root." @@ -3938,9 +3947,8 @@ msgid "%d matches in %d file." msgstr "Ditemukan %d kecocokan." #: editor/find_in_files.cpp -#, fuzzy msgid "%d matches in %d files." -msgstr "Ditemukan %d kecocokan." +msgstr "Ditemukan %d kecocokan dalam %d berkas." #: editor/groups_editor.cpp msgid "Add to Group" @@ -4071,25 +4079,27 @@ msgstr "Kesalahan saat menjalankan skrip post-import:" #: editor/import/resource_importer_scene.cpp msgid "Did you return a Node-derived object in the `post_import()` method?" msgstr "" +"Apakan Anda mengembalikan objek berturunan Node dalam method `post_import()`?" #: editor/import/resource_importer_scene.cpp msgid "Saving..." msgstr "Menyimpan..." #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Select Importer" -msgstr "Mode Seleksi" +msgstr "Pilih Importir" #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Importer:" -msgstr "Impor" +msgstr "Importir:" #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Reset to Defaults" -msgstr "Muat Default" +msgstr "Kembalikan ke Nilai Baku" + +#: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "Simpan Berkas (Tanpa Impor)" #: editor/import_dock.cpp msgid "%d Files" @@ -5054,9 +5064,8 @@ msgid "Got:" msgstr "Yang Didapat:" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Failed SHA-256 hash check" -msgstr "Gagal mengecek hash sha256" +msgstr "Gagal mengecek hash SHA-256" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Asset Download Error:" @@ -5187,14 +5196,12 @@ msgid "Assets ZIP File" msgstr "Berkas Aset ZIP" #: editor/plugins/baked_lightmap_editor_plugin.cpp -#, fuzzy msgid "" "Can't determine a save path for lightmap images.\n" "Save your scene and try again." msgstr "" "Tidak dapat menentukan lokasi penyimpanan untuk gambar lightmap.\n" -"Simpan skena Anda (untuk gambar yang akan disimpan di direktori yang sama), " -"atau pilih lokasi penyimpanan dari properti BakedLightmap." +"Simpan skena Anda dan coba lagi." #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" @@ -5211,26 +5218,30 @@ msgstr "Gagal membuat gambar lightmap, pastikan path dapat ditulis." #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Failed determining lightmap size. Maximum lightmap size too small?" msgstr "" +"Gagal menentukan ukuran lightmap. Ukuran lightmap maksimumnya terlalu kecil?" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" "Some mesh is invalid. Make sure the UV2 channel values are contained within " "the [0.0,1.0] square region." msgstr "" +"Banyak mesh tak valid. Pastikan nilai kanal UV2 diisi dalam rentang wilayah " +"persegi [0.0,1.0]." #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" "Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" +"Editor Godot di-build tanpa dukungan ray tracing, sehingga lightmaps tidak " +"dapat di-bake." #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Bake Lightmaps" msgstr "Panggang Lightmaps" #: editor/plugins/baked_lightmap_editor_plugin.cpp -#, fuzzy msgid "Select lightmap bake file:" -msgstr "Pilih berkas templat" +msgstr "Pilih berkas lightmap bake:" #: editor/plugins/camera_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -5299,50 +5310,43 @@ msgstr "Buat Panduan Horisontal dan Vertikal" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Set CanvasItem \"%s\" Pivot Offset to (%d, %d)" -msgstr "" +msgstr "Atur Offset Pivot CanvasItem \"%s\" ke (%d, %d)" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Rotate %d CanvasItems" -msgstr "Putar CanvasItem" +msgstr "Putar %d CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Rotate CanvasItem \"%s\" to %d degrees" -msgstr "Putar CanvasItem" +msgstr "Putar CanvasItem \"%s\" menjadi %d derajat" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Move CanvasItem \"%s\" Anchor" -msgstr "Pindahkan CanvasItem" +msgstr "Pindahkan Anchor CanvasItem \"%s\"" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Scale Node2D \"%s\" to (%s, %s)" -msgstr "" +msgstr "Skalakan Node2D \"%s\" menjadi (%s, %s)" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Resize Control \"%s\" to (%d, %d)" -msgstr "" +msgstr "Ubah ukuran Control \"%s\" menjadi (%d, %d)" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Scale %d CanvasItems" -msgstr "Skalakan CanvasItem" +msgstr "Skalakan %d CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Scale CanvasItem \"%s\" to (%s, %s)" -msgstr "Skalakan CanvasItem" +msgstr "Skalakan CanvasItem \"%s\" menjadi (%s, %s)" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Move %d CanvasItems" -msgstr "Pindahkan CanvasItem" +msgstr "Pindahkan %d CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Move CanvasItem \"%s\" to (%d, %d)" -msgstr "Pindahkan CanvasItem" +msgstr "Pindahkan CanvasItem \"%s\" ke (%d,%d)" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "" @@ -5677,7 +5681,7 @@ msgstr "Tampilkan Tulang-tulang" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Make Custom Bone(s) from Node(s)" -msgstr "Buat Tulang Kustom(satu/lebih) dari Node(satu/lebih)" +msgstr "Buat Tulang Kustom(satu/lebih) dari Node(satu/lebih)" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Clear Custom Bones" @@ -6335,9 +6339,8 @@ msgid "Can only set point into a ParticlesMaterial process material" msgstr "Hanya dapat mengatur titik ke dalam material proses ParticlesMaterial" #: editor/plugins/particles_2d_editor_plugin.cpp -#, fuzzy msgid "Convert to CPUParticles2D" -msgstr "Konversikan menjadi CPUParticles" +msgstr "Konversikan menjadi CPUParticles2D" #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp @@ -6626,18 +6629,16 @@ msgid "Move Points" msgstr "Geser Titik" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Command: Rotate" -msgstr "Geser: Putar" +msgstr "Comand: Putar" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Shift: Move All" msgstr "Shift: Geser Semua" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Shift+Command: Scale" -msgstr "Shift+Ctrl: Skala" +msgstr "Shift+Command: Skala" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Ctrl: Rotate" @@ -6684,14 +6685,12 @@ msgid "Radius:" msgstr "Radius:" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Copy Polygon to UV" -msgstr "Buat Poligon & UV" +msgstr "Salin Polygon ke UV" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Copy UV to Polygon" -msgstr "Konversikan menjadi Polygon2D" +msgstr "Salin UV ke Polygon" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Clear UV" @@ -7086,9 +7085,8 @@ msgstr "" "'%s' ke node '%s'." #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "[Ignore]" -msgstr "(abaikan)" +msgstr "[abaikan]" #: editor/plugins/script_text_editor.cpp msgid "Line" @@ -7376,9 +7374,8 @@ msgid "Yaw" msgstr "Oleng" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Size" -msgstr "Ukuran: " +msgstr "Ukuran" #: editor/plugins/spatial_editor_plugin.cpp msgid "Objects Drawn" @@ -7580,6 +7577,12 @@ msgid "" "Closed eye: Gizmo is hidden.\n" "Half-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\")." msgstr "" +"Klik untuk mengatur visibilitas.\n" +"\n" +"Mata terbuka: Gizmo tampak.\n" +"Mata tertutup: Gizmo disembunyikan.\n" +"Mata setengah terbuka: Gizmo juga tampak melalui permukaan tidak tembus " +"pandang (\"sinar-x\")." #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Nodes To Floor" @@ -7919,9 +7922,8 @@ msgid "New Animation" msgstr "Animasi Baru" #: editor/plugins/sprite_frames_editor_plugin.cpp -#, fuzzy msgid "Speed:" -msgstr "Kecepatan (FPS):" +msgstr "Kecepatan:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Loop" @@ -8239,13 +8241,12 @@ msgid "Paint Tile" msgstr "Cat Tile" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "" "Shift+LMB: Line Draw\n" "Shift+Command+LMB: Rectangle Paint" msgstr "" "Shift + Klik Kiri: Menggambar Garis\n" -"Shift + Ctrl + Klik Kiri: Cat Persegi Panjang" +"Shift + Command + Klik Kiri: Cat Persegi Panjang" #: editor/plugins/tile_map_editor_plugin.cpp msgid "" @@ -8400,23 +8401,20 @@ msgid "Create a new rectangle." msgstr "Buat persegi panjang baru." #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "New Rectangle" -msgstr "Cat Persegi Panjang" +msgstr "Persegi Panjang Baru" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Create a new polygon." msgstr "Buat poligon baru." #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "New Polygon" -msgstr "Geser Poligon" +msgstr "Poligon Baru" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Delete Selected Shape" -msgstr "Hapus yang Dipilih" +msgstr "Hapus Shape yang Dipilih" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Keep polygon inside region Rect." @@ -8781,7 +8779,6 @@ msgid "Add Node to Visual Shader" msgstr "Tambah Node ke Visual Shader" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Node(s) Moved" msgstr "Node Dipindahkan" @@ -8803,9 +8800,8 @@ msgid "Visual Shader Input Type Changed" msgstr "Tipe Input Visual Shader Berubah" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "UniformRef Name Changed" -msgstr "Tetapkan Nama Uniform" +msgstr "Nama UniformRef diubah" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Vertex" @@ -9230,7 +9226,7 @@ msgstr "Mengembalikan nilai tangen dari parameter." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the hyperbolic tangent of the parameter." -msgstr "Mengembalikan nilai hiperbolik tangen dari parameter." +msgstr "Mengembalikan nilai hiperbolik tangen dari parameter." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Finds the truncated value of the parameter." @@ -9527,7 +9523,7 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "A reference to an existing uniform." -msgstr "" +msgstr "Referensi ke uniform yang ada." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "(Fragment/Light mode only) Scalar derivative function." @@ -9702,7 +9698,7 @@ msgstr "" #: editor/project_export.cpp msgid "Features" -msgstr "Fitur" +msgstr "Fitur-fitur" #: editor/project_export.cpp msgid "Custom (comma-separated):" @@ -9897,7 +9893,7 @@ msgstr "OpenGL ES 3.0" #: editor/project_manager.cpp msgid "Not supported by your GPU drivers." -msgstr "" +msgstr "Tidak didukung oleh driver GPU Anda." #: editor/project_manager.cpp msgid "" @@ -10074,9 +10070,8 @@ msgid "Projects" msgstr "Proyek" #: editor/project_manager.cpp -#, fuzzy msgid "Loading, please wait..." -msgstr "Mendapatkan informasi cermin, silakan tunggu..." +msgstr "Memuat, tunggu sejenak..." #: editor/project_manager.cpp msgid "Last Modified" @@ -10383,7 +10378,7 @@ msgstr "Aksi" #: editor/project_settings_editor.cpp msgid "Deadzone" -msgstr "Deadzone" +msgstr "Zona tidak aktif" #: editor/project_settings_editor.cpp msgid "Device:" @@ -10450,9 +10445,8 @@ msgid "Plugins" msgstr "Pengaya" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Import Defaults" -msgstr "Muat Default" +msgstr "Impor Nilai Baku" #: editor/property_editor.cpp msgid "Preset..." @@ -10515,19 +10509,16 @@ msgid "Batch Rename" msgstr "Ubah Nama Massal" #: editor/rename_dialog.cpp -#, fuzzy msgid "Replace:" -msgstr "Ganti: " +msgstr "Ganti:" #: editor/rename_dialog.cpp -#, fuzzy msgid "Prefix:" -msgstr "Awalan" +msgstr "Awalan:" #: editor/rename_dialog.cpp -#, fuzzy msgid "Suffix:" -msgstr "Akhiran" +msgstr "Akhiran:" #: editor/rename_dialog.cpp msgid "Use Regular Expressions" @@ -10574,9 +10565,9 @@ msgid "Per-level Counter" msgstr "Penghitung per Level" #: editor/rename_dialog.cpp -#, fuzzy msgid "If set, the counter restarts for each group of child nodes." -msgstr "Jika diatur, penghitung akan dimulai ulang untuk setiap grup node anak" +msgstr "" +"Jika diatur, penghitung akan dimulai ulang untuk setiap grup node anak." #: editor/rename_dialog.cpp msgid "Initial value for the counter" @@ -10635,9 +10626,8 @@ msgid "Reset" msgstr "Reset" #: editor/rename_dialog.cpp -#, fuzzy msgid "Regular Expression Error:" -msgstr "Kesalahan Ekspresi Reguler" +msgstr "Kesalahan Ekspresi Reguler:" #: editor/rename_dialog.cpp msgid "At character %s" @@ -10708,19 +10698,16 @@ msgid "Instance Child Scene" msgstr "Instansi Skena Anak" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Can't paste root node into the same scene." -msgstr "Tidak dapat bekerja pada node dari skena luar!" +msgstr "Tidak dapat menempelkan node akar ke dalam skena yang sama." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Paste Node(s)" -msgstr "Rekatkan Node" +msgstr "Tempel Node" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach Script" -msgstr "Lampirkan Skrip" +msgstr "Lepas Skrip" #: editor/scene_tree_dock.cpp msgid "This operation can't be done on the tree root." @@ -10757,9 +10744,8 @@ msgid "Make node as Root" msgstr "Jadikan node sebagai Dasar" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Delete %d nodes and any children?" -msgstr "Hapus node \"%s\" dan anak-anaknya?" +msgstr "Hapus %d node dan semua anaknya?" #: editor/scene_tree_dock.cpp msgid "Delete %d nodes?" @@ -10849,7 +10835,6 @@ msgid "Attach Script" msgstr "Lampirkan Skrip" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Cut Node(s)" msgstr "Potong Node" @@ -10898,14 +10883,14 @@ msgid "Open Documentation" msgstr "Buka Dokumentasi" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "" "Cannot attach a script: there are no languages registered.\n" "This is probably because this editor was built with all language modules " "disabled." msgstr "" -"Tidak dapat melampirkan skrip: tidak ada bahasa yang terdaftar.\n" -"Ini mungkin karena editor ini dibuat dengan semua modul bahasa dinonaktifkan." +"Tidak dapat melampirkan skrip: tidak ada bahasa terdaftar.\n" +"Ini mungkin karena editor ini di-build dengan semua modul bahasa " +"dinonaktifkan." #: editor/scene_tree_dock.cpp msgid "Add Child Node" @@ -10956,14 +10941,12 @@ msgstr "" "akar." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Attach a new or existing script to the selected node." msgstr "Lampirkan skrip baru atau yang sudah ada untuk node yang dipilih." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach the script from the selected node." -msgstr "Bersihkan skrip untuk node yang dipilih." +msgstr "Lepas skrip dari node yang dipilih." #: editor/scene_tree_dock.cpp msgid "Remote" @@ -11664,36 +11647,31 @@ msgstr "" #: modules/lightmapper_cpu/lightmapper_cpu.cpp msgid "Begin Bake" -msgstr "" +msgstr "Mulai Bake" #: modules/lightmapper_cpu/lightmapper_cpu.cpp msgid "Preparing data structures" -msgstr "" +msgstr "Menyiapkan struktur data" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Generate buffers" -msgstr "Buat AABB" +msgstr "Ciptakan buffer" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Direct lighting" -msgstr "Arah" +msgstr "PEncahayaan langsung" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Indirect lighting" -msgstr "Indentasi Kanan" +msgstr "Pencahayaan tak langsung" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Post processing" -msgstr "Pasca Proses" +msgstr "Pasca pemrosesan" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Plotting lightmaps" -msgstr "Plotting Lights:" +msgstr "Memetakan lightmap" #: modules/mono/csharp_script.cpp msgid "Class name can't be a reserved keyword" @@ -12209,7 +12187,7 @@ msgstr "Pilih perangkat pada daftar" #: platform/android/export/export.cpp msgid "Unable to find the 'apksigner' tool." -msgstr "" +msgstr "Tak dapat menemukan perkakas 'apksigner'." #: platform/android/export/export.cpp msgid "" @@ -12226,48 +12204,37 @@ msgstr "" "prasetel proyek." #: platform/android/export/export.cpp -#, fuzzy msgid "Release keystore incorrectly configured in the export preset." -msgstr "" -"Berkas debug keystore belum dikonfigurasi dalam Pengaturan Editor maupun di " -"prasetel proyek." +msgstr "Berkas keystore rilis belum dikonfigurasi di prasetel ekspor." #: platform/android/export/export.cpp -#, fuzzy msgid "A valid Android SDK path is required in Editor Settings." -msgstr "" -"Lokasi Android SDK tidak valid untuk membuat kustom APK dalam Pengaturan " -"Editor." +msgstr "Lokasi Android SDK yang valid dibutuhkan di Pengaturan Editor." #: platform/android/export/export.cpp -#, fuzzy msgid "Invalid Android SDK path in Editor Settings." -msgstr "" -"Lokasi Android SDK tidak valid untuk membuat kustom APK dalam Pengaturan " -"Editor." +msgstr "Lokasi Android SDK tidak valid di Pengaturan Editor." #: platform/android/export/export.cpp msgid "Missing 'platform-tools' directory!" -msgstr "" +msgstr "Direktori 'platform-tools' tidak ada!" #: platform/android/export/export.cpp msgid "Unable to find Android SDK platform-tools' adb command." -msgstr "" +msgstr "Tidak dapat menemukan perintah adb di Android SDK platform-tools." #: platform/android/export/export.cpp -#, fuzzy msgid "Please check in the Android SDK directory specified in Editor Settings." msgstr "" -"Lokasi Android SDK tidak valid untuk membuat kustom APK dalam Pengaturan " -"Editor." +"Silakan cek direktori Android SDK yang diisikan dalam Pengaturan Editor." #: platform/android/export/export.cpp msgid "Missing 'build-tools' directory!" -msgstr "" +msgstr "Direktori 'build-tools' tidak ditemukan!" #: platform/android/export/export.cpp msgid "Unable to find Android SDK build-tools' apksigner command." -msgstr "" +msgstr "Tidak dapat menemukan apksigner dalam Android SDK build-tools." #: platform/android/export/export.cpp msgid "Invalid public key for APK expansion." @@ -12282,42 +12249,51 @@ msgid "" "Invalid \"GodotPaymentV3\" module included in the \"android/modules\" " "project setting (changed in Godot 3.2.2).\n" msgstr "" +"Modul \"GodotPaymentV3\" tidak valid yang dimasukkan dalam pengaturan proyek " +"\"android/modules\" (diubah di Godot 3.2.2)\n" #: platform/android/export/export.cpp msgid "\"Use Custom Build\" must be enabled to use the plugins." -msgstr "" +msgstr "\"Gunakan Build Custom\" harus diaktifkan untuk menggunakan plugin." #: platform/android/export/export.cpp msgid "" "\"Degrees Of Freedom\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR" "\"." msgstr "" +"\"Derajat Kebebasan\" hanya valid ketika \"Mode Xr\" bernilai \"Occulus " +"Mobile VR\"." #: platform/android/export/export.cpp msgid "" "\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"Pelacakan Tangan\" hanya valid ketika \"Mode Xr\" bernilai \"Oculus Mobile " +"VR\"." #: platform/android/export/export.cpp msgid "" "\"Focus Awareness\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"Focus Awareness\" hanya valid ketika \"Mode Xr\" bernilai \"Oculus Mobile " +"VR\"." #: platform/android/export/export.cpp msgid "\"Export AAB\" is only valid when \"Use Custom Build\" is enabled." msgstr "" +"\"Expor AAB\" hanya bisa valid ketika \"Gunakan Build Custom\" diaktifkan." #: platform/android/export/export.cpp msgid "Invalid filename! Android App Bundle requires the *.aab extension." -msgstr "" +msgstr "Nama berkas tak valid! Android App Bundle memerlukan ekstensi *.aab ." #: platform/android/export/export.cpp msgid "APK Expansion not compatible with Android App Bundle." -msgstr "" +msgstr "Ekspansi APK tidak kompatibel dengan Android App Bundle." #: platform/android/export/export.cpp msgid "Invalid filename! Android APK requires the *.apk extension." -msgstr "" +msgstr "Nama berkas tidak valid! APK Android memerlukan ekstensi *.apk ." #: platform/android/export/export.cpp msgid "" @@ -12353,13 +12329,15 @@ msgstr "" #: platform/android/export/export.cpp msgid "Moving output" -msgstr "" +msgstr "Memindahkan keluaran" #: platform/android/export/export.cpp msgid "" "Unable to copy and rename export file, check gradle project directory for " "outputs." msgstr "" +"Tidak dapat menyalin dan mengubah nama berkas ekspor, cek direktori proyek " +"gradle untuk hasilnya." #: platform/iphone/export/export.cpp msgid "Identifier is missing." @@ -12517,10 +12495,14 @@ msgstr "" #: scene/2d/collision_polygon_2d.cpp msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode." msgstr "" +"Poligon tidak valid. Minimal 3 titik dibutuhkan untuk mode pembangunan " +"'Solid'." #: scene/2d/collision_polygon_2d.cpp msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode." msgstr "" +"Poligon tidak valid. Minimal 2 titik dibutuhkan untuk mode pembangunan " +"'Segmen\"." #: scene/2d/collision_shape_2d.cpp msgid "" @@ -12542,14 +12524,13 @@ msgstr "" "ciptakan resource shape untuknya!" #: scene/2d/collision_shape_2d.cpp -#, fuzzy msgid "" "Polygon-based shapes are not meant be used nor edited directly through the " "CollisionShape2D node. Please use the CollisionPolygon2D node instead." msgstr "" -"Bentuk Polygon-based tidak dimaksudkan untuk digunakan atau diedit secara " -"langsung melalui node CollisionShape2D. Silakan gunakan node " -"CollisionPolygon2D sebagai gantinya." +"Bentuk Polygon-based tidak dimaksudkan untuk digunakan atau diedit langsung " +"melalui node CollisionShape2D. Gunakan node CollisionPolygon2D sebagai " +"gantinya." #: scene/2d/cpu_particles_2d.cpp msgid "" @@ -12561,23 +12542,23 @@ msgstr "" #: scene/2d/joints_2d.cpp msgid "Node A and Node B must be PhysicsBody2Ds" -msgstr "" +msgstr "Node A dan Node B harus berupa PhysicsBody2D" #: scene/2d/joints_2d.cpp msgid "Node A must be a PhysicsBody2D" -msgstr "" +msgstr "Node A harus PhysicsBody2D" #: scene/2d/joints_2d.cpp msgid "Node B must be a PhysicsBody2D" -msgstr "" +msgstr "Node B harus PhysicsBody2D" #: scene/2d/joints_2d.cpp msgid "Joint is not connected to two PhysicsBody2Ds" -msgstr "" +msgstr "Persendian tidak terkoneksi dengan 2 PhysicsBody2D" #: scene/2d/joints_2d.cpp msgid "Node A and Node B must be different PhysicsBody2Ds" -msgstr "" +msgstr "Node A dan Node B harus PhysicsBody2D yang berbeda" #: scene/2d/light_2d.cpp msgid "" @@ -12736,32 +12717,27 @@ msgstr "ARVROrigin membutuhkan node anak ARVRCamera." #: scene/3d/baked_lightmap.cpp msgid "Finding meshes and lights" -msgstr "" +msgstr "Mencari mesh dan cahaya" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Preparing geometry (%d/%d)" -msgstr "Mengurai Geometri..." +msgstr "Menyiapkan geometri (%d/%d)" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Preparing environment" -msgstr "Tampilkan Lingkungan" +msgstr "Menyiapkan lingkungan" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Generating capture" -msgstr "Membuat Pemetaan Cahaya" +msgstr "Membuat capture" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Saving lightmaps" -msgstr "Membuat Pemetaan Cahaya" +msgstr "Menyimpan lightmap" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Done" -msgstr "Selesai!" +msgstr "Selesai" #: scene/3d/collision_object.cpp msgid "" @@ -12769,6 +12745,10 @@ msgid "" "Consider adding a CollisionShape or CollisionPolygon as a child to define " "its shape." msgstr "" +"Node ini tidak memiliki shape, jadi tidak bisa bertabrakan atau berinteraksi " +"dengan objek lain.\n" +"Pertimbangkan untuk menambah CollisionShape atau CollisionPolygon sebagai " +"anak untuk mendefinisikan shape-nya." #: scene/3d/collision_polygon.cpp msgid "" @@ -12809,22 +12789,26 @@ msgid "" "Plane shapes don't work well and will be removed in future versions. Please " "don't use them." msgstr "" +"Bentuk plane tidak bekerja baik dan akan dihapus dalam versi mendatang. " +"Mohon untuk tidak menggunakannya." #: scene/3d/collision_shape.cpp msgid "" "ConcavePolygonShape doesn't support RigidBody in another mode than static." msgstr "" +"ConcavePolygonShape tidak mendukung RigidBody dengan mode selain statis." #: scene/3d/cpu_particles.cpp -#, fuzzy msgid "Nothing is visible because no mesh has been assigned." -msgstr "Tidak ada yang tampak karena tidak ada mesh yang ditetapkan." +msgstr "Tidak ada yang tampil karena tidak ada mesh yang ditetapkan." #: scene/3d/cpu_particles.cpp msgid "" "CPUParticles animation requires the usage of a SpatialMaterial whose " "Billboard Mode is set to \"Particle Billboard\"." msgstr "" +"Animasi CPUParticle membutuhkan penggunaan SpatialMaterial yang Mode " +"Billboard nya diatur ke \"Particle Billboard\"." #: scene/3d/gi_probe.cpp msgid "Plotting Meshes" @@ -12845,6 +12829,7 @@ msgstr "" #: scene/3d/light.cpp msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows." msgstr "" +"SpotLight dengan sudut lebih dari 90 derajat tidak dapat memberikan bayangan." #: scene/3d/navigation_mesh.cpp msgid "A NavigationMesh resource must be set or created for this node to work." @@ -12866,17 +12851,24 @@ msgid "" "Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" "\" option for this purpose." msgstr "" +"Partikel berbasis GPU tidak didukung oleh driver video GLES2.\n" +"Gunakan CPUParticles saja. Anda dapat menggunakan opsi \"Konversikan ke " +"CPUParticles\" untuk ini." #: scene/3d/particles.cpp msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" +"Tidak ada yang ditampilkan karena mesh tidak ditetapkan untuk menggambar " +"lintasan." #: scene/3d/particles.cpp msgid "" "Particles animation requires the usage of a SpatialMaterial whose Billboard " "Mode is set to \"Particle Billboard\"." msgstr "" +"Animasi Partikel memerlukan penggunaan SpatialMaterial dengan Mode Billboard " +"\"Particle Billboard\"." #: scene/3d/path.cpp msgid "PathFollow only works when set as a child of a Path node." @@ -12898,39 +12890,41 @@ msgid "" "by the physics engine when running.\n" "Change the size in children collision shapes instead." msgstr "" +"Perubahan ukuran RigidBody (dalam mode karakter atau rigid) akan ditimpa " +"oleh mesin fisika ketika dijalankan.\n" +"Ubah ukuran dari \"collision shape\"-anaknya saja." #: scene/3d/physics_joint.cpp msgid "Node A and Node B must be PhysicsBodies" -msgstr "" +msgstr "Node A dan Node B harus PhysicsBody" #: scene/3d/physics_joint.cpp msgid "Node A must be a PhysicsBody" -msgstr "" +msgstr "Node A harus PhysicsBody" #: scene/3d/physics_joint.cpp msgid "Node B must be a PhysicsBody" -msgstr "" +msgstr "Node B harus PhysicsBody" #: scene/3d/physics_joint.cpp msgid "Joint is not connected to any PhysicsBodies" -msgstr "" +msgstr "Persendian tidak terkoneksi dengan PhysicsBody" #: scene/3d/physics_joint.cpp msgid "Node A and Node B must be different PhysicsBodies" -msgstr "" +msgstr "Node A dan Node B harus PhysicsBody yang berbeda" #: scene/3d/remote_transform.cpp -#, fuzzy msgid "" "The \"Remote Path\" property must point to a valid Spatial or Spatial-" "derived node to work." msgstr "" -"Properti path harus menunjuk ke sebuah node Particles2D yang sah agar " -"bekerja." +"Properti \"Remote Path\" harus menunjuk ke Spatial atau turunannya yang " +"valid agar bekerja." #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh." -msgstr "" +msgstr "Body ini akan diabaikan hingga Anda mengatur mesh-nya." #: scene/3d/soft_body.cpp msgid "" @@ -12938,6 +12932,8 @@ msgid "" "running.\n" "Change the size in children collision shapes instead." msgstr "" +"Perubahan ukuran SoftBody akan ditimpa oleh mesin fisika ketika dijalankan.\n" +"Ubah ukurannya melalui \"collision shape\"-anaknya saja." #: scene/3d/sprite_3d.cpp msgid "" @@ -12952,6 +12948,8 @@ msgid "" "VehicleWheel serves to provide a wheel system to a VehicleBody. Please use " "it as a child of a VehicleBody." msgstr "" +"VehicleWheel berfungsi menyediakan sistem roda ke VehicleBody. Gunakan itu " +"sebagai anak dari VehicleBody." #: scene/3d/world_environment.cpp msgid "" @@ -13082,9 +13080,8 @@ msgid "Must use a valid extension." msgstr "Harus menggunakan ekstensi yang sah." #: scene/gui/graph_edit.cpp -#, fuzzy msgid "Enable grid minimap." -msgstr "Aktifkan Pengancingan" +msgstr "Aktifkan peta mini grid." #: scene/gui/popup.cpp msgid "" @@ -13147,6 +13144,8 @@ msgid "" "The sampler port is connected but not used. Consider changing the source to " "'SamplerPort'." msgstr "" +"Porta sampler terhubung tapi tidak digunakan. Pertimbangkan untuk mengubah " +"sumbernya ke 'SamplerPort'." #: scene/resources/visual_shader_nodes.cpp msgid "Invalid source for preview." diff --git a/editor/translations/is.po b/editor/translations/is.po index 8d36556c04..9ae40b5085 100644 --- a/editor/translations/is.po +++ b/editor/translations/is.po @@ -3542,6 +3542,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3937,6 +3942,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/it.po b/editor/translations/it.po index 67b524937c..a0fb10367a 100644 --- a/editor/translations/it.po +++ b/editor/translations/it.po @@ -29,8 +29,8 @@ # Giuseppe Guerra <me@nyodev.xyz>, 2019. # RHC <rhc.throwaway@gmail.com>, 2019, 2020. # Antonio Giungato <antonio.giungato@gmail.com>, 2019, 2020. -# Marco Galli <mrcgll98@gmail.com>, 2019, 2020. -# MassiminoilTrace <omino.gis@gmail.com>, 2019, 2020. +# Marco Galli <mrcgll98@gmail.com>, 2019, 2020, 2021. +# MassiminoilTrace <omino.gis@gmail.com>, 2019, 2020, 2021. # MARCO BANFI <mbanfi@gmail.com>, 2019. # Marco <rodomar705@gmail.com>, 2019. # Davide Giuliano <davidegiuliano00@gmail.com>, 2019. @@ -56,12 +56,13 @@ # Federico Manzella <ferdiu.manzella@gmail.com>, 2020. # Ziv D <wizdavid@gmail.com>, 2020. # Riteo Siuga <lorenzocerqua@tutanota.com>, 2021. +# Alessandro Mandelli <mandelli.alessandro@ngi.it>, 2021. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-10 22:14+0000\n" -"Last-Translator: riccardo boffelli <riccardo.boffelli.96@gmail.com>\n" +"PO-Revision-Date: 2021-03-24 23:44+0000\n" +"Last-Translator: Alessandro Mandelli <mandelli.alessandro@ngi.it>\n" "Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/" "godot/it/>\n" "Language: it\n" @@ -391,9 +392,8 @@ msgid "Remove Anim Track" msgstr "Rimuovi una traccia d'animazione" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Create NEW track for %s and insert key?" -msgstr "Creare una NUOVA traccia per %s e inserirci la chiave?" +msgstr "Creare una NUOVA traccia per %s e inserire la chiave?" #: editor/animation_track_editor.cpp msgid "Create %d NEW tracks and insert keys?" @@ -1159,7 +1159,7 @@ msgstr "Possiede" #: editor/dependency_editor.cpp msgid "Resources Without Explicit Ownership:" -msgstr "Risorse non Possedute Esplicitamente:" +msgstr "Risorse senza proprietario esplicito:" #: editor/dictionary_property_edit.cpp msgid "Change Dictionary Key" @@ -1890,7 +1890,7 @@ msgstr "Aggiorna" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "All Recognized" -msgstr "Tutti i risconosciuti" +msgstr "Tutti i formati riconosciuti" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "All Files (*)" @@ -2007,7 +2007,7 @@ msgstr "File:" #: editor/editor_file_system.cpp msgid "ScanSources" -msgstr "Scansiona sorgenti" +msgstr "Scansiona i sorgenti" #: editor/editor_file_system.cpp msgid "" @@ -2379,8 +2379,8 @@ msgid "" "option and delete the Default layout." msgstr "" "Layout predefinito dell'editor sovrascritto.\n" -"Per ripristinare il layout predefinito alle impostazioni di base, usa " -"l'opzione elimina layout ed elimina il layout predefinito." +"Per ripristinare il layout predefinito alle impostazioni di base, usare " +"l'opzione elimina layout ed eliminare il layout predefinito." #: editor/editor_node.cpp msgid "Layout name not found!" @@ -3746,6 +3746,11 @@ msgstr "" "reimportarlo manualmente." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Impossibile spostare/rinominare risorse root." @@ -4135,20 +4140,22 @@ msgid "Saving..." msgstr "Salvataggio..." #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Select Importer" -msgstr "Modalità di selezione" +msgstr "Seleziona Importatore" #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Importer:" -msgstr "Importare" +msgstr "Importatore:" #: editor/import_defaults_editor.cpp msgid "Reset to Defaults" msgstr "Ripristinare le impostazioni predefinite" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d File" diff --git a/editor/translations/ja.po b/editor/translations/ja.po index 8afa2de349..6c6340e9b8 100644 --- a/editor/translations/ja.po +++ b/editor/translations/ja.po @@ -36,8 +36,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-08 15:33+0000\n" -"Last-Translator: Wataru Onuki <bettawat@yahoo.co.jp>\n" +"PO-Revision-Date: 2021-04-01 02:04+0000\n" +"Last-Translator: nitenook <admin@alterbaum.net>\n" "Language-Team: Japanese <https://hosted.weblate.org/projects/godot-engine/" "godot/ja/>\n" "Language: ja\n" @@ -45,7 +45,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.5.1\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -3692,6 +3692,11 @@ msgstr "" "ンãƒãƒ¼ãƒˆã—ã¦ä¸‹ã•ã„。" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "ルートã®ãƒªã‚½ãƒ¼ã‚¹ã¯ç§»å‹•/リãƒãƒ¼ãƒ ã§ãã¾ã›ã‚“。" @@ -4095,6 +4100,10 @@ msgid "Reset to Defaults" msgstr "デフォルトをèªè¾¼ã‚€" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d ファイル" @@ -11249,7 +11258,7 @@ msgstr "グラフを表示ã™ã‚‹ã«ã¯ã€ãƒªã‚¹ãƒˆã‹ã‚‰ã‚¢ã‚¤ãƒ†ãƒ ã‚’1ã¤ä»¥ä¸ #: editor/script_editor_debugger.cpp msgid "List of Video Memory Usage by Resource:" -msgstr "リソースã«ã‚ˆã‚‹ãƒ“デオメモリーã®ä½¿ç”¨ä¸€è¦§:" +msgstr "リソースã«ã‚ˆã‚‹ãƒ“デオメモリーã®æ¶ˆè²»é‡ä¸€è¦§:" #: editor/script_editor_debugger.cpp msgid "Total:" @@ -11273,7 +11282,7 @@ msgstr "フォーマット" #: editor/script_editor_debugger.cpp msgid "Usage" -msgstr "使用法" +msgstr "消費é‡" #: editor/script_editor_debugger.cpp msgid "Misc" diff --git a/editor/translations/ka.po b/editor/translations/ka.po index 6828baf211..6d7d40a6ad 100644 --- a/editor/translations/ka.po +++ b/editor/translations/ka.po @@ -3633,6 +3633,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -4042,6 +4047,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/ko.po b/editor/translations/ko.po index 693b726ebf..0fcbd51720 100644 --- a/editor/translations/ko.po +++ b/editor/translations/ko.po @@ -21,12 +21,13 @@ # Jun Hyung Shin <shmishmi79@gmail.com>, 2020. # Yongjin Jo <wnrhd114@gmail.com>, 2020. # Yungjoong Song <yungjoong.song@gmail.com>, 2020. +# Henry LeRoux <henry.leroux@ocsbstudent.ca>, 2021. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-12 09:17+0000\n" -"Last-Translator: Myeongjin Lee <aranet100@gmail.com>\n" +"PO-Revision-Date: 2021-04-05 14:28+0000\n" +"Last-Translator: Henry LeRoux <henry.leroux@ocsbstudent.ca>\n" "Language-Team: Korean <https://hosted.weblate.org/projects/godot-engine/" "godot/ko/>\n" "Language: ko\n" @@ -34,7 +35,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.5.2-dev\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -3664,6 +3665,12 @@ msgstr "" "ìš”." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" +"ì´ íŒŒì¼ì— 대해 ê°€ì ¸ 오기가 비활성화ë˜ì—ˆìœ¼ë©° íŽ¸ì§‘ì„ ìœ„í•´ ì—´ 수 없습니다." + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "리소스 루트를 옮기거나 ì´ë¦„ì„ ë°”ê¿€ 수 없습니다." @@ -4063,6 +4070,10 @@ msgid "Reset to Defaults" msgstr "기본값으로 ìž¬ì„¤ì •" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "íŒŒì¼ %dê°œ" diff --git a/editor/translations/lt.po b/editor/translations/lt.po index 585e4d4447..0796f01fbe 100644 --- a/editor/translations/lt.po +++ b/editor/translations/lt.po @@ -3591,6 +3591,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -4001,6 +4006,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp #, fuzzy msgid "%d Files" msgstr "Redaguoti Filtrus" diff --git a/editor/translations/lv.po b/editor/translations/lv.po index 5512d59238..d8a665caa6 100644 --- a/editor/translations/lv.po +++ b/editor/translations/lv.po @@ -3543,6 +3543,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3938,6 +3943,10 @@ msgid "Reset to Defaults" msgstr "IelÄdÄ“t NoklusÄ“jumu" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d FailÄ" diff --git a/editor/translations/mi.po b/editor/translations/mi.po index 260543a475..5198022282 100644 --- a/editor/translations/mi.po +++ b/editor/translations/mi.po @@ -3488,6 +3488,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3878,6 +3883,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/mk.po b/editor/translations/mk.po index cd72ecd259..0b4e23cccf 100644 --- a/editor/translations/mk.po +++ b/editor/translations/mk.po @@ -3495,6 +3495,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3885,6 +3890,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/ml.po b/editor/translations/ml.po index fb9de4a419..a445086dd6 100644 --- a/editor/translations/ml.po +++ b/editor/translations/ml.po @@ -3500,6 +3500,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3890,6 +3895,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/mr.po b/editor/translations/mr.po index cf3a24a739..00e8ced169 100644 --- a/editor/translations/mr.po +++ b/editor/translations/mr.po @@ -3495,6 +3495,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3885,6 +3890,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/ms.po b/editor/translations/ms.po index c0a7f7cea2..363f8895a3 100644 --- a/editor/translations/ms.po +++ b/editor/translations/ms.po @@ -3810,6 +3810,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -4208,6 +4213,10 @@ msgid "Reset to Defaults" msgstr "Muatkan Lalai" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/nb.po b/editor/translations/nb.po index 9e69510739..172439dc43 100644 --- a/editor/translations/nb.po +++ b/editor/translations/nb.po @@ -16,12 +16,13 @@ # Revolution <revosw@gmail.com>, 2019. # Petter Reinholdtsen <pere-weblate@hungry.com>, 2019, 2020. # Patrick Sletvold <patricksletvold@hotmail.com>, 2021. +# Kristoffer <kskau93@gmail.com>, 2021. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-02-27 00:47+0000\n" -"Last-Translator: Anonymous <GentleSaucepan@protonmail.com>\n" +"PO-Revision-Date: 2021-03-31 03:53+0000\n" +"Last-Translator: Kristoffer <kskau93@gmail.com>\n" "Language-Team: Norwegian BokmÃ¥l <https://hosted.weblate.org/projects/godot-" "engine/godot/nb_NO/>\n" "Language: nb\n" @@ -29,7 +30,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.5\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -663,7 +664,7 @@ msgstr "Velg spor Ã¥ kopiere" #: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp #: editor/scene_tree_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Copy" -msgstr "Lim inn" +msgstr "Kopier" #: editor/animation_track_editor.cpp #, fuzzy @@ -1591,7 +1592,7 @@ msgstr "Velg en Mappe" #: editor/filesystem_dock.cpp editor/project_manager.cpp #: scene/gui/file_dialog.cpp msgid "Create Folder" -msgstr "Lag mappe" +msgstr "Lag Mappe" #: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp #: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp @@ -1706,9 +1707,8 @@ msgid "3D Editor" msgstr "Redigeringsverktøy" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "Script Editor" -msgstr "Ã…pne SkriptEditor" +msgstr "Skript Redigeringsverktøy" #: editor/editor_feature_profile.cpp msgid "Asset Library" @@ -1724,9 +1724,8 @@ msgid "Node Dock" msgstr "Flytt Modus" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "FileSystem Dock" -msgstr "FilSystem" +msgstr "FilSystem Panel" #: editor/editor_feature_profile.cpp #, fuzzy @@ -1882,7 +1881,7 @@ msgstr "Kutt Noder" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "Copy Path" -msgstr "Kopier Sti" +msgstr "Kopier Bane" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp #, fuzzy @@ -1941,27 +1940,27 @@ msgstr "Lagre ei fil" #: editor/editor_file_dialog.cpp msgid "Go Back" -msgstr "GÃ¥ tilbake" +msgstr "GÃ¥ Tilbake" #: editor/editor_file_dialog.cpp msgid "Go Forward" -msgstr "GÃ¥ framover" +msgstr "GÃ¥ Fremover" #: editor/editor_file_dialog.cpp msgid "Go Up" -msgstr "GÃ¥ oppover" +msgstr "GÃ¥ Oppover" #: editor/editor_file_dialog.cpp msgid "Toggle Hidden Files" -msgstr "Veksle visning av skjulte filer" +msgstr "Veksle Visning av Skjulte Filer" #: editor/editor_file_dialog.cpp msgid "Toggle Favorite" -msgstr "Veksle favorittmerkering" +msgstr "Veksle Favorittmarkering" #: editor/editor_file_dialog.cpp msgid "Toggle Mode" -msgstr "Veksle modus" +msgstr "Veksle Modus" #: editor/editor_file_dialog.cpp msgid "Focus Path" @@ -2132,7 +2131,7 @@ msgstr "" #: editor/editor_help_search.cpp editor/editor_node.cpp #: editor/plugins/script_editor_plugin.cpp msgid "Search Help" -msgstr "Søk hjelp" +msgstr "Søk Hjelp" #: editor/editor_help_search.cpp msgid "Case Sensitive" @@ -2244,7 +2243,7 @@ msgstr "Tøm" #: editor/editor_log.cpp msgid "Clear Output" -msgstr "Nullstill resultat" +msgstr "Nullstill Resultat" #: editor/editor_network_profiler.cpp editor/editor_node.cpp #: editor/editor_profiler.cpp @@ -2619,9 +2618,8 @@ msgid "Close Scene" msgstr "Lukk Scene" #: editor/editor_node.cpp -#, fuzzy msgid "Reopen Closed Scene" -msgstr "Lukk Scene" +msgstr "GjenÃ¥pne Lukket Scene" #: editor/editor_node.cpp #, fuzzy @@ -2842,9 +2840,8 @@ msgid "Save Scene" msgstr "Lagre Scene" #: editor/editor_node.cpp -#, fuzzy msgid "Save All Scenes" -msgstr "Lagre alle Scener" +msgstr "Lagre Alle Scener" #: editor/editor_node.cpp msgid "Convert To..." @@ -3036,9 +3033,8 @@ msgid "Editor Layout" msgstr "Redigeringsverktøy Layout" #: editor/editor_node.cpp -#, fuzzy msgid "Take Screenshot" -msgstr "Lagre Scene" +msgstr "Ta Skjermbilde" #: editor/editor_node.cpp msgid "Screenshots are stored in the Editor Data/Settings Folder." @@ -3046,7 +3042,7 @@ msgstr "Skjermavbildninger lagres i redigeringsdata/innstillingsmappen." #: editor/editor_node.cpp msgid "Toggle Fullscreen" -msgstr "Skru av/pÃ¥ Fullskjerm" +msgstr "Veksle Fullskjerm" #: editor/editor_node.cpp #, fuzzy @@ -3119,7 +3115,7 @@ msgstr "" #: editor/editor_node.cpp msgid "Pause Scene" -msgstr "Sett scenen pÃ¥ pause" +msgstr "Sett Scenen PÃ¥ Pause" #: editor/editor_node.cpp msgid "Stop the scene." @@ -3180,9 +3176,8 @@ msgid "Inspector" msgstr "Inspektør" #: editor/editor_node.cpp -#, fuzzy msgid "Expand Bottom Panel" -msgstr "Utvid alle" +msgstr "Utvid Nederste Panel" #: editor/editor_node.cpp msgid "Output" @@ -3282,7 +3277,7 @@ msgstr "Ã…pne 3D-redigeringsverktøy" #: editor/editor_node.cpp msgid "Open Script Editor" -msgstr "Ã…pne SkriptEditor" +msgstr "Ã…pne Skriptredigeringsverktøy" #: editor/editor_node.cpp editor/project_manager.cpp msgid "Open Asset Library" @@ -3804,6 +3799,11 @@ msgstr "" "Status: Import av fil feilet. Reparer filen eller importer igjen manuelt." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp #, fuzzy msgid "Cannot move/rename resources root." msgstr "Kan ikke flytte/endre navn ressursrot" @@ -4009,9 +4009,8 @@ msgid "Create Script" msgstr "Opprett skript" #: editor/find_in_files.cpp editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Find in Files" -msgstr "%d flere filer" +msgstr "Finn i Filer" #: editor/find_in_files.cpp #, fuzzy @@ -4238,6 +4237,10 @@ msgid "Reset to Defaults" msgstr "Last Standard" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d Filer" @@ -5757,9 +5760,8 @@ msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/texture_region_editor_plugin.cpp #: editor/plugins/tile_set_editor_plugin.cpp scene/gui/graph_edit.cpp -#, fuzzy msgid "Zoom Reset" -msgstr "Zoom Ut" +msgstr "Zoom Resett" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -5795,9 +5797,8 @@ msgstr "Roter Modus" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Scale Mode" -msgstr "Velg Modus" +msgstr "Skaler Modus" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -5818,9 +5819,8 @@ msgid "Pan Mode" msgstr "Panorerings-Modus" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Ruler Mode" -msgstr "Velg Modus" +msgstr "Linjal Modus" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy @@ -5828,9 +5828,8 @@ msgid "Toggle smart snapping." msgstr "SlÃ¥ av/pÃ¥ snapping" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Use Smart Snap" -msgstr "Bruk Snap" +msgstr "Bruk Smart Snap" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy @@ -5838,9 +5837,8 @@ msgid "Toggle grid snapping." msgstr "SlÃ¥ av/pÃ¥ snapping" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Use Grid Snap" -msgstr "Bruk Snap" +msgstr "Bruk Rutenett Snap" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy @@ -5948,13 +5946,12 @@ msgid "View" msgstr "Visning" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Always Show Grid" -msgstr "Vis Rutenett" +msgstr "Alltid Vis Rutenett" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Helpers" -msgstr "Vis hjelpere" +msgstr "Vis Hjelpere" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Rulers" @@ -5962,7 +5959,7 @@ msgstr "Vis linjaler" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Guides" -msgstr "Vis veiledere" +msgstr "Vis Veiledere" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy @@ -6036,7 +6033,7 @@ msgstr "Kopier Pose" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Clear Pose" -msgstr "Fjern Pose" +msgstr "Fjern Posering" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Multiply grid step by 2" @@ -6047,9 +6044,8 @@ msgid "Divide grid step by 2" msgstr "Del rutenett-steg med 2" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Pan View" -msgstr "Bakvisning" +msgstr "Panoreringsvisning" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Add %s" @@ -7179,12 +7175,12 @@ msgstr "%s-klassereferanse" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp msgid "Find Next" -msgstr "Finn neste" +msgstr "Finn Neste" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp msgid "Find Previous" -msgstr "Finn forrige" +msgstr "Finn Forrige" #: editor/plugins/script_editor_plugin.cpp #, fuzzy @@ -7234,13 +7230,12 @@ msgid "Open..." msgstr "Ã…pne" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Reopen Closed Script" -msgstr "Kjør Skript" +msgstr "GjenÃ¥pne Lukket Skript" #: editor/plugins/script_editor_plugin.cpp msgid "Save All" -msgstr "Lagre Alle" +msgstr "Lagre Alt" #: editor/plugins/script_editor_plugin.cpp msgid "Soft Reload Script" @@ -7251,9 +7246,8 @@ msgid "Copy Script Path" msgstr "Kopier Skript-Sti" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "History Previous" -msgstr "Finn forrige" +msgstr "Historie Forrige" #: editor/plugins/script_editor_plugin.cpp msgid "History Next" @@ -7299,7 +7293,7 @@ msgstr "Søk" #: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp msgid "Step Into" -msgstr "Tre inn i" +msgstr "Tre Inn I" #: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp msgid "Step Over" @@ -7394,9 +7388,8 @@ msgid "Line" msgstr "Linje:" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Go to Function" -msgstr "Fjern Funksjon" +msgstr "GÃ¥ til Funksjon" #: editor/plugins/script_text_editor.cpp msgid "Only resources from filesystem can be dropped." @@ -7421,7 +7414,7 @@ msgstr "" #: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp msgid "Uppercase" -msgstr "Store versaler" +msgstr "Store bokstaver" #: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp msgid "Lowercase" @@ -7461,9 +7454,8 @@ msgid "Select All" msgstr "Velg Alle" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Delete Line" -msgstr "Slett Valgte" +msgstr "Slett Linje" #: editor/plugins/script_text_editor.cpp msgid "Indent Left" @@ -7475,12 +7467,11 @@ msgstr "Innrykk Høyre" #: editor/plugins/script_text_editor.cpp msgid "Toggle Comment" -msgstr "Veksle kommentar" +msgstr "Veksle Kommentar" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Fold/Unfold Line" -msgstr "Slett Valgte" +msgstr "Veksle Linjebretting" #: editor/plugins/script_text_editor.cpp msgid "Fold All Lines" @@ -7492,34 +7483,31 @@ msgstr "Brett ut alle linjer" #: editor/plugins/script_text_editor.cpp msgid "Clone Down" -msgstr "Klon nedover" +msgstr "Klon Nedover" #: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Evaluate Selection" -msgstr "Skaler Utvalg" +msgstr "Evaluer Seleksjon" #: editor/plugins/script_text_editor.cpp msgid "Trim Trailing Whitespace" msgstr "" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Convert Indent to Spaces" -msgstr "Konverter til store versaler" +msgstr "Konverter Innrykk til Mellomrom" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Convert Indent to Tabs" -msgstr "Konverter til store versaler" +msgstr "Konverter Inrykk til Tabs" #: editor/plugins/script_text_editor.cpp msgid "Auto Indent" -msgstr "Automatisk innrykk" +msgstr "Automatisk Innrykk" #: editor/plugins/script_text_editor.cpp #, fuzzy @@ -7531,19 +7519,16 @@ msgid "Contextual Help" msgstr "" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Toggle Bookmark" -msgstr "Veksle kommentar" +msgstr "Veksle Bokmerke" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Go to Next Bookmark" -msgstr "GÃ¥ til Neste Steg" +msgstr "GÃ¥ til Neste Bokmerke" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Go to Previous Bookmark" -msgstr "GÃ¥ til tidligere redigert dokument." +msgstr "GÃ¥ til Forrige Bokmerke" #: editor/plugins/script_text_editor.cpp #, fuzzy @@ -7575,9 +7560,8 @@ msgid "Go to Next Breakpoint" msgstr "GÃ¥ til Neste Steg" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Go to Previous Breakpoint" -msgstr "GÃ¥ til tidligere redigert dokument." +msgstr "GÃ¥ til Forrige Steg" #: editor/plugins/shader_editor_plugin.cpp msgid "" @@ -7950,7 +7934,7 @@ msgstr "Høyrevisning" #: editor/plugins/spatial_editor_plugin.cpp msgid "Switch Perspective/Orthogonal View" -msgstr "Bytt perspektiv/ortogonal fremvisning" +msgstr "Bytt Perspektiv/Ortogonal Fremvisning" #: editor/plugins/spatial_editor_plugin.cpp msgid "Insert Animation Key" @@ -7974,9 +7958,8 @@ msgid "Transform" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Snap Object to Floor" -msgstr "Snap til rutenett" +msgstr "Snap Objekt til Gulv" #: editor/plugins/spatial_editor_plugin.cpp msgid "Transform Dialog..." @@ -8529,9 +8512,8 @@ msgid "Theme File" msgstr "Tema" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Erase Selection" -msgstr "Fjern Utvalg" +msgstr "Fjern Seleksjon" #: editor/plugins/tile_map_editor_plugin.cpp #, fuzzy @@ -8540,9 +8522,8 @@ msgstr "Ugyldig navn." #: editor/plugins/tile_map_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Cut Selection" -msgstr "Plasser Utvalg I Midten" +msgstr "Klipp ut Seleksjon" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Paint TileMap" @@ -8565,9 +8546,8 @@ msgid "Erase TileMap" msgstr "" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Find Tile" -msgstr "Finn neste" +msgstr "Finn Flis" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Transpose" @@ -8612,14 +8592,12 @@ msgid "Pick Tile" msgstr "" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Rotate Left" -msgstr "Roter Modus" +msgstr "Roter til Venstre" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Rotate Right" -msgstr "Roter Polygon" +msgstr "Roter til Høyre" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Flip Horizontally" @@ -8630,9 +8608,8 @@ msgid "Flip Vertically" msgstr "" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Clear Transform" -msgstr "Anim Forandre Omforming" +msgstr "Nullstill Transformasjon" #: editor/plugins/tile_set_editor_plugin.cpp #, fuzzy @@ -8667,18 +8644,16 @@ msgid "New Atlas" msgstr "Ny %s" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Next Coordinate" -msgstr "Neste skript" +msgstr "Neste Koordinat" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Select the next shape, subtile, or Tile." msgstr "" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Previous Coordinate" -msgstr "Forrige skript" +msgstr "Forrige Koordinat" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Select the previous shape, subtile, or Tile." @@ -8700,9 +8675,8 @@ msgid "Occlusion" msgstr "Rediger Poly" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Navigation" -msgstr "Animasjonsnode" +msgstr "Navigasjon" #: editor/plugins/tile_set_editor_plugin.cpp #, fuzzy @@ -8720,44 +8694,36 @@ msgid "Z Index" msgstr "Panorerings-Modus" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Region Mode" -msgstr "Roter Modus" +msgstr "Region Modus" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Collision Mode" -msgstr "Animasjonsnode" +msgstr "Kollisjon Modus" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Occlusion Mode" -msgstr "Rediger Poly" +msgstr "Okklusjon Modus" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Navigation Mode" -msgstr "Animasjonsnode" +msgstr "Navigasjon Modus" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Bitmask Mode" -msgstr "Roter Modus" +msgstr "Bitmaske Modus" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Priority Mode" -msgstr "Eksporter Prosjekt" +msgstr "Prioritet Modus" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Icon Mode" -msgstr "Panorerings-Modus" +msgstr "Ikon Modus" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Z Index Mode" -msgstr "Panorerings-Modus" +msgstr "Z Indeks Modus" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Copy bitmask." @@ -9049,9 +9015,8 @@ msgid "Detect new changes" msgstr "Lag ny %s" #: editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Changes" -msgstr "Forandre" +msgstr "Endringer" #: editor/plugins/version_control_editor_plugin.cpp msgid "Modified" @@ -10016,7 +9981,7 @@ msgstr "Ressurser" #: editor/project_export.cpp msgid "Export all resources in the project" -msgstr "Eksporter alle ressurser til prosjektet" +msgstr "Eksporter alle ressurser i prosjektet" #: editor/project_export.cpp msgid "Export selected scenes (and dependencies)" @@ -10024,7 +9989,7 @@ msgstr "Eksporter valgte scener (og avhengigheter)" #: editor/project_export.cpp msgid "Export selected resources (and dependencies)" -msgstr "Exporter valgte ressurs (og avhengigheter)" +msgstr "Exporter valgte ressurser (og avhengigheter)" #: editor/project_export.cpp msgid "Export Mode:" @@ -10048,7 +10013,7 @@ msgstr "" #: editor/project_export.cpp msgid "Features" -msgstr "" +msgstr "Egenskaper" #: editor/project_export.cpp msgid "Custom (comma-separated):" @@ -10846,9 +10811,8 @@ msgid "Select Method" msgstr "" #: editor/rename_dialog.cpp editor/scene_tree_dock.cpp -#, fuzzy msgid "Batch Rename" -msgstr "Endre navn" +msgstr "Endre Navn pÃ¥ Parti" #: editor/rename_dialog.cpp msgid "Replace:" @@ -11267,9 +11231,8 @@ msgid "Save Branch as Scene" msgstr "" #: editor/scene_tree_dock.cpp editor/script_editor_debugger.cpp -#, fuzzy msgid "Copy Node Path" -msgstr "Kopier Noder" +msgstr "Kopier Node-bane" #: editor/scene_tree_dock.cpp msgid "Delete (No Confirm)" @@ -12479,24 +12442,20 @@ msgid "Copy Nodes" msgstr "Kopier Noder" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Cut Nodes" -msgstr "Kutt Noder" +msgstr "Klipp ut Noder" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Make Function" -msgstr "Fjern Funksjon" +msgstr "Lag Funksjon" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Refresh Graph" -msgstr "Oppdater" +msgstr "Oppdater Graf" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Edit Member" -msgstr "Medlemmer" +msgstr "Rediger Medlem" #: modules/visual_script/visual_script_flow_control.cpp msgid "Input type not iterable: " diff --git a/editor/translations/nl.po b/editor/translations/nl.po index 52c63ffa85..2716664b7a 100644 --- a/editor/translations/nl.po +++ b/editor/translations/nl.po @@ -3726,6 +3726,11 @@ msgstr "" "handmatig." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Kan de hoofdmap voor bronnen niet verplaatsen of van naam veranderen." @@ -4129,6 +4134,10 @@ msgid "Reset to Defaults" msgstr "Laad standaard" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d Bestanden" diff --git a/editor/translations/or.po b/editor/translations/or.po index 19b87260d6..5e396315c2 100644 --- a/editor/translations/or.po +++ b/editor/translations/or.po @@ -3494,6 +3494,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3884,6 +3889,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/pl.po b/editor/translations/pl.po index d55fee8b72..7da98bc87c 100644 --- a/editor/translations/pl.po +++ b/editor/translations/pl.po @@ -51,7 +51,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-10 22:14+0000\n" +"PO-Revision-Date: 2021-04-01 02:04+0000\n" "Last-Translator: Tomek <kobewi4e@gmail.com>\n" "Language-Team: Polish <https://hosted.weblate.org/projects/godot-engine/" "godot/pl/>\n" @@ -61,7 +61,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.5.2-dev\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -3702,6 +3702,13 @@ msgstr "" "zaimportować rÄ™cznie." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" +"Importowanie zostaÅ‚o wyÅ‚Ä…czone dla tego pliku, wiÄ™c nie może być otwarty do " +"edytowania." + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Nie można przenieść/zmienić nazwy korzenia zasobów." @@ -4104,6 +4111,10 @@ msgid "Reset to Defaults" msgstr "Resetuj do domyÅ›lnych" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "Zachowaj plik (brak importu)" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d plików" @@ -10446,7 +10457,7 @@ msgstr "Wtyczki" #: editor/project_settings_editor.cpp msgid "Import Defaults" -msgstr "Importuj domyÅ›lne" +msgstr "DomyÅ›lny import" #: editor/property_editor.cpp msgid "Preset..." diff --git a/editor/translations/pr.po b/editor/translations/pr.po index 09d967e01d..6f67b1c1be 100644 --- a/editor/translations/pr.po +++ b/editor/translations/pr.po @@ -3609,6 +3609,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -4018,6 +4023,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp #, fuzzy msgid "%d Files" msgstr "Edit yer Variable:" diff --git a/editor/translations/pt.po b/editor/translations/pt.po index dd745d7c56..6020f0557f 100644 --- a/editor/translations/pt.po +++ b/editor/translations/pt.po @@ -3687,6 +3687,11 @@ msgstr "" "manualmente." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Não consegui mover/renomear raiz dos recursos." @@ -4087,6 +4092,10 @@ msgid "Reset to Defaults" msgstr "Restaurar Predefinições" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d Ficheiros" diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po index c2e8116938..45e2050732 100644 --- a/editor/translations/pt_BR.po +++ b/editor/translations/pt_BR.po @@ -112,12 +112,14 @@ # Lucas Castro <castroclucas@gmail.com>, 2021. # Ricardo Zamarrenho Carvalho Correa <ricardozcc17@gmail.com>, 2021. # Diego dos Reis Macedo <diego_dragon97@hotmail.com>, 2021. +# Lucas E. <lukas.ed45@gmail.com>, 2021. +# Gabriel Silveira <gabomfim99@gmail.com>, 2021. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: 2016-05-30\n" -"PO-Revision-Date: 2021-03-10 22:14+0000\n" -"Last-Translator: Renato Rotenberg <renato.rotenberg@gmail.com>\n" +"PO-Revision-Date: 2021-04-05 14:28+0000\n" +"Last-Translator: Gabriel Silveira <gabomfim99@gmail.com>\n" "Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/" "godot-engine/godot/pt_BR/>\n" "Language: pt_BR\n" @@ -125,7 +127,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.5.2-dev\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -2635,23 +2637,24 @@ msgstr "" "falhou." #: editor/editor_node.cpp -#, fuzzy msgid "Unable to find script field for addon plugin at: '%s'." msgstr "" -"Não foi possÃvel encontrar o campo de script para o plugin em: 'res://addons/" -"%s'." +"Não foi possÃvel localizar a área do script para o complemento do plugin em: " +"'%s'." #: editor/editor_node.cpp msgid "Unable to load addon script from path: '%s'." -msgstr "Não foi possÃvel carregar o script complementar do caminho: '%s'." +msgstr "" +"Não foi possÃvel localizar a área do script para o complemento do plugin em: " +"'%s'." #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s' There seems to be an error in " "the code, please check the syntax." msgstr "" -"Não foi possÃvel carregar o script complementar do caminho: '%s' Parece " -"haver um erro no código, por favor verifique a sintaxe." +"Não foi possÃvel localizar a área do script para o complemento do plugin em: " +"'%s'." #: editor/editor_node.cpp msgid "" @@ -3785,6 +3788,13 @@ msgstr "" "reimporte manualmente." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" +"A importação foi desativada para este arquivo, por isso não pode ser aberto " +"para edição." + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "ImpossÃvel mover/renomear raiz dos recursos." @@ -4173,19 +4183,20 @@ msgid "Saving..." msgstr "Salvando..." #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Select Importer" -msgstr "Modo de Seleção" +msgstr "Selecione o arquivo para importar" #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Importer:" -msgstr "Importar" +msgstr "Importar:" #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Reset to Defaults" -msgstr "Usar sRGB Padrão" +msgstr "Redefinir para os padrões" + +#: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "Manter Arquivo (Sem Importação)" #: editor/import_dock.cpp msgid "%d Files" @@ -5159,9 +5170,8 @@ msgid "Got:" msgstr "Obtido:" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Failed SHA-256 hash check" -msgstr "Falha na verificação da hash sha256" +msgstr "Falha na verificação do hash SHA-256" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Asset Download Error:" @@ -5336,7 +5346,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Bake Lightmaps" -msgstr "Bake Lightmaps" +msgstr "Faça mapas de luz" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Select lightmap bake file:" @@ -7446,7 +7456,7 @@ msgstr "Escala: " #: editor/plugins/spatial_editor_plugin.cpp msgid "Translating: " -msgstr "Transladando: " +msgstr "Transladar: " #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotating %s degrees." @@ -8892,7 +8902,7 @@ msgstr "Tipo de Entrada de Shader Visual Alterado" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "UniformRef Name Changed" -msgstr "UniformRef Name foi altearado" +msgstr "Ref. Uniforme Nome alterado" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Vertex" @@ -10500,7 +10510,7 @@ msgstr "Remapeamentos por Localidade:" #: editor/project_settings_editor.cpp msgid "Locale" -msgstr "Locale" +msgstr "Localizar" #: editor/project_settings_editor.cpp msgid "Locales Filter" @@ -10531,9 +10541,8 @@ msgid "Plugins" msgstr "Plugins" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Import Defaults" -msgstr "Carregar Padrão" +msgstr "Importar padrões" #: editor/property_editor.cpp msgid "Preset..." @@ -10545,11 +10554,11 @@ msgstr "Zero" #: editor/property_editor.cpp msgid "Easing In-Out" -msgstr "Easing In-Out" +msgstr "Facilitar Entrada-SaÃda" #: editor/property_editor.cpp msgid "Easing Out-In" -msgstr "Easing Out-In" +msgstr "Facilitar SaÃda-Entrada" #: editor/property_editor.cpp msgid "File..." @@ -11750,12 +11759,10 @@ msgid "Indirect lighting" msgstr "Iluminação indireta" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Post processing" msgstr "Pós-processamento" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Plotting lightmaps" msgstr "Traçando mapas de luz" @@ -12826,9 +12833,8 @@ msgid "Generating capture" msgstr "Gerando captura" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Saving lightmaps" -msgstr "Salvando mapas de luz" +msgstr "Salvando mapas de luz" #: scene/3d/baked_lightmap.cpp msgid "Done" diff --git a/editor/translations/ro.po b/editor/translations/ro.po index 33f5264d71..c1ee0a6492 100644 --- a/editor/translations/ro.po +++ b/editor/translations/ro.po @@ -14,12 +14,13 @@ # Teodor <teo.virghi@yahoo.ro>, 2020. # f0roots <f0rootss@gmail.com>, 2020. # Gigel2 <mihalacher02@gmail.com>, 2020. +# R3ktGamerRO <bluegamermc1@gmail.com>, 2021. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-10-22 21:37+0000\n" -"Last-Translator: Gigel2 <mihalacher02@gmail.com>\n" +"PO-Revision-Date: 2021-03-20 04:18+0000\n" +"Last-Translator: R3ktGamerRO <bluegamermc1@gmail.com>\n" "Language-Team: Romanian <https://hosted.weblate.org/projects/godot-engine/" "godot/ro/>\n" "Language: ro\n" @@ -28,18 +29,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " "20)) ? 1 : 2;\n" -"X-Generator: Weblate 4.3.1\n" +"X-Generator: Weblate 4.5.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp -#, fuzzy msgid "Invalid type argument to convert(), use TYPE_* constants." -msgstr "Argument invalid pentru transformare(), folosiÈ›i constante TYPE_*." +msgstr "Argument invalid pentru convert(), folosiÈ›i constante TYPE_*." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp -#, fuzzy msgid "Expected a string of length 1 (a character)." -msgstr "Se aÈ™teaptă un È™ir de lungime 1 (un caracter)." +msgstr "Se aÈ™teaptă un text cu lungime de 1 (un caracter)." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/mono/glue/gd_glue.cpp @@ -52,9 +51,8 @@ msgid "Invalid input %i (not passed) in expression" msgstr "Intrare invalida %i (nu a fost transmisă) in expresie" #: core/math/expression.cpp -#, fuzzy msgid "self can't be used because instance is null (not passed)" -msgstr "insuÈ™i nu poate fi folosit deoarece instanÈ›a este nulă(nu a trecut)" +msgstr "insuÈ™i nu poate fi folosit deoarece instanÈ›a este nulă (nu a trecut)" #: core/math/expression.cpp msgid "Invalid operands to operator %s, %s and %s." @@ -314,7 +312,7 @@ msgstr "Linear" #: editor/animation_track_editor.cpp msgid "Cubic" -msgstr "Cubic" +msgstr "Cub" #: editor/animation_track_editor.cpp msgid "Clamp Loop Interp" @@ -703,7 +701,7 @@ msgstr "Linia Numărul:" #: editor/code_editor.cpp msgid "%d replaced." -msgstr "%d ÃŽnlocuit" +msgstr "%d ÃŽnlocuit." #: editor/code_editor.cpp editor/editor_help.cpp msgid "%d match." @@ -1042,14 +1040,14 @@ msgid "Owners Of:" msgstr "Stăpâni La:" #: editor/dependency_editor.cpp -#, fuzzy msgid "" "Remove selected files from the project? (no undo)\n" "You can find the removed files in the system trash to restore them." -msgstr "ȘtergeÈ›i fiÈ™ierele selectate din proiect? (AcÈ›iune ireversibilă)" +msgstr "" +"ȘtergeÈ›i fiÈ™ierele selectate din proiect? (AcÈ›iune ireversibilă)\n" +"PoÈ›i gasi fiÈ™ierele È™terse in coÈ™ul de gunoi dacă vrei să le restabileÈ™ti." #: editor/dependency_editor.cpp -#, fuzzy msgid "" "The files being removed are required by other resources in order for them to " "work.\n" @@ -1058,7 +1056,8 @@ msgid "" msgstr "" "FiÈ™ierele în proces de È™tergere sunt necesare pentru alte resurse ca ele să " "sa funcÈ›ioneze.\n" -"ȘtergeÈ›i oricum? (fără anulare)" +"ȘtergeÈ›i oricum? (fără anulare)\n" +"PoÈ›i găsi fiÈ™ierele È™terse in coÈ™ul de gunoi dacă vrei să le restabileÈ™ti." #: editor/dependency_editor.cpp msgid "Cannot remove:" @@ -2665,9 +2664,8 @@ msgid "Close Other Tabs" msgstr "ÃŽnchideÈ›i Celelalte File" #: editor/editor_node.cpp -#, fuzzy msgid "Close Tabs to the Right" -msgstr "ÃŽnchidere file la dreapta" +msgstr "ÃŽnchidere file de la dreapta" #: editor/editor_node.cpp msgid "Close All Tabs" @@ -3141,11 +3139,12 @@ msgid "Open & Run a Script" msgstr "Deschide È™i Execută un Script" #: editor/editor_node.cpp -#, fuzzy msgid "" "The following files are newer on disk.\n" "What action should be taken?" -msgstr "Următoarele file au eÈ™uat extragerea din pachet:" +msgstr "" +"Următoarele fiÈ™iere sunt mai noi pe disk.\n" +"Ce măsuri ar trebui luate?" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp #: editor/plugins/shader_editor_plugin.cpp @@ -3673,6 +3672,11 @@ msgstr "" "manual." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Nu se poate muta/redenumi rădăcina resurselor." @@ -4062,9 +4066,8 @@ msgid "Select Importer" msgstr "Selectare mod" #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Importer:" -msgstr "Importare" +msgstr "Importator:" #: editor/import_defaults_editor.cpp #, fuzzy @@ -4072,6 +4075,10 @@ msgid "Reset to Defaults" msgstr "ÃŽncărcaÈ›i Implicit" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d FiÈ™iere" @@ -5239,9 +5246,8 @@ msgid "Bake Lightmaps" msgstr "Procesează Lightmaps" #: editor/plugins/baked_lightmap_editor_plugin.cpp -#, fuzzy msgid "Select lightmap bake file:" -msgstr "Selectare fiÈ™ier È™ablon" +msgstr "Selectare fiÈ™ier È™ablon pentru harta de lumină:" #: editor/plugins/camera_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -10534,7 +10540,7 @@ msgstr "RedenumeÈ™te" #: editor/rename_dialog.cpp #, fuzzy msgid "Replace:" -msgstr "ÃŽnlocuiÈ›i: " +msgstr "ÃŽnlocuiÈ›i:" #: editor/rename_dialog.cpp msgid "Prefix:" @@ -10648,9 +10654,8 @@ msgid "Reset" msgstr "ResetaÈ›i Zoom-area" #: editor/rename_dialog.cpp -#, fuzzy msgid "Regular Expression Error:" -msgstr "FolosiÈ›i expresii regulate" +msgstr "Eroare de expresie regulată:" #: editor/rename_dialog.cpp msgid "At character %s" @@ -12674,14 +12679,12 @@ msgid "Finding meshes and lights" msgstr "" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Preparing geometry (%d/%d)" -msgstr "Analiza geometriei..." +msgstr "Analiza geometriei (%d/%d)" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Preparing environment" -msgstr "Analiza geometriei..." +msgstr "Pregătim mediul de lucru" #: scene/3d/baked_lightmap.cpp #, fuzzy @@ -12694,9 +12697,8 @@ msgid "Saving lightmaps" msgstr "Se Genereaza Lightmaps" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Done" -msgstr "Efectuat!" +msgstr "Efectuat" #: scene/3d/collision_object.cpp msgid "" @@ -12975,9 +12977,8 @@ msgid "Must use a valid extension." msgstr "Trebuie să utilizaÅ£i o extensie valida." #: scene/gui/graph_edit.cpp -#, fuzzy msgid "Enable grid minimap." -msgstr "Activează aliniere" +msgstr "Activează minimapa in format grilă." #: scene/gui/popup.cpp msgid "" diff --git a/editor/translations/ru.po b/editor/translations/ru.po index 5a443fd1e3..193b47de8c 100644 --- a/editor/translations/ru.po +++ b/editor/translations/ru.po @@ -96,8 +96,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-16 10:40+0000\n" -"Last-Translator: Danil Alexeev <danil@alexeev.xyz>\n" +"PO-Revision-Date: 2021-04-05 14:28+0000\n" +"Last-Translator: narrnika <narr13niki@gmail.com>\n" "Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/" "godot/ru/>\n" "Language: ru\n" @@ -106,7 +106,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.5.2-dev\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -3564,7 +3564,7 @@ msgstr "(Текущий)" #: editor/export_template_manager.cpp msgid "Retrieving mirrors, please wait..." -msgstr "Получение зеркал, пожалуйÑта, подождите..." +msgstr "Получение зеркал, пожалуйÑта, ждите..." #: editor/export_template_manager.cpp msgid "Remove template version '%s'?" @@ -3756,6 +3756,13 @@ msgstr "" "переимпортируйте вручную." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" +"Импорт был отключён Ð´Ð»Ñ Ñтого файла, поÑтому его Ð½ÐµÐ»ÑŒÐ·Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚ÑŒ Ð´Ð»Ñ " +"редактированиÑ." + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "ÐÐµÐ»ÑŒÐ·Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÑтить/переименовать корень." @@ -3919,7 +3926,7 @@ msgid "" "Please Wait..." msgstr "" "Сканирование файлов,\n" -"пожалуйÑта, подождите..." +"пожалуйÑта, ждите..." #: editor/filesystem_dock.cpp msgid "Move" @@ -4156,6 +4163,10 @@ msgid "Reset to Defaults" msgstr "СброÑить наÑтройки" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "Сохранить файл (без импорта)" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d файлов" diff --git a/editor/translations/si.po b/editor/translations/si.po index 0c3a01f0e4..67903c8677 100644 --- a/editor/translations/si.po +++ b/editor/translations/si.po @@ -3521,6 +3521,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3913,6 +3918,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/sk.po b/editor/translations/sk.po index 68da1b1221..3bed9c2661 100644 --- a/editor/translations/sk.po +++ b/editor/translations/sk.po @@ -3655,6 +3655,11 @@ msgstr "" "Status:Import súboru zlihal. ProsÃm opravte súbor a manuálne reimportujte." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Nedá sa presunúť/premenovaÅ¥ \"resources root\"." @@ -4056,6 +4061,10 @@ msgid "Reset to Defaults" msgstr "NaÄÃtaÅ¥ predvolené" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d Súbory" diff --git a/editor/translations/sl.po b/editor/translations/sl.po index 69819f0a36..55c60530b7 100644 --- a/editor/translations/sl.po +++ b/editor/translations/sl.po @@ -3794,6 +3794,11 @@ msgstr "" "Stanje: Uvoz datoteke ni uspel. Popravi datoteko in ponovno roÄno uvozi." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Ni mogoÄe premakniti/preimenovati osnovne vire." @@ -4225,6 +4230,10 @@ msgid "Reset to Defaults" msgstr "Naložite Prevzeto" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp #, fuzzy msgid "%d Files" msgstr " Datoteke" diff --git a/editor/translations/sq.po b/editor/translations/sq.po index f53d0b630a..4ed115ecfb 100644 --- a/editor/translations/sq.po +++ b/editor/translations/sq.po @@ -3733,6 +3733,11 @@ msgstr "" "importoje manualisht." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Nuk mund të leviz/riemërtoj rrenjën e resurseve." @@ -4148,6 +4153,10 @@ msgid "Reset to Defaults" msgstr "Ngarko të Parazgjedhur" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp #, fuzzy msgid "%d Files" msgstr " Skedarët" diff --git a/editor/translations/sr_Cyrl.po b/editor/translations/sr_Cyrl.po index 4fe901f414..b8edfd5d95 100644 --- a/editor/translations/sr_Cyrl.po +++ b/editor/translations/sr_Cyrl.po @@ -3984,6 +3984,11 @@ msgstr "" "Ñами." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Ðе могу померити/преименовати корен реÑурÑа." @@ -4431,6 +4436,10 @@ msgid "Reset to Defaults" msgstr "Учитај уобичајено" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp #, fuzzy msgid "%d Files" msgstr " %d Датотеке" diff --git a/editor/translations/sr_Latn.po b/editor/translations/sr_Latn.po index 3d979c3fc6..8f79f445d8 100644 --- a/editor/translations/sr_Latn.po +++ b/editor/translations/sr_Latn.po @@ -3537,6 +3537,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3930,6 +3935,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/sv.po b/editor/translations/sv.po index a7bc3d6288..125d4c733e 100644 --- a/editor/translations/sv.po +++ b/editor/translations/sv.po @@ -15,18 +15,19 @@ # Anonymous <noreply@weblate.org>, 2020. # Joakim Lundberg <joakim@joakimlundberg.com>, 2020. # Kristoffer Grundström <swedishsailfishosuser@tutanota.com>, 2020. -# Jonas Robertsson <jonas.robertsson@posteo.net>, 2020. +# Jonas Robertsson <jonas.robertsson@posteo.net>, 2020, 2021. # André Andersson <andre.eric.andersson@gmail.com>, 2020. # Andreas Westrell <andreas.westrell@gmail.com>, 2020. # Gustav Andersson <gustav.andersson96@outlook.com>, 2020. # Shaggy <anton_christoffersson@hotmail.com>, 2020. # Marcus Toftedahl <marcus.toftedahl@his.se>, 2020. +# Alex25820 <Alexander_sjogren@hotmail.se>, 2021. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-11-04 02:39+0000\n" -"Last-Translator: Marcus Toftedahl <marcus.toftedahl@his.se>\n" +"PO-Revision-Date: 2021-03-24 23:44+0000\n" +"Last-Translator: Jonas Robertsson <jonas.robertsson@posteo.net>\n" "Language-Team: Swedish <https://hosted.weblate.org/projects/godot-engine/" "godot/sv/>\n" "Language: sv\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.3.2-dev\n" +"X-Generator: Weblate 4.5.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -43,13 +44,13 @@ msgstr "Ogiltligt typargument till convert(), använd TYPE_* konstanter." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp msgid "Expected a string of length 1 (a character)." -msgstr "Förväntas en string av längden 1 (en karaktär)." +msgstr "Förväntade en sträng av längden 1 (ett tecken)." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/mono/glue/gd_glue.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Not enough bytes for decoding bytes, or invalid format." -msgstr "Inte tillräckligt med bytes för avkodning byte, eller ogiltigt format." +msgstr "Inte nog med bytes för att avkoda, eller ogiltigt format." #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" @@ -579,7 +580,7 @@ msgstr "Fördubbla val" #: editor/animation_track_editor.cpp msgid "Duplicate Transposed" -msgstr "Fördubbla Transponerade" +msgstr "Duplicera Transponerade" #: editor/animation_track_editor.cpp msgid "Delete Selection" @@ -599,7 +600,7 @@ msgstr "Optimera Animation" #: editor/animation_track_editor.cpp msgid "Clean-Up Animation" -msgstr "Rensa Animation" +msgstr "Städa-upp Animation" #: editor/animation_track_editor.cpp msgid "Pick the node that will be animated:" @@ -844,6 +845,7 @@ msgstr "" "vilotid." #: editor/connections_dialog.cpp +#, fuzzy msgid "Oneshot" msgstr "Oneshot" @@ -1044,14 +1046,14 @@ msgid "Owners Of:" msgstr "Ägare av:" #: editor/dependency_editor.cpp -#, fuzzy msgid "" "Remove selected files from the project? (no undo)\n" "You can find the removed files in the system trash to restore them." -msgstr "Ta bort valda filer frÃ¥n projektet? (Kan ej Ã¥terställas)" +msgstr "" +"Ta bort valda filer frÃ¥n projektet? (Kan ej Ã¥terställas)\n" +"Du kan hitta de borttagna filerna i systemets papperskorg." #: editor/dependency_editor.cpp -#, fuzzy msgid "" "The files being removed are required by other resources in order for them to " "work.\n" @@ -1059,7 +1061,8 @@ msgid "" "You can find the removed files in the system trash to restore them." msgstr "" "Filerna som tas bort krävs av andra resurser för att de ska fungera.\n" -"Ta bort dem ändÃ¥? (gÃ¥r inte Ã¥ngra)" +"Ta bort dem ändÃ¥? (gÃ¥r inte Ã¥ngra)\n" +"Du kan hitta de borttagna filerna i systemets papperskorg." #: editor/dependency_editor.cpp msgid "Cannot remove:" @@ -1070,9 +1073,8 @@ msgid "Error loading:" msgstr "Fel vid laddning:" #: editor/dependency_editor.cpp -#, fuzzy msgid "Load failed due to missing dependencies:" -msgstr "Scenen misslyckades att ladda pÃ¥ grund av att beroenden saknas:" +msgstr "Inladdning misslyckades pÃ¥ grund av att beroenden saknas:" #: editor/dependency_editor.cpp editor/editor_node.cpp msgid "Open Anyway" @@ -1239,7 +1241,7 @@ msgstr "Dekomprimerar TillgÃ¥ngar" #: editor/editor_asset_installer.cpp editor/project_manager.cpp msgid "The following files failed extraction from package:" -msgstr "Följande filer gick inte att packa upp frÃ¥n tillägget:" +msgstr "Följande filer misslyckades att packas upp frÃ¥n paketet:" #: editor/editor_asset_installer.cpp msgid "And %s more files." @@ -1256,7 +1258,7 @@ msgstr "Klart!" #: editor/editor_asset_installer.cpp msgid "Package Contents:" -msgstr "Packet InnehÃ¥ll:" +msgstr "Paketets InnehÃ¥ll:" #: editor/editor_asset_installer.cpp editor/editor_node.cpp msgid "Install" @@ -1280,7 +1282,7 @@ msgstr "Byt namn pÃ¥ Ljud-Buss" #: editor/editor_audio_buses.cpp msgid "Change Audio Bus Volume" -msgstr "Växla Ljud-Buss Volum" +msgstr "Växla Ljud-Buss Volym" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Solo" @@ -1405,7 +1407,7 @@ msgstr "Lägg till Buss" #: editor/editor_audio_buses.cpp msgid "Add a new Audio Bus to this layout." -msgstr "Lägg till en ny Audio-Buss för detta layout" +msgstr "Lägg till en ny Audio-Buss för denna layout." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1446,21 +1448,16 @@ msgid "Valid characters:" msgstr "Giltiga tecken:" #: editor/editor_autoload_settings.cpp -#, fuzzy msgid "Must not collide with an existing engine class name." -msgstr "" -"Ogiltigt namn. FÃ¥r inte vara samma som ett befintligt engine class-namn." +msgstr "FÃ¥r inte vara samma som ett befintligt engine class-namn." #: editor/editor_autoload_settings.cpp -#, fuzzy msgid "Must not collide with an existing built-in type name." -msgstr "Ogiltigt namn. FÃ¥r inte vara samma som ett befintligt inbyggt typnamn." +msgstr "FÃ¥r inte vara samma som ett befintligt inbyggt typ-namn." #: editor/editor_autoload_settings.cpp -#, fuzzy msgid "Must not collide with an existing global constant name." -msgstr "" -"Ogiltigt namn. FÃ¥r inte vara samma som ett befintligt global constant-namn." +msgstr "FÃ¥r inte vara samma som ett befintligt globalt konstant-namn." #: editor/editor_autoload_settings.cpp msgid "Keyword cannot be used as an autoload name." @@ -1532,7 +1529,6 @@ msgid "Updating Scene" msgstr "Uppdaterar Scen" #: editor/editor_data.cpp -#, fuzzy msgid "Storing local changes..." msgstr "Lagrar lokala ändringar..." @@ -1541,18 +1537,16 @@ msgid "Updating scene..." msgstr "Uppdaterar scen..." #: editor/editor_data.cpp editor/editor_properties.cpp -#, fuzzy msgid "[empty]" -msgstr "(tom)" +msgstr "[tom]" #: editor/editor_data.cpp msgid "[unsaved]" msgstr "[inte sparad]" #: editor/editor_dir_dialog.cpp -#, fuzzy msgid "Please select a base directory first." -msgstr "Vänligen välj en baskatalog först" +msgstr "Vänligen välj en baskatalog först." #: editor/editor_dir_dialog.cpp msgid "Choose a Directory" @@ -1639,21 +1633,20 @@ msgstr "" "Etc 2' i Projektinställningarna." #: editor/editor_export.cpp -#, fuzzy msgid "" "Target platform requires 'PVRTC' texture compression for the driver fallback " "to GLES2.\n" "Enable 'Import Pvrtc' in Project Settings, or disable 'Driver Fallback " "Enabled'." msgstr "" -"MÃ¥lplattformen kräver 'ETC' texturkomprimering för GLES2. Aktivera 'Import " -"Etc' i Projektinställningarna." +"MÃ¥lplattformen kräver 'ETC' texturkomprimering för GLES2.\n" +"Aktivera 'Import Etc' i Projektinställningarna." #: editor/editor_export.cpp platform/android/export/export.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp #: platform/osx/export/export.cpp platform/uwp/export/export.cpp msgid "Custom debug template not found." -msgstr "Mallfil hittades inte:" +msgstr "Mallfil hittades inte." #: editor/editor_export.cpp platform/android/export/export.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp @@ -1684,14 +1677,12 @@ msgid "Asset Library" msgstr "TillgÃ¥ngsbibliotek" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "Scene Tree Editing" -msgstr "Scenträd (Noder):" +msgstr "Scenträd Redigering" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "Node Dock" -msgstr "Node Namn:" +msgstr "Nod Docka" #: editor/editor_feature_profile.cpp #, fuzzy @@ -1741,22 +1732,20 @@ msgid "Enable Contextual Editor" msgstr "Aktivera kontextuell redigerare" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "Enabled Properties:" -msgstr "Egenskaper" +msgstr "Egenskaper:" #: editor/editor_feature_profile.cpp msgid "Enabled Features:" msgstr "Aktivera funktioner:" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "Enabled Classes:" -msgstr "Sök Klasser" +msgstr "Aktiverade Klasser:" #: editor/editor_feature_profile.cpp msgid "File '%s' format is invalid, import aborted." -msgstr "Fil '%s''s format är ogiltig, import avbruten" +msgstr "Fil '%s''s format är ogiltig, import avbruten." #: editor/editor_feature_profile.cpp msgid "" @@ -1767,9 +1756,8 @@ msgstr "" "avbruten." #: editor/editor_feature_profile.cpp -#, fuzzy msgid "Error saving profile to path: '%s'." -msgstr "Fel vid laddning av mall '%s'" +msgstr "Fel vid laddning av mall '%s'." #: editor/editor_feature_profile.cpp msgid "Unset" @@ -1781,9 +1769,8 @@ msgid "Current Profile:" msgstr "Nuvarande Version:" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "Make Current" -msgstr "Nuvarande:" +msgstr "Gör till Nuvarande" #: editor/editor_feature_profile.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -1836,7 +1823,7 @@ msgstr "Exportera Projekt" #: editor/editor_feature_profile.cpp msgid "Manage Editor Feature Profiles" -msgstr "" +msgstr "Hantera Redigerarens Funktions Profiler" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Select Current Folder" @@ -1852,7 +1839,7 @@ msgstr "Välj Denna Mapp" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "Copy Path" -msgstr "Kopiera Sökvägen" +msgstr "Kopiera Sökväg" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp #, fuzzy @@ -1946,33 +1933,28 @@ msgid "Move Favorite Down" msgstr "Flytta Favorit Ner" #: editor/editor_file_dialog.cpp -#, fuzzy msgid "Go to previous folder." -msgstr "GÃ¥ till överordnad mapp" +msgstr "GÃ¥ till föregÃ¥ende mapp." #: editor/editor_file_dialog.cpp -#, fuzzy msgid "Go to next folder." -msgstr "GÃ¥ till överordnad mapp" +msgstr "GÃ¥ till nästa mapp." #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Go to parent folder." msgstr "GÃ¥ till överordnad mapp." #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp -#, fuzzy msgid "Refresh files." -msgstr "Sök Klasser" +msgstr "Uppdatera filer." #: editor/editor_file_dialog.cpp -#, fuzzy msgid "(Un)favorite current folder." -msgstr "Kunde inte skapa mapp." +msgstr "Ta bort nuvarande mapp frÃ¥n favoriter." #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp -#, fuzzy msgid "Toggle the visibility of hidden files." -msgstr "Växla Dolda Filer" +msgstr "Växla synligheten av dolda filer." #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "View items as a grid of thumbnails." @@ -1998,13 +1980,15 @@ msgstr "Fil:" #: editor/editor_file_system.cpp msgid "ScanSources" -msgstr "ScanSources" +msgstr "ScanKällor" #: editor/editor_file_system.cpp msgid "" "There are multiple importers for different types pointing to file %s, import " "aborted" msgstr "" +"Det finns flera importörer för olika typer som pekar pÃ¥ filen %s, import " +"avbruten" #: editor/editor_file_system.cpp msgid "(Re)Importing Assets" @@ -2028,9 +2012,8 @@ msgid "Inherited by:" msgstr "Ärvd av:" #: editor/editor_help.cpp -#, fuzzy msgid "Description" -msgstr "Beskrivning:" +msgstr "Beskrivning" #: editor/editor_help.cpp #, fuzzy @@ -2043,12 +2026,11 @@ msgstr "Egenskaper" #: editor/editor_help.cpp msgid "override:" -msgstr "" +msgstr "skriv över:" #: editor/editor_help.cpp -#, fuzzy msgid "default:" -msgstr "Standard" +msgstr "standard:" #: editor/editor_help.cpp msgid "Methods" @@ -2068,9 +2050,8 @@ msgid "Constants" msgstr "Konstanter" #: editor/editor_help.cpp -#, fuzzy msgid "Property Descriptions" -msgstr "Egenskapsbeskrivning:" +msgstr "Egenskapsbeskrivningar" #: editor/editor_help.cpp #, fuzzy @@ -2086,9 +2067,8 @@ msgstr "" "oss genom att [color=$color][url=$url]bidra med en[/url][/color]!" #: editor/editor_help.cpp -#, fuzzy msgid "Method Descriptions" -msgstr "Metodbeskrivning:" +msgstr "Metodbeskrivningar" #: editor/editor_help.cpp msgid "" @@ -2183,15 +2163,15 @@ msgstr "Egenskaper" #: editor/editor_inspector.cpp editor/project_settings_editor.cpp msgid "Property:" -msgstr "" +msgstr "Egenskap:" #: editor/editor_inspector.cpp msgid "Set" -msgstr "" +msgstr "Sätt" #: editor/editor_inspector.cpp msgid "Set Multiple:" -msgstr "" +msgstr "Sätt Flera:" #: editor/editor_log.cpp msgid "Output:" @@ -2213,9 +2193,8 @@ msgid "Clear" msgstr "Rensa" #: editor/editor_log.cpp -#, fuzzy msgid "Clear Output" -msgstr "Output:" +msgstr "Rensa Utdata" #: editor/editor_network_profiler.cpp editor/editor_node.cpp #: editor/editor_profiler.cpp @@ -2225,11 +2204,11 @@ msgstr "Stanna" #: editor/editor_network_profiler.cpp editor/editor_profiler.cpp #: editor/plugins/animation_state_machine_editor.cpp editor/rename_dialog.cpp msgid "Start" -msgstr "" +msgstr "Starta" #: editor/editor_network_profiler.cpp msgid "%s/s" -msgstr "" +msgstr "%s/s" #: editor/editor_network_profiler.cpp #, fuzzy @@ -2238,7 +2217,7 @@ msgstr "Ladda ner" #: editor/editor_network_profiler.cpp msgid "Up" -msgstr "" +msgstr "Upp" #: editor/editor_network_profiler.cpp editor/editor_node.cpp msgid "Node" @@ -2246,27 +2225,27 @@ msgstr "Nod" #: editor/editor_network_profiler.cpp msgid "Incoming RPC" -msgstr "" +msgstr "Inkommande RPC" #: editor/editor_network_profiler.cpp msgid "Incoming RSET" -msgstr "" +msgstr "Inkommande RSET" #: editor/editor_network_profiler.cpp msgid "Outgoing RPC" -msgstr "" +msgstr "UtgÃ¥ende RPC" #: editor/editor_network_profiler.cpp msgid "Outgoing RSET" -msgstr "" +msgstr "UtgÃ¥ende RSET" #: editor/editor_node.cpp editor/project_manager.cpp msgid "New Window" -msgstr "" +msgstr "Nytt Fönster" #: editor/editor_node.cpp msgid "Imported resources can't be saved." -msgstr "" +msgstr "Importerade resurser kan inte sparas." #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp #: scene/gui/dialogs.cpp @@ -2282,6 +2261,8 @@ msgid "" "This resource can't be saved because it does not belong to the edited scene. " "Make it unique first." msgstr "" +"Resursen kan inte sparas för att den inte hör inte till den redigerade " +"scenen. Gör den unik först." #: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Save Resource As..." @@ -2301,7 +2282,7 @@ msgstr "Fel vid sparande." #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp msgid "Can't open '%s'. The file could have been moved or deleted." -msgstr "" +msgstr "Kan inte öppna '%s'. Filen kan ha flyttats eller tagits bort." #: editor/editor_node.cpp msgid "Error while parsing '%s'." @@ -2340,6 +2321,8 @@ 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 "" +"Scenen kan inte sparas för att det finns en cyklisk instansnings inkusion.\n" +"Försök lösa det och pröva sedan att spara igen." #: editor/editor_node.cpp #, fuzzy @@ -2352,7 +2335,7 @@ msgstr "" #: editor/editor_node.cpp editor/scene_tree_dock.cpp msgid "Can't overwrite scene that is still open!" -msgstr "" +msgstr "Kan inte skriva över en scen som fortfarande är öppen!" #: editor/editor_node.cpp msgid "Can't load MeshLibrary for merging!" @@ -2375,6 +2358,8 @@ msgid "" "An error occurred while trying to save the editor layout.\n" "Make sure the editor's user data path is writable." msgstr "" +"Ett fel uppstod medans editor layouten sparades.\n" +"Se till att editorns användardata sökväg är skriv tillgänglig." #: editor/editor_node.cpp msgid "" @@ -2382,6 +2367,9 @@ msgid "" "To restore the Default layout to its base settings, use the Delete Layout " "option and delete the Default layout." msgstr "" +"Standard editor layouten överskriven.\n" +"För att Ã¥terställa Standard layouten till sina bas inställningar, använd " +"Radera Layout valet och radera Standard Layouten." #: editor/editor_node.cpp msgid "Layout name not found!" @@ -2389,7 +2377,7 @@ msgstr "Layoutnamn hittades inte!" #: editor/editor_node.cpp msgid "Restored the Default layout to its base settings." -msgstr "" +msgstr "Ã…terställde Standard layouten till sina bas inställningar." #: editor/editor_node.cpp msgid "" @@ -2448,7 +2436,7 @@ msgstr "Det finns ingen definierad scen att köra." #: editor/editor_node.cpp msgid "Save scene before running..." -msgstr "" +msgstr "Spara scenen innan du kör..." #: editor/editor_node.cpp msgid "Could not start subprocess!" @@ -2492,7 +2480,7 @@ msgstr "Misslyckades att ladda resurs." #: editor/editor_node.cpp msgid "A root node is required to save the scene." -msgstr "" +msgstr "En root nod krävs för att spara scenen." #: editor/editor_node.cpp msgid "Save Scene As..." @@ -2536,6 +2524,8 @@ msgid "" "The current scene has unsaved changes.\n" "Reload the saved scene anyway? This action cannot be undone." msgstr "" +"Den aktiva scenen har osparade ändringar.\n" +"Vill du ladda om den ändÃ¥? Detta kan inte Ã¥ngras." #: editor/editor_node.cpp #, fuzzy @@ -2721,7 +2711,7 @@ msgstr "Stänga Övriga Flikar" #: editor/editor_node.cpp msgid "Close Tabs to the Right" -msgstr "" +msgstr "Stäng flikar till höger" #: editor/editor_node.cpp #, fuzzy @@ -2746,7 +2736,7 @@ msgstr "%d fler filer" #: editor/editor_node.cpp msgid "Dock Position" -msgstr "" +msgstr "Dockposition" #: editor/editor_node.cpp msgid "Distraction Free Mode" @@ -2836,7 +2826,7 @@ msgstr "Ã…ngra" #: editor/editor_node.cpp editor/plugins/script_text_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Redo" -msgstr "Ã…ngra" +msgstr "Ã…terställ" #: editor/editor_node.cpp msgid "Miscellaneous project or scene-wide tools." @@ -2848,45 +2838,40 @@ msgid "Project" msgstr "Projekt" #: editor/editor_node.cpp -#, fuzzy msgid "Project Settings..." -msgstr "Projektinställningar" +msgstr "Projektinställningar..." #: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Version Control" -msgstr "Version:" +msgstr "Versionshantering" #: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp msgid "Set Up Version Control" -msgstr "" +msgstr "Ställ In Versionshantering" #: editor/editor_node.cpp msgid "Shut Down Version Control" -msgstr "" +msgstr "Stäng Ner Versionshantering" #: editor/editor_node.cpp -#, fuzzy msgid "Export..." -msgstr "Exportera" +msgstr "Exportera..." #: editor/editor_node.cpp msgid "Install Android Build Template..." msgstr "" #: editor/editor_node.cpp -#, fuzzy msgid "Open Project Data Folder" -msgstr "Öppna Projekthanteraren?" +msgstr "Öppna Projekthanteraren" #: editor/editor_node.cpp editor/plugins/tile_set_editor_plugin.cpp msgid "Tools" msgstr "Verktyg" #: editor/editor_node.cpp -#, fuzzy msgid "Orphan Resource Explorer..." -msgstr "Föräldralös Resursutforskare" +msgstr "Föräldralös Resursutforskare..." #: editor/editor_node.cpp msgid "Quit to Project List" @@ -2895,7 +2880,7 @@ msgstr "Avsluta till Projektlistan" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp #: editor/project_export.cpp msgid "Debug" -msgstr "Debugga" +msgstr "Felsök" #: editor/editor_node.cpp msgid "Deploy with Remote Debug" @@ -2927,7 +2912,7 @@ msgstr "" #: editor/editor_node.cpp msgid "Visible Collision Shapes" -msgstr "" +msgstr "Synliga Kollisionsformer" #: editor/editor_node.cpp msgid "" @@ -2976,9 +2961,8 @@ msgid "Editor" msgstr "" #: editor/editor_node.cpp -#, fuzzy msgid "Editor Settings..." -msgstr "ÖvergÃ¥ngar" +msgstr "Redigerarinställningar..." #: editor/editor_node.cpp msgid "Editor Layout" @@ -2994,7 +2978,7 @@ msgstr "" #: editor/editor_node.cpp msgid "Toggle Fullscreen" -msgstr "Fullskärm" +msgstr "Växla Fullskärm" #: editor/editor_node.cpp #, fuzzy @@ -3018,9 +3002,8 @@ msgid "Manage Editor Features..." msgstr "" #: editor/editor_node.cpp -#, fuzzy msgid "Manage Export Templates..." -msgstr "Mallar" +msgstr "Hantera exportmallar..." #: editor/editor_node.cpp editor/plugins/shader_editor_plugin.cpp msgid "Help" @@ -3186,11 +3169,12 @@ msgid "Open & Run a Script" msgstr "Öppna & Kör ett Skript" #: editor/editor_node.cpp -#, fuzzy msgid "" "The following files are newer on disk.\n" "What action should be taken?" -msgstr "Följande filer gick inte att packa upp frÃ¥n tillägget:" +msgstr "" +"Följande filer är nyare pÃ¥ disken.\n" +"Vilka Ã¥tgärder ska vidtas?" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp #: editor/plugins/shader_editor_plugin.cpp @@ -3243,9 +3227,8 @@ msgid "Warning!" msgstr "Varning!" #: editor/editor_path.cpp -#, fuzzy msgid "No sub-resources found." -msgstr "Resurser" +msgstr "Inga underresurser hittades." #: editor/editor_plugin.cpp msgid "Creating Mesh Previews" @@ -3257,9 +3240,8 @@ msgid "Thumbnail..." msgstr "Miniatyr..." #: editor/editor_plugin_settings.cpp -#, fuzzy msgid "Main Script:" -msgstr "Öppna Skript" +msgstr "Huvud Skript:" #: editor/editor_plugin_settings.cpp #, fuzzy @@ -3288,9 +3270,8 @@ msgid "Status:" msgstr "Status:" #: editor/editor_plugin_settings.cpp -#, fuzzy msgid "Edit:" -msgstr "Redigera" +msgstr "Redigera:" #: editor/editor_profiler.cpp msgid "Measure:" @@ -3325,18 +3306,16 @@ msgid "Frame #:" msgstr "" #: editor/editor_profiler.cpp -#, fuzzy msgid "Time" -msgstr "Tid:" +msgstr "Tid" #: editor/editor_profiler.cpp msgid "Calls" msgstr "" #: editor/editor_properties.cpp -#, fuzzy msgid "Edit Text:" -msgstr "Redigera tema..." +msgstr "Redigera Text:" #: editor/editor_properties.cpp editor/script_create_dialog.cpp msgid "On" @@ -3355,9 +3334,8 @@ msgid "[Empty]" msgstr "" #: editor/editor_properties.cpp editor/plugins/root_motion_editor_plugin.cpp -#, fuzzy msgid "Assign..." -msgstr "Tilldela" +msgstr "Tilldela..." #: editor/editor_properties.cpp #, fuzzy @@ -3556,9 +3534,8 @@ msgid "No version.txt found inside templates." msgstr "" #: editor/export_template_manager.cpp -#, fuzzy msgid "Error creating path for templates:" -msgstr "Fel vid laddning av mall '%s'" +msgstr "Fel vid skapande av sökväg för mallar:" #: editor/export_template_manager.cpp msgid "Extracting Export Templates" @@ -3722,15 +3699,19 @@ msgid "Select mirror from list: (Shift+Click: Open in Browser)" msgstr "" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Favorites" -msgstr "Favoriter:" +msgstr "Favoriter" #: editor/filesystem_dock.cpp msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3788,9 +3769,8 @@ msgid "Renaming folder:" msgstr "Byter namn pÃ¥ mappen:" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Duplicating file:" -msgstr "Duplicera" +msgstr "Duplicerar fil:" #: editor/filesystem_dock.cpp #, fuzzy @@ -3798,9 +3778,8 @@ msgid "Duplicating folder:" msgstr "Byter namn pÃ¥ mappen:" #: editor/filesystem_dock.cpp -#, fuzzy msgid "New Inherited Scene" -msgstr "Ny Ärvd Scen..." +msgstr "Ny Ärvd Scen" #: editor/filesystem_dock.cpp #, fuzzy @@ -3817,9 +3796,8 @@ msgid "Instance" msgstr "Instans" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Add to Favorites" -msgstr "Favoriter:" +msgstr "Lägg till i Favoriter" #: editor/filesystem_dock.cpp #, fuzzy @@ -3841,14 +3819,12 @@ msgid "Move To..." msgstr "Flytta Till..." #: editor/filesystem_dock.cpp -#, fuzzy msgid "New Scene..." -msgstr "Ny Scen" +msgstr "Ny Scen..." #: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "New Script..." -msgstr "Nytt Skript" +msgstr "Nytt Skript..." #: editor/filesystem_dock.cpp #, fuzzy @@ -3868,9 +3844,8 @@ msgid "Collapse All" msgstr "Stäng Alla" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Duplicate..." -msgstr "Duplicera" +msgstr "Duplicera..." #: editor/filesystem_dock.cpp #, fuzzy @@ -3942,19 +3917,16 @@ msgid "Find in Files" msgstr "%d fler filer" #: editor/find_in_files.cpp -#, fuzzy msgid "Find:" -msgstr "Hitta" +msgstr "Hitta:" #: editor/find_in_files.cpp -#, fuzzy msgid "Folder:" -msgstr "Skapa Mapp" +msgstr "Mapp:" #: editor/find_in_files.cpp -#, fuzzy msgid "Filters:" -msgstr "Filtrera noder" +msgstr "Filter:" #: editor/find_in_files.cpp msgid "" @@ -3979,11 +3951,11 @@ msgstr "Avbryt" #: editor/find_in_files.cpp msgid "Find: " -msgstr "Hitta:" +msgstr "Hitta: " #: editor/find_in_files.cpp msgid "Replace: " -msgstr "Ersätt:" +msgstr "Ersätt: " #: editor/find_in_files.cpp #, fuzzy @@ -4158,9 +4130,8 @@ msgid "Select Importer" msgstr "Välj Node" #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Importer:" -msgstr "Importera" +msgstr "Importör:" #: editor/import_defaults_editor.cpp #, fuzzy @@ -4168,6 +4139,10 @@ msgid "Reset to Defaults" msgstr "Ladda Standard" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d Filer" @@ -4258,9 +4233,8 @@ msgid "Load an existing resource from disk and edit it." msgstr "" #: editor/inspector_dock.cpp -#, fuzzy msgid "Save the currently edited resource." -msgstr "Spara den nuvarande animationen" +msgstr "Spara den nuvarande redigerade resursen." #: editor/inspector_dock.cpp msgid "Go to the previous edited object in history." @@ -4315,14 +4289,12 @@ msgid "Subfolder:" msgstr "" #: editor/plugin_config_dialog.cpp editor/script_create_dialog.cpp -#, fuzzy msgid "Language:" -msgstr "SprÃ¥k" +msgstr "SprÃ¥k:" #: editor/plugin_config_dialog.cpp -#, fuzzy msgid "Script Name:" -msgstr "Skript giltigt" +msgstr "Skript Namn:" #: editor/plugin_config_dialog.cpp msgid "Activate now?" @@ -4337,9 +4309,8 @@ msgstr "Skapa Prenumeration" #: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp -#, fuzzy msgid "Create points." -msgstr "Radera punkter" +msgstr "Skapa punkter." #: editor/plugins/abstract_polygon_2d_editor.cpp msgid "" @@ -4350,9 +4321,8 @@ msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp -#, fuzzy msgid "Erase points." -msgstr "Radera punkter" +msgstr "Radera punkter." #: editor/plugins/abstract_polygon_2d_editor.cpp #, fuzzy @@ -4385,9 +4355,8 @@ msgstr "Lägg till Animation" #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Load..." -msgstr "Ladda" +msgstr "Ladda..." #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp @@ -4550,9 +4519,8 @@ msgid "Add Node to BlendTree" msgstr "" #: editor/plugins/animation_blend_tree_editor_plugin.cpp -#, fuzzy msgid "Node Moved" -msgstr "Node Namn:" +msgstr "Nod Flyttad" #: editor/plugins/animation_blend_tree_editor_plugin.cpp msgid "Unable to connect, port may be in use or connection may be invalid." @@ -4587,9 +4555,8 @@ msgid "Delete Node(s)" msgstr "Ta bort Nod(er)" #: editor/plugins/animation_blend_tree_editor_plugin.cpp -#, fuzzy msgid "Toggle Filter On/Off" -msgstr "Växla distraktionsfritt läge." +msgstr "Växla Filter PÃ¥/Av" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #, fuzzy @@ -4617,9 +4584,8 @@ msgid "Anim Clips" msgstr "Animklipp:" #: editor/plugins/animation_blend_tree_editor_plugin.cpp -#, fuzzy msgid "Audio Clips" -msgstr "Ljudklipp:" +msgstr "Ljudklipp" #: editor/plugins/animation_blend_tree_editor_plugin.cpp msgid "Functions" @@ -4627,21 +4593,18 @@ msgstr "Funktioner" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Node Renamed" -msgstr "Node Namn:" +msgstr "Nod har bytt Namn" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Add Node..." -msgstr "Lägg Till Node" +msgstr "Lägg Till Node..." #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/root_motion_editor_plugin.cpp -#, fuzzy msgid "Edit Filtered Tracks:" -msgstr "Redigera Filter" +msgstr "Redigera Filtrerade SpÃ¥r:" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #, fuzzy @@ -4762,9 +4725,8 @@ msgid "Animation" msgstr "Animation" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Edit Transitions..." -msgstr "ÖvergÃ¥ngar" +msgstr "Ändra ÖvergÃ¥ngar..." #: editor/plugins/animation_player_editor_plugin.cpp #, fuzzy @@ -4932,14 +4894,12 @@ msgid "" msgstr "" #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Create new nodes." -msgstr "Skapa Ny" +msgstr "Skapa nya noder." #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Connect nodes." -msgstr "Anslut Noder" +msgstr "Anslut noder." #: editor/plugins/animation_state_machine_editor.cpp #, fuzzy @@ -4956,12 +4916,11 @@ msgstr "" #: editor/plugins/animation_state_machine_editor.cpp msgid "Transition: " -msgstr "ÖvergÃ¥ng:" +msgstr "ÖvergÃ¥ng: " #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Play Mode:" -msgstr "Raw-Läge" +msgstr "Spel Läge:" #: editor/plugins/animation_tree_editor_plugin.cpp #: editor/plugins/animation_tree_player_editor_plugin.cpp @@ -5549,9 +5508,8 @@ msgid "Full Rect" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Keep Ratio" -msgstr "Skalnings förhÃ¥llande:" +msgstr "BehÃ¥ll FörhÃ¥llande" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" @@ -5865,9 +5823,8 @@ msgid "Scale mask for inserting keys." msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Insert keys (based on mask)." -msgstr "Anim Infoga Nyckel" +msgstr "Infoga nycklar (baserat pÃ¥ mask)." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "" @@ -6314,16 +6271,16 @@ msgid "Remove item %d?" msgstr "" #: editor/plugins/mesh_library_editor_plugin.cpp -#, fuzzy msgid "" "Update from existing scene?:\n" "%s" -msgstr "Uppdatera frÃ¥n scen" +msgstr "" +"Uppdatera frÃ¥n existerande scen?:\n" +"%s" #: editor/plugins/mesh_library_editor_plugin.cpp -#, fuzzy msgid "Mesh Library" -msgstr "MeshLibrary..." +msgstr "MeshLibrary" #: editor/plugins/mesh_library_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp @@ -6930,21 +6887,16 @@ msgid "Clear Recent Files" msgstr "" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Close and save changes?" -msgstr "" -"Stäng och spara ändringar?\n" -"\"" +msgstr "Stäng och spara ändringar?" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Error writing TextFile:" -msgstr "Fel vid sparande av TileSet!" +msgstr "Fel vid sparande av TextFil:" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Could not load file at:" -msgstr "Fel - Kunde inte skapa Skript i filsystemet." +msgstr "Kunde inte ladda filen vid:" #: editor/plugins/script_editor_plugin.cpp #, fuzzy @@ -6967,9 +6919,8 @@ msgid "Error importing theme." msgstr "Fel vid sparande av scenen." #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Error Importing" -msgstr "Fel vid laddning:" +msgstr "Fel vid Importering" #: editor/plugins/script_editor_plugin.cpp #, fuzzy @@ -7077,9 +7028,8 @@ msgid "File" msgstr "Fil" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Open..." -msgstr "Öppen" +msgstr "Öppna..." #: editor/plugins/script_editor_plugin.cpp #, fuzzy @@ -7114,9 +7064,8 @@ msgid "Theme" msgstr "Tema" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Import Theme..." -msgstr "Importera Tema" +msgstr "Importera Tema..." #: editor/plugins/script_editor_plugin.cpp msgid "Reload Theme" @@ -7172,9 +7121,8 @@ msgid "Debug with External Editor" msgstr "" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Open Godot online documentation." -msgstr "Öppna Senaste" +msgstr "Öppna Godot online dokumentation." #: editor/plugins/script_editor_plugin.cpp msgid "Search the reference documentation." @@ -7218,33 +7166,30 @@ msgid "Connections to method:" msgstr "Anslut Till Node:" #: editor/plugins/script_text_editor.cpp editor/script_editor_debugger.cpp -#, fuzzy msgid "Source" -msgstr "Källa:" +msgstr "Källa" #: editor/plugins/script_text_editor.cpp msgid "Target" msgstr "" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "" "Missing connected method '%s' for signal '%s' from node '%s' to node '%s'." -msgstr "Anslut '%s' till '%s'" +msgstr "" +"Saknar ansluten metod '%s' för signalen '%s' frÃ¥n noden '%s' till noden '%s'." #: editor/plugins/script_text_editor.cpp msgid "[Ignore]" msgstr "" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Line" -msgstr "Rad:" +msgstr "Rad" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Go to Function" -msgstr "Funktion:" +msgstr "GÃ¥ till Funktion" #: editor/plugins/script_text_editor.cpp msgid "Only resources from filesystem can be dropped." @@ -7397,14 +7342,12 @@ msgid "Remove All Bookmarks" msgstr "Ta bort Alla" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Go to Function..." -msgstr "Ta bort Funktion" +msgstr "GÃ¥ till Funktion..." #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Go to Line..." -msgstr "GÃ¥ till Rad" +msgstr "GÃ¥ till Rad..." #: editor/plugins/script_text_editor.cpp #: modules/visual_script/visual_script_editor.cpp @@ -7862,9 +7805,8 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Settings..." -msgstr "Inställningar" +msgstr "Inställningar..." #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Settings" @@ -8034,9 +7976,8 @@ msgid "Update Preview" msgstr "Förhandsgranska" #: editor/plugins/sprite_editor_plugin.cpp -#, fuzzy msgid "Settings:" -msgstr "Inställningar" +msgstr "Inställningar:" #: editor/plugins/sprite_frames_editor_plugin.cpp #, fuzzy @@ -8052,9 +7993,8 @@ msgid "Add Frame" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -#, fuzzy msgid "Unable to load images" -msgstr "Misslyckades att ladda resurs." +msgstr "Det gick inte att läsa in bilder" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "ERROR: Couldn't load frame resource!" @@ -8086,9 +8026,8 @@ msgid "Move Frame" msgstr "Flytta Nod(er)" #: editor/plugins/sprite_frames_editor_plugin.cpp -#, fuzzy msgid "Animations:" -msgstr "Animationer" +msgstr "Animationer:" #: editor/plugins/sprite_frames_editor_plugin.cpp #, fuzzy @@ -8109,9 +8048,8 @@ msgid "Animation Frames:" msgstr "Nytt Animationsnamn:" #: editor/plugins/sprite_frames_editor_plugin.cpp -#, fuzzy msgid "Add a Texture from File" -msgstr "Flytta nuvarande spÃ¥r upp." +msgstr "Lägg till en Textur frÃ¥n en Fil" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Add Frames from a Sprite Sheet" @@ -8222,9 +8160,8 @@ msgid "Remove All" msgstr "Ta bort Alla" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Edit Theme" -msgstr "Redigera tema..." +msgstr "Redigera Tema" #: editor/plugins/theme_editor_plugin.cpp msgid "Theme editing menu." @@ -8371,9 +8308,8 @@ msgid "Erase Selection" msgstr "" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Fix Invalid Tiles" -msgstr "Ogiltigt namn." +msgstr "Fixa Ogiltiga Tiles" #: editor/plugins/tile_map_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp @@ -8595,19 +8531,16 @@ msgid "Copy bitmask." msgstr "" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Paste bitmask." -msgstr "Klistra in Animation" +msgstr "Klistra in bitmask." #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Erase bitmask." -msgstr "Radera punkter" +msgstr "Radera bitmask." #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Create a new rectangle." -msgstr "Skapa Ny" +msgstr "Skapa en ny rektangel." #: editor/plugins/tile_set_editor_plugin.cpp #, fuzzy @@ -8615,9 +8548,8 @@ msgid "New Rectangle" msgstr "Ny Scen" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Create a new polygon." -msgstr "Skapa Prenumeration" +msgstr "Skapa en ny polygon." #: editor/plugins/tile_set_editor_plugin.cpp #, fuzzy @@ -8684,25 +8616,28 @@ msgid "Delete selected Rect." msgstr "Ta bort valda filer?" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "" "Select current edited sub-tile.\n" "Click on another Tile to edit it." -msgstr "Skapa Mapp" +msgstr "" +"Markera nuvarande redigerad sub-tile.\n" +"Klicka pÃ¥ en annan Tile för att redigera den." #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Delete polygon." -msgstr "Radera punkter" +msgstr "Radera polygon." #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "" "LMB: Set bit on.\n" "RMB: Set bit off.\n" "Shift+LMB: Set wildcard bit.\n" "Click on another Tile to edit it." -msgstr "Skapa Mapp" +msgstr "" +"LMB: Aktivera bit.\n" +"RMB: Avaktivera bit.\n" +"Shift+LMB: Aktivera vildkorts bit.\n" +"Klicka pÃ¥ en annan Tile för att redigera den." #: editor/plugins/tile_set_editor_plugin.cpp msgid "" @@ -8718,11 +8653,12 @@ msgid "" msgstr "" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "" "Select sub-tile to change its z index.\n" "Click on another Tile to edit it." -msgstr "Skapa Mapp" +msgstr "" +"Välj sub-tile för att ändra dess z-index.\n" +"Klicka pÃ¥ en annan Tile för att redigera den." #: editor/plugins/tile_set_editor_plugin.cpp msgid "Set Tile Region" @@ -8829,9 +8765,8 @@ msgid "This property can't be changed." msgstr "Ã…tgärden kan inte göras utan en scen." #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "TileSet" -msgstr "TileSet..." +msgstr "TileSet" #: editor/plugins/version_control_editor_plugin.cpp msgid "No VCS addons are available." @@ -8932,14 +8867,12 @@ msgid "(GLES3 only)" msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Add Output" -msgstr "Output:" +msgstr "Lägg till Utdata" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Scalar" -msgstr "Skala:" +msgstr "Skalär" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Vector" @@ -8954,9 +8887,8 @@ msgid "Sampler" msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Add input port" -msgstr "Favoriter:" +msgstr "Lägg till inmatningsport" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Add output port" @@ -8972,9 +8904,8 @@ msgid "Change output port type" msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Change input port name" -msgstr "Ändra Animationsnamn:" +msgstr "Ändra inmatningsport namn" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Change output port name" @@ -8991,9 +8922,8 @@ msgid "Remove output port" msgstr "Ta Bort Mall" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Set expression" -msgstr "Nuvarande Version:" +msgstr "Ställ in uttryck" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Resize VisualShader node" @@ -9012,9 +8942,8 @@ msgid "Add Node to Visual Shader" msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Node(s) Moved" -msgstr "Node Namn:" +msgstr "Nod(er) Flyttade" #: editor/plugins/visual_shader_editor_plugin.cpp #, fuzzy @@ -9054,9 +8983,8 @@ msgid "Light" msgstr "Höger" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Show resulted shader code." -msgstr "Skapa Node" +msgstr "Visa den resulterande skuggningskoden." #: editor/plugins/visual_shader_editor_plugin.cpp #, fuzzy @@ -9064,18 +8992,16 @@ msgid "Create Shader Node" msgstr "Skapa Node" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Color function." -msgstr "Funktion:" +msgstr "Färg funktion." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Color operator." msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Grayscale function." -msgstr "Skapa Funktion" +msgstr "GrÃ¥skala funktion." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Converts HSV vector to RGB equivalent." @@ -9086,9 +9012,8 @@ msgid "Converts RGB vector to HSV equivalent." msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Sepia function." -msgstr "Byt namn pÃ¥ funktion" +msgstr "Sepia funktion." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Burn operator." @@ -9127,14 +9052,12 @@ msgid "SoftLight operator." msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Color constant." -msgstr "Konstant" +msgstr "Färg konstant." #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Color uniform." -msgstr "Transformera" +msgstr "Färg enhetlig." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the boolean result of the %s comparison between two parameters." @@ -9243,9 +9166,8 @@ msgid "'%s' input parameter for vertex and fragment shader mode." msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Scalar function." -msgstr "Skala urval" +msgstr "Skalär funktion." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Scalar operator." @@ -9478,9 +9400,8 @@ msgid "Scalar constant." msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Scalar uniform." -msgstr "Transformera" +msgstr "Skalär uniform." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Perform the cubic texture lookup." @@ -9503,9 +9424,8 @@ msgid "2D texture uniform lookup with triplanar." msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Transform function." -msgstr "Transformera" +msgstr "Transformera funktion." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" @@ -9547,19 +9467,16 @@ msgid "Multiplies vector by transform." msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Transform constant." -msgstr "Transformera" +msgstr "Transformera konstant." #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Transform uniform." -msgstr "Transformera" +msgstr "Transformera uniform." #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Vector function." -msgstr "Ta bort Funktion" +msgstr "Vektor funktion." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Vector operator." @@ -9800,9 +9717,8 @@ msgid "Exporting All" msgstr "Exportera" #: editor/project_export.cpp -#, fuzzy msgid "The given export path doesn't exist:" -msgstr "Sökvägen finns inte." +msgstr "Den angivna export vägen finns inte:" #: editor/project_export.cpp msgid "Export templates for this platform are missing/corrupted:" @@ -9881,9 +9797,8 @@ msgid "Script" msgstr "Nytt Skript" #: editor/project_export.cpp -#, fuzzy msgid "Script Export Mode:" -msgstr "Exportera Projekt" +msgstr "Skript Exporterings Läge:" #: editor/project_export.cpp msgid "Text" @@ -9980,9 +9895,8 @@ msgid "Imported Project" msgstr "" #: editor/project_manager.cpp -#, fuzzy msgid "Invalid Project Name." -msgstr "Projektnamn:" +msgstr "Ogiltigt projektnamn." #: editor/project_manager.cpp #, fuzzy @@ -10115,9 +10029,8 @@ msgid "Error: Project is missing on the filesystem." msgstr "" #: editor/project_manager.cpp -#, fuzzy msgid "Can't open project at '%s'." -msgstr "Kan inte öppna projekt" +msgstr "Kan inte öppna projekt vid '%s'." #: editor/project_manager.cpp msgid "Are you sure to open more than one project?" @@ -10299,9 +10212,8 @@ msgid "Rename Input Action Event" msgstr "" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Change Action deadzone" -msgstr "Ändra Animationsnamn:" +msgstr "Ändra Ã…tgärdens Dödzon" #: editor/project_settings_editor.cpp msgid "Add Input Action Event" @@ -10670,9 +10582,8 @@ msgid "Suffix:" msgstr "" #: editor/rename_dialog.cpp -#, fuzzy msgid "Use Regular Expressions" -msgstr "Nuvarande Version:" +msgstr "Använd Vanliga Uttryck" #: editor/rename_dialog.cpp #, fuzzy @@ -10684,18 +10595,16 @@ msgid "Substitute" msgstr "" #: editor/rename_dialog.cpp -#, fuzzy msgid "Node name" -msgstr "Node Namn:" +msgstr "Nod namn" #: editor/rename_dialog.cpp msgid "Node's parent name, if available" msgstr "" #: editor/rename_dialog.cpp -#, fuzzy msgid "Node type" -msgstr "Node Namn:" +msgstr "Nod typ" #: editor/rename_dialog.cpp #, fuzzy @@ -10726,9 +10635,8 @@ msgid "Initial value for the counter" msgstr "" #: editor/rename_dialog.cpp -#, fuzzy msgid "Step" -msgstr "Steg (s):" +msgstr "Steg" #: editor/rename_dialog.cpp msgid "Amount by which counter is incremented for each node" @@ -10785,9 +10693,8 @@ msgid "Regular Expression Error:" msgstr "Nuvarande Version:" #: editor/rename_dialog.cpp -#, fuzzy msgid "At character %s" -msgstr "Giltiga tecken:" +msgstr "Vid tecken %s" #: editor/reparent_dialog.cpp editor/scene_tree_dock.cpp msgid "Reparent Node" @@ -10898,14 +10805,12 @@ msgid "Make node as Root" msgstr "Gör nod som Rot" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Delete %d nodes and any children?" -msgstr "Ta bort Nod(er)" +msgstr "Ta bort %d noder och alla barn?" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Delete %d nodes?" -msgstr "Ta bort Nod(er)" +msgstr "Ta bort %d noder?" #: editor/scene_tree_dock.cpp msgid "Delete the root node \"%s\"?" @@ -10916,9 +10821,8 @@ msgid "Delete node \"%s\" and its children?" msgstr "" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Delete node \"%s\"?" -msgstr "Ta bort Nod(er)" +msgstr "Ta bort nod \"%s\"?" #: editor/scene_tree_dock.cpp msgid "Can not perform with the root node." @@ -10955,9 +10859,8 @@ msgid "New Scene Root" msgstr "Ny Scenrot" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Create Root Node:" -msgstr "Skapa Node" +msgstr "Skapa Rot Nod:" #: editor/scene_tree_dock.cpp #, fuzzy @@ -11049,7 +10952,7 @@ msgstr "" #: editor/scene_tree_dock.cpp msgid "Add Child Node" -msgstr "Lägg till Barn-Node" +msgstr "Lägg till Barn-Nod" #: editor/scene_tree_dock.cpp #, fuzzy @@ -11079,16 +10982,15 @@ msgstr "" #: editor/scene_tree_dock.cpp editor/script_editor_debugger.cpp msgid "Copy Node Path" -msgstr "Kopiera Node-Sökväg" +msgstr "Kopiera Nod-Sökväg" #: editor/scene_tree_dock.cpp msgid "Delete (No Confirm)" msgstr "" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Add/Create a New Node." -msgstr "Lägga till/Skapa en Ny Node" +msgstr "Lägg till/Skapa en Ny Node." #: editor/scene_tree_dock.cpp msgid "" @@ -11161,9 +11063,8 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -#, fuzzy msgid "Open Script:" -msgstr "Öppna Skript" +msgstr "Öppna Skript:" #: editor/scene_tree_editor.cpp msgid "" @@ -11172,13 +11073,12 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -#, fuzzy msgid "" "Children are not selectable.\n" "Click to make selectable." msgstr "" "Barn är inte valbara.\n" -"Klicka för att göra valbara" +"Klicka för att göra valbara." #: editor/scene_tree_editor.cpp msgid "Toggle Visibility" @@ -11211,14 +11111,12 @@ msgid "Select a Node" msgstr "Välj en Node" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Path is empty." -msgstr "Sökvägen är tom" +msgstr "Sökvägen är tom." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Filename is empty." -msgstr "Sökvägen är tom" +msgstr "Filnamn är tom." #: editor/script_create_dialog.cpp msgid "Path is not local." @@ -11230,9 +11128,8 @@ msgid "Invalid base path." msgstr "Ogiltig Sökväg." #: editor/script_create_dialog.cpp -#, fuzzy msgid "A directory with the same name exists." -msgstr "Katalog med samma namn finns redan" +msgstr "Katalog med samma namn finns redan." #: editor/script_create_dialog.cpp msgid "File does not exist." @@ -11296,14 +11193,12 @@ msgid "Invalid inherited parent name or path." msgstr "" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Script path/name is valid." -msgstr "Skript giltigt" +msgstr "Skript väg/namn är ogiltigt." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Allowed: a-z, A-Z, 0-9, _ and ." -msgstr "TillÃ¥tna: a-z, a-Z, 0-9 och _" +msgstr "TillÃ¥tna: a-z, A-Z, 0-9, _ och ." #: editor/script_create_dialog.cpp #, fuzzy @@ -11311,14 +11206,12 @@ msgid "Built-in script (into scene file)." msgstr "Ã…tgärder med scenfiler." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Will create a new script file." -msgstr "Skapa ny Skript-fil" +msgstr "Kommer att skapa ny skript-fil." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Will load an existing script file." -msgstr "Ladda in befintlig Skript-fil" +msgstr "Kommer att ladda en befintlig Skript-fil." #: editor/script_create_dialog.cpp msgid "Script file already exists." @@ -11331,19 +11224,16 @@ msgid "" msgstr "" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Class Name:" -msgstr "Klassnamn" +msgstr "Klassnamn:" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Template:" -msgstr "Mall" +msgstr "Mall:" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Built-in Script:" -msgstr "Öppna Skript" +msgstr "Inbyggd Skript:" #: editor/script_create_dialog.cpp msgid "Attach Node Script" @@ -11358,9 +11248,8 @@ msgid "Bytes:" msgstr "" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Warning:" -msgstr "Varning" +msgstr "Varning:" #: editor/script_editor_debugger.cpp msgid "Error:" @@ -11377,9 +11266,8 @@ msgid "C++ Error:" msgstr "Fel:" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "C++ Source" -msgstr "Källa:" +msgstr "C++ Källa" #: editor/script_editor_debugger.cpp #, fuzzy @@ -11400,9 +11288,8 @@ msgid "Errors" msgstr "Fel" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Child process connected." -msgstr "Barnprocess Ansluten" +msgstr "Barnprocess ansluten." #: editor/script_editor_debugger.cpp #, fuzzy @@ -11615,9 +11502,8 @@ msgid "Select dependencies of the library for this entry" msgstr "" #: modules/gdnative/gdnative_library_editor_plugin.cpp -#, fuzzy msgid "Remove current entry" -msgstr "Flytta nuvarande spÃ¥r upp." +msgstr "Ta bort aktuell post" #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Double click to create a new entry" @@ -11849,18 +11735,16 @@ msgid "Generate buffers" msgstr "" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Direct lighting" -msgstr "Sektioner:" +msgstr "Direkt ljus" #: modules/lightmapper_cpu/lightmapper_cpu.cpp msgid "Indirect lighting" msgstr "" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Post processing" -msgstr "Nuvarande Version:" +msgstr "Efterbehandling" #: modules/lightmapper_cpu/lightmapper_cpu.cpp #, fuzzy @@ -11986,14 +11870,12 @@ msgid "Set Variable Type" msgstr "" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Input Port" -msgstr "Favoriter:" +msgstr "Lägg till IngÃ¥ngsport" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Output Port" -msgstr "Favoriter:" +msgstr "Lägg till UtgÃ¥ngsport" #: modules/visual_script/visual_script_editor.cpp #, fuzzy @@ -12001,27 +11883,24 @@ msgid "Override an existing built-in function." msgstr "Ogiltigt namn. FÃ¥r inte vara samma som ett befintligt inbyggt typnamn." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Create a new function." -msgstr "Skapa Ny" +msgstr "Skapa en ny funktion." #: modules/visual_script/visual_script_editor.cpp msgid "Variables:" msgstr "Variabler:" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Create a new variable." -msgstr "Skapa Ny" +msgstr "Skapa en ny variabel." #: modules/visual_script/visual_script_editor.cpp msgid "Signals:" msgstr "Signaler:" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Create a new signal." -msgstr "Skapa Prenumeration" +msgstr "Skapa en ny signal." #: modules/visual_script/visual_script_editor.cpp msgid "Name is not a valid identifier:" @@ -12226,33 +12105,28 @@ msgid "Editing Signal:" msgstr "" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Make Tool:" -msgstr "Gör Patch" +msgstr "Skapa Verktyg:" #: modules/visual_script/visual_script_editor.cpp msgid "Members:" msgstr "Medlemmar:" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Change Base Type:" -msgstr "Ändra Typ" +msgstr "Ändra Bas Typ:" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Nodes..." -msgstr "Lägg Till Node" +msgstr "Lägg Till Noder..." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Function..." -msgstr "Lägg till Funktion" +msgstr "Lägg till Funktion..." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "function_name" -msgstr "Funktioner:" +msgstr "funktions_namn" #: modules/visual_script/visual_script_editor.cpp msgid "Select or create a function to edit its graph." @@ -12436,9 +12310,8 @@ msgid "Invalid public key for APK expansion." msgstr "" #: platform/android/export/export.cpp -#, fuzzy msgid "Invalid package name:" -msgstr "Ogiltigt namn." +msgstr "Ogiltigt paket namn:" #: platform/android/export/export.cpp msgid "" @@ -12529,9 +12402,8 @@ msgid "App Store Team ID not specified - cannot configure the project." msgstr "" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Invalid Identifier:" -msgstr "Ogiltig teckenstorlek." +msgstr "Ogiltig identifierare:" #: platform/iphone/export/export.cpp msgid "Required icon is not specified in the preset." @@ -12554,9 +12426,8 @@ msgid "Could not write file:" msgstr "Kunde inte skriva till filen:" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Could not open template for export:" -msgstr "Kunde inte skapa mapp." +msgstr "Kunde inte öppna mall för export:" #: platform/javascript/export/export.cpp msgid "Invalid export template:" @@ -12590,14 +12461,12 @@ msgid "Invalid package publisher display name." msgstr "Ogiltigt namn." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid product GUID." -msgstr "Projektnamn:" +msgstr "Ogiltig produkt GUID." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid publisher GUID." -msgstr "Ogiltig Sökväg" +msgstr "Ogiltigt GUID utgivare." #: platform/uwp/export/export.cpp #, fuzzy @@ -12848,9 +12717,8 @@ msgid "" msgstr "" #: scene/3d/arvr_nodes.cpp -#, fuzzy msgid "ARVROrigin requires an ARVRCamera child node." -msgstr "ARVROrigin kräver en ARVRCamera Barn-Node" +msgstr "ARVROrigin kräver en ARVRCamera Barn-Node." #: scene/3d/baked_lightmap.cpp msgid "Finding meshes and lights" @@ -12875,9 +12743,8 @@ msgid "Saving lightmaps" msgstr "Genererar Lightmaps" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Done" -msgstr "Klar!" +msgstr "Klar" #: scene/3d/collision_object.cpp msgid "" @@ -13088,9 +12955,8 @@ msgid "Invalid animation: '%s'." msgstr "Ogiltig animation: '%s'." #: scene/animation/animation_tree.cpp -#, fuzzy msgid "Nothing connected to input '%s' of node '%s'." -msgstr "Anslut '%s' till '%s'" +msgstr "Inget anslutet till inmatning '%s' av nod '%s'." #: scene/animation/animation_tree.cpp msgid "No root AnimationNode for the graph is set." @@ -13137,9 +13003,8 @@ msgid "Switch between hexadecimal and code values." msgstr "" #: scene/gui/color_picker.cpp -#, fuzzy msgid "Add current color as a preset." -msgstr "Lägg till nuvarande färg som en förinställning" +msgstr "Lägg till nuvarande färg som en förinställning." #: scene/gui/container.cpp msgid "" diff --git a/editor/translations/ta.po b/editor/translations/ta.po index 9f9f40b54b..0fbcb5c3eb 100644 --- a/editor/translations/ta.po +++ b/editor/translations/ta.po @@ -3527,6 +3527,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3921,6 +3926,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/te.po b/editor/translations/te.po index 50c0fb5a4b..de9f84e3a4 100644 --- a/editor/translations/te.po +++ b/editor/translations/te.po @@ -3497,6 +3497,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3887,6 +3892,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/th.po b/editor/translations/th.po index 76a2d3c125..4ac8875aa6 100644 --- a/editor/translations/th.po +++ b/editor/translations/th.po @@ -4,7 +4,7 @@ # This file is distributed under the same license as the Godot source code. # Kaveeta Vivatchai <goodytong@gmail.com>, 2017. # Poommetee Ketson (Noshyaar) <poommetee@protonmail.com>, 2017-2018. -# Thanachart Monpassorn <nunf_2539@hotmail.com>, 2020. +# Thanachart Monpassorn <nunf_2539@hotmail.com>, 2020, 2021. # Anonymous <noreply@weblate.org>, 2020. # Lon3r <mptube.p@gmail.com>, 2020. # Kongfa Warorot <gongpha@hotmail.com>, 2020, 2021. @@ -12,8 +12,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-02-15 10:51+0000\n" -"Last-Translator: Kongfa Warorot <gongpha@hotmail.com>\n" +"PO-Revision-Date: 2021-04-05 14:28+0000\n" +"Last-Translator: Thanachart Monpassorn <nunf_2539@hotmail.com>\n" "Language-Team: Thai <https://hosted.weblate.org/projects/godot-engine/godot/" "th/>\n" "Language: th\n" @@ -21,7 +21,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.5-dev\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -2489,9 +2489,8 @@ msgid "Unable to enable addon plugin at: '%s' parsing of config failed." msgstr "ไม่สามารถเปิดใช้งานปลั๊à¸à¸à¸´à¸™: '%s'" #: editor/editor_node.cpp -#, fuzzy msgid "Unable to find script field for addon plugin at: '%s'." -msgstr "ไม่พบชื่à¸à¸ªà¸„ริปต์ในปลั๊à¸à¸à¸´à¸™: 'res://addons/%s'" +msgstr "ไม่พบไฟล์สคริปต์สำหรับปลั๊à¸à¸à¸´à¸™à¸—ี่: '%s'." #: editor/editor_node.cpp msgid "Unable to load addon script from path: '%s'." @@ -3069,13 +3068,12 @@ msgid "Open & Run a Script" msgstr "เปิดà¹à¸¥à¸°à¸£à¸±à¸™à¸ªà¸„ริปต์" #: editor/editor_node.cpp -#, fuzzy msgid "" "The following files are newer on disk.\n" "What action should be taken?" msgstr "" -"ไฟล์ต่à¸à¹„ปนี้ในดิสà¸à¹Œà¹ƒà¸«à¸¡à¹ˆà¸à¸§à¹ˆà¸²\n" -"จะทำà¸à¸¢à¹ˆà¸²à¸‡à¹„รต่à¸à¹„ป?:" +"ไฟล์เหล่านี้มีความใหม่à¸à¸§à¹ˆà¸²à¸šà¸™à¸”ิสà¸à¹Œ\n" +"ต้à¸à¸‡à¸ˆà¸°à¸—ำà¸à¸¢à¹ˆà¸²à¸‡à¹„รต่à¸à¹„ป?" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp #: editor/plugins/shader_editor_plugin.cpp @@ -3603,6 +3601,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "สถานะ: นำเข้าไฟล์ล้มเหลว à¸à¸£à¸¸à¸“าà¹à¸à¹‰à¹„ขไฟล์à¹à¸¥à¸°à¸™à¸³à¹€à¸‚้าใหม่" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "à¸à¸²à¸£à¸™à¸³à¹€à¸‚้าไฟล์นี้ถูà¸à¸›à¸´à¸”, ดังนั้นจึงไม่สามารถเปิดเพื่à¸à¹à¸à¹‰à¹„ขใดๆได้" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "ไม่สามารถย้าย/เปลี่ยนชื่à¸à¹‚ฟลเดà¸à¸£à¹Œà¸£à¸²à¸" @@ -3988,19 +3991,20 @@ msgid "Saving..." msgstr "à¸à¸³à¸¥à¸±à¸‡à¸šà¸±à¸™à¸—ึà¸..." #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Select Importer" -msgstr "โหมดเลืà¸à¸" +msgstr "เลืà¸à¸à¸•à¸±à¸§à¸™à¸³à¹€à¸‚้า" #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Importer:" -msgstr "นำเข้า" +msgstr "ตัวนำเข้า:" #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Reset to Defaults" -msgstr "โหลดค่าเริ่มต้น" +msgstr "รีเซ็ตเป็นค่าเริ่มต้น" + +#: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "เà¸à¹‡à¸šà¹„ฟล์ (ไม่นำเข้า)" #: editor/import_dock.cpp msgid "%d Files" @@ -4957,9 +4961,8 @@ msgid "Got:" msgstr "ที่ได้รับ:" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Failed SHA-256 hash check" -msgstr "ผิดพลาดในà¸à¸²à¸£à¸•à¸£à¸§à¸ˆà¸ªà¸à¸šà¹à¸®à¸Š SHA256" +msgstr "ผิดพลาดในà¸à¸²à¸£à¸•à¸£à¸§à¸ˆà¸ªà¸à¸šà¹à¸®à¸Š SHA-256" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Asset Download Error:" @@ -5090,13 +5093,12 @@ msgid "Assets ZIP File" msgstr "ทรัพยาà¸à¸£à¹„ฟล์ ZIP" #: editor/plugins/baked_lightmap_editor_plugin.cpp -#, fuzzy msgid "" "Can't determine a save path for lightmap images.\n" "Save your scene and try again." msgstr "" -"ไม่สามารถเลืà¸à¸à¸•à¸³à¹à¸«à¸™à¹ˆà¸‡à¸—ี่จะบันทึà¸à¸ าพ lightmap\n" -"à¸à¸£à¸¸à¸“าบันทึà¸à¸‰à¸²à¸ (เพื่à¸à¸šà¸±à¸™à¸—ึà¸à¸ าพในโฟลเดà¸à¸£à¹Œà¹€à¸”ียวà¸à¸±à¸™) หรืà¸à¸£à¸°à¸šà¸¸à¸•à¸³à¹à¸«à¸™à¹ˆà¸‡à¹ƒà¸™à¸„ุณสมบัติขà¸à¸‡ BakedLightmap" +"ไม่สามารถà¸à¸³à¸«à¸™à¸”ตำà¹à¸«à¸™à¹ˆà¸‡à¸à¸²à¸£à¸šà¸±à¸™à¸—ึà¸à¸ªà¸³à¸«à¸£à¸±à¸šà¸ าพ lightmap\n" +"ลà¸à¸‡à¸šà¸±à¸™à¸—ึà¸à¸‰à¸²à¸à¸‚à¸à¸‡à¸„ุณà¹à¸¥à¹‰à¸§à¸¥à¸à¸‡à¸à¸µà¸à¸„รั้ง" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" @@ -5111,27 +5113,28 @@ msgstr "ผิดพลาดขณะสร้างภาพ lightmap à¸à¸£à¸ #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Failed determining lightmap size. Maximum lightmap size too small?" -msgstr "" +msgstr "à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ขนาด lightmap ล้มเหลว ขนาด lightmap สูงสุดเล็à¸à¹€à¸à¸´à¸™à¹„ป?" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" "Some mesh is invalid. Make sure the UV2 channel values are contained within " "the [0.0,1.0] square region." -msgstr "" +msgstr "mesh บางส่วนไม่ถูà¸à¸•à¹‰à¸à¸‡ ตรวจสà¸à¸šà¹ƒà¸«à¹‰à¹à¸™à¹ˆà¹ƒà¸ˆà¸§à¹ˆà¸²à¸„่า UV2 à¸à¸¢à¸¹à¹ˆà¹ƒà¸™à¸žà¸·à¹‰à¸™à¸—ี่สี่เหลี่ยม [0.0,1.0]" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" "Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" +"เà¸à¸”ิเตà¸à¸£à¹Œ Godot ถูà¸à¸ªà¸£à¹‰à¸²à¸‡à¹‚ดยไม่ได้สนับสนุน ray tracing ดังนั้นจึงไม่สามารถ bake lightmaps " +"ได้" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Bake Lightmaps" msgstr "สร้าง Lightmaps" #: editor/plugins/baked_lightmap_editor_plugin.cpp -#, fuzzy msgid "Select lightmap bake file:" -msgstr "เลืà¸à¸à¹„ฟล์เทมเพลต" +msgstr "เลืà¸à¸à¹„ฟล์ bake ขà¸à¸‡ lightmap :" #: editor/plugins/camera_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -6211,9 +6214,8 @@ msgid "Can only set point into a ParticlesMaterial process material" msgstr "สามารถà¸à¸³à¸«à¸™à¸”จุดให้à¹à¸à¹ˆ ParticlesMaterial เท่านั้น" #: editor/plugins/particles_2d_editor_plugin.cpp -#, fuzzy msgid "Convert to CPUParticles2D" -msgstr "à¹à¸›à¸¥à¸‡à¹€à¸›à¹‡à¸™ CPUParticles" +msgstr "à¹à¸›à¸¥à¸‡à¹€à¸›à¹‡à¸™ CPUParticles2D" #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp @@ -7238,9 +7240,8 @@ msgid "Yaw" msgstr "Yaw" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Size" -msgstr "ขนาด: " +msgstr "ขนาด" #: editor/plugins/spatial_editor_plugin.cpp msgid "Objects Drawn" @@ -9876,9 +9877,8 @@ msgid "Projects" msgstr "โปรเจà¸à¸•à¹Œ" #: editor/project_manager.cpp -#, fuzzy msgid "Loading, please wait..." -msgstr "à¸à¸³à¸¥à¸±à¸‡à¹€à¸£à¸µà¸¢à¸à¸‚้à¸à¸¡à¸¹à¸¥ โปรดรà¸..." +msgstr "à¸à¸³à¸¥à¸±à¸‡à¹‚หลด โปรดรà¸..." #: editor/project_manager.cpp msgid "Last Modified" @@ -10246,9 +10246,8 @@ msgid "Plugins" msgstr "ปลั๊à¸à¸à¸´à¸™" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Import Defaults" -msgstr "โหลดค่าเริ่มต้น" +msgstr "นำเข้าค่าเริ่มต้น" #: editor/property_editor.cpp msgid "Preset..." @@ -10497,12 +10496,10 @@ msgid "Instance Child Scene" msgstr "à¸à¸´à¸™à¸ªà¹à¸•à¸™à¸‹à¹Œà¸‰à¸²à¸à¸¥à¸¹à¸" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Can't paste root node into the same scene." -msgstr "ทำà¸à¸±à¸šà¹‚หนดขà¸à¸‡à¸‰à¸²à¸à¸à¸·à¹ˆà¸™à¹„ม่ได้!" +msgstr "ไม่สามารถวางโหนดราà¸à¹ƒà¸™à¸‰à¸²à¸à¹€à¸”ียวà¸à¸±à¸™" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Paste Node(s)" msgstr "วางโหนด" @@ -10632,7 +10629,6 @@ msgid "Attach Script" msgstr "à¹à¸™à¸šà¸ªà¸„ริปต์" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Cut Node(s)" msgstr "ตัดโหนด" @@ -11437,36 +11433,31 @@ msgstr "มà¸à¸šà¸—รัพยาà¸à¸£ MeshLibrary ให้à¸à¸±à¸š GridMap #: modules/lightmapper_cpu/lightmapper_cpu.cpp msgid "Begin Bake" -msgstr "" +msgstr "เริ่มต้น Bake" #: modules/lightmapper_cpu/lightmapper_cpu.cpp msgid "Preparing data structures" -msgstr "" +msgstr "à¸à¸³à¸¥à¸±à¸‡à¹€à¸•à¸£à¸µà¸¢à¸¡à¹‚ครงสร้างข้à¸à¸¡à¸¹à¸¥" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Generate buffers" -msgstr "สร้าง AABB" +msgstr "สร้างบัฟเฟà¸à¸£à¹Œ" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Direct lighting" -msgstr "ทิศทาง" +msgstr "lighting à¹à¸šà¸šà¸•à¸£à¸‡" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Indirect lighting" -msgstr "ย่à¸à¸«à¸™à¹‰à¸²à¸‚วา" +msgstr "lighting à¹à¸šà¸šà¸à¹‰à¸à¸¡" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Post processing" msgstr "หลังประมวลผล" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Plotting lightmaps" -msgstr "วางà¹à¸™à¸§à¹à¸ªà¸‡:" +msgstr "à¸à¸³à¸¥à¸±à¸‡à¸žà¸¥à¹‡à¸à¸• lightmaps" #: modules/mono/csharp_script.cpp msgid "Class name can't be a reserved keyword" @@ -11966,9 +11957,8 @@ msgid "Select device from the list" msgstr "เลืà¸à¸à¸à¸¸à¸›à¸à¸£à¸“์จาà¸à¸£à¸²à¸¢à¸Šà¸·à¹ˆà¸" #: platform/android/export/export.cpp -#, fuzzy msgid "Unable to find the 'apksigner' tool." -msgstr "ไม่สามารถหา zipalign tool" +msgstr "ไม่สามารถหาเครื่à¸à¸‡à¸¡à¸·à¸ 'apksigner'" #: platform/android/export/export.cpp msgid "" @@ -11985,14 +11975,12 @@ msgid "Release keystore incorrectly configured in the export preset." msgstr "Release keystore à¸à¸³à¸«à¸™à¸”ค่าไว้à¸à¸¢à¹ˆà¸²à¸‡à¹„ม่ถูà¸à¸•à¹‰à¸à¸‡à¹ƒà¸™à¸žà¸£à¸µà¹€à¸‹à¹‡à¸•à¸ªà¸³à¸«à¸£à¸±à¸šà¸à¸²à¸£à¸ªà¹ˆà¸‡à¸à¸à¸" #: platform/android/export/export.cpp -#, fuzzy msgid "A valid Android SDK path is required in Editor Settings." -msgstr "ที่à¸à¸¢à¸¹à¹ˆ Android SDK ผิดพลาดสำหรับà¸à¸²à¸£à¸ªà¸£à¹‰à¸²à¸‡à¹à¸šà¸šà¸à¸³à¸«à¸™à¸”เà¸à¸‡à¹ƒà¸™à¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่าเà¸à¸”ิเตà¸à¸£à¹Œ" +msgstr "ต้à¸à¸‡à¸à¸²à¸£à¸—ี่à¸à¸¢à¸¹à¹ˆà¸‚à¸à¸‡ Android SDK ที่ถูà¸à¸•à¹‰à¸à¸‡ ในà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่าเà¸à¸”ิเตà¸à¸£à¹Œ" #: platform/android/export/export.cpp -#, fuzzy msgid "Invalid Android SDK path in Editor Settings." -msgstr "ที่à¸à¸¢à¸¹à¹ˆ Android SDK ผิดพลาดสำหรับà¸à¸²à¸£à¸ªà¸£à¹‰à¸²à¸‡à¹à¸šà¸šà¸à¸³à¸«à¸™à¸”เà¸à¸‡à¹ƒà¸™à¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่าเà¸à¸”ิเตà¸à¸£à¹Œ" +msgstr "ที่à¸à¸¢à¸¹à¹ˆ Android SDK ไม่ถูà¸à¸•à¹‰à¸à¸‡à¹ƒà¸™à¸•à¸±à¹‰à¸‡à¸„่าขà¸à¸‡à¹€à¸à¸”ิเตà¸à¸£à¹Œ" #: platform/android/export/export.cpp msgid "Missing 'platform-tools' directory!" @@ -12000,12 +11988,11 @@ msgstr "ไดเร็à¸à¸—à¸à¸£à¸µ 'platform-tools' หายไป!" #: platform/android/export/export.cpp msgid "Unable to find Android SDK platform-tools' adb command." -msgstr "" +msgstr "ไม่พบคำสั่ง adb ขà¸à¸‡ Android SDK platform-tools" #: platform/android/export/export.cpp -#, fuzzy msgid "Please check in the Android SDK directory specified in Editor Settings." -msgstr "ที่à¸à¸¢à¸¹à¹ˆ Android SDK ผิดพลาดสำหรับà¸à¸²à¸£à¸ªà¸£à¹‰à¸²à¸‡à¹à¸šà¸šà¸à¸³à¸«à¸™à¸”เà¸à¸‡à¹ƒà¸™à¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่าเà¸à¸”ิเตà¸à¸£à¹Œ" +msgstr "โปรดตรวจสà¸à¸šà¹ƒà¸™à¹„ดเร็à¸à¸—à¸à¸£à¸µ Android SDK ที่ระบุใตัวตั้งค่าขà¸à¸‡à¹€à¸à¸”ิเตà¸à¸£à¹Œ" #: platform/android/export/export.cpp msgid "Missing 'build-tools' directory!" @@ -12013,7 +12000,7 @@ msgstr "ไดเร็à¸à¸—à¸à¸£à¸µ 'build-tools' หายไป!" #: platform/android/export/export.cpp msgid "Unable to find Android SDK build-tools' apksigner command." -msgstr "" +msgstr "ไม่พบคำสั่ง apksigner ขà¸à¸‡ Android SDK build-tools" #: platform/android/export/export.cpp msgid "Invalid public key for APK expansion." @@ -12261,11 +12248,11 @@ msgstr "CollisionPolygon2D ที่ว่างเปล่าจะไม่ภ#: scene/2d/collision_polygon_2d.cpp msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode." -msgstr "" +msgstr "โพลีà¸à¸à¸™à¹„ม่ถูà¸à¸•à¹‰à¸à¸‡ ต้à¸à¸‡à¸¡à¸µà¸à¸¢à¹ˆà¸²à¸‡à¸™à¹‰à¸à¸¢ 3 จุด ในโหมดà¸à¸²à¸£à¸ªà¸£à¹‰à¸²à¸‡à¹à¸šà¸š 'Solids'" #: scene/2d/collision_polygon_2d.cpp msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode." -msgstr "" +msgstr "โพลีà¸à¸à¸™à¹„ม่ถูà¸à¸•à¹‰à¸à¸‡ ต้à¸à¸‡à¸¡à¸µà¸à¸¢à¹ˆà¸²à¸‡à¸™à¹‰à¸à¸¢ 2 จุด ในโหมดà¸à¸²à¸£à¸ªà¸£à¹‰à¸²à¸‡à¹à¸šà¸š 'Segments'" #: scene/2d/collision_shape_2d.cpp msgid "" @@ -12454,27 +12441,23 @@ msgstr "ARVROrigin จำเป็นต้à¸à¸‡à¸¡à¸µ ARVRCamera เป็นà #: scene/3d/baked_lightmap.cpp msgid "Finding meshes and lights" -msgstr "" +msgstr "à¸à¸³à¸¥à¸±à¸‡à¸«à¸² meshes à¹à¸¥à¸° lights" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Preparing geometry (%d/%d)" -msgstr "วิเคราะห์พื้นผิว..." +msgstr "à¸à¸³à¸¥à¸±à¸‡à¹€à¸•à¸£à¸µà¸¢à¸¡à¸£à¸¹à¸›à¹€à¸£à¸‚าคณิต (%d/%d)" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Preparing environment" -msgstr "à¹à¸ªà¸”งสภาพà¹à¸§à¸”ล้à¸à¸¡" +msgstr "à¸à¸³à¸¥à¸±à¸‡à¹€à¸•à¸£à¸µà¸¢à¸¡à¸ªà¸ าพà¹à¸§à¸”ล้à¸à¸¡" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Generating capture" -msgstr "à¸à¸³à¸¥à¸±à¸‡à¸ªà¸£à¹‰à¸²à¸‡ Lightmaps" +msgstr "à¸à¸³à¸¥à¸±à¸‡à¸ªà¸£à¹‰à¸²à¸‡ capture" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Saving lightmaps" -msgstr "à¸à¸³à¸¥à¸±à¸‡à¸ªà¸£à¹‰à¸²à¸‡ Lightmaps" +msgstr "à¸à¸³à¸¥à¸±à¸‡à¸šà¸±à¸™à¸—ึภlightmaps" #: scene/3d/baked_lightmap.cpp msgid "Done" @@ -12846,7 +12829,7 @@ msgstr "ขนาดวิวพà¸à¸£à¹Œà¸•à¸ˆà¸°à¸•à¹‰à¸à¸‡à¸¡à¸²à¸à¸à¸§à¹ˆ msgid "" "The sampler port is connected but not used. Consider changing the source to " "'SamplerPort'." -msgstr "" +msgstr "พà¸à¸£à¹Œà¸•à¸•à¸±à¸§à¸à¸¢à¹ˆà¸²à¸‡à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸•à¹ˆà¸à¸à¸¢à¸¹à¹ˆà¹à¸•à¹ˆà¹„ม่ได้ใช้ ควรที่จะเปลี่ยนเป็น \"SamplerPort\"" #: scene/resources/visual_shader_nodes.cpp msgid "Invalid source for preview." diff --git a/editor/translations/tr.po b/editor/translations/tr.po index 9a815d3f25..619bd94bb1 100644 --- a/editor/translations/tr.po +++ b/editor/translations/tr.po @@ -61,8 +61,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-16 10:40+0000\n" -"Last-Translator: furkan atalar <fatalar55@gmail.com>\n" +"PO-Revision-Date: 2021-03-31 03:53+0000\n" +"Last-Translator: OÄŸuz Ersen <oguzersen@protonmail.com>\n" "Language-Team: Turkish <https://hosted.weblate.org/projects/godot-engine/" "godot/tr/>\n" "Language: tr\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.5.2-dev\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -2579,9 +2579,8 @@ msgstr "" "baÅŸarısız oldu." #: editor/editor_node.cpp -#, fuzzy msgid "Unable to find script field for addon plugin at: '%s'." -msgstr "Eklentideki betik alanı bulunamıyor: 'res://addons/%s'." +msgstr "Eklentide için betik alanı bulunamıyor: '%s'." #: editor/editor_node.cpp msgid "Unable to load addon script from path: '%s'." @@ -3722,6 +3721,13 @@ msgstr "" "aktarın." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" +"İçe aktarma bu dosya için devre dışı bırakıldı, bu nedenle düzenleme için " +"açılamıyor." + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Kaynakların kökü taşınamaz/yeniden adlandırılamaz." @@ -4124,6 +4130,10 @@ msgid "Reset to Defaults" msgstr "Varsayılanlara dön" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "Dosyayı Koru (İçeri Aktarma Yok)" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d Dosya" @@ -10450,9 +10460,8 @@ msgid "Plugins" msgstr "Eklentiler" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Import Defaults" -msgstr "Varsayılanları İçe Aktar" +msgstr "Öntanımlı İçe Aktarma Ayarları" #: editor/property_editor.cpp msgid "Preset..." @@ -12494,11 +12503,12 @@ msgstr "BoÅŸ bir CollisionPolygon2D'nin çarpışmaya hiçbir etkisi yoktur." #: scene/2d/collision_polygon_2d.cpp msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode." -msgstr "" +msgstr "Geçersiz çokgen. 'Solids' oluÅŸturma modunda en az 3 nokta gereklidir." #: scene/2d/collision_polygon_2d.cpp msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode." msgstr "" +"Geçersiz çokgen. 'Segments' oluÅŸturma modunda en az 2 nokta gereklidir." #: scene/2d/collision_shape_2d.cpp msgid "" diff --git a/editor/translations/tzm.po b/editor/translations/tzm.po index c4614c7eb3..893d4134db 100644 --- a/editor/translations/tzm.po +++ b/editor/translations/tzm.po @@ -3495,6 +3495,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3885,6 +3890,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "" diff --git a/editor/translations/uk.po b/editor/translations/uk.po index 6a8af58119..3dd58a87f4 100644 --- a/editor/translations/uk.po +++ b/editor/translations/uk.po @@ -20,8 +20,8 @@ msgid "" msgstr "" "Project-Id-Version: Ukrainian (Godot Engine)\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-10 22:14+0000\n" -"Last-Translator: Tymofij Lytvynenko <till.svit@gmail.com>\n" +"PO-Revision-Date: 2021-03-31 03:53+0000\n" +"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n" "Language-Team: Ukrainian <https://hosted.weblate.org/projects/godot-engine/" "godot/uk/>\n" "Language: uk\n" @@ -30,7 +30,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.5.2-dev\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -3695,6 +3695,13 @@ msgstr "" "імпортуйте вручну." #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" +"Ð†Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ файла вимкнено, тому його не можна відкрити Ð´Ð»Ñ " +"редагуваннÑ." + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "Ðеможливо переміÑтити/перейменувати корінь реÑурÑів." @@ -4095,6 +4102,10 @@ msgid "Reset to Defaults" msgstr "Відновити типові параметри" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "Зберегти файл (не імпортувати)" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d файлів" diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po index a2e1decab6..78698e90ba 100644 --- a/editor/translations/ur_PK.po +++ b/editor/translations/ur_PK.po @@ -3561,6 +3561,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "" @@ -3965,6 +3970,10 @@ msgid "Reset to Defaults" msgstr "" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp #, fuzzy msgid "%d Files" msgstr "Ø§Ø«Ø§Ø«Û Ú©ÛŒ زپ Ùائل" diff --git a/editor/translations/vi.po b/editor/translations/vi.po index 94692dc9b2..fa600ca176 100644 --- a/editor/translations/vi.po +++ b/editor/translations/vi.po @@ -22,7 +22,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-08 15:33+0000\n" +"PO-Revision-Date: 2021-04-05 14:28+0000\n" "Last-Translator: Rev <revolnoom7801@gmail.com>\n" "Language-Team: Vietnamese <https://hosted.weblate.org/projects/godot-engine/" "godot/vi/>\n" @@ -31,7 +31,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.5.1\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -51,11 +51,11 @@ msgstr "Không đủ byte để giải mã, hoặc định dạng không hợp l #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" -msgstr "Dữ liệu và o không hợp lệ %i (không được thông qua)" +msgstr "Äầu và o %i không hợp lệ (không được thông qua) trong biểu thức" #: core/math/expression.cpp msgid "self can't be used because instance is null (not passed)" -msgstr "self không thể sá» dụng vì instance là null (không thông qua)" +msgstr "Không thể sá» dụng self vì instance là null (không thông qua)" #: core/math/expression.cpp msgid "Invalid operands to operator %s, %s and %s." @@ -75,7 +75,7 @@ msgstr "Äối số không hợp lệ để dá»±ng '%s'" #: core/math/expression.cpp msgid "On call to '%s':" -msgstr "Khi cuá»™c gá»i đến '%s':" +msgstr "Khi gá»i đến '%s':" #: core/ustring.cpp msgid "B" @@ -175,27 +175,23 @@ msgstr "Äổi Function Gá»i Animation" #: editor/animation_track_editor.cpp msgid "Anim Multi Change Keyframe Time" -msgstr "Äổi nhiá»u thá»i gian khung hình" +msgstr "" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Anim Multi Change Transition" -msgstr "Äổi Transition Animation" +msgstr "" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Anim Multi Change Transform" -msgstr "Äổi Transform Animation" +msgstr "" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Anim Multi Change Keyframe Value" -msgstr "Äổi giá trị khung hình" +msgstr "" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Anim Multi Change Call" -msgstr "Äổi Function Gá»i Animation" +msgstr "" #: editor/animation_track_editor.cpp msgid "Change Animation Length" @@ -224,11 +220,11 @@ msgstr "Theo dõi Ä‘Æ°á»ng cong Bezier" #: editor/animation_track_editor.cpp msgid "Audio Playback Track" -msgstr "Bản nhạc phát lại âm thanh" +msgstr "Kênh Âm Thanh" #: editor/animation_track_editor.cpp msgid "Animation Playback Track" -msgstr "NgÆ°ng chạy animation. (S)" +msgstr "Kênh Hoạt Ảnh" #: editor/animation_track_editor.cpp msgid "Animation length (frames)" @@ -265,7 +261,7 @@ msgstr "Thay đổi Ä‘Æ°á»ng dẫn Track" #: editor/animation_track_editor.cpp msgid "Toggle this track on/off." -msgstr "Báºt hoặc tắt track nà y, on/off" +msgstr "Báºt/tắt kênh nà y." #: editor/animation_track_editor.cpp msgid "Update Mode (How this property is set)" @@ -285,7 +281,7 @@ msgstr "Bá» track nà y." #: editor/animation_track_editor.cpp msgid "Time (s): " -msgstr "BÆ°á»›c: " +msgstr "Thá»i gian (s): " #: editor/animation_track_editor.cpp msgid "Toggle Track Enabled" @@ -407,7 +403,7 @@ msgstr "Sắp xếp lại Tracks" #: editor/animation_track_editor.cpp msgid "Transform tracks only apply to Spatial-based nodes." -msgstr "Các chuyển đổi chỉ có thể áp dụng cho các node Spatial" +msgstr "Các chuyển đổi chỉ có thể áp dụng cho các nút dá»±a trên kiểu Spatial." #: editor/animation_track_editor.cpp msgid "" @@ -432,7 +428,7 @@ msgstr "" #: editor/animation_track_editor.cpp msgid "Not possible to add a new track without a root" -msgstr "Không thể thêm track má»›i mà không có root." +msgstr "Không thể thêm track má»›i mà không có root" #: editor/animation_track_editor.cpp msgid "Invalid track for Bezier (no suitable sub-properties)" @@ -444,7 +440,7 @@ msgstr "Thêm Bezier Track" #: editor/animation_track_editor.cpp msgid "Track path is invalid, so can't add a key." -msgstr "ÄÆ°á»ng dẫn không hợp lệ, không thể thêm khoá." +msgstr "ÄÆ°á»ng dẫn không hợp lệ, nên không thể thêm khóa." #: editor/animation_track_editor.cpp msgid "Track is not of type Spatial, can't insert key" @@ -503,25 +499,21 @@ msgid "" "Alternatively, use an import preset that imports animations to separate " "files." msgstr "" -"Cáianimation nà y thuá»™c vá» má»™t cảnh đã nháºp, vì váºy những thay đổi đối vá»›i " -"các bản nhạc đã nháºp sẽ không được lÆ°u.\n" +"Hoạt ảnh nà y thuá»™c vá» má»™t Cảnh được Nháºp, nên các thay đổi lên track được " +"Nháºp sẽ không được lÆ°u lại.\n" "\n" -"Äể báºt khả năng thêm các bản nhạc tùy chỉnh, hãy Ä‘iá»u hÆ°á»›ng đến cà i đặt nháºp " -"của cảnh và đặt\n" -"\"animation > LÆ°u trữ\" thà nh \"Tệp\", báºt \"Hoạt hình> Giữ các bản nhạc tùy " -"chỉnh\", sau đó nháºp lại.(vn)\n" -"\"Animation > Storage\" to \"Files\", enable \"Animation > Keep Custom Tracks" -"\", sau đó nháºp lại (english).\n" -"Hoặc, sá» dụng cà i đặt trÆ°á»›c nháºp khẩu nháºp hình ảnh Ä‘á»™ng để tách các tệp." +"Äể báºt khả năng thêm track tùy ý, Ä‘i đến cà i đặt của Cảnh được Nháºp rồi đặt\n" +"\"Hoạt Ảnh > LÆ°u trữ\" thà nh \"Tệp\", báºt \"Hoạt ảnh > Giữ các track tùy " +"chỉnh\", sau đó Nháºp lại.\n" +"Hoặc, dùng má»™t Cà i đặt trÆ°á»›c nháºp để Nháºp hoạt ảnh ra các tệp khác nhau." #: editor/animation_track_editor.cpp msgid "Warning: Editing imported animation" msgstr "Cảnh bảo: Chỉnh sá»a hoạt ảnh đã nháºp" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Select an AnimationPlayer node to create and edit animations." -msgstr "Chá»n má»™t AnimationPlayer từ Scene Tree để chỉnh sá»a animation." +msgstr "Chá»n má»™t AnimationPlayer để tạo và chỉnh sá»a Hoạt Ảnh." #: editor/animation_track_editor.cpp msgid "Only show tracks from nodes selected in tree." @@ -533,7 +525,7 @@ msgstr "Nhóm các track bởi nút hoặc hiển thị chúng dạng danh sách #: editor/animation_track_editor.cpp msgid "Snap:" -msgstr "Chụp:" +msgstr "DÃnh:" #: editor/animation_track_editor.cpp msgid "Animation step value." @@ -652,12 +644,11 @@ msgstr "Dá»n dẹp" #: editor/animation_track_editor.cpp msgid "Scale Ratio:" -msgstr "Tỉ lệ Scale:" +msgstr "Tỉ lệ phóng đại:" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Select Tracks to Copy" -msgstr "Chá»n các Track để sao chép:" +msgstr "Chá»n các Track để sao chép" #: editor/animation_track_editor.cpp editor/editor_log.cpp #: editor/editor_properties.cpp @@ -670,7 +661,7 @@ msgstr "Sao chép" #: editor/animation_track_editor.cpp msgid "Select All/None" -msgstr "Chá»n tất cả/ hoặc không" +msgstr "Chá»n/Bá» tất cả" #: editor/animation_track_editor_plugins.cpp msgid "Add Audio Track Clip" @@ -678,7 +669,7 @@ msgstr "Thêm Track Âm thanh" #: editor/animation_track_editor_plugins.cpp msgid "Change Audio Track Clip Start Offset" -msgstr "Thay đổi thá»i Ä‘iểm bắt đầu phát track âm thanh." +msgstr "Thay đổi thá»i Ä‘iểm bắt đầu phát track âm thanh" #: editor/animation_track_editor_plugins.cpp msgid "Change Audio Track Clip End Offset" @@ -705,19 +696,16 @@ msgid "Line Number:" msgstr "Dòng số:" #: editor/code_editor.cpp -#, fuzzy msgid "%d replaced." -msgstr "Thay thế ..." +msgstr "Äã thay %d." #: editor/code_editor.cpp editor/editor_help.cpp -#, fuzzy msgid "%d match." -msgstr "Tìm thấy %d khá»›p." +msgstr "%d khá»›p." #: editor/code_editor.cpp editor/editor_help.cpp -#, fuzzy msgid "%d matches." -msgstr "Tìm thấy %d khá»›p." +msgstr "%d khá»›p." #: editor/code_editor.cpp editor/find_in_files.cpp msgid "Match Case" @@ -737,7 +725,7 @@ msgstr "Thay thế tất cả" #: editor/code_editor.cpp msgid "Selection Only" -msgstr "Chỉ lá»±a chá»n" +msgstr "Chỉ chá»n" #: editor/code_editor.cpp editor/plugins/script_text_editor.cpp #: editor/plugins/text_editor.cpp @@ -746,7 +734,7 @@ msgstr "Chuẩn" #: editor/code_editor.cpp editor/plugins/script_editor_plugin.cpp msgid "Toggle Scripts Panel" -msgstr "" +msgstr "Hiện/Ẩn bảng Tệp lệnh" #: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/texture_region_editor_plugin.cpp @@ -762,7 +750,7 @@ msgstr "Thu nhá»" #: editor/code_editor.cpp msgid "Reset Zoom" -msgstr "Äặt lại phóng" +msgstr "Äặt lại Ä‘á»™ phóng" #: editor/code_editor.cpp msgid "Warnings" @@ -827,7 +815,7 @@ msgstr "Thêm đối số mở rá»™ng:" #: editor/connections_dialog.cpp msgid "Extra Call Arguments:" -msgstr "Mở rá»™ng Äối số được gá»i:" +msgstr "Äối số mở rá»™ng được gá»i:" #: editor/connections_dialog.cpp msgid "Receiver Method:" @@ -845,7 +833,7 @@ msgstr "Trì hoãn" msgid "" "Defers the signal, storing it in a queue and only firing it at idle time." msgstr "" -"Trì hoãn tÃn hiệu, lÆ°u và o má»™t hà ng chá» và chỉ kÃch nó và o thá»i gian rãnh." +"Trì hoãn tÃn hiệu, lÆ°u và o má»™t hà ng chá» và chỉ kÃch nó và o thá»i gian rảnh." #: editor/connections_dialog.cpp msgid "Oneshot" @@ -1048,11 +1036,12 @@ msgid "Owners Of:" msgstr "Sở hữu của:" #: editor/dependency_editor.cpp -#, fuzzy msgid "" "Remove selected files from the project? (no undo)\n" "You can find the removed files in the system trash to restore them." -msgstr "Gỡ bá» các tệp đã chá»n trong dá»± án? (Không thể khôi phục)" +msgstr "" +"Gỡ bá» các tệp đã chá»n trong dá»± án? (Không thể khôi phục)\n" +"Bạn có thể khôi phục chúng trong thùng rác của hệ thống." #: editor/dependency_editor.cpp msgid "" @@ -1061,6 +1050,9 @@ msgid "" "Remove them anyway? (no undo)\n" "You can find the removed files in the system trash to restore them." msgstr "" +"Các tà i nguyên khác cần những tệp bị xóa nà y má»›i hoạt Ä‘á»™ng được.\n" +"Vẫn xóa hả? (không hồi được đâu)\n" +"Bạn có thể khôi phục chúng trong thùng rác hệ thống." #: editor/dependency_editor.cpp msgid "Cannot remove:" @@ -1072,11 +1064,11 @@ msgstr "Lá»—i tải nạp:" #: editor/dependency_editor.cpp msgid "Load failed due to missing dependencies:" -msgstr "" +msgstr "Tải thất bại do thiếu phần phụ thuá»™c:" #: editor/dependency_editor.cpp editor/editor_node.cpp msgid "Open Anyway" -msgstr "Luôn mở" +msgstr "Cứ mở thôi" #: editor/dependency_editor.cpp msgid "Which action should be taken?" @@ -1092,7 +1084,7 @@ msgstr "Lá»—i tải nạp!" #: editor/dependency_editor.cpp msgid "Permanently delete %d item(s)? (No undo!)" -msgstr "Xoá vÄ©nh viá»…n các đối tượng %d? (Không thể hoà n lại!)" +msgstr "Xoá vÄ©nh viá»…n %d đối tượng? (Không thể hoà n lại!)" #: editor/dependency_editor.cpp msgid "Show Dependencies" @@ -1116,7 +1108,7 @@ msgstr "Sở hữu" #: editor/dependency_editor.cpp msgid "Resources Without Explicit Ownership:" -msgstr "" +msgstr "Tà i nguyên không có quyá»n sở hữu rõ rà ng:" #: editor/dictionary_property_edit.cpp msgid "Change Dictionary Key" @@ -1166,14 +1158,12 @@ msgid "Gold Sponsors" msgstr "Nhà tà i trợ Và ng" #: editor/editor_about.cpp -#, fuzzy msgid "Silver Sponsors" -msgstr "NgÆ°á»i ủng há»™ Bạc" +msgstr "Nhà tà i trợ Bạc" #: editor/editor_about.cpp -#, fuzzy msgid "Bronze Sponsors" -msgstr "NgÆ°á»i ủng há»™ Äồng" +msgstr "Nhà tà i trợ Äồng" #: editor/editor_about.cpp msgid "Mini Sponsors" @@ -1197,15 +1187,13 @@ msgstr "NgÆ°á»i ủng há»™" #: editor/editor_about.cpp msgid "License" -msgstr "Cấp phép" +msgstr "Giấy phép" #: editor/editor_about.cpp -#, fuzzy msgid "Third-party Licenses" -msgstr "Cấp phép nhóm thứ ba" +msgstr "Giấy phép bên thứ ba" #: editor/editor_about.cpp -#, fuzzy msgid "" "Godot Engine relies on a number of third-party free and open source " "libraries, all compatible with the terms of its MIT license. The following " @@ -1230,27 +1218,24 @@ msgid "Licenses" msgstr "Các giấy phép" #: editor/editor_asset_installer.cpp editor/project_manager.cpp -#, fuzzy msgid "Error opening package file, not in ZIP format." -msgstr "Lá»—i không thể mở gói, không phải dạng nén." +msgstr "Lá»—i không thể mở gói, không phải dạng nén ZIP." #: editor/editor_asset_installer.cpp -#, fuzzy msgid "%s (Already Exists)" -msgstr "Tam giác đã tồn tại." +msgstr "%s (Äã tồn tại)" #: editor/editor_asset_installer.cpp msgid "Uncompressing Assets" -msgstr "Giải nén Assets" +msgstr "Giải nén tà i nguyên" #: editor/editor_asset_installer.cpp editor/project_manager.cpp msgid "The following files failed extraction from package:" -msgstr "" +msgstr "Không thể lấy các tệp sau khá»i gói:" #: editor/editor_asset_installer.cpp -#, fuzzy msgid "And %s more files." -msgstr "%d thêm các tệp tin" +msgstr "Và %s tệp nữa." #: editor/editor_asset_installer.cpp editor/project_manager.cpp msgid "Package installed successfully!" @@ -1262,9 +1247,8 @@ msgid "Success!" msgstr "Thà nh công!" #: editor/editor_asset_installer.cpp -#, fuzzy msgid "Package Contents:" -msgstr "Ná»™i dung:" +msgstr "Trong Gói có:" #: editor/editor_asset_installer.cpp editor/editor_node.cpp msgid "Install" @@ -1284,11 +1268,11 @@ msgstr "Thêm hiệu ứng" #: editor/editor_audio_buses.cpp msgid "Rename Audio Bus" -msgstr "" +msgstr "Äổi tên Bus âm thanh" #: editor/editor_audio_buses.cpp msgid "Change Audio Bus Volume" -msgstr "" +msgstr "Thay đổi âm lượng Bus" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Solo" @@ -1296,7 +1280,7 @@ msgstr "" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Mute" -msgstr "" +msgstr "Báºt/Tắt Âm Thanh của Bus" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Bypass Effects" @@ -1308,19 +1292,19 @@ msgstr "" #: editor/editor_audio_buses.cpp msgid "Add Audio Bus Effect" -msgstr "" +msgstr "Thêm hiệu ứng và o Bus âm thanh" #: editor/editor_audio_buses.cpp msgid "Move Bus Effect" -msgstr "" +msgstr "Di chuyển hiệu ứng Bus" #: editor/editor_audio_buses.cpp msgid "Delete Bus Effect" -msgstr "" +msgstr "Xóa hiệu ứng của Bus" #: editor/editor_audio_buses.cpp msgid "Drag & drop to rearrange." -msgstr "" +msgstr "Kéo & thả để sắp xếp lại." #: editor/editor_audio_buses.cpp msgid "Solo" @@ -1336,12 +1320,12 @@ msgstr "" #: editor/editor_audio_buses.cpp msgid "Bus options" -msgstr "" +msgstr "Tùy chá»n Bus" #: editor/editor_audio_buses.cpp editor/filesystem_dock.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "Duplicate" -msgstr "Nhân bản" +msgstr "Nhân đôi" #: editor/editor_audio_buses.cpp msgid "Reset Volume" @@ -1357,23 +1341,23 @@ msgstr "Âm thanh" #: editor/editor_audio_buses.cpp msgid "Add Audio Bus" -msgstr "" +msgstr "Thêm Bus âm thanh" #: editor/editor_audio_buses.cpp msgid "Master bus can't be deleted!" -msgstr "" +msgstr "Không thể xóa Bus âm thanh chủ!" #: editor/editor_audio_buses.cpp msgid "Delete Audio Bus" -msgstr "" +msgstr "Xóa Bus âm thanh" #: editor/editor_audio_buses.cpp msgid "Duplicate Audio Bus" -msgstr "" +msgstr "Nhân bản Bus âm thanh" #: editor/editor_audio_buses.cpp msgid "Reset Bus Volume" -msgstr "" +msgstr "Äặt lại âm lượng Bus" #: editor/editor_audio_buses.cpp msgid "Move Audio Bus" @@ -1381,7 +1365,7 @@ msgstr "" #: editor/editor_audio_buses.cpp msgid "Save Audio Bus Layout As..." -msgstr "" +msgstr "LÆ°u bố cục Bus âm thanh thà nh..." #: editor/editor_audio_buses.cpp msgid "Location for New Layout..." @@ -1389,7 +1373,7 @@ msgstr "Vị trà cho Bố cục má»›i..." #: editor/editor_audio_buses.cpp msgid "Open Audio Bus Layout" -msgstr "" +msgstr "Mở bố cục Bus âm thanh" #: editor/editor_audio_buses.cpp msgid "There is no '%s' file." @@ -1401,20 +1385,19 @@ msgstr "Bố trÃ" #: editor/editor_audio_buses.cpp msgid "Invalid file, not an audio bus layout." -msgstr "" +msgstr "Sai kiểu tệp, không phải bố cục bus âm thanh." #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Error saving file: %s" -msgstr "Lá»—i tải font." +msgstr "Lá»—i lÆ°u tệp: %s" #: editor/editor_audio_buses.cpp msgid "Add Bus" -msgstr "" +msgstr "Thêm Bus" #: editor/editor_audio_buses.cpp msgid "Add a new Audio Bus to this layout." -msgstr "" +msgstr "Thêm Bus âm thanh má»›i cho bố cục." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1424,7 +1407,7 @@ msgstr "Nạp" #: editor/editor_audio_buses.cpp msgid "Load an existing Bus Layout." -msgstr "" +msgstr "Nạp má»™t bố cục Bus có sẵn." #: editor/editor_audio_buses.cpp msgid "Save As" @@ -1432,7 +1415,7 @@ msgstr "LÆ°u thà nh" #: editor/editor_audio_buses.cpp msgid "Save this Bus Layout to a file." -msgstr "" +msgstr "LÆ°u bố cục Bus nà y và o tệp." #: editor/editor_audio_buses.cpp editor/import_dock.cpp msgid "Load Default" @@ -1440,11 +1423,11 @@ msgstr "Nạp mặc định" #: editor/editor_audio_buses.cpp msgid "Load the default Bus Layout." -msgstr "" +msgstr "Nạp bố cục Bus mặc định." #: editor/editor_audio_buses.cpp msgid "Create a new Bus Layout." -msgstr "" +msgstr "Tạo bố cục Bus má»›i." #: editor/editor_autoload_settings.cpp msgid "Invalid name." @@ -1456,15 +1439,15 @@ msgstr "Ký tá»± hợp lệ:" #: editor/editor_autoload_settings.cpp msgid "Must not collide with an existing engine class name." -msgstr "" +msgstr "Không được trùng tên vá»›i má»™t lá»›p có sẵn của công cụ láºp trình." #: editor/editor_autoload_settings.cpp msgid "Must not collide with an existing built-in type name." -msgstr "" +msgstr "Không được trùng vá»›i tên má»™t kiểu có sẵn đã tồn tại." #: editor/editor_autoload_settings.cpp msgid "Must not collide with an existing global constant name." -msgstr "" +msgstr "Không được trùng vá»›i tên má»™t hằng số toà n cục đã tồn tại." #: editor/editor_autoload_settings.cpp msgid "Keyword cannot be used as an autoload name." @@ -1476,7 +1459,7 @@ msgstr "Nạp tá»± Ä‘á»™ng '%s' đã tồn tại!" #: editor/editor_autoload_settings.cpp msgid "Rename Autoload" -msgstr "Äổi tên" +msgstr "Äổi tên Nạp tá»± Ä‘á»™ng" #: editor/editor_autoload_settings.cpp msgid "Toggle AutoLoad Globals" @@ -1488,7 +1471,7 @@ msgstr "" #: editor/editor_autoload_settings.cpp msgid "Remove Autoload" -msgstr "" +msgstr "Xóa Nạp tá»± Ä‘á»™ng" #: editor/editor_autoload_settings.cpp editor/editor_plugin_settings.cpp msgid "Enable" @@ -1500,7 +1483,7 @@ msgstr "Sắp xếp lại Autoloads" #: editor/editor_autoload_settings.cpp msgid "Can't add autoload:" -msgstr "" +msgstr "Không thể thêm nạp tá»± Ä‘á»™ng:" #: editor/editor_autoload_settings.cpp msgid "Add AutoLoad" @@ -1549,7 +1532,7 @@ msgstr "[rá»—ng]" #: editor/editor_data.cpp msgid "[unsaved]" -msgstr "[chÆ°a save]" +msgstr "[chÆ°a lÆ°u]" #: editor/editor_dir_dialog.cpp msgid "Please select a base directory first." @@ -1587,7 +1570,7 @@ msgstr "LÆ°u trữ tệp tin:" #: editor/editor_export.cpp msgid "No export template found at the expected path:" -msgstr "" +msgstr "Không thấy mẫu xuất nà o ở Ä‘Æ°á»ng dẫn mong đợi:" #: editor/editor_export.cpp msgid "Packing" @@ -1621,22 +1604,20 @@ msgstr "" "Trình Ä‘iá»u khiển Dá»± phòng'." #: editor/editor_export.cpp -#, fuzzy msgid "" "Target platform requires 'PVRTC' texture compression for GLES2. Enable " "'Import Pvrtc' in Project Settings." msgstr "" -"Ná»n tảng yêu cầu dùng kiểu nén 'ETC' cho GLES2. Báºt 'Nháºp ETC' trong Cà i đặt " -"Dá»± án." +"Ná»n tảng yêu cầu dùng kiểu nén 'PVRTC' cho GLES2. Hãy báºt 'Nháºp Pvrtc' trong " +"Cà i đặt Dá»± án." #: editor/editor_export.cpp -#, fuzzy msgid "" "Target platform requires 'ETC2' or 'PVRTC' texture compression for GLES3. " "Enable 'Import Etc 2' or 'Import Pvrtc' in Project Settings." msgstr "" -"Ná»n tảng yêu cầu dùng kiểu nén 'ETC2' cho GLES3. Báºt 'Nháºp ETC2' trong Cà i " -"đặt Dá»± án." +"Ná»n tảng yêu cầu dùng kiểu nén 'ETC2' hoặc 'PVRTC' cho GLES3. Hãy báºt 'Nháºp " +"ETC2' hoặc 'Nháºp Pvrtc' trong Cà i đặt Dá»± án." #: editor/editor_export.cpp #, fuzzy @@ -1659,8 +1640,9 @@ msgstr "Không tìm thấy mẫu gỡ lá»—i tuỳ chỉnh." #: editor/editor_export.cpp platform/android/export/export.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp #: platform/osx/export/export.cpp platform/uwp/export/export.cpp +#, fuzzy msgid "Custom release template not found." -msgstr "" +msgstr "Không tìm thấy mẫu phát hà nh tùy chỉnh." #: editor/editor_export.cpp platform/javascript/export/export.cpp msgid "Template file not found:" @@ -1725,7 +1707,7 @@ msgstr "(Äã tắt trình chỉnh sá»a)" #: editor/editor_feature_profile.cpp msgid "Class Options:" -msgstr "Tuỳ chá»n lá»›p:" +msgstr "Tuỳ chá»n Lá»›p:" #: editor/editor_feature_profile.cpp msgid "Enable Contextual Editor" @@ -1748,11 +1730,10 @@ msgid "File '%s' format is invalid, import aborted." msgstr "Tệp '%s' định dạng không hợp lệ, huá»· nháºp và o." #: editor/editor_feature_profile.cpp -#, fuzzy msgid "" "Profile '%s' already exists. Remove it first before importing, import " "aborted." -msgstr "Hồ sÆ¡ '%s' đã tồn tại. Di chuyển hồ sÆ¡ trÆ°á»›c khi nháºp, huá»· nháºp." +msgstr "Hồ sÆ¡ '%s' đã tồn tại. Hãy xóa hồ sÆ¡ đấy trÆ°á»›c khi nháºp, đã dừng nháºp." #: editor/editor_feature_profile.cpp msgid "Error saving profile to path: '%s'." @@ -1763,9 +1744,8 @@ msgid "Unset" msgstr "BỠđặt" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "Current Profile:" -msgstr "Hồ sÆ¡ hiện tại" +msgstr "Hồ sÆ¡ hiện tại:" #: editor/editor_feature_profile.cpp msgid "Make Current" @@ -1780,16 +1760,15 @@ msgstr "Má»›i" #: editor/editor_feature_profile.cpp editor/editor_node.cpp #: editor/project_manager.cpp msgid "Import" -msgstr "Nháºp và o" +msgstr "Nháºp" #: editor/editor_feature_profile.cpp editor/project_export.cpp msgid "Export" msgstr "Xuất ra" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "Available Profiles:" -msgstr "Hồ sÆ¡ khả dụng" +msgstr "Hồ sÆ¡ khả dụng:" #: editor/editor_feature_profile.cpp msgid "Class Options" @@ -1856,7 +1835,7 @@ msgstr "Là m má»›i" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "All Recognized" -msgstr "" +msgstr "Äã nháºn diện hết" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "All Files (*)" @@ -1919,39 +1898,35 @@ msgstr "Táºp trung ÄÆ°á»ng dẫn" #: editor/editor_file_dialog.cpp msgid "Move Favorite Up" -msgstr "Di chuyển Ưa thÃch lên" +msgstr "Di chuyển mục Ưa thÃch lên" #: editor/editor_file_dialog.cpp msgid "Move Favorite Down" -msgstr "Di chuyển Ưa thÃch xuống" +msgstr "Di chuyển mục Ưa thÃch xuống" #: editor/editor_file_dialog.cpp -#, fuzzy msgid "Go to previous folder." -msgstr "Äến thÆ° mục cha" +msgstr "Quay lại thÆ° mục trÆ°á»›c." #: editor/editor_file_dialog.cpp -#, fuzzy msgid "Go to next folder." -msgstr "Äến thÆ° mục cha" +msgstr "Äến thÆ° mục tiếp theo." #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Go to parent folder." -msgstr "Äến thÆ° mục cha" +msgstr "Äến thÆ° mục mẹ." #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp -#, fuzzy msgid "Refresh files." -msgstr "Tìm kiếm tệp tin" +msgstr "Là m má»›i các tệp." #: editor/editor_file_dialog.cpp msgid "(Un)favorite current folder." msgstr "Bá» yêu thÃch thÆ° mục hiện tại." #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp -#, fuzzy msgid "Toggle the visibility of hidden files." -msgstr "Báºt tắt hiện các tệp tin ẩn." +msgstr "Hiện/ẩn các tệp ẩn." #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "View items as a grid of thumbnails." @@ -1984,10 +1959,12 @@ msgid "" "There are multiple importers for different types pointing to file %s, import " "aborted" msgstr "" +"Có nhiá»u trình nháºp cho nhiá»u loại khác nhau cùng chỉ đến tệp %s, đã ngừng " +"nháºp" #: editor/editor_file_system.cpp msgid "(Re)Importing Assets" -msgstr "" +msgstr "Nháºp lại tà i nguyên" #: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp msgid "Top" @@ -2007,28 +1984,24 @@ msgid "Inherited by:" msgstr "Äược thừa kế bởi:" #: editor/editor_help.cpp -#, fuzzy msgid "Description" -msgstr "Mô tả:" +msgstr "Mô tả" #: editor/editor_help.cpp -#, fuzzy msgid "Online Tutorials" -msgstr "HÆ°á»›ng dẫn trá»±c tuyến:" +msgstr "HÆ°á»›ng dẫn trá»±c tuyến" #: editor/editor_help.cpp msgid "Properties" msgstr "Thuá»™c tÃnh" #: editor/editor_help.cpp -#, fuzzy msgid "override:" -msgstr "Ghi đè" +msgstr "Ghi đè:" #: editor/editor_help.cpp -#, fuzzy msgid "default:" -msgstr "Mặc định" +msgstr "mặc định:" #: editor/editor_help.cpp msgid "Methods" @@ -2036,7 +2009,7 @@ msgstr "Hà m" #: editor/editor_help.cpp msgid "Theme Properties" -msgstr "" +msgstr "Cà i đặt Tông mà u" #: editor/editor_help.cpp msgid "Enumerations" @@ -2044,23 +2017,23 @@ msgstr "" #: editor/editor_help.cpp msgid "Constants" -msgstr "" +msgstr "Hằng số" #: editor/editor_help.cpp -#, fuzzy msgid "Property Descriptions" -msgstr "Mô tả ngắn gá»n:" +msgstr "Mô tả thuá»™c tÃnh" #: editor/editor_help.cpp -#, fuzzy msgid "(value)" -msgstr "Giá trị:" +msgstr "(giá trị)" #: editor/editor_help.cpp msgid "" "There is currently no description for this property. Please help us by " "[color=$color][url=$url]contributing one[/url][/color]!" msgstr "" +"Hiện thuá»™c tÃnh nà y chÆ°a được mô tả. Các bạn [color=$color][url=$url]đóng " +"góp[/url][/color] giúp chúng mình nha!" #: editor/editor_help.cpp msgid "Method Descriptions" @@ -2071,21 +2044,21 @@ msgid "" "There is currently no description for this method. Please help us by [color=" "$color][url=$url]contributing one[/url][/color]!" msgstr "" +"Hiện phÆ°Æ¡ng thức nà y chÆ°a được mô tả. Các bạn [color=$color][url=$url]đóng " +"góp[/url][/color] giúp chúng mình nha!" #: editor/editor_help_search.cpp editor/editor_node.cpp #: editor/plugins/script_editor_plugin.cpp msgid "Search Help" -msgstr "Tìm sá»± giúp đỡ" +msgstr "Tìm trợ giúp" #: editor/editor_help_search.cpp -#, fuzzy msgid "Case Sensitive" -msgstr "Äóng Cảnh" +msgstr "Phân biệt hoa thÆ°á»ng" #: editor/editor_help_search.cpp -#, fuzzy msgid "Show Hierarchy" -msgstr "Tìm kiếm" +msgstr "Hiện cấp báºc" #: editor/editor_help_search.cpp msgid "Display All" @@ -2093,27 +2066,28 @@ msgstr "Hiển thị tất cả" #: editor/editor_help_search.cpp msgid "Classes Only" -msgstr "Chỉ các Lá»›p" +msgstr "Chỉ tìm Lá»›p" #: editor/editor_help_search.cpp msgid "Methods Only" -msgstr "Chỉ các Hà m" +msgstr "Chỉ tìm Hà m" #: editor/editor_help_search.cpp msgid "Signals Only" -msgstr "Chỉ các TÃn hiệu" +msgstr "Chỉ tìm TÃn hiệu" #: editor/editor_help_search.cpp msgid "Constants Only" -msgstr "Chỉ các Äịnh nghÄ©a" +msgstr "Chỉ tìm Hằng số" #: editor/editor_help_search.cpp msgid "Properties Only" -msgstr "Chỉ các Thuá»™c tÃnh" +msgstr "Chỉ tìm Thuá»™c tÃnh" #: editor/editor_help_search.cpp +#, fuzzy msgid "Theme Properties Only" -msgstr "" +msgstr "Chỉ tìm thuá»™c tÃnh Tông mà u" #: editor/editor_help_search.cpp msgid "Member Type" @@ -2124,28 +2098,25 @@ msgid "Class" msgstr "Lá»›p" #: editor/editor_help_search.cpp -#, fuzzy msgid "Method" msgstr "Hà m" #: editor/editor_help_search.cpp editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Signal" msgstr "TÃn hiệu" #: editor/editor_help_search.cpp editor/plugins/theme_editor_plugin.cpp msgid "Constant" -msgstr "Cố định" +msgstr "Hằng số" #: editor/editor_help_search.cpp -#, fuzzy msgid "Property" -msgstr "Thuá»™c tÃnh:" +msgstr "Thuá»™c tÃnh" #: editor/editor_help_search.cpp #, fuzzy msgid "Theme Property" -msgstr "Thuá»™c tÃnh:" +msgstr "Thuá»™c tÃnh Tông mà u" #: editor/editor_inspector.cpp editor/project_settings_editor.cpp msgid "Property:" @@ -2193,16 +2164,15 @@ msgstr "Bắt đầu" #: editor/editor_network_profiler.cpp msgid "%s/s" -msgstr "" +msgstr "%s/s" #: editor/editor_network_profiler.cpp -#, fuzzy msgid "Down" -msgstr "Tải" +msgstr "Xuống" #: editor/editor_network_profiler.cpp msgid "Up" -msgstr "" +msgstr "Lên" #: editor/editor_network_profiler.cpp editor/editor_node.cpp msgid "Node" @@ -2210,23 +2180,23 @@ msgstr "Nút" #: editor/editor_network_profiler.cpp msgid "Incoming RPC" -msgstr "" +msgstr "RPC đến" #: editor/editor_network_profiler.cpp msgid "Incoming RSET" -msgstr "" +msgstr "RSET đến" #: editor/editor_network_profiler.cpp msgid "Outgoing RPC" -msgstr "" +msgstr "RPC Ä‘i" #: editor/editor_network_profiler.cpp msgid "Outgoing RSET" -msgstr "" +msgstr "RSET Ä‘i" #: editor/editor_node.cpp editor/project_manager.cpp msgid "New Window" -msgstr "" +msgstr "Cá»a sổ má»›i" #: editor/editor_node.cpp msgid "Imported resources can't be saved." @@ -2235,19 +2205,19 @@ msgstr "Tà i nguyên đã nháºp không thể lÆ°u." #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp #: scene/gui/dialogs.cpp msgid "OK" -msgstr "" +msgstr "OK" #: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Error saving resource!" -msgstr "" +msgstr "Lá»—i lÆ°u tà i nguyên!" #: editor/editor_node.cpp msgid "" "This resource can't be saved because it does not belong to the edited scene. " "Make it unique first." msgstr "" -"Tà i nguyên nà y không thể lÆ°u vì nó không thuá»™c cảnh đã chỉnh sá»a. Tạo nó là " -"duy nhất." +"Không thể lÆ°u tà i nguyên nà y vì nó không thuá»™c cảnh đã chỉnh sá»a. Là m nó Ä‘á»™c " +"nhất đã." #: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Save Resource As..." @@ -2275,11 +2245,11 @@ msgstr "Lá»—i khi Ä‘ang phân tÃch '%s'." #: editor/editor_node.cpp msgid "Unexpected end of file '%s'." -msgstr "" +msgstr "Tệp kết thúc bất ngá» '%s'." #: editor/editor_node.cpp msgid "Missing '%s' or its dependencies." -msgstr "" +msgstr "Thiếu '%s' hoặc các phần phụ thuá»™c." #: editor/editor_node.cpp msgid "Error while loading '%s'." @@ -2299,15 +2269,15 @@ msgstr "Tạo hình thu nhá»" #: editor/editor_node.cpp msgid "This operation can't be done without a tree root." -msgstr "Hoạt Ä‘á»™ng không thể hoà n tất khi không có nút gốc." +msgstr "Hà nh Ä‘á»™ng không thể hoà n thà nh mà không có nút gốc." #: editor/editor_node.cpp msgid "" "This scene can't be saved because there is a cyclic instancing inclusion.\n" "Please resolve it and then attempt to save again." msgstr "" -"Cảnh nà y không thể lÆ°u vì đây bao má»™t trÆ°á»ng hợp theo chu kỳ.\n" -"Giải quyết nó và cố gắng lÆ°u lại." +"Không thể lÆ°u cảnh nà y vì bạn Ä‘ang instancing chồng chéo nối vòng nhau.\n" +"Giải quyết vòng nối đã rồi hãy thá» lÆ°u lại sau." #: editor/editor_node.cpp msgid "" @@ -2323,15 +2293,15 @@ msgstr "Không thể ghi đè cảnh vẫn Ä‘ang mở!" #: editor/editor_node.cpp msgid "Can't load MeshLibrary for merging!" -msgstr "" +msgstr "Không thể nạp MeshLibrary để sáp nháºp!" #: editor/editor_node.cpp msgid "Error saving MeshLibrary!" -msgstr "" +msgstr "Lá»—i lÆ°u MeshLibrary!" #: editor/editor_node.cpp msgid "Can't load TileSet for merging!" -msgstr "" +msgstr "Không thể tải TileSet để sáp nháºp!" #: editor/editor_node.cpp msgid "Error saving TileSet!" @@ -2342,6 +2312,8 @@ msgid "" "An error occurred while trying to save the editor layout.\n" "Make sure the editor's user data path is writable." msgstr "" +"Có lá»—i khi Ä‘ang lÆ°u bố cục trình chỉnh sá»a.\n" +"Hãy thá» kiểm tra quyá»n ghi lên Ä‘Æ°á»ng dẫn dữ liệu của ngÆ°á»i dùng xem." #: editor/editor_node.cpp msgid "" @@ -2349,15 +2321,17 @@ msgid "" "To restore the Default layout to its base settings, use the Delete Layout " "option and delete the Default layout." msgstr "" +"Bố cục mặc định của trình chỉnh sá»a đã bị ghi đè.\n" +"Äể hồi lại bố cục mặc định vá» cà i đặt gốc, sá» dụng tùy chá»n \"Xóa bố cục\" " +"rồi xóa bố cục \"Mặc định\"." #: editor/editor_node.cpp msgid "Layout name not found!" -msgstr "Tên bố cục không tìm thấy!" +msgstr "Không tìm thấy tên bố cục!" #: editor/editor_node.cpp -#, fuzzy msgid "Restored the Default layout to its base settings." -msgstr "Äã khôi phục bố cục mặc định cho các thiết láºp." +msgstr "Äã khôi phục bố cục mặc định vá» thiết láºp gốc." #: editor/editor_node.cpp msgid "" @@ -2365,8 +2339,8 @@ msgid "" "Please read the documentation relevant to importing scenes to better " "understand this workflow." msgstr "" -"Tà i nguyên thuá»™c vá» cảnh đã nháºp, nó không thể chỉnh sá»a.\n" -"Äá»c tà i liệu liên quan để cách nháºp Cảnh để hiểu rõ quy trình việc nà y." +"Tà i nguyên thuá»™c vá» cảnh đã nháºp, nên không thể sá»a được.\n" +"Hãy Ä‘á»c hÆ°á»›ng dẫn vá» cách nháºp Cảnh để hiểu thêm vá» quy trình nà y." #: editor/editor_node.cpp msgid "" @@ -2381,8 +2355,8 @@ msgid "" "This resource was imported, so it's not editable. Change its settings in the " "import panel and then re-import." msgstr "" -"Tà i nguyên đã được nháºp và o, không thể chỉnh sá»a. Thay đổi cà i đặt của nó " -"trong bảng Nháºp và o, sau đó nháºp và o lại." +"Tà i nguyên nà y được nháºp, nên không thể chỉnh sá»a. Thay đổi cà i đặt của nó " +"trong bảng Nháºp, sau đó Nháºp lại." #: editor/editor_node.cpp msgid "" @@ -2391,10 +2365,9 @@ msgid "" "Please read the documentation relevant to importing scenes to better " "understand this workflow." msgstr "" -"Cảnh nà y đã được nháºp và o, những thay đổi sẽ không được giữ lại.\n" -"Tạo thá»±c thể nó hoặc kế thừa sẽ cho phép thá»±c hiện các thay đổi.\n" -"Äá»c tà i liệu tà i liệu liên quan đến nháºp Cảnh để hiểu rõ vá» quy trình việc " -"nà y." +"Do Cảnh nà y được nháºp, nên những thay đổi sẽ không được giữ lại.\n" +"Thá»±c hiện khởi tạo đối tượng hoặc kế thừa sẽ cho phép việc chỉnh sá»a.\n" +"Hãy Ä‘á»c hÆ°á»›ng dẫn liên quan đến nháºp Cảnh để hiểu thêm vá» quy trình nà y." #: editor/editor_node.cpp msgid "" @@ -2411,19 +2384,19 @@ msgstr "Không có cảnh được xác định để chạy." #: editor/editor_node.cpp msgid "Save scene before running..." -msgstr "" +msgstr "LÆ°u cảnh trÆ°á»›c khi chạy..." #: editor/editor_node.cpp msgid "Could not start subprocess!" -msgstr "Không thể bắt đầu quá trình nhá»!" +msgstr "Không thể bắt đầu quá trình phụ!" #: editor/editor_node.cpp editor/filesystem_dock.cpp msgid "Open Scene" -msgstr "Mở Scene" +msgstr "Mở Cảnh" #: editor/editor_node.cpp msgid "Open Base Scene" -msgstr "Mở Scene Mẫu" +msgstr "Mở Cảnh cÆ¡ sở" #: editor/editor_node.cpp msgid "Quick Open..." @@ -2431,11 +2404,11 @@ msgstr "Mở nhanh ..." #: editor/editor_node.cpp msgid "Quick Open Scene..." -msgstr "Mở Scene nhanh..." +msgstr "Mở Nhanh Cảnh..." #: editor/editor_node.cpp msgid "Quick Open Script..." -msgstr "Mở Script nhanh..." +msgstr "Mở Nhanh Tệp lệnh..." #: editor/editor_node.cpp msgid "Save & Close" @@ -2455,11 +2428,11 @@ msgstr "Yêu cầu má»™t nút gốc khi lÆ°u cảnh." #: editor/editor_node.cpp msgid "Save Scene As..." -msgstr "LÆ°u Scene vá»›i tên..." +msgstr "LÆ°u Cảnh thà nh..." #: editor/editor_node.cpp editor/scene_tree_dock.cpp msgid "This operation can't be done without a scene." -msgstr "Thao tác nà y phải có scene má»›i là m được." +msgstr "Thao tác nà y phải có Cảnh má»›i là m được." #: editor/editor_node.cpp msgid "Export Mesh Library" @@ -2479,26 +2452,27 @@ msgstr "Thao tác nà y phải có node được chá»n má»›i là m được." #: editor/editor_node.cpp msgid "Current scene not saved. Open anyway?" -msgstr "Scene hiện tại chÆ°a save. Kệ mở luôn?" +msgstr "Cảnh hiện tại chÆ°a lÆ°u. Kệ mở luôn?" #: editor/editor_node.cpp msgid "Can't reload a scene that was never saved." -msgstr "Không thể nạp má»™t cảnh mà chÆ°a lÆ°u bao giá»." +msgstr "Không thể nạp má»™t cảnh chÆ°a lÆ°u bao giá»." #: editor/editor_node.cpp -#, fuzzy msgid "Reload Saved Scene" -msgstr "LÆ°u Cảnh" +msgstr "Tải lại Cảnh đã lÆ°u" #: editor/editor_node.cpp msgid "" "The current scene has unsaved changes.\n" "Reload the saved scene anyway? This action cannot be undone." msgstr "" +"Cảnh hiện tại có thay đổi chÆ°a được lÆ°u.\n" +"Vẫn tải lại à ? Không hoà n tác được đâu." #: editor/editor_node.cpp msgid "Quick Run Scene..." -msgstr "Chạy Scene nhanh..." +msgstr "Chạy nhanh Cảnh..." #: editor/editor_node.cpp msgid "Quit" @@ -2545,9 +2519,8 @@ msgid "Close Scene" msgstr "Äóng Cảnh" #: editor/editor_node.cpp -#, fuzzy msgid "Reopen Closed Scene" -msgstr "Äóng Cảnh" +msgstr "Mở lại Cảnh đã đóng" #: editor/editor_node.cpp msgid "Unable to enable addon plugin at: '%s' parsing of config failed." @@ -2559,18 +2532,22 @@ msgstr "" #: editor/editor_node.cpp msgid "Unable to load addon script from path: '%s'." -msgstr "" +msgstr "Không thể nạp tệp lệnh bổ trợ từ Ä‘Æ°á»ng dẫn: '%s'." #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s' There seems to be an error in " "the code, please check the syntax." msgstr "" +"Không thể nạp tệp lệnh bổ trợ từ Ä‘Æ°á»ng dẫn: '%s' Có vẻ có lá»—i trong mã " +"nguồn, hãy kiểm tra lại cú pháp." #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s' Base type is not EditorPlugin." msgstr "" +"Không thể tải script addon từ Ä‘Æ°á»ng dẫn: '%s' Kiểu gốc không phải " +"EditorPlugin." #: editor/editor_node.cpp msgid "Unable to load addon script from path: '%s' Script is not in tool mode." @@ -2676,7 +2653,7 @@ msgstr "Chuyển Tab cảnh" #: editor/editor_node.cpp msgid "%d more files or folders" -msgstr "%d thêm các tệp hoặc thÆ° mục." +msgstr "%d tệp hoặc thÆ° mục nữa" #: editor/editor_node.cpp msgid "%d more folders" @@ -2692,11 +2669,11 @@ msgstr "Vị trà Dock" #: editor/editor_node.cpp msgid "Distraction Free Mode" -msgstr "" +msgstr "Chế Ä‘á»™ táºp trung" #: editor/editor_node.cpp msgid "Toggle distraction-free mode." -msgstr "" +msgstr "Báºt tắt chế Ä‘á»™ táºp trung." #: editor/editor_node.cpp msgid "Add a new scene." @@ -2753,7 +2730,7 @@ msgstr "LÆ°u Cảnh" #: editor/editor_node.cpp msgid "Save All Scenes" -msgstr "LÆ°u tất cả Cảnh" +msgstr "LÆ°u hết các Cảnh" #: editor/editor_node.cpp msgid "Convert To..." @@ -2761,11 +2738,11 @@ msgstr "Chuyển đổi ..." #: editor/editor_node.cpp msgid "MeshLibrary..." -msgstr "" +msgstr "MeshLibrary..." #: editor/editor_node.cpp msgid "TileSet..." -msgstr "" +msgstr "TileSet..." #: editor/editor_node.cpp editor/plugins/script_text_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp @@ -2788,7 +2765,7 @@ msgstr "Dá»± Ãn" #: editor/editor_node.cpp msgid "Project Settings..." -msgstr "Cà i đặt Dá»± Ãn" +msgstr "Cà i đặt Dá»± Ãn..." #: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp msgid "Version Control" @@ -2796,21 +2773,19 @@ msgstr "Theo dõi phiên bản" #: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp msgid "Set Up Version Control" -msgstr "" +msgstr "Cà i đặt trình Ä‘iá»u khiển phiên bản" #: editor/editor_node.cpp msgid "Shut Down Version Control" -msgstr "" +msgstr "Tắt trình Ä‘iá»u khiển phiên bản" #: editor/editor_node.cpp -#, fuzzy msgid "Export..." -msgstr "Xuất ra" +msgstr "Xuất..." #: editor/editor_node.cpp -#, fuzzy msgid "Install Android Build Template..." -msgstr "Cà i đặt mẫu xây dá»±ng Android" +msgstr "Cà i đặt mẫu xây dá»±ng Android..." #: editor/editor_node.cpp msgid "Open Project Data Folder" @@ -2870,13 +2845,15 @@ msgstr "" #: editor/editor_node.cpp msgid "Visible Collision Shapes" -msgstr "" +msgstr "Các khối va chạm thấy được" #: editor/editor_node.cpp msgid "" "When this option is enabled, collision shapes and raycast nodes (for 2D and " "3D) will be visible in the running project." msgstr "" +"Khi báºt tùy chá»n nà y, các khối va chạm và nút chiếu tia (2D và 3D) sẽ được " +"hiển thị trong dá»± án Ä‘ang chạy." #: editor/editor_node.cpp msgid "Visible Navigation" @@ -2887,10 +2864,12 @@ msgid "" "When this option is enabled, navigation meshes and polygons will be visible " "in the running project." msgstr "" +"Khi báºt tùy chá»n nà y, các lÆ°á»›i/Ä‘a giác Ä‘iá»u hÆ°á»›ng sẽ hiển thị trong dá»± án " +"Ä‘ang chạy." #: editor/editor_node.cpp msgid "Synchronize Scene Changes" -msgstr "" +msgstr "Äồng bá»™ hóa các thay đổi lên Cảnh" #: editor/editor_node.cpp msgid "" @@ -2902,7 +2881,7 @@ msgstr "" #: editor/editor_node.cpp msgid "Synchronize Script Changes" -msgstr "" +msgstr "Äồng bá»™ hóa thay đổi trong Tệp lệnh" #: editor/editor_node.cpp msgid "" @@ -2917,9 +2896,8 @@ msgid "Editor" msgstr "Editor (trình biên táºp)" #: editor/editor_node.cpp -#, fuzzy msgid "Editor Settings..." -msgstr "Cà i đặt Trình biên táºp" +msgstr "Cà i đặt Trình biên táºp..." #: editor/editor_node.cpp msgid "Editor Layout" @@ -2927,12 +2905,12 @@ msgstr "Cà i đặt Bố cục" #: editor/editor_node.cpp msgid "Take Screenshot" -msgstr "" +msgstr "Chụp mà n hình" #: editor/editor_node.cpp -#, fuzzy msgid "Screenshots are stored in the Editor Data/Settings Folder." -msgstr "Mở thÆ° mục dữ liệu Trình biên táºp" +msgstr "" +"Ảnh chụp mà n hình được lÆ°u ở thÆ° mục Dữ liệu/Cà i đặt của trình biên táºp." #: editor/editor_node.cpp msgid "Toggle Fullscreen" @@ -2949,16 +2927,15 @@ msgstr "Mở thÆ° mục dữ liệu Trình biên táºp" #: editor/editor_node.cpp msgid "Open Editor Data Folder" -msgstr "" +msgstr "Mở thÆ° mục dữ liệu Trình biên táºp" #: editor/editor_node.cpp msgid "Open Editor Settings Folder" -msgstr "" +msgstr "Mở thÆ° mục Thiết láºp Trình biên táºp" #: editor/editor_node.cpp -#, fuzzy msgid "Manage Editor Features..." -msgstr "Quản lý tÃnh năng Trình biên táºp" +msgstr "Quản lý tÃnh năng Trình biên táºp..." #: editor/editor_node.cpp msgid "Manage Export Templates..." @@ -2983,7 +2960,7 @@ msgstr "Báo lá»—i" #: editor/editor_node.cpp msgid "Send Docs Feedback" -msgstr "" +msgstr "Gá»i ý kiến phản hồi vá» hÆ°á»›ng dẫn" #: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp msgid "Community" @@ -3040,7 +3017,7 @@ msgstr "LÆ°u & Khởi Ä‘á»™ng lại" #: editor/editor_node.cpp msgid "Spins when the editor window redraws." -msgstr "" +msgstr "Xoay khi cá»a sổ trình biên soạn được vẽ lại." #: editor/editor_node.cpp msgid "Update Continuously" @@ -3052,11 +3029,11 @@ msgstr "Cáºp nháºt khi có thay đổi" #: editor/editor_node.cpp msgid "Hide Update Spinner" -msgstr "" +msgstr "Ẩn cái xoay xoay cáºp nháºt" #: editor/editor_node.cpp msgid "FileSystem" -msgstr "" +msgstr "Hệ thống tệp tin" #: editor/editor_node.cpp msgid "Inspector" @@ -3125,7 +3102,7 @@ msgstr "Xuất thÆ° viện ra" #: editor/editor_node.cpp msgid "Merge With Existing" -msgstr "" +msgstr "Hợp nhất vá»›i Hiện có" #: editor/editor_node.cpp msgid "Open & Run a Script" @@ -3171,7 +3148,7 @@ msgstr "Mở Trình biên táºp 3D" #: editor/editor_node.cpp msgid "Open Script Editor" -msgstr "Mở Trình biên táºp Mã lệnh" +msgstr "Mở Trình biên soạn Mã lệnh" #: editor/editor_node.cpp editor/project_manager.cpp msgid "Open Asset Library" @@ -3179,11 +3156,11 @@ msgstr "Mở ThÆ° viện Nguyên liệu" #: editor/editor_node.cpp msgid "Open the next Editor" -msgstr "" +msgstr "Mở Trình biên soạn tiếp theo" #: editor/editor_node.cpp msgid "Open the previous Editor" -msgstr "" +msgstr "Mở Trình biên soạn trÆ°á»›c đó" #: editor/editor_node.h msgid "Warning!" @@ -3191,15 +3168,15 @@ msgstr "Cảnh báo!" #: editor/editor_path.cpp msgid "No sub-resources found." -msgstr "" +msgstr "Không tìm thấy tà i nguyên phụ." #: editor/editor_plugin.cpp msgid "Creating Mesh Previews" -msgstr "" +msgstr "Tạo bản xem trÆ°á»›c lÆ°á»›i" #: editor/editor_plugin.cpp msgid "Thumbnail..." -msgstr "" +msgstr "Ảnh thu nhá»..." #: editor/editor_plugin_settings.cpp msgid "Main Script:" @@ -3207,11 +3184,11 @@ msgstr "Mã lệnh chÃnh:" #: editor/editor_plugin_settings.cpp msgid "Edit Plugin" -msgstr "" +msgstr "Chỉnh phần má»m bổ trợ" #: editor/editor_plugin_settings.cpp msgid "Installed Plugins:" -msgstr "" +msgstr "Các phần má»m bổ trợ đã cà i:" #: editor/editor_plugin_settings.cpp editor/plugin_config_dialog.cpp msgid "Update" @@ -3240,7 +3217,7 @@ msgstr "Äo đạc:" #: editor/editor_profiler.cpp msgid "Frame Time (sec)" -msgstr "" +msgstr "Thá»i gian khung hình (giây)" #: editor/editor_profiler.cpp msgid "Average Time (sec)" @@ -3248,15 +3225,15 @@ msgstr "Thá»i gian trung bình (giây)" #: editor/editor_profiler.cpp msgid "Frame %" -msgstr "" +msgstr "Khung hình %" #: editor/editor_profiler.cpp msgid "Physics Frame %" -msgstr "" +msgstr "Khung hình Váºt lý %" #: editor/editor_profiler.cpp msgid "Inclusive" -msgstr "" +msgstr "Bao gồm" #: editor/editor_profiler.cpp msgid "Self" @@ -3264,28 +3241,27 @@ msgstr "" #: editor/editor_profiler.cpp msgid "Frame #:" -msgstr "" +msgstr "Khung hình #:" #: editor/editor_profiler.cpp msgid "Time" -msgstr "" +msgstr "Thá»i gian" #: editor/editor_profiler.cpp msgid "Calls" msgstr "" #: editor/editor_properties.cpp -#, fuzzy msgid "Edit Text:" -msgstr "LÆ°u Theme" +msgstr "Sá»a văn bản:" #: editor/editor_properties.cpp editor/script_create_dialog.cpp msgid "On" -msgstr "" +msgstr "Báºt" #: editor/editor_properties.cpp msgid "Layer" -msgstr "" +msgstr "Lá»›p" #: editor/editor_properties.cpp msgid "Bit %d, value %d" @@ -3297,24 +3273,26 @@ msgstr "[Rá»—ng]" #: editor/editor_properties.cpp editor/plugins/root_motion_editor_plugin.cpp msgid "Assign..." -msgstr "" +msgstr "Gán..." #: editor/editor_properties.cpp -#, fuzzy msgid "Invalid RID" -msgstr "ÄÆ°á»ng dẫn sai." +msgstr "Số RID không hợp lệ" #: editor/editor_properties.cpp msgid "" "The selected resource (%s) does not match any type expected for this " "property (%s)." msgstr "" +"Kiểu của tà i nguyên đã chá»n (%s) không dùng được cho thuá»™c tÃnh nà y (%s)." #: editor/editor_properties.cpp msgid "" "Can't create a ViewportTexture on resources saved as a file.\n" "Resource needs to belong to a scene." msgstr "" +"Không thể tạo ViewportTexture trên các tà i nguyên được lÆ°u dÆ°á»›i dạng tệp.\n" +"Tà i nguyên phải thuá»™c vá» má»™t cảnh." #: editor/editor_properties.cpp msgid "" @@ -3326,7 +3304,7 @@ msgstr "" #: editor/editor_properties.cpp editor/property_editor.cpp msgid "Pick a Viewport" -msgstr "" +msgstr "Chá»n cổng xem" #: editor/editor_properties.cpp editor/property_editor.cpp msgid "New Script" @@ -3361,11 +3339,11 @@ msgstr "Dán" #: editor/editor_properties.cpp editor/property_editor.cpp msgid "Convert To %s" -msgstr "" +msgstr "Chuyển thà nh %s" #: editor/editor_properties.cpp editor/property_editor.cpp msgid "Selected node is not a Viewport!" -msgstr "" +msgstr "Nút được chá»n không phải Cổng xem!" #: editor/editor_properties_array_dict.cpp msgid "Size: " @@ -3405,27 +3383,27 @@ msgstr "Ghi logic của bạn trong hà m _run()." #: editor/editor_run_script.cpp msgid "There is an edited scene already." -msgstr "" +msgstr "Äã có má»™t cảnh được chỉnh sá»a." #: editor/editor_run_script.cpp msgid "Couldn't instance script:" -msgstr "" +msgstr "Không thể tạo tệp lệnh:" #: editor/editor_run_script.cpp msgid "Did you forget the 'tool' keyword?" -msgstr "" +msgstr "Bạn quên từ khóa 'tool' à ?" #: editor/editor_run_script.cpp msgid "Couldn't run script:" -msgstr "" +msgstr "Không thể chạy tệp lệnh:" #: editor/editor_run_script.cpp msgid "Did you forget the '_run' method?" -msgstr "" +msgstr "Bạn quên phÆ°Æ¡ng thức '_run' à ?" #: editor/editor_spin_slider.cpp msgid "Hold Ctrl to round to integers. Hold Shift for more precise changes." -msgstr "" +msgstr "Giữ Ctrl để là m tròn vá» số nguyên. Giữ Shift để sá»a tỉ mỉ hÆ¡n." #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" @@ -3474,8 +3452,9 @@ msgid "(Current)" msgstr "(Hiện tại)" #: editor/export_template_manager.cpp +#, fuzzy msgid "Retrieving mirrors, please wait..." -msgstr "" +msgstr "Äang tìm các trang mirror, đợi xÃu..." #: editor/export_template_manager.cpp msgid "Remove template version '%s'?" @@ -3503,21 +3482,24 @@ msgstr "TrÃch xuất các Mẫu xuất bản" #: editor/export_template_manager.cpp msgid "Importing:" -msgstr "" +msgstr "Äang Nháºp:" #: editor/export_template_manager.cpp msgid "Error getting the list of mirrors." -msgstr "" +msgstr "Có lá»—i khi lấy các trang mirror." #: editor/export_template_manager.cpp +#, fuzzy msgid "Error parsing JSON of mirror list. Please report this issue!" -msgstr "" +msgstr "Có lá»—i khi phân tÃch JSON của danh sách trang mirror. Hãy báo cáo lá»—i!" #: editor/export_template_manager.cpp msgid "" "No download links found for this version. Direct download is only available " "for official releases." msgstr "" +"Không tìm thấy liên kết để tải phiên bản nà y. Chỉ có thể tải trá»±c tiếp các " +"bản chÃnh thức." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp @@ -3565,13 +3547,12 @@ msgstr "" "Các lÆ°u trữ mẫu xuất bản có vấn Ä‘á» có thể được tìm thấy tại '%s'." #: editor/export_template_manager.cpp -#, fuzzy msgid "Error requesting URL:" -msgstr "Lá»—i khi yêu cầu Ä‘Æ°á»ng dẫn: " +msgstr "Lá»—i khi yêu cầu Ä‘Æ°á»ng dẫn:" #: editor/export_template_manager.cpp msgid "Connecting to Mirror..." -msgstr "" +msgstr "Äang kết nối tá»›i trang Mirror..." #: editor/export_template_manager.cpp msgid "Disconnected" @@ -3617,7 +3598,7 @@ msgstr "Lá»—i SSL Handshake" #: editor/export_template_manager.cpp msgid "Uncompressing Android Build Sources" -msgstr "" +msgstr "Giải nén nguồn xây dá»±ng Android" #: editor/export_template_manager.cpp msgid "Current Version:" @@ -3646,24 +3627,30 @@ msgstr "Các mẫu xuất bản Godot" #: editor/export_template_manager.cpp msgid "Export Template Manager" -msgstr "" +msgstr "Trình quản lý Mẫu Xuất" #: editor/export_template_manager.cpp msgid "Download Templates" msgstr "Tải Xuống Các Mẫu Xuất Bản" #: editor/export_template_manager.cpp +#, fuzzy msgid "Select mirror from list: (Shift+Click: Open in Browser)" -msgstr "" +msgstr "Chá»n trang mirror từ danh sách: (Shift+Nhấp: Mở trong trình duyệt)" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Favorites" -msgstr "Ưa thÃch:" +msgstr "Ưa thÃch" #: editor/filesystem_dock.cpp msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" +"Trạng thái: Nháºp tệp thất bại. Hãy sá»a tệp rồi nháºp lại theo cách thủ công." + +#: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" #: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." @@ -3710,6 +3697,11 @@ msgid "" "\n" "Do you wish to overwrite them?" msgstr "" +"Các tệp hoặc thÆ° mục sau xung Ä‘á»™t vá»›i các mục ở vị trà đÃch '%s':\n" +"\n" +"%s\n" +"\n" +"Bạn có muốn ghi đè không?" #: editor/filesystem_dock.cpp msgid "Renaming file:" @@ -3765,9 +3757,8 @@ msgid "Move To..." msgstr "Di chuyển đến..." #: editor/filesystem_dock.cpp -#, fuzzy msgid "New Scene..." -msgstr "Tạo Cảnh Má»›i" +msgstr "Tạo Cảnh Má»›i..." #: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp msgid "New Script..." @@ -3965,7 +3956,7 @@ msgstr "Các nút trong Nhóm" #: editor/groups_editor.cpp msgid "Empty groups will be automatically removed." -msgstr "" +msgstr "Các nhóm trống sẽ tá»± Ä‘á»™ng bị xóa." #: editor/groups_editor.cpp #, fuzzy @@ -4019,11 +4010,11 @@ msgstr "" #: editor/import/resource_importer_scene.cpp #: editor/plugins/mesh_library_editor_plugin.cpp msgid "Import Scene" -msgstr "" +msgstr "Nháºp cảnh" #: editor/import/resource_importer_scene.cpp msgid "Importing Scene..." -msgstr "" +msgstr "Äang nháºp cảnh ..." #: editor/import/resource_importer_scene.cpp msgid "Generating Lightmaps" @@ -4031,27 +4022,28 @@ msgstr "" #: editor/import/resource_importer_scene.cpp msgid "Generating for Mesh: " -msgstr "" +msgstr "Tạo cho lÆ°á»›i: " #: editor/import/resource_importer_scene.cpp msgid "Running Custom Script..." -msgstr "" +msgstr "Chạy Tệp lệnh Tá»± chá»n ..." #: editor/import/resource_importer_scene.cpp msgid "Couldn't load post-import script:" -msgstr "" +msgstr "Không thể tải tệp lệnh sau nháºp:" #: editor/import/resource_importer_scene.cpp msgid "Invalid/broken script for post-import (check console):" -msgstr "" +msgstr "Táºp lệnh sau nháºp không hợp lệ/há»ng (hãy xem bảng Ä‘iá»u khiển):" #: editor/import/resource_importer_scene.cpp msgid "Error running post-import script:" -msgstr "" +msgstr "Lá»—i khi chạy táºp lệnh sau nháºp:" #: editor/import/resource_importer_scene.cpp msgid "Did you return a Node-derived object in the `post_import()` method?" msgstr "" +"Bạn có trả vá» má»™t váºt kế thừa Nút trong phÆ°Æ¡ng thức 'post_import' không đấy?" #: editor/import/resource_importer_scene.cpp msgid "Saving..." @@ -4063,9 +4055,8 @@ msgid "Select Importer" msgstr "Chế Ä‘á»™ chá»n" #: editor/import_defaults_editor.cpp -#, fuzzy msgid "Importer:" -msgstr "Nháºp và o" +msgstr "Công cụ nháºp:" #: editor/import_defaults_editor.cpp #, fuzzy @@ -4073,9 +4064,12 @@ msgid "Reset to Defaults" msgstr "Nạp mặc định" #: editor/import_dock.cpp -#, fuzzy +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" -msgstr " Tệp tin" +msgstr "%d Tệp" #: editor/import_dock.cpp msgid "Set as Default for '%s'" @@ -4090,9 +4084,8 @@ msgid "Import As:" msgstr "Nháºp và o vá»›i:" #: editor/import_dock.cpp -#, fuzzy msgid "Preset" -msgstr "Cà i sẵn ..." +msgstr "Cà i sẵn" #: editor/import_dock.cpp msgid "Reimport" @@ -4105,16 +4098,18 @@ msgstr "LÆ°u các cảnh, nháºp và o lại và khởi Ä‘á»™ng lại" #: editor/import_dock.cpp msgid "Changing the type of an imported file requires editor restart." -msgstr "" +msgstr "Sá»a kiểu của tệp đã nháºp yêu cầu khởi Ä‘á»™ng lại trình biên soạn." #: editor/import_dock.cpp msgid "" "WARNING: Assets exist that use this resource, they may stop loading properly." msgstr "" +"CẢNH BÃO: Có tà i nguyên khác sá» dụng tà i nguyên nà y, chúng có thể gặp trục " +"trặc khi nạp đấy." #: editor/inspector_dock.cpp msgid "Failed to load resource." -msgstr "" +msgstr "Nạp tà i nguyên thất bại." #: editor/inspector_dock.cpp msgid "Expand All Properties" @@ -4147,7 +4142,7 @@ msgstr "" #: editor/inspector_dock.cpp msgid "Make Sub-Resources Unique" -msgstr "" +msgstr "Biến tà i nguyên phụ thà nh Ä‘á»™c nhất" #: editor/inspector_dock.cpp msgid "Open in Help" @@ -4155,11 +4150,11 @@ msgstr "Mở trong Trợ giúp" #: editor/inspector_dock.cpp msgid "Create a new resource in memory and edit it." -msgstr "" +msgstr "Tạo tà i nguyên má»›i trong bá»™ nhá»› rồi chỉnh sá»a." #: editor/inspector_dock.cpp msgid "Load an existing resource from disk and edit it." -msgstr "" +msgstr "Tải tà i nguyên có sẵn trong Ä‘Ä©a rồi chỉnh sá»a." #: editor/inspector_dock.cpp msgid "Save the currently edited resource." @@ -4167,15 +4162,15 @@ msgstr "LÆ°u tà i nguyên đã chỉnh sá»a hiện tại." #: editor/inspector_dock.cpp msgid "Go to the previous edited object in history." -msgstr "" +msgstr "Äi tá»›i đối tượng má»›i chỉnh sá»a trÆ°á»›c đó trong lịch sá»." #: editor/inspector_dock.cpp msgid "Go to the next edited object in history." -msgstr "" +msgstr "Äi đến đối tượng được chỉnh sá»a liá»n sau trong lịch sá»." #: editor/inspector_dock.cpp msgid "History of recently edited objects." -msgstr "" +msgstr "Lịch sá» các đối tượng được chỉnh sá»a gần đây." #: editor/inspector_dock.cpp msgid "Object properties." @@ -4199,7 +4194,7 @@ msgstr "Chá»n nút duy nhất để chỉnh sá»a tÃnh hiệu và nhóm của #: editor/plugin_config_dialog.cpp msgid "Edit a Plugin" -msgstr "" +msgstr "Chỉnh phần má»m bổ trợ" #: editor/plugin_config_dialog.cpp #, fuzzy @@ -4208,7 +4203,7 @@ msgstr "Tạo & Sá»a" #: editor/plugin_config_dialog.cpp msgid "Plugin Name:" -msgstr "" +msgstr "Tên phần má»m bổ trợ:" #: editor/plugin_config_dialog.cpp msgid "Subfolder:" @@ -4266,7 +4261,7 @@ msgstr "Sá»a Polygon (Gỡ Ä‘iểm)" #: editor/plugins/abstract_polygon_2d_editor.cpp msgid "Remove Polygon And Point" -msgstr "" +msgstr "Xóa Ä‘a giác và điểm" #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp @@ -4316,7 +4311,7 @@ msgstr "Thêm Ä‘iểm Hoạt ảnh" #: editor/plugins/animation_blend_space_1d_editor.cpp msgid "Remove BlendSpace1D Point" -msgstr "" +msgstr "Xóa Ä‘iểm BlendSpace1D" #: editor/plugins/animation_blend_space_1d_editor.cpp msgid "Move BlendSpace1D Node Point" @@ -4344,7 +4339,7 @@ msgstr "" #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp scene/gui/graph_edit.cpp msgid "Enable snap and show grid." -msgstr "KÃch hoạt Snap và hiện Grid." +msgstr "Báºt DÃnh và hiện lÆ°á»›i." #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp @@ -4355,7 +4350,7 @@ msgstr "Äiểm" #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_blend_tree_editor_plugin.cpp msgid "Open Editor" -msgstr "" +msgstr "Mở Trình biên soạn" #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp @@ -4384,7 +4379,7 @@ msgstr "Äổi Thá»i gian Chuyển Animation" #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Remove BlendSpace2D Point" -msgstr "" +msgstr "Xóa Ä‘iểm BlendSpace2D" #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -4406,11 +4401,11 @@ msgstr "Báºt tắt Ưa thÃch" #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create triangles by connecting points." -msgstr "" +msgstr "Nối các Ä‘iểm để tạo tam giác." #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Erase points and triangles." -msgstr "" +msgstr "Xóa tam giác và các Ä‘iểm." #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Generate blend triangles automatically (instead of manually)" @@ -4496,19 +4491,16 @@ msgstr "" "TrÃnh phát hoạt ảnh không có Ä‘Æ°á»ng dẫn nút Gốc, không thể truy xuất tên." #: editor/plugins/animation_blend_tree_editor_plugin.cpp -#, fuzzy msgid "Anim Clips" -msgstr "Âm thanh:" +msgstr "Các Ä‘oạn hoạt ảnh" #: editor/plugins/animation_blend_tree_editor_plugin.cpp -#, fuzzy msgid "Audio Clips" -msgstr "Âm thanh:" +msgstr "Các Ä‘oạn âm thanh" #: editor/plugins/animation_blend_tree_editor_plugin.cpp -#, fuzzy msgid "Functions" -msgstr "Hà m:" +msgstr "Hà m" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/animation_state_machine_editor.cpp @@ -4646,7 +4638,7 @@ msgstr "Chỉnh sá»a Chuyển tiếp ..." #: editor/plugins/animation_player_editor_plugin.cpp msgid "Open in Inspector" -msgstr "" +msgstr "Mở trong Trình kiểm tra" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Display list of animations in player." @@ -4741,9 +4733,8 @@ msgid "Move Node" msgstr "Di chuyển Nút" #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Transition exists!" -msgstr "Chuyển tiếp: " +msgstr "Chuyển tiếp đã tồn tại!" #: editor/plugins/animation_state_machine_editor.cpp msgid "Add Transition" @@ -5004,23 +4995,20 @@ msgid "Request failed, return code:" msgstr "Yêu cầu thất bại, trả lại code:" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Request failed." msgstr "Yêu cầu thất bại." #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Cannot save response to:" -msgstr "Không thể gỡ bá»:" +msgstr "Không thể lÆ°u phản hồi tá»›i:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Write error." -msgstr "" +msgstr "Ghi bị lá»—i." #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Request failed, too many redirects" -msgstr "Yêu cầu thất bại, gá»i lại quá nhiá»u" +msgstr "Yêu cầu thất bại, chuyển hÆ°á»›ng quá nhiá»u" #: editor/plugins/asset_library_editor_plugin.cpp #, fuzzy @@ -5028,14 +5016,12 @@ msgid "Redirect loop." msgstr "Chuyển hÆ°á»›ng vòng lặp." #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Request failed, timeout" -msgstr "Yêu cầu thất bại, trả lại code:" +msgstr "Yêu cầu thất bại, quá thá»i gian chá»" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Timeout." -msgstr "Thá»i gian:" +msgstr "Quá giá»." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Bad download hash, assuming file has been tampered with." @@ -5051,7 +5037,7 @@ msgstr "Nháºn được:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Failed SHA-256 hash check" -msgstr "" +msgstr "Kiểm tra băm SHA-256 thất bại" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Asset Download Error:" @@ -5078,9 +5064,8 @@ msgid "Idle" msgstr "Chạy không" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Install..." -msgstr "Cà i đặt" +msgstr "Cà i đặt..." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Retry" @@ -5096,29 +5081,27 @@ msgstr "Tải xuống nguyên liệu nà y đã được tiến hà nh!" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Recently Updated" -msgstr "" +msgstr "Cáºp nháºt gần đây" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Least Recently Updated" -msgstr "" +msgstr "Lâu chÆ°a cáºp nháºt nhất" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Name (A-Z)" -msgstr "" +msgstr "Tên (A-Z)" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Name (Z-A)" -msgstr "" +msgstr "Tên (Z-A)" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "License (A-Z)" -msgstr "Cấp phép" +msgstr "Giấy phép (A-Z)" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "License (Z-A)" -msgstr "Cấp phép" +msgstr "Giấy phép (Z-A)" #: editor/plugins/asset_library_editor_plugin.cpp msgid "First" @@ -5142,16 +5125,15 @@ msgstr "Tất cả" #: editor/plugins/asset_library_editor_plugin.cpp msgid "No results for \"%s\"." -msgstr "" +msgstr "Không tìm thấy kết quả cho \"%s\"." #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Import..." -msgstr "Nháºp và o" +msgstr "Nháºp..." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Plugins..." -msgstr "" +msgstr "Các phần má»m bổ trợ..." #: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp msgid "Sort:" @@ -5163,12 +5145,11 @@ msgstr "Danh mục:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Site:" -msgstr "" +msgstr "Trang:" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Support" -msgstr "Há»— trợ ..." +msgstr "Há»— trợ" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Official" @@ -5179,9 +5160,8 @@ msgid "Testing" msgstr "Kiểm tra" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Loading..." -msgstr "Nạp ..." +msgstr "Äang tải..." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Assets ZIP File" @@ -5225,7 +5205,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "Select lightmap bake file:" -msgstr "Chá»n file template" +msgstr "Chá»n tệp bake lightmap:" #: editor/plugins/camera_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -5234,24 +5214,23 @@ msgstr "Xem thá»" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Configure Snap" -msgstr "Cấu hình Snap" +msgstr "Cà i đặt DÃnh" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Grid Offset:" -msgstr "" +msgstr "Äá»™ lệch lÆ°á»›i:" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Grid Step:" -msgstr "" +msgstr "BÆ°á»›c lÆ°á»›i:" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Primary Line Every:" -msgstr "" +msgstr "ÄÆ°á»ng kẻ chÃnh Má»—i:" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "steps" -msgstr "2 bÆ°á»›c" +msgstr "bÆ°á»›c" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Rotation Offset:" @@ -5259,98 +5238,85 @@ msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Rotation Step:" -msgstr "" +msgstr "BÆ°á»›c xoay:" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Scale Step:" -msgstr "Tá»· lệ:" +msgstr "BÆ°á»›c thu phóng:" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Move Vertical Guide" -msgstr "" +msgstr "Di chuyển Ä‘Æ°á»ng căn dá»c" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Create Vertical Guide" -msgstr "Tạo Folder" +msgstr "Tạo Ä‘Æ°á»ng căn dá»c" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Remove Vertical Guide" -msgstr "Xoá Variable" +msgstr "Xoá Ä‘Æ°á»ng căn dá»c" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Move Horizontal Guide" -msgstr "" +msgstr "Di chuyển Ä‘Æ°á»ng căn ngang" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Create Horizontal Guide" -msgstr "Tạo Ä‘Æ°á»ng Guide ngang" +msgstr "Tạo Ä‘Æ°á»ng căn ngang" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Remove Horizontal Guide" -msgstr "Hủy key không đúng chuẩn" +msgstr "Xóa Ä‘Æ°á»ng căn ngang" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Create Horizontal and Vertical Guides" -msgstr "" +msgstr "Tạo Ä‘Æ°á»ng căn ngang và dá»c" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Set CanvasItem \"%s\" Pivot Offset to (%d, %d)" -msgstr "" +msgstr "Äặt Ä‘á»™ dá»i của CanvasItem \"%s\" tá»›i (%d, %d)" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Rotate %d CanvasItems" -msgstr "Xoay CanvasItem" +msgstr "Xoay %d CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Rotate CanvasItem \"%s\" to %d degrees" -msgstr "Xoay CanvasItem" +msgstr "Xoay CanvasItem \"%s\" thà nh %d Ä‘á»™" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Move CanvasItem \"%s\" Anchor" -msgstr "Di chuyển CanvasItem" +msgstr "Di chuyển neo CanvasItem \"%s\"" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Scale Node2D \"%s\" to (%s, %s)" -msgstr "" +msgstr "Thu phóng Node2D \"%s\" thà nh (%s, %s)" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Resize Control \"%s\" to (%d, %d)" -msgstr "" +msgstr "Chỉnh kÃch cỡ Nút Äiá»u khiển \"%s\" thà nh (%d, %d)" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Scale %d CanvasItems" -msgstr "Tỉ lệ CanvasItem" +msgstr "Thu phóng %d CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Scale CanvasItem \"%s\" to (%s, %s)" -msgstr "Tỉ lệ CanvasItem" +msgstr "Thu phóng CanvasItem \"%s\" thà nh (%s, %s)" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Move %d CanvasItems" -msgstr "Di chuyển CanvasItem" +msgstr "Di chuyển %d CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Move CanvasItem \"%s\" to (%d, %d)" -msgstr "Di chuyển CanvasItem" +msgstr "Di chuyển CanvasItem \"%s\" tá»›i (%d, %d)" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "" "Children of containers have their anchors and margins values overridden by " "their parent." -msgstr "" -"Mục con trong thùng chứa có giá trị neo và lá» của chúng được ghi đè bởi cha " -"chúng." +msgstr "Các nút Container sẽ ép các nút con theo neo và lá» mà nó xác định." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Presets for the anchors and margins values of a Control node." @@ -5361,28 +5327,28 @@ msgid "" "When active, moving Control nodes changes their anchors instead of their " "margins." msgstr "" -"Khi hoạt Ä‘á»™ng, các nút Control di chuyển thay đổi các neo thay vì lá» của " -"chúng." +"Khi báºt, di chuyển các nút Control sẽ thay đổi neo thay vì lá» của chúng." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Top Left" -msgstr "" +msgstr "Góc trên trái" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Top Right" -msgstr "" +msgstr "Góc trên phải" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Bottom Right" -msgstr "" +msgstr "Góc dÆ°á»›i phải" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Bottom Left" -msgstr "" +msgstr "Góc dÆ°á»›i trái" #: editor/plugins/canvas_item_editor_plugin.cpp +#, fuzzy msgid "Center Left" -msgstr "" +msgstr "Trung tâm Bên trái" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Center Top" @@ -5428,16 +5394,15 @@ msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Full Rect" -msgstr "" +msgstr "Rá»™ng hết cỡ" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Keep Ratio" -msgstr "Tỉ lệ Scale:" +msgstr "Giữ Tỉ lệ" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" -msgstr "Chỉ các neo" +msgstr "Chỉ neo" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Change Anchors and Margins" @@ -5486,9 +5451,8 @@ msgid "Paste Pose" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Clear Guides" -msgstr "Xoá khung xÆ°Æ¡ng" +msgstr "Xóa hết Ä‘Æ°á»ng căn" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Create Custom Bone(s) from Node(s)" @@ -5511,6 +5475,8 @@ msgid "" "Warning: Children of a container get their position and size determined only " "by their parent." msgstr "" +"Cảnh báo: Nút Container đã xác định kÃch cỡ và vị trà cho các nút con của nó " +"rồi." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/texture_region_editor_plugin.cpp @@ -5537,7 +5503,7 @@ msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Alt+RMB: Depth list selection" -msgstr "" +msgstr "Alt+chuá»™t phải: Chá»n theo tầng" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -5552,7 +5518,7 @@ msgstr "Chế Ä‘á»™ Xoay" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Scale Mode" -msgstr "Chế Ä‘á»™ Tỉ lệ" +msgstr "Chế Ä‘á»™ căn Tỉ lệ" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -5569,7 +5535,7 @@ msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Pan Mode" -msgstr "" +msgstr "Chế Ä‘á»™ Xoay" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy @@ -5578,95 +5544,92 @@ msgstr "Chế Ä‘á»™ Tỉ lệ" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Toggle smart snapping." -msgstr "" +msgstr "Báºt tắt DÃnh thông minh." #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Use Smart Snap" -msgstr "Sá» dụng Snap" +msgstr "Sá» dụng DÃnh thông minh" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Toggle grid snapping." -msgstr "" +msgstr "Báºt tắt DÃnh lÆ°á»›i." #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Use Grid Snap" -msgstr "Sá» dụng Snap" +msgstr "Sá» dụng DÃnh lÆ°á»›i" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snapping Options" -msgstr "" +msgstr "Tùy chá»n DÃnh" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Rotation Snap" -msgstr "" +msgstr "Dùng DÃnh ở chế Ä‘á»™ Xoay" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Use Scale Snap" -msgstr "Sá» dụng Snap" +msgstr "DÃnh theo bÆ°á»›c tỉ lệ" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap Relative" -msgstr "" +msgstr "DÃnh tÆ°Æ¡ng đối" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Pixel Snap" -msgstr "" +msgstr "DÃnh Ä‘iểm ảnh" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Smart Snapping" -msgstr "" +msgstr "DÃnh thông minh" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Configure Snap..." -msgstr "" +msgstr "Cà i đặt DÃnh..." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to Parent" -msgstr "" +msgstr "DÃnh vá» nút Mẹ" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to Node Anchor" -msgstr "Snap đến neo của Nút" +msgstr "DÃnh nút và o Ä‘iểm neo" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to Node Sides" -msgstr "Snap sang hai bên nút" +msgstr "DÃnh và o các cạnh của Nút" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to Node Center" -msgstr "Snap đến chÃnh giữa nút" +msgstr "DÃnh và o tâm Nút" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to Other Nodes" -msgstr "Snap đế các nút khác" +msgstr "DÃnh và o các Nút khác" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to Guides" -msgstr "" +msgstr "DÃnh và o ÄÆ°á»ng căn" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Lock the selected object in place (can't be moved)." -msgstr "" +msgstr "Khóa vị trà váºt (không cho dịch chuyển)." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Unlock the selected object (can be moved)." -msgstr "" +msgstr "Thôi khóa vị trà váºt (cho phép di chuyển)." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Makes sure the object's children are not selectable." -msgstr "" +msgstr "Hãy chắc rằng nút con của váºt ở trạng thái Không thể chá»n." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Restores the object's children's ability to be selected." -msgstr "" +msgstr "Khôi phục khả năng được chá»n nút con của váºt." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Skeleton Options" @@ -5674,7 +5637,7 @@ msgstr "Cà i đặt Khung xÆ°Æ¡ng" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Bones" -msgstr "" +msgstr "Hiển thị XÆ°Æ¡ng" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Make Custom Bone(s) from Node(s)" @@ -5696,7 +5659,7 @@ msgstr "Hiện lÆ°á»›i" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Helpers" -msgstr "" +msgstr "Hiển thị trợ giúp" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Rulers" @@ -5704,19 +5667,19 @@ msgstr "Hiện thÆ°á»›c" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Guides" -msgstr "" +msgstr "Hiện Ä‘Æ°á»ng căn" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Origin" -msgstr "" +msgstr "Hiện Gốc" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Viewport" -msgstr "" +msgstr "Hiện Cổng xem" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Group And Lock Icons" -msgstr "" +msgstr "Hiện biểu tượng Nhóm và Khóa" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Center Selection" @@ -5724,7 +5687,7 @@ msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Frame Selection" -msgstr "" +msgstr "Lá»±a chá»n khung hình" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Preview Canvas Scale" @@ -5745,7 +5708,7 @@ msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy msgid "Insert keys (based on mask)." -msgstr "Chèn Key Anim" +msgstr "Chèn Khóa (dá»±a trên mask)." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "" @@ -5771,7 +5734,7 @@ msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Copy Pose" -msgstr "" +msgstr "Sao chép TÆ° thế" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Clear Pose" @@ -5779,11 +5742,11 @@ msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Multiply grid step by 2" -msgstr "" +msgstr "Gấp đôi bÆ°á»›c lÆ°á»›i" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Divide grid step by 2" -msgstr "" +msgstr "Chia đôi bÆ°á»›c lÆ°á»›i" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Pan View" @@ -5809,7 +5772,7 @@ msgstr "Tạo Nút" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "Error instancing scene from %s" -msgstr "" +msgstr "Lá»—i khởi tạo cảnh từ %s" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Change Default Type" @@ -5837,7 +5800,7 @@ msgstr "Sá»a Poly (Xoá Ä‘iểm)" #: editor/plugins/collision_shape_2d_editor_plugin.cpp msgid "Set Handle" -msgstr "" +msgstr "Äặt tay nắm" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp @@ -5848,9 +5811,8 @@ msgstr "" #: editor/plugins/cpu_particles_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp -#, fuzzy msgid "Restart" -msgstr "Restart ngay" +msgstr "Khởi Ä‘á»™ng lại" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp @@ -5861,7 +5823,7 @@ msgstr "" #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp msgid "Particles" -msgstr "" +msgstr "Hạt" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp @@ -5876,12 +5838,12 @@ msgstr "" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Solid Pixels" -msgstr "" +msgstr "Äiểm ảnh rắn" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Border Pixels" -msgstr "" +msgstr "Äiểm ảnh viá»n" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp @@ -5922,12 +5884,13 @@ msgid "Flat 1" msgstr "" #: editor/plugins/curve_editor_plugin.cpp editor/property_editor.cpp +#, fuzzy msgid "Ease In" -msgstr "" +msgstr "TrÆ°á»n và o" #: editor/plugins/curve_editor_plugin.cpp editor/property_editor.cpp msgid "Ease Out" -msgstr "" +msgstr "TrÆ°á»n ra" #: editor/plugins/curve_editor_plugin.cpp msgid "Smoothstep" @@ -5935,11 +5898,11 @@ msgstr "" #: editor/plugins/curve_editor_plugin.cpp msgid "Modify Curve Point" -msgstr "" +msgstr "Sá»a Ä‘iểm uốn" #: editor/plugins/curve_editor_plugin.cpp msgid "Modify Curve Tangent" -msgstr "" +msgstr "Sá»a tiếp tuyến Ä‘iểm uốn" #: editor/plugins/curve_editor_plugin.cpp msgid "Load Curve Preset" @@ -5965,11 +5928,11 @@ msgstr "Tịnh tuyến" #: editor/plugins/curve_editor_plugin.cpp msgid "Load Preset" -msgstr "" +msgstr "Nạp cà i đặt trÆ°á»›c" #: editor/plugins/curve_editor_plugin.cpp msgid "Remove Curve Point" -msgstr "" +msgstr "Xóa Ä‘iểm uốn" #: editor/plugins/curve_editor_plugin.cpp msgid "Toggle Curve Linear Tangent" @@ -5977,7 +5940,7 @@ msgstr "" #: editor/plugins/curve_editor_plugin.cpp msgid "Hold Shift to edit tangents individually" -msgstr "" +msgstr "Giữ Shift để sá»a từng tiếp tuyến má»™t" #: editor/plugins/curve_editor_plugin.cpp #, fuzzy @@ -5994,11 +5957,11 @@ msgstr "" #: editor/plugins/item_list_editor_plugin.cpp msgid "Item %d" -msgstr "" +msgstr "Mục %d" #: editor/plugins/item_list_editor_plugin.cpp msgid "Items" -msgstr "" +msgstr "Mục" #: editor/plugins/item_list_editor_plugin.cpp msgid "Item List Editor" @@ -6010,7 +5973,7 @@ msgstr "" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh is empty!" -msgstr "" +msgstr "LÆ°á»›i trống!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Couldn't create a Trimesh collision shape." @@ -6022,7 +5985,7 @@ msgstr "" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "This doesn't work on scene root!" -msgstr "" +msgstr "Không thể áp dụng lên Cảnh gốc!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Trimesh Static Shape" @@ -6057,7 +6020,7 @@ msgstr "Tạo hình dạng lồi" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Navigation Mesh" -msgstr "" +msgstr "Tạo lÆ°á»›i Ä‘iá»u hÆ°á»›ng" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Contained Mesh is not of type ArrayMesh." @@ -6069,7 +6032,7 @@ msgstr "" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "No mesh to debug." -msgstr "" +msgstr "Không có lÆ°á»›i để gỡ lá»—i." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Model has no UV in this layer" @@ -6077,7 +6040,7 @@ msgstr "" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "MeshInstance lacks a Mesh!" -msgstr "" +msgstr "MeshInstance thiếu lÆ°á»›i!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh has not surface to create outlines from!" @@ -6089,15 +6052,15 @@ msgstr "" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Could not create outline!" -msgstr "" +msgstr "Không thể tạo Ä‘Æ°á»ng viá»n!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Outline" -msgstr "" +msgstr "Tạo Ä‘Æ°á»ng viá»n" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh" -msgstr "" +msgstr "LÆ°á»›i" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Trimesh Static Body" @@ -6109,6 +6072,8 @@ msgid "" "automatically.\n" "This is the most accurate (but slowest) option for collision detection." msgstr "" +"Tạo má»™t StaticBody rồi tá»± Ä‘á»™ng gắn má»™t khối va chạm hình Ä‘a giác.\n" +"Äây là tùy chá»n phát hiện va chạm chÃnh xác (nhÆ°ng cháºm) nhất." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Trimesh Collision Sibling" @@ -6119,6 +6084,8 @@ msgid "" "Creates a polygon-based collision shape.\n" "This is the most accurate (but slowest) option for collision detection." msgstr "" +"Tạo má»™t khối va chạm Ä‘a giác.\n" +"Äây là cách phát hiện va chạm chÃnh xác (nhÆ°ng cháºm) nhất." #: editor/plugins/mesh_instance_editor_plugin.cpp #, fuzzy @@ -6130,6 +6097,8 @@ msgid "" "Creates a single convex collision shape.\n" "This is the fastest (but least accurate) option for collision detection." msgstr "" +"Tạo má»™t khối va chạm lồi.\n" +"Äây là cách phát hiện va chạm nhanh (nhÆ°ng ẩu) nhất." #: editor/plugins/mesh_instance_editor_plugin.cpp #, fuzzy @@ -6141,10 +6110,12 @@ msgid "" "Creates a polygon-based collision shape.\n" "This is a performance middle-ground between the two above options." msgstr "" +"Tạo má»™t khối va chạm Ä‘a giác.\n" +"Äây là tùy chá»n có hiệu suất cân bằng so vá»›i hai tùy chá»n trên." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Outline Mesh..." -msgstr "" +msgstr "Tạo lÆ°á»›i viá»n..." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "" @@ -6168,11 +6139,11 @@ msgstr "" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Outline Mesh" -msgstr "" +msgstr "Tạo lÆ°á»›i viá»n" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Outline Size:" -msgstr "" +msgstr "KÃch cỡ viá»n:" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "UV Channel Debug" @@ -6180,13 +6151,15 @@ msgstr "" #: editor/plugins/mesh_library_editor_plugin.cpp msgid "Remove item %d?" -msgstr "" +msgstr "Xóa mục %d?" #: editor/plugins/mesh_library_editor_plugin.cpp msgid "" "Update from existing scene?:\n" "%s" msgstr "" +"Cáºp nháºt từ cảnh hiện có?:\n" +"%s" #: editor/plugins/mesh_library_editor_plugin.cpp #, fuzzy @@ -6196,19 +6169,19 @@ msgstr "Xuất Mesh Library" #: editor/plugins/mesh_library_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp msgid "Add Item" -msgstr "" +msgstr "Thêm mục" #: editor/plugins/mesh_library_editor_plugin.cpp msgid "Remove Selected Item" -msgstr "" +msgstr "Xóa mục đã chá»n" #: editor/plugins/mesh_library_editor_plugin.cpp msgid "Import from Scene" -msgstr "" +msgstr "Nháºp từ Cảnh" #: editor/plugins/mesh_library_editor_plugin.cpp msgid "Update from Scene" -msgstr "" +msgstr "Cáºp nháºt từ Cảnh" #: editor/plugins/multimesh_editor_plugin.cpp msgid "No mesh source specified (and no MultiMesh set in node)." @@ -6221,15 +6194,15 @@ msgstr "" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Mesh source is invalid (invalid path)." -msgstr "" +msgstr "Nguồn lÆ°á»›i không hợp lệ (Ä‘Æ°á»ng dẫn không hợp lệ)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Mesh source is invalid (not a MeshInstance)." -msgstr "" +msgstr "Nguồn lÆ°á»›i không hợp lệ (không phải MeshInstance)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Mesh source is invalid (contains no Mesh resource)." -msgstr "" +msgstr "Nguồn lÆ°á»›i không hợp lệ (không chứa tà i nguyên LÆ°á»›i)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "No surface source specified." @@ -6333,7 +6306,7 @@ msgstr "Xóa Animation" #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp msgid "Generation Time (sec):" -msgstr "" +msgstr "Thá»i gian tạo (giây):" #: editor/plugins/particles_editor_plugin.cpp msgid "The geometry's faces don't contain any area." @@ -6346,7 +6319,7 @@ msgstr "Cảnh không chứa tệp lệnh." #: editor/plugins/particles_editor_plugin.cpp msgid "\"%s\" doesn't inherit from Spatial." -msgstr "" +msgstr "\"%s\" không kế thừa từ Spatial." #: editor/plugins/particles_editor_plugin.cpp msgid "\"%s\" doesn't contain geometry." @@ -6394,7 +6367,7 @@ msgstr "" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Remove Point from Curve" -msgstr "" +msgstr "Xóa Ä‘iểm khá»i Ä‘Æ°á»ng cong" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Remove Out-Control from Curve" @@ -6407,7 +6380,7 @@ msgstr "" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp msgid "Add Point to Curve" -msgstr "" +msgstr "Thêm Äiểm và o ÄÆ°á»ng cong" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Split Curve" @@ -6415,7 +6388,7 @@ msgstr "Chia Ä‘Æ°á»ng Curve" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Move Point in Curve" -msgstr "" +msgstr "Di chuyển Äiểm trên ÄÆ°á»ng cong" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Move In-Control in Curve" @@ -6442,7 +6415,7 @@ msgstr "Nhấp: Tạo Point" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Left Click: Split Segment (in curve)" -msgstr "" +msgstr "Chuá»™t trái: Phân tách các Ä‘oạn (trong Ä‘Æ°á»ng cong)" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp @@ -6456,7 +6429,7 @@ msgstr "" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp msgid "Add Point (in empty space)" -msgstr "" +msgstr "Thêm Ä‘iểm (trong không gian trống)" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp @@ -6466,31 +6439,33 @@ msgstr "Xóa Point" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp msgid "Close Curve" -msgstr "" +msgstr "Äóng Ä‘Æ°á»ng cong" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp editor/plugins/theme_editor_plugin.cpp #: editor/plugins/visual_shader_editor_plugin.cpp editor/project_export.cpp msgid "Options" -msgstr "" +msgstr "Tùy chá»n" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp +#, fuzzy msgid "Mirror Handle Angles" -msgstr "" +msgstr "Äối xứng góc tay cầm" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp +#, fuzzy msgid "Mirror Handle Lengths" -msgstr "" +msgstr "Äối xứng Ä‘á»™ dà i tay cầm" #: editor/plugins/path_editor_plugin.cpp msgid "Curve Point #" -msgstr "" +msgstr "Äiểm uốn #" #: editor/plugins/path_editor_plugin.cpp msgid "Set Curve Point Position" -msgstr "" +msgstr "Äặt vị trà điểm uốn" #: editor/plugins/path_editor_plugin.cpp msgid "Set Curve In Position" @@ -6502,7 +6477,7 @@ msgstr "" #: editor/plugins/path_editor_plugin.cpp msgid "Split Path" -msgstr "" +msgstr "Tách Ä‘Æ°á»ng" #: editor/plugins/path_editor_plugin.cpp msgid "Remove Path Point" @@ -6518,12 +6493,11 @@ msgstr "" #: editor/plugins/path_editor_plugin.cpp msgid "Split Segment (in curve)" -msgstr "" +msgstr "Phân tách Ä‘oạn (trong Ä‘Æ°á»ng cong)" #: editor/plugins/physical_bone_plugin.cpp -#, fuzzy msgid "Move Joint" -msgstr "Di chuyển đến..." +msgstr "Di chuyển Khá»›p" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "" @@ -6532,7 +6506,7 @@ msgstr "Thuá»™c tÃnh xÆ°Æ¡ng của nút Polygon2D không trỠđến nút Skel #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Sync Bones" -msgstr "" +msgstr "Äồng bá»™ XÆ°Æ¡ng" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "" @@ -6564,7 +6538,7 @@ msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Invalid Polygon (need 3 different vertices)" -msgstr "" +msgstr "Äa giác không hợp lệ (cần 3 đỉnh khác nhau)" #: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy @@ -6602,9 +6576,8 @@ msgid "UV" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Points" -msgstr "Di chuyển đến..." +msgstr "Các Äiểm" #: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy @@ -6613,12 +6586,11 @@ msgstr "Tạo" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Bones" -msgstr "" +msgstr "XÆ°Æ¡ng" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Move Points" -msgstr "Di chuyển đến..." +msgstr "Di chuyển các Ä‘iểm" #: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy @@ -6627,31 +6599,31 @@ msgstr "Kéo: Xoay" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Shift: Move All" -msgstr "" +msgstr "Shift: Di chuyển tất" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Shift+Command: Scale" -msgstr "" +msgstr "Shift+Command: Thu phóng" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Ctrl: Rotate" -msgstr "" +msgstr "Ctrl: Xoay" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Shift+Ctrl: Scale" -msgstr "" +msgstr "Shift+Ctrl: Thu phóng" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Move Polygon" -msgstr "" +msgstr "Di chuyển Ä‘a g" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Rotate Polygon" -msgstr "" +msgstr "Xoay Ä‘a giác" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Scale Polygon" -msgstr "" +msgstr "Thu phóng Ä‘a giác" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create a custom polygon. Enables custom polygon rendering." @@ -6673,7 +6645,7 @@ msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Radius:" -msgstr "" +msgstr "Bán kÃnh:" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Copy Polygon to UV" @@ -6690,19 +6662,19 @@ msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Grid Settings" -msgstr "" +msgstr "Thiết láºp lÆ°á»›i" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Snap" -msgstr "" +msgstr "DÃnh" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Enable Snap" -msgstr "" +msgstr "Báºt DÃnh" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Grid" -msgstr "" +msgstr "LÆ°á»›i" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Show Grid" @@ -6710,44 +6682,44 @@ msgstr "Hiện lÆ°á»›i" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Configure Grid:" -msgstr "" +msgstr "Cà i đặt LÆ°á»›i:" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Grid Offset X:" -msgstr "" +msgstr "Äá»™ lệch X của LÆ°á»›i:" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Grid Offset Y:" -msgstr "" +msgstr "Äá»™ lệch Y của LÆ°á»›i:" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Grid Step X:" -msgstr "" +msgstr "BÆ°á»›c LÆ°á»›i trục X:" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Grid Step Y:" -msgstr "" +msgstr "BÆ°á»›c LÆ°á»›i trục Y:" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Sync Bones to Polygon" -msgstr "" +msgstr "Äồng bá»™ XÆ°Æ¡ng vá»›i Äa giác" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "ERROR: Couldn't load resource!" -msgstr "" +msgstr "Lá»–I: Không thể nạp tà i nguyên!" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "Add Resource" -msgstr "" +msgstr "Thêm tà i nguyên" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "Rename Resource" -msgstr "" +msgstr "Äổi tên tà i nguyên" #: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Delete Resource" -msgstr "" +msgstr "Xóa tà i nguyên" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "Resource clipboard is empty!" @@ -6755,7 +6727,7 @@ msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "Paste Resource" -msgstr "" +msgstr "Dán tà i nguyên" #: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/scene_tree_editor.cpp @@ -6767,16 +6739,16 @@ msgstr "" #: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Type:" -msgstr "" +msgstr "Kiểu:" #: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp msgid "Open in Editor" -msgstr "" +msgstr "Mở trong Trình biên soạn" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "Load Resource" -msgstr "" +msgstr "Nạp tà i nguyên" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "ResourcePreloader" @@ -6784,11 +6756,11 @@ msgstr "" #: editor/plugins/root_motion_editor_plugin.cpp msgid "AnimationTree has no path set to an AnimationPlayer" -msgstr "" +msgstr "AnimationTree chÆ°a đặt Ä‘Æ°á»ng dẫn đến AnimationPlayer nà o" #: editor/plugins/root_motion_editor_plugin.cpp msgid "Path to AnimationPlayer is invalid" -msgstr "" +msgstr "ÄÆ°á»ng dẫn tá»›i AnimationPlayer không hợp lệ" #: editor/plugins/script_editor_plugin.cpp msgid "Clear Recent Files" @@ -6796,11 +6768,11 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp msgid "Close and save changes?" -msgstr "" +msgstr "Äóng và lÆ°u thay đổi?" #: editor/plugins/script_editor_plugin.cpp msgid "Error writing TextFile:" -msgstr "" +msgstr "Lá»—i viết TextFile:" #: editor/plugins/script_editor_plugin.cpp #, fuzzy @@ -6808,29 +6780,24 @@ msgid "Could not load file at:" msgstr "Không viết được file:" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Error saving file!" -msgstr "Lá»—i tải font." +msgstr "Lá»—i lÆ°u tệp!" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Error while saving theme." -msgstr "Lá»—i khi lÆ°u scene." +msgstr "Lá»—i khi lÆ°u Tông mà u." #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Error Saving" -msgstr "Lá»—i di chuyển:" +msgstr "Lá»—i Khi LÆ°u" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Error importing theme." -msgstr "Lá»—i khi lÆ°u scene." +msgstr "Lá»—i khi nháºp Tông mà u." #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Error Importing" -msgstr "Lá»—i di chuyển:" +msgstr "Lá»—i Khi Nháºp" #: editor/plugins/script_editor_plugin.cpp #, fuzzy @@ -6849,7 +6816,7 @@ msgstr "LÆ°u Scene vá»›i tên..." #: editor/plugins/script_editor_plugin.cpp msgid "Can't obtain the script for running." -msgstr "" +msgstr "Không thể lấy tệp lệnh để chạy." #: editor/plugins/script_editor_plugin.cpp msgid "Script failed reloading, check console for errors." @@ -6866,33 +6833,33 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp msgid "Import Theme" -msgstr "" +msgstr "Nháºp Tông mà u" #: editor/plugins/script_editor_plugin.cpp msgid "Error while saving theme" -msgstr "" +msgstr "Lá»—i khi lÆ°u Tông mà u" #: editor/plugins/script_editor_plugin.cpp msgid "Error saving" -msgstr "" +msgstr "Lá»—i khi lÆ°u" #: editor/plugins/script_editor_plugin.cpp msgid "Save Theme As..." -msgstr "" +msgstr "LÆ°u Tông mà u thà nh..." #: editor/plugins/script_editor_plugin.cpp msgid "%s Class Reference" -msgstr "" +msgstr "Tham khảo Lá»›p %s" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp msgid "Find Next" -msgstr "Tìm tiếp theo" +msgstr "Tìm tiếp" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp msgid "Find Previous" -msgstr "" +msgstr "Tìm trÆ°á»›c đó" #: editor/plugins/script_editor_plugin.cpp #, fuzzy @@ -6901,7 +6868,7 @@ msgstr "Lá»c các thuá»™c tÃnh" #: editor/plugins/script_editor_plugin.cpp msgid "Toggle alphabetical sorting of the method list." -msgstr "" +msgstr "Báºt/tắt sắp xếp danh sách phÆ°Æ¡ng thức theo bảng chữ cái." #: editor/plugins/script_editor_plugin.cpp #, fuzzy @@ -6910,7 +6877,7 @@ msgstr "Lá»c các nút" #: editor/plugins/script_editor_plugin.cpp msgid "Sort" -msgstr "" +msgstr "Sắp xếp" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp @@ -6926,20 +6893,19 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp msgid "Next script" -msgstr "" +msgstr "Tệp lệnh tiếp theo" #: editor/plugins/script_editor_plugin.cpp msgid "Previous script" -msgstr "" +msgstr "Tệp lệnh trÆ°á»›c đó" #: editor/plugins/script_editor_plugin.cpp msgid "File" -msgstr "" +msgstr "Tệp" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Open..." -msgstr "Mở" +msgstr "Mở..." #: editor/plugins/script_editor_plugin.cpp #, fuzzy @@ -6948,7 +6914,7 @@ msgstr "Tạo Script" #: editor/plugins/script_editor_plugin.cpp msgid "Save All" -msgstr "" +msgstr "LÆ°u tất cả" #: editor/plugins/script_editor_plugin.cpp msgid "Soft Reload Script" @@ -6956,7 +6922,7 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp msgid "Copy Script Path" -msgstr "" +msgstr "Sao chép Ä‘Æ°á»ng dẫn tệp lệnh" #: editor/plugins/script_editor_plugin.cpp #, fuzzy @@ -6970,19 +6936,19 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp msgid "Theme" -msgstr "" +msgstr "Tông mà u" #: editor/plugins/script_editor_plugin.cpp msgid "Import Theme..." -msgstr "" +msgstr "Nháºp Tông mà u..." #: editor/plugins/script_editor_plugin.cpp msgid "Reload Theme" -msgstr "" +msgstr "Tải lại Tông mà u" #: editor/plugins/script_editor_plugin.cpp msgid "Save Theme" -msgstr "LÆ°u Theme" +msgstr "LÆ°u Tông mà u" #: editor/plugins/script_editor_plugin.cpp msgid "Close All" @@ -7031,11 +6997,11 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp msgid "Open Godot online documentation." -msgstr "" +msgstr "Mở tà i liệu Godot trá»±c tuyến." #: editor/plugins/script_editor_plugin.cpp msgid "Search the reference documentation." -msgstr "" +msgstr "Tìm tà i liệu tham khảo." #: editor/plugins/script_editor_plugin.cpp msgid "Go to previous edited document." @@ -7089,12 +7055,11 @@ msgstr "" #: editor/plugins/script_text_editor.cpp msgid "[Ignore]" -msgstr "" +msgstr "[Bá» qua]" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Line" -msgstr "Dòng:" +msgstr "Dòng" #: editor/plugins/script_text_editor.cpp #, fuzzy @@ -7120,15 +7085,15 @@ msgstr "Chá»n mà u" #: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp msgid "Convert Case" -msgstr "" +msgstr "Chuyển đổi Hoa thÆ°á»ng" #: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp msgid "Uppercase" -msgstr "" +msgstr "Chữ hoa" #: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp msgid "Lowercase" -msgstr "" +msgstr "Chữ thÆ°á»ng" #: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp msgid "Capitalize" @@ -7136,22 +7101,21 @@ msgstr "" #: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp msgid "Syntax Highlighter" -msgstr "" +msgstr "Nổi mà u cú pháp" #: editor/plugins/script_text_editor.cpp #: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp msgid "Bookmarks" -msgstr "" +msgstr "Dấu trang" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Breakpoints" -msgstr "Tạo các Ä‘iểm." +msgstr "Äiểm dừng" #: editor/plugins/script_text_editor.cpp #: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp msgid "Go To" -msgstr "" +msgstr "Äi tá»›i" #: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp @@ -7165,31 +7129,31 @@ msgstr "Chá»n Toà n Bá»™" #: editor/plugins/script_text_editor.cpp msgid "Delete Line" -msgstr "" +msgstr "Xóa dòng" #: editor/plugins/script_text_editor.cpp msgid "Indent Left" -msgstr "" +msgstr "Thụt lá» Trái" #: editor/plugins/script_text_editor.cpp msgid "Indent Right" -msgstr "" +msgstr "Thụt lá» phải" #: editor/plugins/script_text_editor.cpp msgid "Toggle Comment" -msgstr "" +msgstr "Báºt/tắt chú thÃch" #: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" -msgstr "" +msgstr "Cuá»™n/Trải dòng" #: editor/plugins/script_text_editor.cpp msgid "Fold All Lines" -msgstr "" +msgstr "Cuá»™n tất cả các dòng" #: editor/plugins/script_text_editor.cpp msgid "Unfold All Lines" -msgstr "" +msgstr "Trải tất cả các dòng" #: editor/plugins/script_text_editor.cpp msgid "Clone Down" @@ -7206,19 +7170,19 @@ msgstr "Chá»n Scale" #: editor/plugins/script_text_editor.cpp msgid "Trim Trailing Whitespace" -msgstr "" +msgstr "Xóa khoảng trắng cuối dòng" #: editor/plugins/script_text_editor.cpp msgid "Convert Indent to Spaces" -msgstr "" +msgstr "Chuyển thụt lá» thà nh Dấu cách" #: editor/plugins/script_text_editor.cpp msgid "Convert Indent to Tabs" -msgstr "" +msgstr "Chuyển thụt lá» thà nh Tab" #: editor/plugins/script_text_editor.cpp msgid "Auto Indent" -msgstr "" +msgstr "Thụt lá» Tá»± Ä‘á»™ng" #: editor/plugins/script_text_editor.cpp #, fuzzy @@ -7246,26 +7210,25 @@ msgstr "Äến Step trÆ°á»›c đó" #: editor/plugins/script_text_editor.cpp msgid "Remove All Bookmarks" -msgstr "" +msgstr "Xóa hết má»i dấu trang" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Go to Function..." -msgstr "Xoá Function" +msgstr "Äi tá»›i Hà m..." #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Go to Line..." -msgstr "Äến Dòng" +msgstr "Äến Dòng..." #: editor/plugins/script_text_editor.cpp #: modules/visual_script/visual_script_editor.cpp +#, fuzzy msgid "Toggle Breakpoint" -msgstr "" +msgstr "Tạo Ä‘iểm dừng" #: editor/plugins/script_text_editor.cpp msgid "Remove All Breakpoints" -msgstr "" +msgstr "Xóa hết má»i Ä‘iểm dừng" #: editor/plugins/script_text_editor.cpp #, fuzzy @@ -7302,19 +7265,19 @@ msgstr "" #: editor/plugins/skeleton_2d_editor_plugin.cpp msgid "Skeleton2D" -msgstr "" +msgstr "Skeleton2D" #: editor/plugins/skeleton_2d_editor_plugin.cpp msgid "Make Rest Pose (From Bones)" -msgstr "" +msgstr "Tạo tÆ° thế nghỉ (Từ XÆ°Æ¡ng)" #: editor/plugins/skeleton_2d_editor_plugin.cpp msgid "Set Bones to Rest Pose" -msgstr "" +msgstr "Äặt XÆ°Æ¡ng thà nh TÆ° thế Nghỉ" #: editor/plugins/skeleton_editor_plugin.cpp msgid "Create physical bones" -msgstr "" +msgstr "Tạo xÆ°Æ¡ng váºt lý" #: editor/plugins/skeleton_editor_plugin.cpp #, fuzzy @@ -7322,8 +7285,9 @@ msgid "Skeleton" msgstr "Xóa Point" #: editor/plugins/skeleton_editor_plugin.cpp +#, fuzzy msgid "Create physical skeleton" -msgstr "" +msgstr "Tạo bá»™ xÆ°Æ¡ng váºt lý" #: editor/plugins/skeleton_ik_editor_plugin.cpp msgid "Play IK" @@ -7386,9 +7350,8 @@ msgid "Yaw" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Size" -msgstr "KÃch thÆ°á»›c: " +msgstr "KÃch cỡ" #: editor/plugins/spatial_editor_plugin.cpp msgid "Objects Drawn" @@ -7468,7 +7431,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "No parent to instance a child at." -msgstr "" +msgstr "Không có nút mẹ để khởi tạo nút con." #: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "This operation requires a single selected node." @@ -7480,7 +7443,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Lock View Rotation" -msgstr "" +msgstr "Khóa xoay ở chế Ä‘á»™ xem" #: editor/plugins/spatial_editor_plugin.cpp msgid "Display Normal" @@ -7508,19 +7471,20 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "View Information" -msgstr "" +msgstr "Xem thông tin" #: editor/plugins/spatial_editor_plugin.cpp msgid "View FPS" -msgstr "" +msgstr "Xem tốc Ä‘á»™ khung hình" #: editor/plugins/spatial_editor_plugin.cpp msgid "Half Resolution" -msgstr "" +msgstr "Ná»a Ä‘á»™ phân giải" #: editor/plugins/spatial_editor_plugin.cpp +#, fuzzy msgid "Audio Listener" -msgstr "" +msgstr "Trình nghe âm thanh" #: editor/plugins/spatial_editor_plugin.cpp #, fuzzy @@ -7533,7 +7497,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Not available when using the GLES2 renderer." -msgstr "" +msgstr "Không khả dụng khi sá» dụng trình kết xuất GLES2." #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Left" @@ -7569,13 +7533,15 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "View Rotation Locked" -msgstr "" +msgstr "Äã khóa xoay ở chế Ä‘á»™ xem" #: editor/plugins/spatial_editor_plugin.cpp msgid "" "Note: The FPS value displayed is the editor's framerate.\n" "It cannot be used as a reliable indication of in-game performance." msgstr "" +"LÆ°u ý: Tốc Ä‘á»™ khung hình được hiển thị là của trình biên soạn.\n" +"Äừng lấy đó là m mốc để đánh giá hiệu suất." #: editor/plugins/spatial_editor_plugin.cpp msgid "XForm Dialog" @@ -7591,8 +7557,9 @@ msgid "" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp +#, fuzzy msgid "Snap Nodes To Floor" -msgstr "Snap các nút đến Floor" +msgstr "DÃnh Nút lên Sà n" #: editor/plugins/spatial_editor_plugin.cpp msgid "Couldn't find a solid floor to snap the selection to." @@ -7604,38 +7571,41 @@ msgid "" "Alt+Drag: Move\n" "Alt+RMB: Depth list selection" msgstr "" +"Kéo: Xoay\n" +"Alt+Kéo: Di chuyển\n" +"Alt+Chuá»™t phải: Chá»n theo tầng" #: editor/plugins/spatial_editor_plugin.cpp msgid "Use Local Space" -msgstr "" +msgstr "Sá» dụng Không gian Cục bá»™" #: editor/plugins/spatial_editor_plugin.cpp msgid "Use Snap" -msgstr "Sá» dụng Snap" +msgstr "Sá» dụng DÃnh" #: editor/plugins/spatial_editor_plugin.cpp msgid "Bottom View" -msgstr "" +msgstr "Góc nhìn đáy" #: editor/plugins/spatial_editor_plugin.cpp msgid "Top View" -msgstr "" +msgstr "Góc nhìn đỉnh" #: editor/plugins/spatial_editor_plugin.cpp msgid "Rear View" -msgstr "" +msgstr "Góc nhìn lÆ°ng" #: editor/plugins/spatial_editor_plugin.cpp msgid "Front View" -msgstr "" +msgstr "Góc nhìn trá»±c diện" #: editor/plugins/spatial_editor_plugin.cpp msgid "Left View" -msgstr "" +msgstr "Góc nhìn trái" #: editor/plugins/spatial_editor_plugin.cpp msgid "Right View" -msgstr "" +msgstr "Góc nhìn phải" #: editor/plugins/spatial_editor_plugin.cpp msgid "Switch Perspective/Orthogonal View" @@ -7643,7 +7613,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Insert Animation Key" -msgstr "" +msgstr "Chèn khóa Hoạt ảnh" #: editor/plugins/spatial_editor_plugin.cpp msgid "Focus Origin" @@ -7659,24 +7629,26 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp #: editor/plugins/visual_shader_editor_plugin.cpp +#, fuzzy msgid "Transform" -msgstr "" +msgstr "Biến đổi" #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Object to Floor" -msgstr "" +msgstr "DÃnh Váºt lên Sà n" #: editor/plugins/spatial_editor_plugin.cpp +#, fuzzy msgid "Transform Dialog..." -msgstr "" +msgstr "Há»™p thoại Biến đổi ..." #: editor/plugins/spatial_editor_plugin.cpp msgid "1 Viewport" -msgstr "" +msgstr "1 Cổng xem" #: editor/plugins/spatial_editor_plugin.cpp msgid "2 Viewports" -msgstr "" +msgstr "2 Cổng xem" #: editor/plugins/spatial_editor_plugin.cpp msgid "2 Viewports (Alt)" @@ -7684,7 +7656,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "3 Viewports" -msgstr "" +msgstr "3 Cổng xem" #: editor/plugins/spatial_editor_plugin.cpp msgid "3 Viewports (Alt)" @@ -7692,7 +7664,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "4 Viewports" -msgstr "" +msgstr "4 Cổng xem" #: editor/plugins/spatial_editor_plugin.cpp msgid "Gizmos" @@ -7704,7 +7676,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "View Grid" -msgstr "" +msgstr "Xem LÆ°á»›i" #: editor/plugins/spatial_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7714,7 +7686,7 @@ msgstr "Äang kết nối..." #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Settings" -msgstr "" +msgstr "Thiết láºp DÃnh" #: editor/plugins/spatial_editor_plugin.cpp msgid "Translate Snap:" @@ -7722,15 +7694,15 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotate Snap (deg.):" -msgstr "" +msgstr "DÃnh theo BÆ°á»›c xoay (Ä‘á»™):" #: editor/plugins/spatial_editor_plugin.cpp msgid "Scale Snap (%):" -msgstr "" +msgstr "Thu Phóng DÃnh (%):" #: editor/plugins/spatial_editor_plugin.cpp msgid "Viewport Settings" -msgstr "" +msgstr "Cà i đặt Cổng xem" #: editor/plugins/spatial_editor_plugin.cpp msgid "Perspective FOV (deg.):" @@ -7754,11 +7726,11 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotate (deg.):" -msgstr "" +msgstr "Xoay (theo Ä‘á»™):" #: editor/plugins/spatial_editor_plugin.cpp msgid "Scale (ratio):" -msgstr "" +msgstr "Thu phóng (theo tỉ lệ):" #: editor/plugins/spatial_editor_plugin.cpp msgid "Transform Type" @@ -7766,11 +7738,11 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Pre" -msgstr "" +msgstr "TrÆ°á»›c" #: editor/plugins/spatial_editor_plugin.cpp msgid "Post" -msgstr "" +msgstr "Sau" #: editor/plugins/spatial_editor_plugin.cpp msgid "Nameless gizmo" @@ -7793,7 +7765,7 @@ msgstr "Tạo" #: editor/plugins/sprite_editor_plugin.cpp msgid "Polygon2D Preview" -msgstr "" +msgstr "Xem trÆ°á»›c Polygon2D" #: editor/plugins/sprite_editor_plugin.cpp #, fuzzy @@ -7816,8 +7788,9 @@ msgid "LightOccluder2D Preview" msgstr "Tạo Folder" #: editor/plugins/sprite_editor_plugin.cpp +#, fuzzy msgid "Sprite is empty!" -msgstr "" +msgstr "Sprite trống!" #: editor/plugins/sprite_editor_plugin.cpp msgid "Can't convert a sprite using animation frames to mesh." @@ -7829,7 +7802,7 @@ msgstr "" #: editor/plugins/sprite_editor_plugin.cpp msgid "Convert to Mesh2D" -msgstr "" +msgstr "Chuyển thà nh Mesh2D" #: editor/plugins/sprite_editor_plugin.cpp msgid "Invalid geometry, can't create polygon." @@ -7863,11 +7836,11 @@ msgstr "" #: editor/plugins/sprite_editor_plugin.cpp msgid "Simplification: " -msgstr "" +msgstr "ÄÆ¡n giản hóa: " #: editor/plugins/sprite_editor_plugin.cpp msgid "Shrink (Pixels): " -msgstr "" +msgstr "Thu nhá» (Äiểm ảnh): " #: editor/plugins/sprite_editor_plugin.cpp msgid "Grow (Pixels): " @@ -7879,7 +7852,7 @@ msgstr "" #: editor/plugins/sprite_editor_plugin.cpp msgid "Settings:" -msgstr "" +msgstr "Cà i đặt:" #: editor/plugins/sprite_frames_editor_plugin.cpp #, fuzzy @@ -7888,15 +7861,15 @@ msgstr "Xoá lá»±a chá»n" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Add %d Frame(s)" -msgstr "" +msgstr "Thêm %d Khung hình" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Add Frame" -msgstr "" +msgstr "Thêm Khung hình" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Unable to load images" -msgstr "" +msgstr "Không tải được hình ảnh" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "ERROR: Couldn't load frame resource!" @@ -7912,15 +7885,15 @@ msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Add Empty" -msgstr "" +msgstr "Thêm Rá»—ng" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Change Animation FPS" -msgstr "" +msgstr "Thay đổi tốc Ä‘á»™ hoạt ảnh" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "(empty)" -msgstr "" +msgstr "(trống)" #: editor/plugins/sprite_frames_editor_plugin.cpp #, fuzzy @@ -7928,9 +7901,8 @@ msgid "Move Frame" msgstr "Di chuyển Nút" #: editor/plugins/sprite_frames_editor_plugin.cpp -#, fuzzy msgid "Animations:" -msgstr "Các Công cụ Animation" +msgstr "Các hoạt ảnh:" #: editor/plugins/sprite_frames_editor_plugin.cpp #, fuzzy @@ -7939,11 +7911,11 @@ msgstr "Tạo Animation má»›i" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed:" -msgstr "" +msgstr "Tốc Ä‘á»™:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Loop" -msgstr "" +msgstr "Lặp" #: editor/plugins/sprite_frames_editor_plugin.cpp #, fuzzy @@ -7961,19 +7933,19 @@ msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" -msgstr "" +msgstr "Chèn Rá»—ng (TrÆ°á»›c)" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (After)" -msgstr "" +msgstr "Chèn Rá»—ng (Sau)" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Move (Before)" -msgstr "" +msgstr "Di chuyển (TrÆ°á»›c)" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Move (After)" -msgstr "" +msgstr "Di chuyển (Sau)" #: editor/plugins/sprite_frames_editor_plugin.cpp #, fuzzy @@ -7982,15 +7954,15 @@ msgstr "Chá»n Points" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Horizontal:" -msgstr "" +msgstr "Ngang:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Vertical:" -msgstr "" +msgstr "Dá»c:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Select/Clear All Frames" -msgstr "" +msgstr "Chá»n/Xóa Tất cả Khung hình" #: editor/plugins/sprite_frames_editor_plugin.cpp #, fuzzy @@ -7999,7 +7971,7 @@ msgstr "Tạo từ Scene" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "SpriteFrames" -msgstr "" +msgstr "SpriteFrames" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Set Region Rect" @@ -8007,11 +7979,11 @@ msgstr "" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Set Margin" -msgstr "" +msgstr "Äặt Lá»" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Snap Mode:" -msgstr "" +msgstr "Chế Ä‘á»™ DÃnh:" #: editor/plugins/texture_region_editor_plugin.cpp #: scene/resources/visual_shader.cpp @@ -8020,11 +7992,11 @@ msgstr "Không có" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Pixel Snap" -msgstr "" +msgstr "DÃnh Äiểm ảnh" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Grid Snap" -msgstr "" +msgstr "DÃnh lÆ°á»›i" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Auto Slice" @@ -8036,7 +8008,7 @@ msgstr "" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Step:" -msgstr "" +msgstr "BÆ°á»›c:" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Sep.:" @@ -8044,7 +8016,7 @@ msgstr "" #: editor/plugins/texture_region_editor_plugin.cpp msgid "TextureRegion" -msgstr "" +msgstr "TextureRegion" #: editor/plugins/theme_editor_plugin.cpp msgid "Add All Items" @@ -8052,24 +8024,23 @@ msgstr "" #: editor/plugins/theme_editor_plugin.cpp msgid "Add All" -msgstr "" +msgstr "Thêm Tất cả" #: editor/plugins/theme_editor_plugin.cpp msgid "Remove All Items" -msgstr "" +msgstr "Xóa tất cả các mục" #: editor/plugins/theme_editor_plugin.cpp editor/project_manager.cpp msgid "Remove All" -msgstr "" +msgstr "Xoá tất cả" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Edit Theme" -msgstr "LÆ°u Theme" +msgstr "Chỉnh Tông mà u" #: editor/plugins/theme_editor_plugin.cpp msgid "Theme editing menu." -msgstr "" +msgstr "Menu chỉnh Tông mà u." #: editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" @@ -8081,7 +8052,7 @@ msgstr "" #: editor/plugins/theme_editor_plugin.cpp msgid "Create Empty Template" -msgstr "" +msgstr "Tạo Mẫu Trống" #: editor/plugins/theme_editor_plugin.cpp msgid "Create Empty Editor Template" @@ -8089,7 +8060,7 @@ msgstr "" #: editor/plugins/theme_editor_plugin.cpp msgid "Create From Current Editor Theme" -msgstr "" +msgstr "Tạo từ Tông mà u Trình biên soạn hiện tại" #: editor/plugins/theme_editor_plugin.cpp #, fuzzy @@ -8103,7 +8074,7 @@ msgstr "Tắt" #: editor/plugins/theme_editor_plugin.cpp msgid "Item" -msgstr "" +msgstr "Mục" #: editor/plugins/theme_editor_plugin.cpp #, fuzzy @@ -8112,11 +8083,11 @@ msgstr "Tắt" #: editor/plugins/theme_editor_plugin.cpp msgid "Check Item" -msgstr "" +msgstr "Äánh dấu mục" #: editor/plugins/theme_editor_plugin.cpp msgid "Checked Item" -msgstr "" +msgstr "Mục đã đánh dấu" #: editor/plugins/theme_editor_plugin.cpp msgid "Radio Item" @@ -8132,23 +8103,23 @@ msgstr "" #: editor/plugins/theme_editor_plugin.cpp msgid "Submenu" -msgstr "" +msgstr "Menu phụ" #: editor/plugins/theme_editor_plugin.cpp msgid "Subitem 1" -msgstr "" +msgstr "Mục phụ 1" #: editor/plugins/theme_editor_plugin.cpp msgid "Subitem 2" -msgstr "" +msgstr "Mục phụ 2" #: editor/plugins/theme_editor_plugin.cpp msgid "Has" -msgstr "" +msgstr "Có" #: editor/plugins/theme_editor_plugin.cpp msgid "Many" -msgstr "" +msgstr "Nhiá»u" #: editor/plugins/theme_editor_plugin.cpp #, fuzzy @@ -8174,7 +8145,7 @@ msgstr "Chỉnh Thá»i gian Chuyển Animation" #: editor/plugins/theme_editor_plugin.cpp msgid "Subtree" -msgstr "" +msgstr "Cây con" #: editor/plugins/theme_editor_plugin.cpp msgid "Has,Many,Options" @@ -8182,12 +8153,12 @@ msgstr "" #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" -msgstr "" +msgstr "Kiểu Dữ liệu:" #: editor/plugins/theme_editor_plugin.cpp #: editor/plugins/tile_set_editor_plugin.cpp msgid "Icon" -msgstr "" +msgstr "Biểu tượng" #: editor/plugins/theme_editor_plugin.cpp editor/rename_dialog.cpp msgid "Style" @@ -8199,20 +8170,19 @@ msgstr "" #: editor/plugins/theme_editor_plugin.cpp msgid "Color" -msgstr "" +msgstr "Mà u" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Theme File" -msgstr "Mở" +msgstr "Tệp Tông mà u" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Erase Selection" -msgstr "" +msgstr "Xóa Lá»±a chá»n" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Fix Invalid Tiles" -msgstr "" +msgstr "Sá»a các ô không hợp lệ" #: editor/plugins/tile_map_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp @@ -8222,11 +8192,11 @@ msgstr "Nhân đôi lá»±a chá»n" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Paint TileMap" -msgstr "" +msgstr "Tô TileMap" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Line Draw" -msgstr "" +msgstr "Vẽ Ä‘Æ°á»ng" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Rectangle Paint" @@ -8238,7 +8208,7 @@ msgstr "" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Erase TileMap" -msgstr "" +msgstr "Xóa TileMap" #: editor/plugins/tile_map_editor_plugin.cpp #, fuzzy @@ -8247,7 +8217,7 @@ msgstr "Tìm tiếp theo" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Transpose" -msgstr "" +msgstr "Chuyển vị" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Disable Autotile" @@ -8258,17 +8228,17 @@ msgid "Enable Priority" msgstr "" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Filter tiles" -msgstr "Lá»c tệp tin ..." +msgstr "Lá»c ô" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Give a TileSet resource to this TileMap to use its tiles." msgstr "" +"Hãy cung cấp tà i nguyên TileSet cho TileMap nà y để sá» dụng các ô của nó." #: editor/plugins/tile_map_editor_plugin.cpp msgid "Paint Tile" -msgstr "" +msgstr "Tô ô" #: editor/plugins/tile_map_editor_plugin.cpp msgid "" @@ -8284,23 +8254,23 @@ msgstr "" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Pick Tile" -msgstr "" +msgstr "Chá»n ô" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Rotate Left" -msgstr "" +msgstr "Xoay Trái" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Rotate Right" -msgstr "" +msgstr "Xoay Phải" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Flip Horizontally" -msgstr "" +msgstr "Láºt Ngang" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Flip Vertically" -msgstr "" +msgstr "Láºt Dá»c" #: editor/plugins/tile_map_editor_plugin.cpp #, fuzzy @@ -8308,14 +8278,12 @@ msgid "Clear Transform" msgstr "Äổi Transform Animation" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Add Texture(s) to TileSet." -msgstr "Chèn Texture(s) và o TileSet" +msgstr "Thêm Há»a tiết và o TileSet." #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Remove selected Texture from TileSet." -msgstr "Xóa Texture hiện tại từ TileSet" +msgstr "Xóa Há»a tiết hiện tại khá»i TileSet." #: editor/plugins/tile_set_editor_plugin.cpp msgid "Create from Scene" @@ -8341,7 +8309,7 @@ msgstr "Má»›i %s" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Next Coordinate" -msgstr "" +msgstr "Tá»a Ä‘á»™ tiếp theo" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Select the next shape, subtile, or Tile." @@ -8372,7 +8340,7 @@ msgstr "Tạo" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Navigation" -msgstr "" +msgstr "Äiá»u hÆ°á»›ng" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Bitmask" @@ -8402,7 +8370,7 @@ msgstr "Tạo" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Navigation Mode" -msgstr "Chế Ä‘á»™ Navigation" +msgstr "Chế Ä‘á»™ di chuyển" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Bitmask Mode" @@ -8426,9 +8394,8 @@ msgid "Copy bitmask." msgstr "" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Paste bitmask." -msgstr "Dán Animation" +msgstr "Dán bitmask." #: editor/plugins/tile_set_editor_plugin.cpp msgid "Erase bitmask." @@ -8444,9 +8411,8 @@ msgid "New Rectangle" msgstr "Tạo Cảnh Má»›i" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Create a new polygon." -msgstr "Tạo" +msgstr "Tạo Ä‘a giác má»›i." #: editor/plugins/tile_set_editor_plugin.cpp #, fuzzy @@ -8464,11 +8430,11 @@ msgstr "" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Enable snap and show grid (configurable via the Inspector)." -msgstr "" +msgstr "Báºt DÃnh và hiện lÆ°á»›i (có thể cà i đặt thông qua Trình kiểm tra)." #: editor/plugins/tile_set_editor_plugin.cpp msgid "Display Tile Names (Hold Alt Key)" -msgstr "" +msgstr "Hiển thị tên ô (Giữ phÃm Alt)" #: editor/plugins/tile_set_editor_plugin.cpp msgid "" @@ -8476,21 +8442,20 @@ msgid "" msgstr "" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Remove selected texture? This will remove all tiles which use it." -msgstr "Xóa Texture hiện tại từ TileSet" +msgstr "Xóa Há»a tiết đã chá»n? Các ô dùng há»a tiết nà y cÅ©ng bốc hÆ¡i luôn đó." #: editor/plugins/tile_set_editor_plugin.cpp msgid "You haven't selected a texture to remove." -msgstr "" +msgstr "Bạn chÆ°a chá»n há»a tiết để xóa." #: editor/plugins/tile_set_editor_plugin.cpp msgid "Create from scene? This will overwrite all current tiles." -msgstr "" +msgstr "Tạo từ Cảnh? Việc nà y sẽ ghi đè lên tất cả các ô hiện tại." #: editor/plugins/tile_set_editor_plugin.cpp msgid "Merge from scene?" -msgstr "" +msgstr "Hợp nhất từ cảnh?" #: editor/plugins/tile_set_editor_plugin.cpp #, fuzzy @@ -8499,7 +8464,7 @@ msgstr "Xóa Template" #: editor/plugins/tile_set_editor_plugin.cpp msgid "%s file(s) were not added because was already on the list." -msgstr "" +msgstr "%s tệp không được thêm và o vì đã có trong danh sách." #: editor/plugins/tile_set_editor_plugin.cpp msgid "" @@ -8519,9 +8484,8 @@ msgid "" msgstr "" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Delete polygon." -msgstr "Tạo" +msgstr "Xóa Ä‘a giác." #: editor/plugins/tile_set_editor_plugin.cpp msgid "" @@ -8594,7 +8558,7 @@ msgstr "" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Make Polygon Concave" -msgstr "" +msgstr "Biến thà nh Ä‘a giác lõm" #: editor/plugins/tile_set_editor_plugin.cpp #, fuzzy @@ -8608,7 +8572,7 @@ msgstr "Xóa Template" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Remove Collision Polygon" -msgstr "" +msgstr "Xóa khối va chạm Ä‘a giác" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Remove Occlusion Polygon" @@ -8621,11 +8585,11 @@ msgstr "Xóa Animation" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Edit Tile Priority" -msgstr "" +msgstr "Chỉnh Ä‘á»™ Æ°u tiên của ô" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Edit Tile Z Index" -msgstr "" +msgstr "Sá»a chiá»u sâu (Z) của ô" #: editor/plugins/tile_set_editor_plugin.cpp #, fuzzy @@ -8649,7 +8613,7 @@ msgstr "Tạo" #: editor/plugins/tile_set_editor_plugin.cpp msgid "This property can't be changed." -msgstr "" +msgstr "Không thể thay đổi thuá»™c tÃnh nà y." #: editor/plugins/tile_set_editor_plugin.cpp #, fuzzy @@ -8658,11 +8622,11 @@ msgstr "Xuất Tile Set" #: editor/plugins/version_control_editor_plugin.cpp msgid "No VCS addons are available." -msgstr "" +msgstr "Không có phần má»m kiểm soát phiên bản khả dụng." #: editor/plugins/version_control_editor_plugin.cpp msgid "Error" -msgstr "" +msgstr "Lá»—i" #: editor/plugins/version_control_editor_plugin.cpp msgid "No files added to stage" @@ -8679,11 +8643,11 @@ msgstr "" #: editor/plugins/version_control_editor_plugin.cpp msgid "Version Control System" -msgstr "" +msgstr "Phần má»m kiểm soát phiên bản" #: editor/plugins/version_control_editor_plugin.cpp msgid "Initialize" -msgstr "" +msgstr "Khởi tạo" #: editor/plugins/version_control_editor_plugin.cpp msgid "Staging area" @@ -8735,7 +8699,7 @@ msgstr "Äổi" #: editor/plugins/version_control_editor_plugin.cpp #: modules/gdnative/gdnative_library_singleton_editor.cpp msgid "Status" -msgstr "" +msgstr "Trạng thái" #: editor/plugins/version_control_editor_plugin.cpp msgid "View file diffs before committing them to the latest version" @@ -8751,7 +8715,7 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "(GLES3 only)" -msgstr "" +msgstr "(Chỉ dà nh cho GLES3)" #: editor/plugins/visual_shader_editor_plugin.cpp #, fuzzy @@ -8759,17 +8723,16 @@ msgid "Add Output" msgstr "Thêm Input" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Scalar" -msgstr "Tá»· lệ:" +msgstr "Tá»· lệ" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Vector" -msgstr "" +msgstr "Vector" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Boolean" -msgstr "" +msgstr "Boolean" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Sampler" @@ -8782,7 +8745,7 @@ msgstr "Thêm Input" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Add output port" -msgstr "" +msgstr "Thêm cổng đầu ra" #: editor/plugins/visual_shader_editor_plugin.cpp #, fuzzy @@ -8796,11 +8759,11 @@ msgstr "Äổi dạng mặc định" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Change input port name" -msgstr "" +msgstr "Äổi tên cổng đầu và o" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Change output port name" -msgstr "" +msgstr "Äổi tên cổng đầu ra" #: editor/plugins/visual_shader_editor_plugin.cpp #, fuzzy @@ -8827,7 +8790,7 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Set Input Default Port" -msgstr "" +msgstr "Äặt cổng đầu và o mặc định" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Add Node to Visual Shader" @@ -8862,11 +8825,11 @@ msgstr "Äối số đã thay đổi" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Vertex" -msgstr "" +msgstr "Äỉnh" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Fragment" -msgstr "" +msgstr "Mảnh" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Light" @@ -8896,16 +8859,15 @@ msgstr "Tạo Function" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Converts HSV vector to RGB equivalent." -msgstr "" +msgstr "Chuyển đổi vector HSV sang RGB tÆ°Æ¡ng Ä‘Æ°Æ¡ng." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Converts RGB vector to HSV equivalent." -msgstr "" +msgstr "Chuyển đổi vector RGB sang HSV tÆ°Æ¡ng Ä‘Æ°Æ¡ng." #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Sepia function." -msgstr "Äổi tên Hà m" +msgstr "Hà m Sepia." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Burn operator." @@ -8956,19 +8918,19 @@ msgstr "Äổi Transform Animation" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the boolean result of the %s comparison between two parameters." -msgstr "" +msgstr "Trả vá» kết quả boolean của phép so sánh %s giữa hai tham số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Equal (==)" -msgstr "" +msgstr "Bằng (==)" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Greater Than (>)" -msgstr "" +msgstr "Lá»›n hÆ¡n (>)" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Greater Than or Equal (>=)" -msgstr "" +msgstr "Lá»›n hÆ¡n hoặc Bằng (>=)" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" @@ -8981,24 +8943,28 @@ msgid "" "Returns the boolean result of the comparison between INF and a scalar " "parameter." msgstr "" +"Trả vá» kết quả boolean của phép so sánh giữa Vô cùng (INF) và má»™t tham số vô " +"hÆ°á»›ng." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" "Returns the boolean result of the comparison between NaN and a scalar " "parameter." msgstr "" +"Trả vá» kết quả boolean so sánh giữa NaN (Không phải số) và má»™t tham số vô " +"hÆ°á»›ng." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Less Than (<)" -msgstr "" +msgstr "Nhá» hÆ¡n (<)" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Less Than or Equal (<=)" -msgstr "" +msgstr "Nhá» hÆ¡n hoặc Bằng (<=)" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Not Equal (!=)" -msgstr "" +msgstr "Không bằng (!=)" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" @@ -9012,17 +8978,19 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the boolean result of the comparison between two parameters." -msgstr "" +msgstr "Trả vá» kết quả boolean so sánh giữa hai tham số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" "Returns the boolean result of the comparison between INF (or NaN) and a " "scalar parameter." msgstr "" +"Trả vá» kết quả boolean của phép so sánh giữa INF (hoặc NaN) và má»™t tham số " +"vô hÆ°á»›ng." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Boolean constant." -msgstr "" +msgstr "Hằng số Boolean." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Boolean uniform." @@ -9034,7 +9002,7 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Input parameter." -msgstr "" +msgstr "Tham số đầu và o." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "'%s' input parameter for vertex and fragment shader modes." @@ -9071,43 +9039,43 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "E constant (2.718282). Represents the base of the natural logarithm." -msgstr "" +msgstr "Hằng số E (2,718282). CÆ¡ số của logarit tá»± nhiên." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Epsilon constant (0.00001). Smallest possible scalar number." -msgstr "" +msgstr "Hằng số Epsilon (0,00001). Số vô hÆ°á»›ng nhá» nhất có thể." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Phi constant (1.618034). Golden ratio." -msgstr "" +msgstr "Hằng số Phi (1.618034). Tá»· lệ và ng." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Pi/4 constant (0.785398) or 45 degrees." -msgstr "" +msgstr "Hằng số Pi/4 (0,785398) hay còn là 45 Ä‘á»™." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Pi/2 constant (1.570796) or 90 degrees." -msgstr "" +msgstr "Hằng số Pi/2 (1.570796) hay còn là 90 Ä‘á»™." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Pi constant (3.141593) or 180 degrees." -msgstr "" +msgstr "Hằng số Pi (3,141593) hay còn là 180 Ä‘á»™." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Tau constant (6.283185) or 360 degrees." -msgstr "" +msgstr "Hằng số Tau (6,283185) hay còn là 360 Ä‘á»™." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Sqrt2 constant (1.414214). Square root of 2." -msgstr "" +msgstr "Hằng số Sqrt2 (1,414214). Căn báºc hai của 2." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the absolute value of the parameter." -msgstr "" +msgstr "Trả vá» giá trị tuyệt đối của tham số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the arc-cosine of the parameter." -msgstr "" +msgstr "Trả vá» arc-cosine của tham số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the inverse hyperbolic cosine of the parameter." @@ -9115,7 +9083,7 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the arc-sine of the parameter." -msgstr "" +msgstr "Trả vá» arc-sin của tham số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the inverse hyperbolic sine of the parameter." @@ -9123,11 +9091,11 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the arc-tangent of the parameter." -msgstr "" +msgstr "Trả vá» arc-tan của tham số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the arc-tangent of the parameters." -msgstr "" +msgstr "Trả vá» arc-tan của các tham số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the inverse hyperbolic tangent of the parameter." @@ -9136,7 +9104,7 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" "Finds the nearest integer that is greater than or equal to the parameter." -msgstr "" +msgstr "Tìm số nguyên gần nhất lá»›n hÆ¡n hoặc bằng tham số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Constrains a value to lie between two further values." @@ -9144,7 +9112,7 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the cosine of the parameter." -msgstr "" +msgstr "Trả vá» cosine của tham số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the hyperbolic cosine of the parameter." @@ -9152,23 +9120,23 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Converts a quantity in radians to degrees." -msgstr "" +msgstr "Äổi radian vá» Ä‘á»™." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Base-e Exponential." -msgstr "" +msgstr "LÅ©y thừa cÆ¡ số e." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Base-2 Exponential." -msgstr "" +msgstr "LÅ©y thừa cÆ¡ số 2." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Finds the nearest integer less than or equal to the parameter." -msgstr "" +msgstr "Tìm số nguyên gần nhất nhá» hÆ¡n hoặc bằng tham số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Computes the fractional part of the argument." -msgstr "" +msgstr "TÃnh phần phân số của tham số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the inverse of the square root of the parameter." @@ -9176,19 +9144,19 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Natural logarithm." -msgstr "" +msgstr "Logarit tá»± nhiên." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Base-2 logarithm." -msgstr "" +msgstr "Logarit cÆ¡ số 2." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the greater of two values." -msgstr "" +msgstr "Trả vá» giá trị lá»›n hÆ¡n trong hai giá trị." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the lesser of two values." -msgstr "" +msgstr "Trả vá» giá trị nhá» hÆ¡n trong hai giá trị." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Linear interpolation between two scalars." @@ -9196,7 +9164,7 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the opposite value of the parameter." -msgstr "" +msgstr "Trả vá» giá trị đối của tham số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "1.0 - scalar" @@ -9205,11 +9173,11 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" "Returns the value of the first parameter raised to the power of the second." -msgstr "" +msgstr "Trả vá» lÅ©y thừa cÆ¡ số tham số đầu tiên có số mÅ© tham số thứ hai." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Converts a quantity in degrees to radians." -msgstr "" +msgstr "Äổi từ Ä‘á»™ vá» radian." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "1.0 / scalar" @@ -9217,23 +9185,23 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Finds the nearest integer to the parameter." -msgstr "" +msgstr "Tìm số nguyên gần tham số nhất." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Finds the nearest even integer to the parameter." -msgstr "" +msgstr "Tìm số nguyên chẵn gần tham số nhất." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Clamps the value between 0.0 and 1.0." -msgstr "" +msgstr "Kẹp giá trị trong khoảng từ 0.0 đến 1.0." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Extracts the sign of the parameter." -msgstr "" +msgstr "Lấy tÃnh âm/dÆ°Æ¡ng của tham số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the sine of the parameter." -msgstr "" +msgstr "Trả vá» sin của tham số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the hyperbolic sine of the parameter." @@ -9241,7 +9209,7 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the square root of the parameter." -msgstr "" +msgstr "Trả vá» căn báºc hai của tham số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" @@ -9261,7 +9229,7 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the tangent of the parameter." -msgstr "" +msgstr "Trả vá» tan của tham số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the hyperbolic tangent of the parameter." @@ -9273,15 +9241,15 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Adds scalar to scalar." -msgstr "" +msgstr "Cá»™ng hai số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Divides scalar by scalar." -msgstr "" +msgstr "Chia hai số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Multiplies scalar by scalar." -msgstr "" +msgstr "Nhân hai số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the remainder of the two scalars." @@ -9289,11 +9257,11 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Subtracts scalar from scalar." -msgstr "" +msgstr "Trừ hai số." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Scalar constant." -msgstr "" +msgstr "Hằng số vô hÆ°á»›ng." #: editor/plugins/visual_shader_editor_plugin.cpp #, fuzzy @@ -9323,7 +9291,7 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp #, fuzzy msgid "Transform function." -msgstr "Tạo" +msgstr "Hà m biến hóa." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" @@ -9375,9 +9343,8 @@ msgid "Transform uniform." msgstr "Tạo" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Vector function." -msgstr "Xoá Function" +msgstr "Hà m Vector." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Vector operator." @@ -9744,9 +9711,8 @@ msgid "Export All" msgstr "Xuất Tile Set" #: editor/project_export.cpp editor/project_manager.cpp -#, fuzzy msgid "ZIP File" -msgstr " Tệp tin" +msgstr "Tệp ZIP" #: editor/project_export.cpp msgid "Godot Game Pack" @@ -10051,11 +10017,8 @@ msgid "Projects" msgstr "Dá»± án" #: editor/project_manager.cpp -#, fuzzy msgid "Loading, please wait..." -msgstr "" -"Äang quét các tệp tin,\n" -"Chá» má»™t chút ..." +msgstr "Äang tải, đợi xÃu..." #: editor/project_manager.cpp msgid "Last Modified" @@ -10131,9 +10094,8 @@ msgid "" msgstr "" #: editor/project_settings_editor.cpp -#, fuzzy msgid "An action with the name '%s' already exists." -msgstr "Lá»–I: Tên animation trùng lặp!" +msgstr "Hà nh Ä‘á»™ng vá»›i tên '%s' đã tồn tại." #: editor/project_settings_editor.cpp msgid "Rename Input Action Event" @@ -10451,15 +10413,15 @@ msgstr "" #: editor/property_editor.cpp msgid "File..." -msgstr "" +msgstr "Tệp tin..." #: editor/property_editor.cpp msgid "Dir..." -msgstr "" +msgstr "ThÆ° mục..." #: editor/property_editor.cpp msgid "Assign" -msgstr "" +msgstr "Gán" #: editor/property_editor.cpp msgid "Select Node" @@ -10467,7 +10429,7 @@ msgstr "Chá»n nút" #: editor/property_editor.cpp msgid "Error loading file: Not a resource!" -msgstr "" +msgstr "Lá»—i tải tệp: Không phải tà i nguyên!" #: editor/property_editor.cpp msgid "Pick a Node" @@ -10475,11 +10437,11 @@ msgstr "Lấy má»™t nút" #: editor/property_editor.cpp msgid "Bit %d, val %d." -msgstr "" +msgstr "Bit %d, giá trị %d." #: editor/property_selector.cpp msgid "Select Property" -msgstr "" +msgstr "Chá»n Thuá»™c tÃnh" #: editor/property_selector.cpp msgid "Select Virtual Method" @@ -10487,7 +10449,7 @@ msgstr "" #: editor/property_selector.cpp msgid "Select Method" -msgstr "" +msgstr "Chá»n PhÆ°Æ¡ng thức" #: editor/rename_dialog.cpp editor/scene_tree_dock.cpp #, fuzzy @@ -10495,30 +10457,28 @@ msgid "Batch Rename" msgstr "Äổi tên" #: editor/rename_dialog.cpp -#, fuzzy msgid "Replace:" -msgstr "Thay thế: " +msgstr "Thay thế:" #: editor/rename_dialog.cpp msgid "Prefix:" -msgstr "" +msgstr "Tiá»n tố:" #: editor/rename_dialog.cpp msgid "Suffix:" -msgstr "" +msgstr "Háºu tố:" #: editor/rename_dialog.cpp -#, fuzzy msgid "Use Regular Expressions" -msgstr "Phiên bản hiện tại:" +msgstr "Dùng Regular Expression" #: editor/rename_dialog.cpp msgid "Advanced Options" -msgstr "" +msgstr "Tùy chá»n Nâng cao" #: editor/rename_dialog.cpp msgid "Substitute" -msgstr "" +msgstr "Thay thế" #: editor/rename_dialog.cpp msgid "Node name" @@ -10534,7 +10494,7 @@ msgstr "Loại nút" #: editor/rename_dialog.cpp msgid "Current scene name" -msgstr "" +msgstr "Tên Cảnh hiện tại" #: editor/rename_dialog.cpp msgid "Root node name" @@ -10551,18 +10511,16 @@ msgid "Per-level Counter" msgstr "" #: editor/rename_dialog.cpp -#, fuzzy msgid "If set, the counter restarts for each group of child nodes." -msgstr "Nếu đặt bá»™ đếm khởi Ä‘á»™ng lại cho từng nhóm nút con" +msgstr "Nếu được đặt, bá»™ đếm sẽ khởi Ä‘á»™ng lại vá»›i từng nhóm nút con." #: editor/rename_dialog.cpp msgid "Initial value for the counter" -msgstr "" +msgstr "Giá trị đếm ban đầu" #: editor/rename_dialog.cpp -#, fuzzy msgid "Step" -msgstr "BÆ°á»›c (s):" +msgstr "BÆ°á»›c" #: editor/rename_dialog.cpp msgid "Amount by which counter is incremented for each node" @@ -10570,21 +10528,23 @@ msgstr "Giá trị mà bá»™ đếm tăng lên cho má»—i nút" #: editor/rename_dialog.cpp msgid "Padding" -msgstr "" +msgstr "Äệm" #: editor/rename_dialog.cpp msgid "" "Minimum number of digits for the counter.\n" "Missing digits are padded with leading zeros." msgstr "" +"Số chữ số tối thiểu cho bá»™ đếm.\n" +"Äệm thêm 0 ở đầu nếu thiếu chữ số." #: editor/rename_dialog.cpp msgid "Post-Process" -msgstr "" +msgstr "Háºu xá» lý" #: editor/rename_dialog.cpp msgid "Keep" -msgstr "" +msgstr "Giữ" #: editor/rename_dialog.cpp msgid "PascalCase to snake_case" @@ -10600,11 +10560,11 @@ msgstr "" #: editor/rename_dialog.cpp msgid "To Lowercase" -msgstr "" +msgstr "Hoa thà nh ThÆ°á»ng" #: editor/rename_dialog.cpp msgid "To Uppercase" -msgstr "" +msgstr "ThÆ°á»ng thà nh Hoa" #: editor/rename_dialog.cpp #, fuzzy @@ -10617,9 +10577,8 @@ msgid "Regular Expression Error:" msgstr "Phiên bản hiện tại:" #: editor/rename_dialog.cpp -#, fuzzy msgid "At character %s" -msgstr "Ký tá»± hợp lệ:" +msgstr "Tại kà tá»± %s" #: editor/reparent_dialog.cpp editor/scene_tree_dock.cpp msgid "Reparent Node" @@ -10643,19 +10602,19 @@ msgstr "" #: editor/run_settings_dialog.cpp msgid "Current Scene" -msgstr "" +msgstr "Cảnh Hiện tại" #: editor/run_settings_dialog.cpp msgid "Main Scene" -msgstr "" +msgstr "Cảnh chÃnh" #: editor/run_settings_dialog.cpp msgid "Main Scene Arguments:" -msgstr "" +msgstr "Tham số Cảnh chÃnh:" #: editor/run_settings_dialog.cpp msgid "Scene Run Settings" -msgstr "" +msgstr "Cà i đặt chạy Cảnh" #: editor/scene_tree_dock.cpp msgid "No parent to instance the scenes at." @@ -10663,7 +10622,7 @@ msgstr "" #: editor/scene_tree_dock.cpp msgid "Error loading scene from %s" -msgstr "" +msgstr "Lá»—i tải cảnh từ %s" #: editor/scene_tree_dock.cpp msgid "" @@ -10675,7 +10634,7 @@ msgstr "" #: editor/scene_tree_dock.cpp msgid "Instance Scene(s)" -msgstr "" +msgstr "Khởi tạo Cảnh" #: editor/scene_tree_dock.cpp msgid "Replace with Branch Scene" @@ -10683,12 +10642,11 @@ msgstr "" #: editor/scene_tree_dock.cpp msgid "Instance Child Scene" -msgstr "" +msgstr "Khởi tạo Cảnh con" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Can't paste root node into the same scene." -msgstr "Không thể hoạt Ä‘á»™ng trên các nút từ ngoại cảnh!" +msgstr "Không thể dán Nút Gốc và o cùng má»™t Cảnh." #: editor/scene_tree_dock.cpp #, fuzzy @@ -10702,7 +10660,7 @@ msgstr "ÄÃnh kèm Script" #: editor/scene_tree_dock.cpp msgid "This operation can't be done on the tree root." -msgstr "" +msgstr "Thao tác nà y không thể áp dụng lên gốc của cây." #: editor/scene_tree_dock.cpp msgid "Move Node In Parent" @@ -10728,7 +10686,7 @@ msgstr "Nút phải thuá»™c cảnh đã chỉnh sá»a để trở thà nh gốc." #: editor/scene_tree_dock.cpp msgid "Instantiated scenes can't become root" -msgstr "" +msgstr "Cảnh khởi tạo không thể thà nh gốc" #: editor/scene_tree_dock.cpp msgid "Make node as Root" @@ -10761,11 +10719,11 @@ msgstr "Không thể thá»±c hiện vá»›i nút gốc." #: editor/scene_tree_dock.cpp msgid "This operation can't be done on instanced scenes." -msgstr "" +msgstr "Không thể thá»±c hiện thao tác nà y trên Cảnh được khởi tạo." #: editor/scene_tree_dock.cpp msgid "Save New Scene As..." -msgstr "" +msgstr "LÆ°u Cảnh Má»›i Thà nh..." #: editor/scene_tree_dock.cpp msgid "" @@ -10797,11 +10755,11 @@ msgstr "Tạo Nút Gốc:" #: editor/scene_tree_dock.cpp msgid "2D Scene" -msgstr "2D Scene" +msgstr "Cảnh 2D" #: editor/scene_tree_dock.cpp msgid "3D Scene" -msgstr "3D Scene" +msgstr "Cảnh 3D" #: editor/scene_tree_dock.cpp msgid "User Interface" @@ -10841,6 +10799,7 @@ msgid "" "Couldn't save new scene. Likely dependencies (instances) couldn't be " "satisfied." msgstr "" +"Không thể lÆ°u cảnh má»›i. Có vẻ là do không thá»a mãn được các phần phụ thuá»™c." #: editor/scene_tree_dock.cpp msgid "Error saving scene." @@ -10848,19 +10807,19 @@ msgstr "Lá»—i khi lÆ°u scene." #: editor/scene_tree_dock.cpp msgid "Error duplicating scene to save it." -msgstr "" +msgstr "Lá»—i khi nhân bản cảnh để lÆ°u." #: editor/scene_tree_dock.cpp msgid "Sub-Resources" -msgstr "" +msgstr "Tà i nguyên phụ" #: editor/scene_tree_dock.cpp msgid "Clear Inheritance" -msgstr "" +msgstr "Xóa Kế thừa" #: editor/scene_tree_dock.cpp msgid "Editable Children" -msgstr "" +msgstr "Các nút Con có thể sá»a" #: editor/scene_tree_dock.cpp msgid "Load As Placeholder" @@ -10868,7 +10827,7 @@ msgstr "" #: editor/scene_tree_dock.cpp msgid "Open Documentation" -msgstr "" +msgstr "Mở HÆ°á»›ng dẫn" #: editor/scene_tree_dock.cpp msgid "" @@ -10888,7 +10847,7 @@ msgstr "Thu gá»n Tất cả" #: editor/scene_tree_dock.cpp msgid "Change Type" -msgstr "" +msgstr "Äổi Kiểu" #: editor/scene_tree_dock.cpp msgid "Reparent to New Node" @@ -10896,15 +10855,15 @@ msgstr "Reparent đến nút má»›i" #: editor/scene_tree_dock.cpp msgid "Make Scene Root" -msgstr "" +msgstr "Biến Cảnh thà nh Gốc" #: editor/scene_tree_dock.cpp msgid "Merge From Scene" -msgstr "" +msgstr "Hợp nhất từ Cảnh" #: editor/scene_tree_dock.cpp editor/script_editor_debugger.cpp msgid "Save Branch as Scene" -msgstr "" +msgstr "LÆ°u Nhánh thà nh Cảnh" #: editor/scene_tree_dock.cpp editor/script_editor_debugger.cpp msgid "Copy Node Path" @@ -10912,7 +10871,7 @@ msgstr "Sao chép Ä‘Æ°á»ng dẫn nút" #: editor/scene_tree_dock.cpp msgid "Delete (No Confirm)" -msgstr "" +msgstr "Xóa (Không há»i lại)" #: editor/scene_tree_dock.cpp msgid "Add/Create a New Node." @@ -10941,11 +10900,11 @@ msgstr "" #: editor/scene_tree_dock.cpp msgid "Local" -msgstr "" +msgstr "Cục bá»™" #: editor/scene_tree_dock.cpp msgid "Clear Inheritance? (No Undo!)" -msgstr "" +msgstr "Xóa Kế thừa? (Mất tăm luôn đấy!)" #: editor/scene_tree_editor.cpp msgid "Toggle Visible" @@ -10994,9 +10953,8 @@ msgstr "" "Nhấp để hiện khung nhóm." #: editor/scene_tree_editor.cpp -#, fuzzy msgid "Open Script:" -msgstr "Tạo Script" +msgstr "Mở Tệp lệnh:" #: editor/scene_tree_editor.cpp msgid "" @@ -11011,6 +10969,8 @@ msgid "" "Children are not selectable.\n" "Click to make selectable." msgstr "" +"Không thể chá»n Con của nút nà y.\n" +"Bấm và o đây để có thể chá»n chúng." #: editor/scene_tree_editor.cpp msgid "Toggle Visibility" @@ -11021,6 +10981,8 @@ msgid "" "AnimationPlayer is pinned.\n" "Click to unpin." msgstr "" +"AnimationPlayer đã được ghim.\n" +"Bấm để bá» ghim." #: editor/scene_tree_editor.cpp msgid "Invalid node name, the following characters are not allowed:" @@ -11044,11 +11006,11 @@ msgstr "Chá»n má»™t Nút" #: editor/script_create_dialog.cpp msgid "Path is empty." -msgstr "" +msgstr "ÄÆ°á»ng dẫn trống." #: editor/script_create_dialog.cpp msgid "Filename is empty." -msgstr "" +msgstr "Tên tệp trống." #: editor/script_create_dialog.cpp msgid "Path is not local." @@ -11069,17 +11031,16 @@ msgid "File does not exist." msgstr "Tệp không tồn tại." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Invalid extension." -msgstr "Phải sá» dụng extension có hiệu lá»±c" +msgstr "Tên Ä‘uôi không hợp lệ." #: editor/script_create_dialog.cpp msgid "Wrong extension chosen." -msgstr "" +msgstr "Sai Ä‘uôi mở rá»™ng." #: editor/script_create_dialog.cpp msgid "Error loading template '%s'" -msgstr "" +msgstr "Lá»—i nạp mẫu '%s'" #: editor/script_create_dialog.cpp msgid "Error - Could not create script in filesystem." @@ -11087,7 +11048,7 @@ msgstr "" #: editor/script_create_dialog.cpp msgid "Error loading script from %s" -msgstr "" +msgstr "Lá»—i nạp tệp lệnh từ %s" #: editor/script_create_dialog.cpp #, fuzzy @@ -11095,12 +11056,13 @@ msgid "Overrides" msgstr "Ghi đè" #: editor/script_create_dialog.cpp +#, fuzzy msgid "N/A" -msgstr "" +msgstr "Không có" #: editor/script_create_dialog.cpp msgid "Open Script / Choose Location" -msgstr "" +msgstr "Mở tệp lệnh / Chá»n vị trÃ" #: editor/script_create_dialog.cpp #, fuzzy @@ -11108,8 +11070,9 @@ msgid "Open Script" msgstr "Tạo Script" #: editor/script_create_dialog.cpp +#, fuzzy msgid "File exists, it will be reused." -msgstr "" +msgstr "Tệp tồn tại, và sẽ được dùng lại." #: editor/script_create_dialog.cpp #, fuzzy @@ -11117,9 +11080,8 @@ msgid "Invalid path." msgstr "ÄÆ°á»ng dẫn sai." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Invalid class name." -msgstr "KÃch thÆ°á»›c font không hợp lệ." +msgstr "Tên Lá»›p không hợp lệ." #: editor/script_create_dialog.cpp msgid "Invalid inherited parent name or path." @@ -11132,11 +11094,11 @@ msgstr "Animation tree khả dụng." #: editor/script_create_dialog.cpp msgid "Allowed: a-z, A-Z, 0-9, _ and ." -msgstr "" +msgstr "Äược dùng: a-z, A-Z, 0-9, _ và ." #: editor/script_create_dialog.cpp msgid "Built-in script (into scene file)." -msgstr "" +msgstr "Tệp lệnh tÃch hợp (và o tệp cảnh)." #: editor/script_create_dialog.cpp msgid "Will create a new script file." @@ -11144,7 +11106,7 @@ msgstr "Sẽ tạo má»™t tệp lệnh má»›i." #: editor/script_create_dialog.cpp msgid "Will load an existing script file." -msgstr "" +msgstr "Sẽ nạp má»™t tệp lệnh đã tồn tại." #: editor/script_create_dialog.cpp #, fuzzy @@ -11156,20 +11118,20 @@ msgid "" "Note: Built-in scripts have some limitations and can't be edited using an " "external editor." msgstr "" +"LÆ°u ý: Tệp lệnh tÃch hợp có má»™t số hạn chế và không thể chỉnh sá»a bằng trình " +"biên soạn bên ngoà i." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Class Name:" -msgstr "Lá»›p:" +msgstr "Tên Lá»›p:" #: editor/script_create_dialog.cpp msgid "Template:" msgstr "Bản mẫu:" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Built-in Script:" -msgstr "Tạo Script" +msgstr "Tệp lệnh có sẵn:" #: editor/script_create_dialog.cpp msgid "Attach Node Script" @@ -11181,27 +11143,23 @@ msgstr "" #: editor/script_editor_debugger.cpp msgid "Bytes:" -msgstr "" +msgstr "Bytes:" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Warning:" -msgstr "Cảnh báo" +msgstr "Cảnh báo:" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Error:" -msgstr "Lá»—i!" +msgstr "Lá»—i:" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "C++ Error" -msgstr "Lá»—i!" +msgstr "Lá»—i C++" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "C++ Error:" -msgstr "Lá»—i!" +msgstr "Lá»—i C++:" #: editor/script_editor_debugger.cpp #, fuzzy @@ -11209,13 +11167,13 @@ msgid "C++ Source" msgstr "Sao chép Tà i nguyên" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Source:" -msgstr "Quét nguồn" +msgstr "Nguồn:" #: editor/script_editor_debugger.cpp +#, fuzzy msgid "C++ Source:" -msgstr "" +msgstr "Tệp nguồn C++:" #: editor/script_editor_debugger.cpp msgid "Stack Trace" @@ -11223,25 +11181,23 @@ msgstr "" #: editor/script_editor_debugger.cpp msgid "Errors" -msgstr "" +msgstr "Lá»—i" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Child process connected." -msgstr "Các Nút đã ngắt Kết nối" +msgstr "Äã kết nối tiến trình con." #: editor/script_editor_debugger.cpp msgid "Copy Error" -msgstr "" +msgstr "Sao chép lá»—i" #: editor/script_editor_debugger.cpp msgid "Video RAM" msgstr "" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Skip Breakpoints" -msgstr "Tạo các Ä‘iểm." +msgstr "Lá» Ä‘i Ä‘iểm dừng" #: editor/script_editor_debugger.cpp msgid "Inspect Previous Instance" @@ -11265,28 +11221,31 @@ msgid "Network Profiler" msgstr "Xuất hồ sÆ¡" #: editor/script_editor_debugger.cpp +#, fuzzy msgid "Monitor" -msgstr "" +msgstr "Mà n hình" #: editor/script_editor_debugger.cpp msgid "Value" -msgstr "" +msgstr "Giá trị" #: editor/script_editor_debugger.cpp +#, fuzzy msgid "Monitors" -msgstr "" +msgstr "Mà n hình" #: editor/script_editor_debugger.cpp msgid "Pick one or more items from the list to display the graph." -msgstr "" +msgstr "Chá»n má»™t hoặc nhiá»u mục từ danh sách để hiển thị biểu đồ." #: editor/script_editor_debugger.cpp msgid "List of Video Memory Usage by Resource:" msgstr "" #: editor/script_editor_debugger.cpp +#, fuzzy msgid "Total:" -msgstr "" +msgstr "Tổng:" #: editor/script_editor_debugger.cpp #, fuzzy @@ -11295,23 +11254,24 @@ msgstr "Xuất hồ sÆ¡" #: editor/script_editor_debugger.cpp msgid "Resource Path" -msgstr "" +msgstr "ÄÆ°á»ng dẫn Tà i nguyên" #: editor/script_editor_debugger.cpp msgid "Type" -msgstr "" +msgstr "Kiểu" #: editor/script_editor_debugger.cpp msgid "Format" -msgstr "" +msgstr "Äịnh dạng" #: editor/script_editor_debugger.cpp msgid "Usage" msgstr "" #: editor/script_editor_debugger.cpp +#, fuzzy msgid "Misc" -msgstr "" +msgstr "Khác" #: editor/script_editor_debugger.cpp msgid "Clicked Control:" @@ -11335,15 +11295,15 @@ msgstr "" #: editor/settings_config_dialog.cpp msgid "Erase Shortcut" -msgstr "" +msgstr "Xóa lối tắt" #: editor/settings_config_dialog.cpp msgid "Restore Shortcut" -msgstr "" +msgstr "Khôi phục lối tắt" #: editor/settings_config_dialog.cpp msgid "Change Shortcut" -msgstr "" +msgstr "Thay đổi Lối tắt" #: editor/settings_config_dialog.cpp msgid "Editor Settings" @@ -11351,7 +11311,7 @@ msgstr "Cà i đặt Trình biên táºp" #: editor/settings_config_dialog.cpp msgid "Shortcuts" -msgstr "" +msgstr "Lối tắt" #: editor/settings_config_dialog.cpp msgid "Binding" @@ -11359,7 +11319,7 @@ msgstr "" #: editor/spatial_editor_gizmos.cpp msgid "Change Light Radius" -msgstr "" +msgstr "Thay đổi bán kÃnh ánh sáng" #: editor/spatial_editor_gizmos.cpp msgid "Change AudioStreamPlayer3D Emission Angle" @@ -11386,8 +11346,9 @@ msgid "Change Probe Extents" msgstr "" #: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp +#, fuzzy msgid "Change Sphere Shape Radius" -msgstr "" +msgstr "Thay đổi bán kÃnh hình cầu" #: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp msgid "Change Box Shape Extents" @@ -11517,7 +11478,7 @@ msgstr "" #: modules/gdscript/gdscript_functions.cpp msgid "Invalid instance dictionary (invalid subclasses)" -msgstr "" +msgstr "Từ Ä‘iển không hợp lệ (Lá»›p con không hợp lệ)" #: modules/gdscript/gdscript_functions.cpp msgid "Object can't provide a length." @@ -11679,9 +11640,8 @@ msgid "Indirect lighting" msgstr "" #: modules/lightmapper_cpu/lightmapper_cpu.cpp -#, fuzzy msgid "Post processing" -msgstr "Phiên bản hiện tại:" +msgstr "Háºu xá» lÃ" #: modules/lightmapper_cpu/lightmapper_cpu.cpp msgid "Plotting lightmaps" @@ -11689,7 +11649,7 @@ msgstr "" #: modules/mono/csharp_script.cpp msgid "Class name can't be a reserved keyword" -msgstr "" +msgstr "Tên Lá»›p không được trùng vá»›i từ khóa" #: modules/mono/mono_gd/gd_mono_utils.cpp msgid "End of inner exception stack trace" @@ -11701,15 +11661,15 @@ msgstr "" #: modules/recast/navigation_mesh_editor_plugin.cpp msgid "Clear the navigation mesh." -msgstr "" +msgstr "Xóa lÆ°á»›i Ä‘iá»u hÆ°á»›ng." #: modules/recast/navigation_mesh_generator.cpp msgid "Setting up Configuration..." -msgstr "" +msgstr "Thiết láºp cấu hình ..." #: modules/recast/navigation_mesh_generator.cpp msgid "Calculating grid size..." -msgstr "" +msgstr "TÃnh kÃch thÆ°á»›c lÆ°á»›i ..." #: modules/recast/navigation_mesh_generator.cpp msgid "Creating heightfield..." @@ -11729,11 +11689,11 @@ msgstr "" #: modules/recast/navigation_mesh_generator.cpp msgid "Partitioning..." -msgstr "" +msgstr "Phân vùng ..." #: modules/recast/navigation_mesh_generator.cpp msgid "Creating contours..." -msgstr "" +msgstr "Tạo Ä‘Æ°á»ng viá»n ..." #: modules/recast/navigation_mesh_generator.cpp msgid "Creating polymesh..." @@ -11745,7 +11705,7 @@ msgstr "" #: modules/recast/navigation_mesh_generator.cpp msgid "Navigation Mesh Generator Setup:" -msgstr "" +msgstr "Thiết láºp trình tạo lÆ°á»›i Ä‘iá»u hÆ°á»›ng:" #: modules/recast/navigation_mesh_generator.cpp msgid "Parsing Geometry..." @@ -11753,7 +11713,7 @@ msgstr "" #: modules/recast/navigation_mesh_generator.cpp msgid "Done!" -msgstr "" +msgstr "Xong!" #: modules/visual_script/visual_script.cpp msgid "" @@ -11780,45 +11740,44 @@ msgstr "" #: modules/visual_script/visual_script.cpp msgid "Node returned an invalid sequence output: " -msgstr "Nút trả vỠđầu ra là chuá»—i không hợp lệ: " +msgstr "Nút trả vá» chuá»—i không hợp lệ: " #: modules/visual_script/visual_script.cpp msgid "Found sequence bit but not the node in the stack, report bug!" -msgstr "Tìm ra chuá»—i bit nhÆ°ng không phải nút trong ngăn xếp, báo cáo lá»—i!" +msgstr "" +"Tìm thấy chuá»—i bit nhÆ°ng không phải là nút trong ngăn xếp, báo cáo lá»—i!" #: modules/visual_script/visual_script.cpp msgid "Stack overflow with stack depth: " -msgstr "" +msgstr "Trà n ngăn xếp ở ngăn xếp tầng: " #: modules/visual_script/visual_script_editor.cpp msgid "Change Signal Arguments" -msgstr "" +msgstr "Thay đổi đối số tÃn hiệu" #: modules/visual_script/visual_script_editor.cpp msgid "Change Argument Type" -msgstr "" +msgstr "Thay đổi loại đối số" #: modules/visual_script/visual_script_editor.cpp msgid "Change Argument name" -msgstr "" +msgstr "Thay đổi tên đối số" #: modules/visual_script/visual_script_editor.cpp msgid "Set Variable Default Value" -msgstr "" +msgstr "Äặt giá trị mặc định cho biến" #: modules/visual_script/visual_script_editor.cpp msgid "Set Variable Type" -msgstr "" +msgstr "Äặt loại biến" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Input Port" -msgstr "Thêm Input" +msgstr "Thêm cổng và o" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Output Port" -msgstr "Thêm Input" +msgstr "Thêm cổng ra" #: modules/visual_script/visual_script_editor.cpp msgid "Override an existing built-in function." @@ -11826,24 +11785,23 @@ msgstr "" #: modules/visual_script/visual_script_editor.cpp msgid "Create a new function." -msgstr "Tạo má»™t hà m má»›i." +msgstr "Tạo hà m má»›i." #: modules/visual_script/visual_script_editor.cpp msgid "Variables:" -msgstr "" +msgstr "Biến:" #: modules/visual_script/visual_script_editor.cpp msgid "Create a new variable." -msgstr "Tạo má»™t biến má»›i." +msgstr "Tạo biến má»›i." #: modules/visual_script/visual_script_editor.cpp msgid "Signals:" msgstr "TÃn hiệu:" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Create a new signal." -msgstr "Tạo" +msgstr "Tạo tÃn hiệu má»›i." #: modules/visual_script/visual_script_editor.cpp msgid "Name is not a valid identifier:" @@ -11851,7 +11809,7 @@ msgstr "" #: modules/visual_script/visual_script_editor.cpp msgid "Name already in use by another func/var/signal:" -msgstr "" +msgstr "Tên đã được sá» dụng bởi func/var/singal khác:" #: modules/visual_script/visual_script_editor.cpp msgid "Rename Function" @@ -11870,9 +11828,8 @@ msgid "Add Function" msgstr "Thêm Hà m" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Delete input port" -msgstr "Xoá Function" +msgstr "Xoá cổng và o" #: modules/visual_script/visual_script_editor.cpp msgid "Add Variable" @@ -11883,22 +11840,20 @@ msgid "Add Signal" msgstr "Thêm TÃn hiệu" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Remove Input Port" -msgstr "Xoá Function" +msgstr "Xóa cổng và o" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Remove Output Port" -msgstr "Xóa Template" +msgstr "Xóa cổng ra" #: modules/visual_script/visual_script_editor.cpp msgid "Change Expression" -msgstr "" +msgstr "Thay đổi biểu thức" #: modules/visual_script/visual_script_editor.cpp msgid "Remove VisualScript Nodes" -msgstr "Gỡ bá» các nút VisualScript" +msgstr "Xóa các nút VisualScript" #: modules/visual_script/visual_script_editor.cpp msgid "Duplicate VisualScript Nodes" @@ -11914,11 +11869,11 @@ msgstr "" #: modules/visual_script/visual_script_editor.cpp msgid "Hold %s to drop a simple reference to the node." -msgstr "Giữ %s và thả để tham chiếu Ä‘Æ¡n giản đế nút." +msgstr "Giữ %s để thả má»™t tham chiếu Ä‘Æ¡n giản lên nút." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a simple reference to the node." -msgstr "Giữ Ctrl và thả để tham chiếu Ä‘Æ¡n giản đến nút." +msgstr "Giữ Ctrl để thả má»™t tà i liệu tham khảo Ä‘Æ¡n giản đến nút." #: modules/visual_script/visual_script_editor.cpp msgid "Hold %s to drop a Variable Setter." @@ -11930,11 +11885,11 @@ msgstr "" #: modules/visual_script/visual_script_editor.cpp msgid "Add Preload Node" -msgstr "Thêm nút Preload" +msgstr "Thêm nút tải trÆ°á»›c" #: modules/visual_script/visual_script_editor.cpp msgid "Add Node(s) From Tree" -msgstr "Thêm các nút từ cây" +msgstr "Thêm nút từ cây" #: modules/visual_script/visual_script_editor.cpp msgid "" @@ -11952,7 +11907,7 @@ msgstr "" #: modules/visual_script/visual_script_editor.cpp msgid "Change Base Type" -msgstr "" +msgstr "Thay đổi loại cÆ¡ sở" #: modules/visual_script/visual_script_editor.cpp msgid "Move Node(s)" @@ -11964,7 +11919,7 @@ msgstr "Gỡ bá» nút VisualScript" #: modules/visual_script/visual_script_editor.cpp msgid "Connect Nodes" -msgstr "Kết nối các nút" +msgstr "Kết nối nút" #: modules/visual_script/visual_script_editor.cpp msgid "Disconnect Nodes" @@ -11980,15 +11935,15 @@ msgstr "Kết nối trình tá»± nút" #: modules/visual_script/visual_script_editor.cpp msgid "Script already has function '%s'" -msgstr "" +msgstr "Tệp lệnh đã có hà m '%s'" #: modules/visual_script/visual_script_editor.cpp msgid "Change Input Value" -msgstr "" +msgstr "Thay đổi giá trị đầu và o" #: modules/visual_script/visual_script_editor.cpp msgid "Resize Comment" -msgstr "" +msgstr "Thay đổi kÃch thÆ°á»›c Nháºn xét" #: modules/visual_script/visual_script_editor.cpp msgid "Can't copy the function node." @@ -11996,7 +11951,7 @@ msgstr "Không thể sao chép nút chức năng." #: modules/visual_script/visual_script_editor.cpp msgid "Clipboard is empty!" -msgstr "" +msgstr "Clipboard trống!" #: modules/visual_script/visual_script_editor.cpp msgid "Paste VisualScript Nodes" @@ -12019,17 +11974,16 @@ msgid "Try to only have one sequence input in selection." msgstr "" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Create Function" -msgstr "Äổi tên Hà m" +msgstr "Tạo Hà m" #: modules/visual_script/visual_script_editor.cpp msgid "Remove Function" -msgstr "Xoá Function" +msgstr "Xoá Hà m" #: modules/visual_script/visual_script_editor.cpp msgid "Remove Variable" -msgstr "Xoá Variable" +msgstr "Xoá Biến" #: modules/visual_script/visual_script_editor.cpp msgid "Editing Variable:" @@ -12052,27 +12006,24 @@ msgid "Members:" msgstr "Những Thà nh viên:" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Change Base Type:" -msgstr "Äổi %s Loại" +msgstr "Äổi Kiểu Gốc:" #: modules/visual_script/visual_script_editor.cpp msgid "Add Nodes..." msgstr "Thêm các nút..." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Function..." -msgstr "Thêm Hà m" +msgstr "Thêm Hà m..." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "function_name" -msgstr "Hà m:" +msgstr "ten_ham" #: modules/visual_script/visual_script_editor.cpp msgid "Select or create a function to edit its graph." -msgstr "" +msgstr "Chá»n hoặc tạo má»™t hà m để chỉnh đồ thị." #: modules/visual_script/visual_script_editor.cpp msgid "Delete Selected" @@ -12084,21 +12035,19 @@ msgstr "Tìm loại Node" #: modules/visual_script/visual_script_editor.cpp msgid "Copy Nodes" -msgstr "Sao chép các nút" +msgstr "Sao chép nút" #: modules/visual_script/visual_script_editor.cpp msgid "Cut Nodes" msgstr "Cắt các nút" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Make Function" -msgstr "Äổi tên Hà m" +msgstr "Tạo Hà m" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Refresh Graph" -msgstr "Là m má»›i" +msgstr "Là m má»›i đồ thị" #: modules/visual_script/visual_script_editor.cpp msgid "Edit Member" @@ -12106,19 +12055,19 @@ msgstr "" #: modules/visual_script/visual_script_flow_control.cpp msgid "Input type not iterable: " -msgstr "" +msgstr "Kiểu đầu và o không lặp được: " #: modules/visual_script/visual_script_flow_control.cpp msgid "Iterator became invalid" -msgstr "" +msgstr "Trá» lặp không còn hợp lệ" #: modules/visual_script/visual_script_flow_control.cpp msgid "Iterator became invalid: " -msgstr "" +msgstr "Trá» lặp không còn hợp lệ: " #: modules/visual_script/visual_script_func_nodes.cpp msgid "Invalid index property name." -msgstr "" +msgstr "Tên thuá»™c tÃnh chỉ mục không hợp lệ." #: modules/visual_script/visual_script_func_nodes.cpp msgid "Base object is not a Node!" @@ -12126,37 +12075,41 @@ msgstr "Äối tượng cÆ¡ sở không phải má»™t nút!" #: modules/visual_script/visual_script_func_nodes.cpp msgid "Path does not lead Node!" -msgstr "Path không chỉ đến Node!" +msgstr "ÄÆ°á»ng dẫn không chỉ đến Nút!" #: modules/visual_script/visual_script_func_nodes.cpp msgid "Invalid index property name '%s' in node %s." -msgstr "" +msgstr "Tên thuá»™c tÃnh chỉ mục '%s' ở nút '%s' không hợp lệ." #: modules/visual_script/visual_script_nodes.cpp msgid ": Invalid argument of type: " -msgstr "" +msgstr ": Tham số có loại không hợp lệ: " #: modules/visual_script/visual_script_nodes.cpp msgid ": Invalid arguments: " -msgstr "" +msgstr ": Tham số không hợp lệ: " #: modules/visual_script/visual_script_nodes.cpp msgid "VariableGet not found in script: " -msgstr "" +msgstr "Không tìm thấy VariableGet trong tệp lệnh: " #: modules/visual_script/visual_script_nodes.cpp +#, fuzzy msgid "VariableSet not found in script: " -msgstr "" +msgstr "Không tìm thấy VariableSet trong tệp lệnh: " #: modules/visual_script/visual_script_nodes.cpp msgid "Custom node has no _step() method, can't process graph." -msgstr "" +msgstr "Nút tùy chá»n không có phÆ°Æ¡ng thức _step(), không thể xá» là đồ thị." #: modules/visual_script/visual_script_nodes.cpp +#, fuzzy msgid "" "Invalid return value from _step(), must be integer (seq out), or string " "(error)." msgstr "" +"_step() trả giá trị không hợp lệ, phải là số nguyên (seq out), hoặc xâu " +"(lá»—i)." #: modules/visual_script/visual_script_property_selector.cpp msgid "Search VisualScript" @@ -12164,15 +12117,15 @@ msgstr "Tìm VisualScript" #: modules/visual_script/visual_script_property_selector.cpp msgid "Get %s" -msgstr "" +msgstr "Lấy %s" #: modules/visual_script/visual_script_property_selector.cpp msgid "Set %s" -msgstr "" +msgstr "Gán %s" #: platform/android/export/export.cpp msgid "Package name is missing." -msgstr "" +msgstr "Thiếu tên gói." #: platform/android/export/export.cpp msgid "Package segments must be of non-zero length." @@ -12180,11 +12133,11 @@ msgstr "" #: platform/android/export/export.cpp msgid "The character '%s' is not allowed in Android application package names." -msgstr "" +msgstr "Không được phép cho kà tá»± '%s' và o tên gói phần má»m Android." #: platform/android/export/export.cpp msgid "A digit cannot be the first character in a package segment." -msgstr "" +msgstr "Không thể có chữ số là m kà tá»± đầu tiên trong má»™t phần của gói." #: platform/android/export/export.cpp msgid "The character '%s' cannot be the first character in a package segment." @@ -12192,15 +12145,15 @@ msgstr "" #: platform/android/export/export.cpp msgid "The package must have at least one '.' separator." -msgstr "" +msgstr "Kà tá»± phân cách '.' phải xuất hiện Ãt nhất má»™t lần trong tên gói." #: platform/android/export/export.cpp msgid "Select device from the list" -msgstr "" +msgstr "Chá»n thiết bị trong danh sách" #: platform/android/export/export.cpp msgid "Unable to find the 'apksigner' tool." -msgstr "" +msgstr "Không tìm thấy công cụ 'apksigner'." #: platform/android/export/export.cpp msgid "" @@ -12228,11 +12181,11 @@ msgstr "" #: platform/android/export/export.cpp msgid "Missing 'platform-tools' directory!" -msgstr "" +msgstr "Thiếu thÆ° mục 'platform-tools'!" #: platform/android/export/export.cpp msgid "Unable to find Android SDK platform-tools' adb command." -msgstr "" +msgstr "Không tìm thấy lệnh adb trong bá»™ Android SDK platform-tools." #: platform/android/export/export.cpp msgid "Please check in the Android SDK directory specified in Editor Settings." @@ -12240,26 +12193,27 @@ msgstr "" #: platform/android/export/export.cpp msgid "Missing 'build-tools' directory!" -msgstr "" +msgstr "Thiếu thÆ° mục 'build-tools'!" #: platform/android/export/export.cpp msgid "Unable to find Android SDK build-tools' apksigner command." -msgstr "" +msgstr "Không tìm thấy lệnh apksigner của bá»™ Android SDK build-tools." #: platform/android/export/export.cpp msgid "Invalid public key for APK expansion." -msgstr "" +msgstr "Khóa công khai của bá»™ APK mở rá»™ng không hợp lệ." #: platform/android/export/export.cpp -#, fuzzy msgid "Invalid package name:" -msgstr "KÃch thÆ°á»›c font không hợp lệ." +msgstr "Tên gói không hợp lệ:" #: platform/android/export/export.cpp msgid "" "Invalid \"GodotPaymentV3\" module included in the \"android/modules\" " "project setting (changed in Godot 3.2.2).\n" msgstr "" +"Cà i đặt dá»± án chứa module không hợp lệ \"GodotPaymentV3\" ở mục \"android/" +"modules\" (đã thay đổi từ Godot 3.2.2).\n" #: platform/android/export/export.cpp msgid "\"Use Custom Build\" must be enabled to use the plugins." @@ -12269,12 +12223,14 @@ msgstr "" msgid "" "\"Degrees Of Freedom\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR" "\"." -msgstr "" +msgstr "\"Báºc tá»± do\" chỉ dùng được khi \"Xr Mode\" là \"Oculus Mobile VR\"." #: platform/android/export/export.cpp msgid "" "\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"Theo dõi chuyển Ä‘á»™ng tay\" chỉ dùng được khi \"Xr Mode\" là \"Oculus " +"Mobile VR\"." #: platform/android/export/export.cpp msgid "" @@ -12284,10 +12240,11 @@ msgstr "" #: platform/android/export/export.cpp msgid "\"Export AAB\" is only valid when \"Use Custom Build\" is enabled." msgstr "" +"\"Xuất AAB\" chỉ dùng được khi \"Sá» dụng Bản dá»±ng tùy chỉnh\" được báºt." #: platform/android/export/export.cpp msgid "Invalid filename! Android App Bundle requires the *.aab extension." -msgstr "" +msgstr "Tên tệp không hợp lệ! Android App Bundle cần Ä‘uôi *.aab ở cuối." #: platform/android/export/export.cpp msgid "APK Expansion not compatible with Android App Bundle." @@ -12295,7 +12252,7 @@ msgstr "" #: platform/android/export/export.cpp msgid "Invalid filename! Android APK requires the *.apk extension." -msgstr "" +msgstr "Tên tệp không hợp lệ! Android APK cần Ä‘uôi *.apk ở cuối." #: platform/android/export/export.cpp msgid "" @@ -12326,8 +12283,8 @@ msgid "" "Building of Android project failed, check output for the error.\n" "Alternatively visit docs.godotengine.org for Android build documentation." msgstr "" -"Xây dá»±ng dá»± án Android không thà nh công, kiểm tra lá»—i đầu ra.\n" -"Hoặc truy cáºp 'docs.godotengine.org' xem tà i liệu xây dá»±ng Android." +"Xây dá»±ng dá»± án Android thất bại, hãy kiểm tra đầu ra để biết lá»—i.\n" +"Hoặc truy cáºp 'docs.godotengine.org' để xem cách xây dá»±ng Android." #: platform/android/export/export.cpp msgid "Moving output" @@ -12362,7 +12319,7 @@ msgstr "" #: platform/javascript/export/export.cpp msgid "Stop HTTP Server" -msgstr "" +msgstr "Dừng Máy chủ HTTP" #: platform/javascript/export/export.cpp msgid "Run in Browser" @@ -12378,11 +12335,11 @@ msgstr "Không viết được file:" #: platform/javascript/export/export.cpp msgid "Could not open template for export:" -msgstr "" +msgstr "Không thể mở bản mẫu để xuất:" #: platform/javascript/export/export.cpp msgid "Invalid export template:" -msgstr "" +msgstr "Bản xuất mẫu không hợp lệ:" #: platform/javascript/export/export.cpp msgid "Could not read custom HTML shell:" @@ -12422,49 +12379,52 @@ msgid "Invalid publisher GUID." msgstr "KÃch thÆ°á»›c font không hợp lệ." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid background color." -msgstr "KÃch thÆ°á»›c font không hợp lệ." +msgstr "Mà u ná»n không hợp lệ." #: platform/uwp/export/export.cpp msgid "Invalid Store Logo image dimensions (should be 50x50)." -msgstr "" +msgstr "KÃch thÆ°á»›c ảnh Logo Store không hợp lệ (phải là 50x50)." #: platform/uwp/export/export.cpp msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." -msgstr "" +msgstr "KÃch thÆ°á»›c ảnh logo vuông 44x44 không hợp lệ (phải là 44x44)." #: platform/uwp/export/export.cpp msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." -msgstr "" +msgstr "KÃch thÆ°á»›c ảnh logo vuông 71x71 không hợp lệ (phải là 71x71)." #: platform/uwp/export/export.cpp msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." -msgstr "" +msgstr "KÃch thÆ°á»›c ảnh logo vuông 150x150 không hợp lệ (phải là 150x150)." #: platform/uwp/export/export.cpp msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." -msgstr "" +msgstr "KÃch thÆ°á»›c ảnh logo vuông 310x310 không hợp lệ (phải là 310x310)." #: platform/uwp/export/export.cpp msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." -msgstr "" +msgstr "KÃch thÆ°á»›c ảnh logo 310x150 không hợp lệ (phải là 310x150)." #: platform/uwp/export/export.cpp msgid "Invalid splash screen image dimensions (should be 620x300)." -msgstr "" +msgstr "Ảnh mở mà n có kÃch thÆ°á»›c không hợp lệ (phải là 620x300)." #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the \"Frames\" property in " "order for AnimatedSprite to display frames." msgstr "" +"Tà i nguyên SpriteFrames phải được tạo hoặc đặt trong thuá»™c tÃnh \"Khung hình" +"\" thì AnimatedSprite má»›i hiển thị các khung hình được." #: scene/2d/canvas_modulate.cpp msgid "" "Only one visible CanvasModulate is allowed per scene (or set of instanced " "scenes). The first created one will work, while the rest will be ignored." msgstr "" +"Chỉ cho phép má»™t CanvasModulate (không ẩn) ứng vá»›i má»™t Cảnh (hoặc má»™t táºp " +"Cảnh đã được tạo). Cái đầu tiên sẽ chạy, những cái sau sẽ bị lá» Ä‘i." #: scene/2d/collision_object_2d.cpp msgid "" @@ -12472,6 +12432,10 @@ msgid "" "Consider adding a CollisionShape2D or CollisionPolygon2D as a child to " "define its shape." msgstr "" +"Nút nà y không có hình thù, nên không thể va chạm hoặc tÆ°Æ¡ng tác vá»›i các váºt " +"khác.\n" +"Hãy thêm nút con CollisionShape2D hoặc CollisionPolygon2D để định dạng cho " +"nút nà y." #: scene/2d/collision_polygon_2d.cpp msgid "" @@ -12479,18 +12443,21 @@ msgid "" "CollisionObject2D derived node. Please only use it as a child of Area2D, " "StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape." msgstr "" +"CollisionPolygon2D nhằm mục Ä‘Ãch tạo khối va chạm cho những nút kế thừa từ " +"CollisionObject2D. Váºy nên hãy cho nút ấy là m con của Area2D, StaticBody2D, " +"RigidBody2D, KinematicBody2D, ... để tạo khối va chạm." #: scene/2d/collision_polygon_2d.cpp msgid "An empty CollisionPolygon2D has no effect on collision." -msgstr "" +msgstr "ColiisionPolygon2D rá»—ng sẽ không phản ứng gì khi có va chạm." #: scene/2d/collision_polygon_2d.cpp msgid "Invalid polygon. At least 3 points are needed in 'Solids' build mode." -msgstr "" +msgstr "Äa giác không hợp lệ. Cần Ãt nhất 3 Ä‘iểm trong chế Ä‘á»™ dá»±ng \"Solids\"." #: scene/2d/collision_polygon_2d.cpp msgid "Invalid polygon. At least 2 points are needed in 'Segments' build mode." -msgstr "" +msgstr "Äa giác không hợp lệ. Cần Ãt nhất 2 Ä‘iểm trong chế Ä‘á»™ dá»±ng 'Segments'." #: scene/2d/collision_shape_2d.cpp msgid "" @@ -12498,44 +12465,52 @@ msgid "" "CollisionObject2D derived node. Please only use it as a child of Area2D, " "StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape." msgstr "" +"CollisionShape2D nhằm mục Ä‘Ãch tạo khối va chạm cho những nút kế thừa từ " +"CollisionObject2D. Váºy nên hãy cho nút ấy là m con của Area2D, StaticBody2D, " +"RigidBody2D, KinematicBody2D, ... để tạo khối va chạm." #: scene/2d/collision_shape_2d.cpp msgid "" "A shape must be provided for CollisionShape2D to function. Please create a " "shape resource for it!" msgstr "" +"CollisionShape2D cần má»™t khối hình má»›i hoạt Ä‘á»™ng được. Hãy tạo má»™t tà i " +"nguyên khối hình cho nó!" #: scene/2d/collision_shape_2d.cpp msgid "" "Polygon-based shapes are not meant be used nor edited directly through the " "CollisionShape2D node. Please use the CollisionPolygon2D node instead." msgstr "" +"Khối hình Ä‘a giác không được nhằm để dùng hoặc chỉnh sá»a thông qua nút " +"CollisionShape2D. Hãy chuyển qua dùng nút CollisionPolygon2D." #: scene/2d/cpu_particles_2d.cpp msgid "" "CPUParticles2D animation requires the usage of a CanvasItemMaterial with " "\"Particles Animation\" enabled." msgstr "" +"Hoạt ảnh CPUParticles2D cần CanvasItemMaterial báºt \"Particles Animation\"." #: scene/2d/joints_2d.cpp msgid "Node A and Node B must be PhysicsBody2Ds" -msgstr "" +msgstr "Nút A và Nút B phải là PhysicsBody2D" #: scene/2d/joints_2d.cpp msgid "Node A must be a PhysicsBody2D" -msgstr "" +msgstr "Nút A phải là PhysicsBody2D" #: scene/2d/joints_2d.cpp msgid "Node B must be a PhysicsBody2D" -msgstr "" +msgstr "Nút B phải là PhysicsBody2D" #: scene/2d/joints_2d.cpp msgid "Joint is not connected to two PhysicsBody2Ds" -msgstr "" +msgstr "Khá»›p nối chÆ°a kết nối tá»›i hai PhysicsBody2D" #: scene/2d/joints_2d.cpp msgid "Node A and Node B must be different PhysicsBody2Ds" -msgstr "" +msgstr "Nút A và Nút B phải là 2 PhysicsBody2D khác nhau" #: scene/2d/light_2d.cpp msgid "" @@ -12568,6 +12543,7 @@ msgstr "" msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +"Nút ParallaxLayer chỉ hoạt Ä‘á»™ng khi là con của má»™t nút ParallaxBackground." #: scene/2d/particles_2d.cpp msgid "" @@ -12587,10 +12563,11 @@ msgid "" "Particles2D animation requires the usage of a CanvasItemMaterial with " "\"Particles Animation\" enabled." msgstr "" +"Hoạt ảnh Particles2D cần CanvasItemMaterial báºt \"Particles Animation\"." #: scene/2d/path_2d.cpp msgid "PathFollow2D only works when set as a child of a Path2D node." -msgstr "" +msgstr "PathFollow2D chỉ hoạt Ä‘á»™ng khi được đặt là m con của má»™t nút Path2D." #: scene/2d/physics_body_2d.cpp msgid "" @@ -12602,6 +12579,8 @@ msgstr "" #: scene/2d/remote_transform_2d.cpp msgid "Path property must point to a valid Node2D node to work." msgstr "" +"Thuá»™c tÃnh ÄÆ°á»ng dẫn phải chỉ đến má»™t nút Node2D hợp lệ thì má»›i hoạt Ä‘á»™ng " +"được." #: scene/2d/skeleton_2d.cpp msgid "This Bone2D chain should end at a Skeleton2D node." @@ -12610,11 +12589,12 @@ msgstr "" #: scene/2d/skeleton_2d.cpp msgid "A Bone2D only works with a Skeleton2D or another Bone2D as parent node." msgstr "" +"Bone2D chỉ hoạt Ä‘á»™ng khi là con má»™t nút Skeleton2D hoặc má»™t Bone2D khác ." #: scene/2d/skeleton_2d.cpp msgid "" "This bone lacks a proper REST pose. Go to the Skeleton2D node and set one." -msgstr "" +msgstr "Thanh xÆ°Æ¡ng nà y thiếu dáng NGHỈ. Hãy đặt má»™t dáng tại nút Skeleton2D." #: scene/2d/tile_map.cpp msgid "" @@ -12645,13 +12625,15 @@ msgstr "" #: scene/3d/arvr_nodes.cpp msgid "ARVRAnchor must have an ARVROrigin node as its parent." -msgstr "" +msgstr "ARVRAnchor phải là con của nút ARVROrigin." #: scene/3d/arvr_nodes.cpp msgid "" "The anchor ID must not be 0 or this anchor won't be bound to an actual " "anchor." msgstr "" +"ID của neo phải là 0, nếu không thì neo nà y sẽ không bị rà ng buá»™c vá»›i neo " +"thá»±c." #: scene/3d/arvr_nodes.cpp msgid "ARVROrigin requires an ARVRCamera child node." @@ -12913,7 +12895,7 @@ msgstr "" #: scene/gui/color_picker.cpp msgid "Pick a color from the editor window." -msgstr "Chá»n má»™t mà u từ cá»a sổ biên táºp" +msgstr "Chá»n má»™t mà u từ cá»a sổ biên táºp." #: scene/gui/color_picker.cpp msgid "HSV" @@ -13014,7 +12996,7 @@ msgstr "" #: scene/resources/visual_shader_nodes.cpp msgid "Invalid source for preview." -msgstr "nguồn vô hiệu cho xem trÆ°á»›c" +msgstr "Nguồn vô hiệu cho xem trÆ°á»›c." #: scene/resources/visual_shader_nodes.cpp msgid "Invalid source for shader." diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po index deca89e9ea..e043d0f05a 100644 --- a/editor/translations/zh_CN.po +++ b/editor/translations/zh_CN.po @@ -81,7 +81,7 @@ msgid "" msgstr "" "Project-Id-Version: Chinese (Simplified) (Godot Engine)\n" "POT-Creation-Date: 2018-01-20 12:15+0200\n" -"PO-Revision-Date: 2021-03-16 10:40+0000\n" +"PO-Revision-Date: 2021-04-05 14:28+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" @@ -90,7 +90,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.5.2-dev\n" +"X-Generator: Weblate 4.6-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -790,7 +790,7 @@ msgstr "æ ‡å‡†" #: editor/code_editor.cpp editor/plugins/script_editor_plugin.cpp msgid "Toggle Scripts Panel" -msgstr "å¼€å¯ï¼å…³é—脚本é¢æ¿" +msgstr "切æ¢è„šæœ¬é¢æ¿" #: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/texture_region_editor_plugin.cpp @@ -1376,7 +1376,7 @@ msgstr "总线选项" #: editor/editor_audio_buses.cpp editor/filesystem_dock.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "Duplicate" -msgstr "æ‹·è´" +msgstr "å¤åˆ¶" #: editor/editor_audio_buses.cpp msgid "Reset Volume" @@ -3660,6 +3660,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "状æ€ï¼šå¯¼å…¥æ–‡ä»¶å¤±è´¥ã€‚请手动修å¤æ–‡ä»¶åŽé‡æ–°å¯¼å…¥ã€‚" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "该文件的导入已被ç¦ç”¨ï¼Œå› æ¤ä¸èƒ½æ‰“开进行编辑。" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "æ— æ³•ç§»åŠ¨æˆ–é‡å‘½åæ ¹èµ„æºã€‚" @@ -4057,6 +4062,10 @@ msgid "Reset to Defaults" msgstr "é‡ç½®ä¸ºé»˜è®¤å€¼" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "ä¿ç•™æ–‡ä»¶ï¼ˆä¸å¯¼å…¥ï¼‰" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d 个文件" @@ -5195,7 +5204,7 @@ msgstr "设置å¸é™„" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Grid Offset:" -msgstr "ç½‘æ ¼å移é‡:" +msgstr "ç½‘æ ¼å移:" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Grid Step:" @@ -5211,7 +5220,7 @@ msgstr "æ¥" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Rotation Offset:" -msgstr "旋转å移é‡:" +msgstr "旋转å移:" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Rotation Step:" @@ -7493,7 +7502,7 @@ msgstr "" "\n" "ç眼:Gizmo å¯è§ã€‚\n" "é—眼:Gizmo éšè—。\n" -"åŠç眼:Gizmo 也å¯ç©¿è¿‡ä¸é€æ˜Žçš„表é¢å¯è§ï¼ˆâ€œX-Ray - X å…‰â€ï¼‰ã€‚" +"åŠç眼:Gizmo 也å¯ç©¿è¿‡ä¸é€æ˜Žçš„表é¢å¯è§ï¼ˆâ€œX å…‰â€ï¼‰ã€‚" #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Nodes To Floor" @@ -7922,7 +7931,7 @@ msgstr "自动è£å‰ª" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Offset:" -msgstr "å移é‡ï¼š" +msgstr "å移:" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Step:" diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po index 2009ba8f20..030f678592 100644 --- a/editor/translations/zh_HK.po +++ b/editor/translations/zh_HK.po @@ -3764,6 +3764,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "狀態:導入檔案失敗。請修æ£æª”案並å†æ‰‹å‹•å°Žå…¥ã€‚" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp #, fuzzy msgid "Cannot move/rename resources root." msgstr "ä¸èƒ½ç§»å‹•ï¼é‡æ–°å‘½å resources root." @@ -4189,6 +4194,10 @@ msgid "Reset to Defaults" msgstr "é è¨" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp #, fuzzy msgid "%d Files" msgstr "檔案" diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po index 62ef5a616c..2c60984b36 100644 --- a/editor/translations/zh_TW.po +++ b/editor/translations/zh_TW.po @@ -3610,6 +3610,11 @@ msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "狀態:檔案匯入失敗。請修æ£æª”案並手動é‡æ–°åŒ¯å…¥ã€‚" #: editor/filesystem_dock.cpp +msgid "" +"Importing has been disabled for this file, so it can't be opened for editing." +msgstr "" + +#: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." msgstr "無法移動或é‡æ–°å‘½åæ ¹è³‡æºã€‚" @@ -4007,6 +4012,10 @@ msgid "Reset to Defaults" msgstr "é‡è¨ç‚ºé è¨" #: editor/import_dock.cpp +msgid "Keep File (No Import)" +msgstr "" + +#: editor/import_dock.cpp msgid "%d Files" msgstr "%d 個檔案" diff --git a/main/main.cpp b/main/main.cpp index 951fce35ba..aa925c508c 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1551,8 +1551,8 @@ Error Main::setup2(Thread::ID p_main_tid_override) { { GLOBAL_DEF_RST_NOVAL("input_devices/pen_tablet/driver", ""); - GLOBAL_DEF_RST_NOVAL("input_devices/pen_tablet/driver.windows", ""); - ProjectSettings::get_singleton()->set_custom_property_info("input_devices/pen_tablet/driver.windows", PropertyInfo(Variant::STRING, "input_devices/pen_tablet/driver.windows", PROPERTY_HINT_ENUM, "wintab,winink")); + GLOBAL_DEF_RST_NOVAL("input_devices/pen_tablet/driver.Windows", ""); + ProjectSettings::get_singleton()->set_custom_property_info("input_devices/pen_tablet/driver.Windows", PropertyInfo(Variant::STRING, "input_devices/pen_tablet/driver.Windows", PROPERTY_HINT_ENUM, "wintab,winink")); } if (tablet_driver == "") { // specified in project.godot diff --git a/methods.py b/methods.py index 725fb36caa..6f1e7a7279 100644 --- a/methods.py +++ b/methods.py @@ -646,6 +646,9 @@ def generate_vs_project(env, num_jobs): "-j%s" % num_jobs, ] + if env["tests"]: + common_build_postfix.append("tests=yes") + if env["custom_modules"]: common_build_postfix.append("custom_modules=%s" % env["custom_modules"]) @@ -658,6 +661,8 @@ def generate_vs_project(env, num_jobs): add_to_vs_project(env, env.modules_sources) add_to_vs_project(env, env.scene_sources) add_to_vs_project(env, env.servers_sources) + if env["tests"]: + add_to_vs_project(env, env.tests_sources) add_to_vs_project(env, env.editor_sources) for header in glob_recursive("**/*.h"): diff --git a/misc/dist/html/editor.html b/misc/dist/html/editor.html index 99ac2379ce..4785f54973 100644 --- a/misc/dist/html/editor.html +++ b/misc/dist/html/editor.html @@ -1,8 +1,10 @@ <!DOCTYPE html> -<html xmlns='http://www.w3.org/1999/xhtml' lang='' xml:lang=''> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en"> <head> - <meta charset='utf-8' /> - <meta name='viewport' content='width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no' /> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no" /> + <meta name="author" content="Godot Engine" /> + <meta name="description" content="Use the Godot Engine editor directly in your web browser, without having to install anything." /> <meta name="mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="application-name" content="Godot" /> @@ -11,7 +13,14 @@ <meta name="msapplication-navbutton-color" content="#478cbf" /> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta name="msapplication-starturl" content="/latest" /> - <link id='-gd-engine-icon' rel='icon' type='image/png' href='favicon.png' /> + <meta property="og:site_name" content="Godot Engine Web Editor" /> + <meta property="og:url" name="twitter:url" content="https://editor.godotengine.org/releases/latest/" /> + <meta property="og:title" name="twitter:title" content="Free and open source 2D and 3D game engine" /> + <meta property="og:description" name="twitter:description" content="Use the Godot Engine editor directly in your web browser, without having to install anything." /> + <meta property="og:image" name="twitter:image" content="https://godotengine.org/themes/godotengine/assets/og_image.png" /> + <meta property="og:type" content="website" /> + <meta name="twitter:card" content="summary" /> + <link id="-gd-engine-icon" rel="icon" type="image/png" href="favicon.png" /> <link rel="apple-touch-icon" type="image/png" href="favicon.png" /> <link rel="manifest" href="manifest.json" /> <title>Godot Engine Web Editor (@GODOT_VERSION@)</title> @@ -204,8 +213,8 @@ <button id="btn-tab-game" class="btn tab-btn" disabled="disabled" onclick="showTab('game')">Game</button> <button id="btn-close-game" class="btn close-btn" disabled="disabled" onclick="closeGame()">×</button> </div> - <div id='tabs'> - <div id='tab-loader'> + <div id="tabs"> + <div id="tab-loader"> <div style="color: #e0e0e0;" id="persistence"> <label for="videoMode" style="display: none;">Select video driver:</label><br /> <select id="videoMode" style="display: none;"> @@ -213,7 +222,7 @@ <option value="GLES3">WebGL 2</option> </select> <br /> - <img src="logo.svg" width="1024" height="414" style="width: auto; height: auto; max-width: 85%; max-height: 250px" /> + <img src="logo.svg" alt="Godot Engine logo" width="1024" height="414" style="width: auto; height: auto; max-width: 85%; max-height: 250px" /> <br /> @GODOT_VERSION@ <br /> @@ -221,7 +230,7 @@ <br /> <br /> <br /> - <label for="zip-file" style="margin-right: 1rem">Preload project ZIP:</label> <input id="zip-file" type="file" id="files" name="files" style="margin-bottom: 1rem"/> + <label for="zip-file" style="margin-right: 1rem">Preload project ZIP:</label> <input id="zip-file" type="file" name="files" style="margin-bottom: 1rem"/> <br /> <a href="demo.zip">(Try this for example)</a> <br /> @@ -233,21 +242,21 @@ <a href="https://docs.godotengine.org/en/latest/tutorials/editor/using_the_web_editor.html">Web editor documentation</a> </div> </div> - <div id='tab-editor' style="display: none;"> - <canvas id='editor-canvas' tabindex="1"> + <div id="tab-editor" style="display: none;"> + <canvas id="editor-canvas" tabindex="1"> HTML5 canvas appears to be unsupported in the current browser.<br /> Please try updating or use a different browser. </canvas> </div> - <div id='tab-game' style="display: none;"> - <canvas id='game-canvas' tabindex="2"> + <div id="tab-game" style="display: none;"> + <canvas id="game-canvas" tabindex="2"> HTML5 canvas appears to be unsupported in the current browser.<br /> Please try updating or use a different browser. </canvas> </div> - <div id='tab-status' style="display: none;"> - <div id='status-progress' style='display: none;' oncontextmenu='event.preventDefault();'><div id ='status-progress-inner'></div></div> - <div id='status-indeterminate' style='display: none;' oncontextmenu='event.preventDefault();'> + <div id="tab-status" style="display: none;"> + <div id="status-progress" style="display: none;" oncontextmenu="event.preventDefault();"><div id="status-progress-inner"></div></div> + <div id="status-indeterminate" style="display: none;" oncontextmenu="event.preventDefault();"> <div></div> <div></div> <div></div> @@ -257,7 +266,7 @@ <div></div> <div></div> </div> - <div id='status-notice' class='godot' style='display: none;'></div> + <div id="status-notice" class="godot" style="display: none;"></div> </div> </div> <script> @@ -267,7 +276,7 @@ } }); </script> - <script src='godot.tools.js'></script> + <script src="godot.tools.js"></script> <script>//<![CDATA[ var editor = null; diff --git a/misc/dist/html/manifest.json b/misc/dist/html/manifest.json index 6fbed737c7..0ca27b3742 100644 --- a/misc/dist/html/manifest.json +++ b/misc/dist/html/manifest.json @@ -1,7 +1,7 @@ { - "name": "Godot Engine", + "name": "Godot Engine Web Editor", "short_name": "Godot", - "description": "Multi-platform 2D and 3D game engine with a feature-rich editor", + "description": "Multi-platform 2D and 3D game engine with a feature-rich editor (Web edition)", "lang": "en", "start_url": "./godot.tools.html", "display": "standalone", diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp index 7c27292e59..93642f2d5c 100644 --- a/modules/bullet/bullet_physics_server.cpp +++ b/modules/bullet/bullet_physics_server.cpp @@ -433,12 +433,6 @@ void BulletPhysicsServer3D::area_set_ray_pickable(RID p_area, bool p_enable) { area->set_ray_pickable(p_enable); } -bool BulletPhysicsServer3D::area_is_ray_pickable(RID p_area) const { - AreaBullet *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, false); - return area->is_ray_pickable(); -} - RID BulletPhysicsServer3D::body_create(BodyMode p_mode, bool p_init_sleeping) { RigidBodyBullet *body = bulletnew(RigidBodyBullet); body->set_mode(p_mode); @@ -842,12 +836,6 @@ void BulletPhysicsServer3D::body_set_ray_pickable(RID p_body, bool p_enable) { body->set_ray_pickable(p_enable); } -bool BulletPhysicsServer3D::body_is_ray_pickable(RID p_body) const { - RigidBodyBullet *body = rigid_body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, false); - return body->is_ray_pickable(); -} - PhysicsDirectBodyState3D *BulletPhysicsServer3D::body_get_direct_state(RID p_body) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, nullptr); @@ -880,7 +868,7 @@ RID BulletPhysicsServer3D::soft_body_create(bool p_init_sleeping) { CreateThenReturnRID(soft_body_owner, body); } -void BulletPhysicsServer3D::soft_body_update_rendering_server(RID p_body, class SoftBodyRenderingServerHandler *p_rendering_server_handler) { +void BulletPhysicsServer3D::soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -922,6 +910,13 @@ void BulletPhysicsServer3D::soft_body_set_mesh(RID p_body, const REF &p_mesh) { body->set_soft_mesh(p_mesh); } +AABB BulletPhysicsServer::soft_body_get_bounds(RID p_body) const { + SoftBodyBullet *body = soft_body_owner.get(p_body); + ERR_FAIL_COND_V(!body, AABB()); + + return body->get_bounds(); +} + void BulletPhysicsServer3D::soft_body_set_collision_layer(RID p_body, uint32_t p_layer) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -1002,34 +997,19 @@ void BulletPhysicsServer3D::soft_body_set_transform(RID p_body, const Transform body->set_soft_transform(p_transform); } -Vector3 BulletPhysicsServer3D::soft_body_get_vertex_position(RID p_body, int vertex_index) const { - const SoftBodyBullet *body = soft_body_owner.getornull(p_body); - Vector3 pos; - ERR_FAIL_COND_V(!body, pos); - - body->get_node_position(vertex_index, pos); - return pos; -} - void BulletPhysicsServer3D::soft_body_set_ray_pickable(RID p_body, bool p_enable) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_ray_pickable(p_enable); } -bool BulletPhysicsServer3D::soft_body_is_ray_pickable(RID p_body) const { - SoftBodyBullet *body = soft_body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, false); - return body->is_ray_pickable(); -} - void BulletPhysicsServer3D::soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_simulation_precision(p_simulation_precision); } -int BulletPhysicsServer3D::soft_body_get_simulation_precision(RID p_body) { +int BulletPhysicsServer3D::soft_body_get_simulation_precision(RID p_body) const { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_simulation_precision(); @@ -1041,13 +1021,13 @@ void BulletPhysicsServer3D::soft_body_set_total_mass(RID p_body, real_t p_total_ body->set_total_mass(p_total_mass); } -real_t BulletPhysicsServer3D::soft_body_get_total_mass(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_total_mass(RID p_body) const { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_total_mass(); } -void BulletPhysicsServer3D::soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) { +void BulletPhysicsServer3D::soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) const { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_linear_stiffness(p_stiffness); @@ -1059,61 +1039,25 @@ real_t BulletPhysicsServer3D::soft_body_get_linear_stiffness(RID p_body) { return body->get_linear_stiffness(); } -void BulletPhysicsServer3D::soft_body_set_angular_stiffness(RID p_body, real_t p_stiffness) { - SoftBodyBullet *body = soft_body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - body->set_angular_stiffness(p_stiffness); -} - -real_t BulletPhysicsServer3D::soft_body_get_angular_stiffness(RID p_body) { - SoftBodyBullet *body = soft_body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0.f); - return body->get_angular_stiffness(); -} - -void BulletPhysicsServer3D::soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) { - SoftBodyBullet *body = soft_body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - body->set_volume_stiffness(p_stiffness); -} - -real_t BulletPhysicsServer3D::soft_body_get_volume_stiffness(RID p_body) { - SoftBodyBullet *body = soft_body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0.f); - return body->get_volume_stiffness(); -} - void BulletPhysicsServer3D::soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_pressure_coefficient(p_pressure_coefficient); } -real_t BulletPhysicsServer3D::soft_body_get_pressure_coefficient(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_pressure_coefficient(RID p_body) const { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_pressure_coefficient(); } -void BulletPhysicsServer3D::soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) { - SoftBodyBullet *body = soft_body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - return body->set_pose_matching_coefficient(p_pose_matching_coefficient); -} - -real_t BulletPhysicsServer3D::soft_body_get_pose_matching_coefficient(RID p_body) { - SoftBodyBullet *body = soft_body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0.f); - return body->get_pose_matching_coefficient(); -} - void BulletPhysicsServer3D::soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_damping_coefficient(p_damping_coefficient); } -real_t BulletPhysicsServer3D::soft_body_get_damping_coefficient(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_damping_coefficient(RID p_body) const { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_damping_coefficient(); @@ -1125,7 +1069,7 @@ void BulletPhysicsServer3D::soft_body_set_drag_coefficient(RID p_body, real_t p_ body->set_drag_coefficient(p_drag_coefficient); } -real_t BulletPhysicsServer3D::soft_body_get_drag_coefficient(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_drag_coefficient(RID p_body) const { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_drag_coefficient(); @@ -1137,7 +1081,7 @@ void BulletPhysicsServer3D::soft_body_move_point(RID p_body, int p_point_index, body->set_node_position(p_point_index, p_global_position); } -Vector3 BulletPhysicsServer3D::soft_body_get_point_global_position(RID p_body, int p_point_index) { +Vector3 BulletPhysicsServer3D::soft_body_get_point_global_position(RID p_body, int p_point_index) const { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, Vector3(0., 0., 0.)); Vector3 pos; @@ -1145,14 +1089,6 @@ Vector3 BulletPhysicsServer3D::soft_body_get_point_global_position(RID p_body, i return pos; } -Vector3 BulletPhysicsServer3D::soft_body_get_point_offset(RID p_body, int p_point_index) const { - SoftBodyBullet *body = soft_body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, Vector3()); - Vector3 res; - body->get_node_offset(p_point_index, res); - return res; -} - void BulletPhysicsServer3D::soft_body_remove_all_pinned_points(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -1165,7 +1101,7 @@ void BulletPhysicsServer3D::soft_body_pin_point(RID p_body, int p_point_index, b body->set_node_mass(p_point_index, p_pin ? 0 : 1); } -bool BulletPhysicsServer3D::soft_body_is_point_pinned(RID p_body, int p_point_index) { +bool BulletPhysicsServer3D::soft_body_is_point_pinned(RID p_body, int p_point_index) const { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_node_mass(p_point_index); diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h index 97b719ae8e..856ff74963 100644 --- a/modules/bullet/bullet_physics_server.h +++ b/modules/bullet/bullet_physics_server.h @@ -163,7 +163,6 @@ public: virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) override; virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) override; virtual void area_set_ray_pickable(RID p_area, bool p_enable) override; - virtual bool area_is_ray_pickable(RID p_area) const override; /* RIGID BODY API */ @@ -250,7 +249,6 @@ public: virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) override; virtual void body_set_ray_pickable(RID p_body, bool p_enable) override; - virtual bool body_is_ray_pickable(RID p_body) const override; // this function only works on physics process, errors and returns null otherwise virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override; @@ -262,13 +260,15 @@ public: virtual RID soft_body_create(bool p_init_sleeping = false) override; - virtual void soft_body_update_rendering_server(RID p_body, class SoftBodyRenderingServerHandler *p_rendering_server_handler) override; + virtual void soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) override; virtual void soft_body_set_space(RID p_body, RID p_space) override; virtual RID soft_body_get_space(RID p_body) const override; virtual void soft_body_set_mesh(RID p_body, const REF &p_mesh) override; + virtual AABB soft_body_get_bounds(RID p_body) const override; + virtual void soft_body_set_collision_layer(RID p_body, uint32_t p_layer) override; virtual uint32_t soft_body_get_collision_layer(RID p_body) const override; @@ -284,46 +284,33 @@ public: /// Special function. This function has bad performance virtual void soft_body_set_transform(RID p_body, const Transform &p_transform) override; - virtual Vector3 soft_body_get_vertex_position(RID p_body, int vertex_index) const override; virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) override; - virtual bool soft_body_is_ray_pickable(RID p_body) const override; virtual void soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) override; - virtual int soft_body_get_simulation_precision(RID p_body) override; + virtual int soft_body_get_simulation_precision(RID p_body) const override; virtual void soft_body_set_total_mass(RID p_body, real_t p_total_mass) override; - virtual real_t soft_body_get_total_mass(RID p_body) override; + virtual real_t soft_body_get_total_mass(RID p_body) const override; virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) override; - virtual real_t soft_body_get_linear_stiffness(RID p_body) override; - - virtual void soft_body_set_angular_stiffness(RID p_body, real_t p_stiffness) override; - virtual real_t soft_body_get_angular_stiffness(RID p_body) override; - - virtual void soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) override; - virtual real_t soft_body_get_volume_stiffness(RID p_body) override; + virtual real_t soft_body_get_linear_stiffness(RID p_body) const override; virtual void soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) override; - virtual real_t soft_body_get_pressure_coefficient(RID p_body) override; - - virtual void soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) override; - virtual real_t soft_body_get_pose_matching_coefficient(RID p_body) override; + virtual real_t soft_body_get_pressure_coefficient(RID p_body) const override; virtual void soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) override; - virtual real_t soft_body_get_damping_coefficient(RID p_body) override; + virtual real_t soft_body_get_damping_coefficient(RID p_body) const override; virtual void soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) override; - virtual real_t soft_body_get_drag_coefficient(RID p_body) override; + virtual real_t soft_body_get_drag_coefficient(RID p_body) const override; virtual void soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) override; - virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) override; - - virtual Vector3 soft_body_get_point_offset(RID p_body, int p_point_index) const override; + virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) const override; virtual void soft_body_remove_all_pinned_points(RID p_body) override; virtual void soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) override; - virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) override; + virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) const override; /* JOINT API */ diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp index 82876ab77c..471b154813 100644 --- a/modules/bullet/shape_bullet.cpp +++ b/modules/bullet/shape_bullet.cpp @@ -375,11 +375,17 @@ ConcavePolygonShapeBullet::~ConcavePolygonShapeBullet() { } void ConcavePolygonShapeBullet::set_data(const Variant &p_data) { - setup(p_data); + Dictionary d = p_data; + ERR_FAIL_COND(!d.has("faces")); + + setup(d["faces"]); } Variant ConcavePolygonShapeBullet::get_data() const { - return faces; + Dictionary d; + d["faces"] = faces; + + return d; } PhysicsServer3D::ShapeType ConcavePolygonShapeBullet::get_type() const { diff --git a/modules/bullet/soft_body_bullet.cpp b/modules/bullet/soft_body_bullet.cpp index a8980984a7..2c8727baf2 100644 --- a/modules/bullet/soft_body_bullet.cpp +++ b/modules/bullet/soft_body_bullet.cpp @@ -65,7 +65,7 @@ void SoftBodyBullet::on_enter_area(AreaBullet *p_area) {} void SoftBodyBullet::on_exit_area(AreaBullet *p_area) {} -void SoftBodyBullet::update_rendering_server(SoftBodyRenderingServerHandler *p_rendering_server_handler) { +void SoftBodyBullet::update_rendering_server(RenderingServerHandler *p_rendering_server_handler) { if (!bt_soft_body) { return; } @@ -141,6 +141,24 @@ void SoftBodyBullet::set_soft_transform(const Transform &p_transform) { move_all_nodes(p_transform); } +AABB SoftBodyBullet::get_bounds() const { + if (!bt_soft_body) { + return AABB(); + } + + btVector3 aabb_min; + btVector3 aabb_max; + bt_soft_body->getAabb(aabb_min, aabb_max); + + btVector3 size(aabb_max - aabb_min); + + AABB aabb; + B_TO_G(aabb_min, aabb.position); + B_TO_G(size, aabb.size); + + return aabb; +} + void SoftBodyBullet::move_all_nodes(const Transform &p_transform) { if (!bt_soft_body) { return; @@ -169,25 +187,6 @@ void SoftBodyBullet::get_node_position(int p_node_index, Vector3 &r_position) co } } -void SoftBodyBullet::get_node_offset(int p_node_index, Vector3 &r_offset) const { - if (soft_mesh.is_null()) { - return; - } - - Array arrays = soft_mesh->surface_get_arrays(0); - Vector<Vector3> vertices(arrays[RS::ARRAY_VERTEX]); - - if (0 <= p_node_index && vertices.size() > p_node_index) { - r_offset = vertices[p_node_index]; - } -} - -void SoftBodyBullet::get_node_offset(int p_node_index, btVector3 &r_offset) const { - Vector3 off; - get_node_offset(p_node_index, off); - G_TO_B(off, r_offset); -} - void SoftBodyBullet::set_node_mass(int node_index, btScalar p_mass) { if (0 >= p_mass) { pin_node(node_index); @@ -259,20 +258,6 @@ void SoftBodyBullet::set_linear_stiffness(real_t p_val) { } } -void SoftBodyBullet::set_angular_stiffness(real_t p_val) { - angular_stiffness = p_val; - if (bt_soft_body) { - mat0->m_kAST = angular_stiffness; - } -} - -void SoftBodyBullet::set_volume_stiffness(real_t p_val) { - volume_stiffness = p_val; - if (bt_soft_body) { - mat0->m_kVST = volume_stiffness; - } -} - void SoftBodyBullet::set_simulation_precision(int p_val) { simulation_precision = p_val; if (bt_soft_body) { @@ -290,13 +275,6 @@ void SoftBodyBullet::set_pressure_coefficient(real_t p_val) { } } -void SoftBodyBullet::set_pose_matching_coefficient(real_t p_val) { - pose_matching_coefficient = p_val; - if (bt_soft_body) { - bt_soft_body->m_cfg.kMT = pose_matching_coefficient; - } -} - void SoftBodyBullet::set_damping_coefficient(real_t p_val) { damping_coefficient = p_val; if (bt_soft_body) { @@ -409,8 +387,6 @@ void SoftBodyBullet::setup_soft_body() { bt_soft_body->generateBendingConstraints(2, mat0); mat0->m_kLST = linear_stiffness; - mat0->m_kAST = angular_stiffness; - mat0->m_kVST = volume_stiffness; // Clusters allow to have Soft vs Soft collision but doesn't work well right now @@ -430,7 +406,6 @@ void SoftBodyBullet::setup_soft_body() { bt_soft_body->m_cfg.kDP = damping_coefficient; bt_soft_body->m_cfg.kDG = drag_coefficient; bt_soft_body->m_cfg.kPR = pressure_coefficient; - bt_soft_body->m_cfg.kMT = pose_matching_coefficient; bt_soft_body->setTotalMass(total_mass); btSoftBodyHelpers::ReoptimizeLinkOrder(bt_soft_body); diff --git a/modules/bullet/soft_body_bullet.h b/modules/bullet/soft_body_bullet.h index 23f6fba9a6..87023b2517 100644 --- a/modules/bullet/soft_body_bullet.h +++ b/modules/bullet/soft_body_bullet.h @@ -55,6 +55,8 @@ @author AndreaCatania */ +class RenderingServerHandler; + class SoftBodyBullet : public CollisionObjectBullet { private: btSoftBody *bt_soft_body = nullptr; @@ -67,10 +69,7 @@ private: int simulation_precision = 5; real_t total_mass = 1.; real_t linear_stiffness = 0.5; // [0,1] - real_t angular_stiffness = 0.5; // [0,1] - real_t volume_stiffness = 0.5; // [0,1] real_t pressure_coefficient = 0.; // [-inf,+inf] - real_t pose_matching_coefficient = 0.; // [0,1] real_t damping_coefficient = 0.01; // [0,1] real_t drag_coefficient = 0.; // [0,1] Vector<int> pinned_nodes; @@ -99,7 +98,7 @@ public: _FORCE_INLINE_ btSoftBody *get_bt_soft_body() const { return bt_soft_body; } - void update_rendering_server(class SoftBodyRenderingServerHandler *p_rendering_server_handler); + void update_rendering_server(RenderingServerHandler *p_rendering_server_handler); void set_soft_mesh(const Ref<Mesh> &p_mesh); void destroy_soft_body(); @@ -107,14 +106,12 @@ public: // Special function. This function has bad performance void set_soft_transform(const Transform &p_transform); + AABB get_bounds() const; + void move_all_nodes(const Transform &p_transform); void set_node_position(int node_index, const Vector3 &p_global_position); void set_node_position(int node_index, const btVector3 &p_global_position); void get_node_position(int node_index, Vector3 &r_position) const; - // Heavy function, Please cache this info - void get_node_offset(int node_index, Vector3 &r_offset) const; - // Heavy function, Please cache this info - void get_node_offset(int node_index, btVector3 &r_offset) const; void set_node_mass(int node_index, btScalar p_mass); btScalar get_node_mass(int node_index) const; @@ -129,21 +126,12 @@ public: void set_linear_stiffness(real_t p_val); _FORCE_INLINE_ real_t get_linear_stiffness() const { return linear_stiffness; } - void set_angular_stiffness(real_t p_val); - _FORCE_INLINE_ real_t get_angular_stiffness() const { return angular_stiffness; } - - void set_volume_stiffness(real_t p_val); - _FORCE_INLINE_ real_t get_volume_stiffness() const { return volume_stiffness; } - void set_simulation_precision(int p_val); _FORCE_INLINE_ int get_simulation_precision() const { return simulation_precision; } void set_pressure_coefficient(real_t p_val); _FORCE_INLINE_ real_t get_pressure_coefficient() const { return pressure_coefficient; } - void set_pose_matching_coefficient(real_t p_val); - _FORCE_INLINE_ real_t get_pose_matching_coefficient() const { return pose_matching_coefficient; } - void set_damping_coefficient(real_t p_val); _FORCE_INLINE_ real_t get_damping_coefficient() const { return damping_coefficient; } diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp index 8b46447f04..7387842259 100644 --- a/modules/csg/csg.cpp +++ b/modules/csg/csg.cpp @@ -931,7 +931,7 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_ // Delete the old faces in reverse index order. merge_faces_idx.sort(); - merge_faces_idx.invert(); + merge_faces_idx.reverse(); for (int i = 0; i < merge_faces_idx.size(); ++i) { faces.remove(merge_faces_idx[i]); } diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index b97ee6ce4c..77be493be9 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -1679,7 +1679,7 @@ CSGBrush *CSGPolygon3D::_build_brush() { Vector<Point2> final_polygon = polygon; if (Triangulate::get_area(final_polygon) > 0) { - final_polygon.invert(); + final_polygon.reverse(); } Vector<int> triangles = Geometry2D::triangulate_polygon(final_polygon); diff --git a/modules/fbx/data/fbx_mesh_data.cpp b/modules/fbx/data/fbx_mesh_data.cpp index 883651943e..b088dd8640 100644 --- a/modules/fbx/data/fbx_mesh_data.cpp +++ b/modules/fbx/data/fbx_mesh_data.cpp @@ -417,6 +417,7 @@ void FBXMeshData::sanitize_vertex_weights(const ImportState &state) { int bind_id = 0; for (const FBXDocParser::Cluster *cluster : fbx_skin->Clusters()) { + ERR_CONTINUE_MSG(!state.fbx_bone_map.has(cluster->TargetNode()->ID()), "Missing bone map for cluster target node with id " + uitos(cluster->TargetNode()->ID()) + "."); Ref<FBXBone> bone = state.fbx_bone_map[cluster->TargetNode()->ID()]; skeleton_to_skin_bind_id.insert(bone->godot_bone_id, bind_id); bind_id++; diff --git a/modules/fbx/data/fbx_skeleton.cpp b/modules/fbx/data/fbx_skeleton.cpp index 622b589feb..1ac4922acf 100644 --- a/modules/fbx/data/fbx_skeleton.cpp +++ b/modules/fbx/data/fbx_skeleton.cpp @@ -69,7 +69,7 @@ void FBXSkeleton::init_skeleton(const ImportState &state) { // Make sure the bone name is unique. const String bone_name = bone->bone_name; int same_name_count = 0; - for (int y = x; y < skeleton_bone_count; y++) { + for (int y = x + 1; y < skeleton_bone_count; y++) { Ref<FBXBone> other_bone = skeleton_bones[y]; if (other_bone.is_valid()) { if (other_bone->bone_name == bone_name) { diff --git a/modules/fbx/editor_scene_importer_fbx.cpp b/modules/fbx/editor_scene_importer_fbx.cpp index 6576147b2b..4d15ca93c1 100644 --- a/modules/fbx/editor_scene_importer_fbx.cpp +++ b/modules/fbx/editor_scene_importer_fbx.cpp @@ -94,7 +94,7 @@ Node3D *EditorSceneImporterFBX::import_scene(const String &p_path, uint32_t p_fl Error err; FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err); - ERR_FAIL_COND_V(!f, NULL); + ERR_FAIL_COND_V(!f, nullptr); { PackedByteArray data; @@ -260,8 +260,9 @@ T EditorSceneImporterFBX::_interpolate_track(const Vector<float> &p_times, const //could use binary search, worth it? int idx = -1; for (int i = 0; i < p_times.size(); i++) { - if (p_times[i] > p_time) + if (p_times[i] > p_time) { break; + } idx++; } @@ -334,7 +335,7 @@ Node3D *EditorSceneImporterFBX::_generate_scene( ImportState state; state.is_blender_fbx = p_is_blender_fbx; state.path = p_path; - state.animation_player = NULL; + state.animation_player = nullptr; // create new root node for scene Node3D *scene_root = memnew(Node3D); @@ -610,8 +611,9 @@ Node3D *EditorSceneImporterFBX::_generate_scene( for (const FBXDocParser::Geometry *mesh : geometry) { print_verbose("[doc] [" + itos(mesh->ID()) + "] mesh: " + fbx_node->node_name); - if (mesh == nullptr) + if (mesh == nullptr) { continue; + } const FBXDocParser::MeshGeometry *mesh_geometry = dynamic_cast<const FBXDocParser::MeshGeometry *>(mesh); if (mesh_geometry) { @@ -628,7 +630,7 @@ Node3D *EditorSceneImporterFBX::_generate_scene( mesh_data_precached->mesh_node = fbx_node; // mesh node, mesh id - mesh_node = mesh_data_precached->create_fbx_mesh(state, mesh_geometry, fbx_node->fbx_model, (p_flags & IMPORT_USE_COMPRESSION) != 0); + mesh_node = mesh_data_precached->create_fbx_mesh(state, mesh_geometry, fbx_node->fbx_model, false); if (!state.MeshNodes.has(mesh_id)) { state.MeshNodes.insert(mesh_id, fbx_node); } @@ -1132,7 +1134,7 @@ Node3D *EditorSceneImporterFBX::_generate_scene( max_duration = animation_track_time; } - rot_values.push_back(final_rotation); + rot_values.push_back(final_rotation.normalized()); rot_times.push_back(animation_track_time); } diff --git a/modules/fbx/editor_scene_importer_fbx.h b/modules/fbx/editor_scene_importer_fbx.h index 39f8648b0f..4bb2c9d21b 100644 --- a/modules/fbx/editor_scene_importer_fbx.h +++ b/modules/fbx/editor_scene_importer_fbx.h @@ -128,7 +128,7 @@ public: virtual void get_extensions(List<String> *r_extensions) const override; virtual uint32_t get_import_flags() const override; - virtual Node3D *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = NULL) override; + virtual Node3D *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; }; #endif // TOOLS_ENABLED diff --git a/modules/fbx/fbx_parser/ByteSwapper.h b/modules/fbx/fbx_parser/ByteSwapper.h index f759c9117c..5c16383974 100644 --- a/modules/fbx/fbx_parser/ByteSwapper.h +++ b/modules/fbx/fbx_parser/ByteSwapper.h @@ -264,8 +264,9 @@ struct Getter { le = !le; if (le) { ByteSwapper<T, (sizeof(T) > 1 ? true : false)>()(inout); - } else + } else { ByteSwapper<T, false>()(inout); + } } }; diff --git a/modules/fbx/fbx_parser/FBXAnimation.cpp b/modules/fbx/fbx_parser/FBXAnimation.cpp index b11e2c7f55..4ab5edebb1 100644 --- a/modules/fbx/fbx_parser/FBXAnimation.cpp +++ b/modules/fbx/fbx_parser/FBXAnimation.cpp @@ -130,7 +130,7 @@ AnimationCurve::~AnimationCurve() { AnimationCurveNode::AnimationCurveNode(uint64_t id, const ElementPtr element, const std::string &name, const Document &doc, const char *const *target_prop_whitelist /*= NULL*/, size_t whitelist_size /*= 0*/) : - Object(id, element, name), target(), doc(doc) { + Object(id, element, name), doc(doc) { const ScopePtr sc = GetRequiredScope(element); // find target node diff --git a/modules/fbx/fbx_parser/FBXDocument.cpp b/modules/fbx/fbx_parser/FBXDocument.cpp index bcf7fa1565..d156db201b 100644 --- a/modules/fbx/fbx_parser/FBXDocument.cpp +++ b/modules/fbx/fbx_parser/FBXDocument.cpp @@ -93,7 +93,7 @@ using namespace Util; // ------------------------------------------------------------------------------------------------ LazyObject::LazyObject(uint64_t id, const ElementPtr element, const Document &doc) : - doc(doc), element(element), id(id), flags() { + doc(doc), element(element), id(id) { // empty } @@ -252,7 +252,7 @@ FileGlobalSettings::~FileGlobalSettings() { // ------------------------------------------------------------------------------------------------ Document::Document(const Parser &parser, const ImportSettings &settings) : - settings(settings), parser(parser), SafeToImport(false) { + settings(settings), parser(parser) { // Cannot use array default initialization syntax because vc8 fails on it for (unsigned int &timeStamp : creationTimeStamp) { timeStamp = 0; diff --git a/modules/fbx/fbx_parser/FBXDocument.h b/modules/fbx/fbx_parser/FBXDocument.h index b810197d7e..20e635a6a4 100644 --- a/modules/fbx/fbx_parser/FBXDocument.h +++ b/modules/fbx/fbx_parser/FBXDocument.h @@ -670,7 +670,7 @@ public: uint8_t *RelinquishContent() { uint8_t *ptr = content; - content = 0; + content = nullptr; return ptr; } diff --git a/modules/fbx/fbx_parser/FBXImportSettings.h b/modules/fbx/fbx_parser/FBXImportSettings.h index 97ce496eaf..b016db174b 100644 --- a/modules/fbx/fbx_parser/FBXImportSettings.h +++ b/modules/fbx/fbx_parser/FBXImportSettings.h @@ -80,60 +80,52 @@ namespace FBXDocParser { /** FBX import settings, parts of which are publicly accessible via their corresponding AI_CONFIG constants */ struct ImportSettings { - ImportSettings() : - strictMode(true), readAllLayers(true), readAllMaterials(true), readMaterials(true), readTextures(true), readCameras(true), readLights(true), readAnimations(true), readWeights(true), preservePivots(true), optimizeEmptyAnimationCurves(true), useLegacyEmbeddedTextureNaming(false), removeEmptyBones(true), convertToMeters(false) { - // empty - } - /** enable strict mode: * - only accept fbx 2012, 2013 files * - on the slightest error, give up. * * Basically, strict mode means that the fbx file will actually - * be validated. Strict mode is off by default. */ - bool strictMode; + * be validated.*/ + bool strictMode = true; /** specifies whether all geometry layers are read and scanned for * usable data channels. The FBX spec indicates that many readers * will only read the first channel and that this is in some way * the recommended way- in reality, however, it happens a lot that - * vertex data is spread among multiple layers. The default - * value for this option is true.*/ - bool readAllLayers; + * vertex data is spread among multiple layers.*/ + bool readAllLayers = true; /** specifies whether all materials are read, or only those that * are referenced by at least one mesh. Reading all materials * may make FBX reading a lot slower since all objects - * need to be processed . - * This bit is ignored unless readMaterials=true*/ - bool readAllMaterials; + * need to be processed. + * This bit is ignored unless readMaterials=true.*/ + bool readAllMaterials = true; /** import materials (true) or skip them and assign a default - * material. The default value is true.*/ - bool readMaterials; + * material.*/ + bool readMaterials = true; - /** import embedded textures? Default value is true.*/ - bool readTextures; + /** import embedded textures?*/ + bool readTextures = true; - /** import cameras? Default value is true.*/ - bool readCameras; + /** import cameras?*/ + bool readCameras = true; - /** import light sources? Default value is true.*/ - bool readLights; + /** import light sources?*/ + bool readLights = true; /** import animations (i.e. animation curves, the node - * skeleton is always imported). Default value is true. */ - bool readAnimations; + * skeleton is always imported).*/ + bool readAnimations = true; - /** read bones (vertex weights and deform info). - * Default value is true. */ - bool readWeights; + /** read bones (vertex weights and deform info).*/ + bool readWeights = true; /** preserve transformation pivots and offsets. Since these can * not directly be represented in assimp, additional dummy * nodes will be generated. Note that settings this to false - * can make animation import a lot slower. The default value - * is true. + * can make animation import a lot slower. * * The naming scheme for the generated nodes is: * <OriginalName>_$AssimpFbx$_<TransformName> @@ -149,24 +141,21 @@ struct ImportSettings { * Scaling * Rotation **/ - bool preservePivots; + bool preservePivots = true; /** do not import animation curves that specify a constant - * values matching the corresponding node transformation. - * The default value is true. */ - bool optimizeEmptyAnimationCurves; + * values matching the corresponding node transformation.*/ + bool optimizeEmptyAnimationCurves = true; - /** use legacy naming for embedded textures eg: (*0, *1, *2) - */ - bool useLegacyEmbeddedTextureNaming; + /** use legacy naming for embedded textures eg: (*0, *1, *2).*/ + bool useLegacyEmbeddedTextureNaming = false; - /** Empty bones shall be removed - */ - bool removeEmptyBones; + /** Empty bones shall be removed.*/ + bool removeEmptyBones = true; - /** Set to true to perform a conversion from cm to meter after the import - */ - bool convertToMeters; + /** Set to true to perform a conversion from cm to meter after + * the import.*/ + bool convertToMeters = false; }; } // namespace FBXDocParser diff --git a/modules/fbx/fbx_parser/FBXMaterial.cpp b/modules/fbx/fbx_parser/FBXMaterial.cpp index 9970a2b0b1..219da1b2f4 100644 --- a/modules/fbx/fbx_parser/FBXMaterial.cpp +++ b/modules/fbx/fbx_parser/FBXMaterial.cpp @@ -171,7 +171,7 @@ Material::~Material() { // ------------------------------------------------------------------------------------------------ Texture::Texture(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name) : - Object(id, element, name), uvScaling(1.0f, 1.0f), media(nullptr) { + Object(id, element, name), uvScaling(1.0f, 1.0f) { const ScopePtr sc = GetRequiredScope(element); const ElementPtr Type = sc->GetElement("Type"); @@ -267,10 +267,10 @@ LayeredTexture::LayeredTexture(uint64_t id, const ElementPtr element, const Docu ElementPtr BlendModes = sc->GetElement("BlendModes"); ElementPtr Alphas = sc->GetElement("Alphas"); - if (BlendModes != 0) { + if (BlendModes != nullptr) { blendMode = (BlendMode)ParseTokenAsInt(GetRequiredToken(BlendModes, 0)); } - if (Alphas != 0) { + if (Alphas != nullptr) { alpha = ParseTokenAsFloat(GetRequiredToken(Alphas, 0)); } } @@ -297,7 +297,7 @@ void LayeredTexture::fillTexture(const Document &doc) { // ------------------------------------------------------------------------------------------------ Video::Video(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name) : - Object(id, element, name), contentLength(0), content(0) { + Object(id, element, name) { const ScopePtr sc = GetRequiredScope(element); const ElementPtr Type = sc->GetElement("Type"); diff --git a/modules/fbx/fbx_parser/FBXMeshGeometry.cpp b/modules/fbx/fbx_parser/FBXMeshGeometry.cpp index ccc06550fe..a28e7565c6 100644 --- a/modules/fbx/fbx_parser/FBXMeshGeometry.cpp +++ b/modules/fbx/fbx_parser/FBXMeshGeometry.cpp @@ -88,7 +88,7 @@ using namespace Util; // ------------------------------------------------------------------------------------------------ Geometry::Geometry(uint64_t id, const ElementPtr element, const std::string &name, const Document &doc) : - Object(id, element, name), skin() { + Object(id, element, name) { const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(ID(), "Deformer"); for (const Connection *con : conns) { const Skin *sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element); diff --git a/modules/fbx/fbx_parser/FBXParseTools.h b/modules/fbx/fbx_parser/FBXParseTools.h index 21472f5b7b..b4003bbec5 100644 --- a/modules/fbx/fbx_parser/FBXParseTools.h +++ b/modules/fbx/fbx_parser/FBXParseTools.h @@ -61,7 +61,7 @@ inline bool IsLineEnd(char_t c) { // Special version of the function, providing higher accuracy and safety // It is mainly used by fast_atof to prevent ugly and unwanted integer overflows. // ------------------------------------------------------------------------------------ -inline uint64_t strtoul10_64(const char *in, bool &errored, const char **out = 0, unsigned int *max_inout = 0) { +inline uint64_t strtoul10_64(const char *in, bool &errored, const char **out = nullptr, unsigned int *max_inout = nullptr) { unsigned int cur = 0; uint64_t value = 0; diff --git a/modules/fbx/fbx_parser/FBXParser.cpp b/modules/fbx/fbx_parser/FBXParser.cpp index 44c24ff926..166d98bb8c 100644 --- a/modules/fbx/fbx_parser/FBXParser.cpp +++ b/modules/fbx/fbx_parser/FBXParser.cpp @@ -216,7 +216,7 @@ Scope::~Scope() { // ------------------------------------------------------------------------------------------------ Parser::Parser(const TokenList &tokens, bool is_binary) : - tokens(tokens), last(), current(), cursor(tokens.begin()), is_binary(is_binary) { + tokens(tokens), cursor(tokens.begin()), is_binary(is_binary) { root = new_Scope(*this, true); scopes.push_back(root); } diff --git a/modules/fbx/fbx_parser/FBXProperties.cpp b/modules/fbx/fbx_parser/FBXProperties.cpp index 8ab94e1ef4..ea023b2629 100644 --- a/modules/fbx/fbx_parser/FBXProperties.cpp +++ b/modules/fbx/fbx_parser/FBXProperties.cpp @@ -145,8 +145,7 @@ std::string PeekPropertyName(const Element &element) { } // namespace // ------------------------------------------------------------------------------------------------ -PropertyTable::PropertyTable() : - templateProps(), element() { +PropertyTable::PropertyTable() { } // ------------------------------------------------------------------------------------------------ @@ -216,8 +215,9 @@ DirectPropertyMap PropertyTable::GetUnparsedProperties() const { // Loop through all the lazy properties (which is all the properties) for (const LazyPropertyMap::value_type &element : lazyProps) { // Skip parsed properties - if (props.end() != props.find(element.first)) + if (props.end() != props.find(element.first)) { continue; + } // Read the element's value. // Wrap the naked pointer (since the call site is required to acquire ownership) @@ -225,8 +225,9 @@ DirectPropertyMap PropertyTable::GetUnparsedProperties() const { Property *prop = ReadTypedProperty(element.second); // Element could not be read. Skip it. - if (!prop) + if (!prop) { continue; + } // Add to result result[element.first] = prop; diff --git a/modules/fbx/fbx_parser/FBXUtil.cpp b/modules/fbx/fbx_parser/FBXUtil.cpp index 80ea5fab4c..4295cb6f5e 100644 --- a/modules/fbx/fbx_parser/FBXUtil.cpp +++ b/modules/fbx/fbx_parser/FBXUtil.cpp @@ -122,8 +122,9 @@ static const uint8_t base64DecodeTable[128] = { uint8_t DecodeBase64(char ch) { const auto idx = static_cast<uint8_t>(ch); - if (idx > 127) + if (idx > 127) { return 255; + } return base64DecodeTable[idx]; } @@ -211,8 +212,9 @@ std::string EncodeBase64(const char *data, size_t length) { EncodeByteBlock(&finalBytes[0], encoded_string, iEncodedByte); // add '=' at the end - for (size_t i = 0; i < 4 * extraBytes / 3; i++) + for (size_t i = 0; i < 4 * extraBytes / 3; i++) { encoded_string[encodedBytes - i - 1] = '='; + } } return encoded_string; } diff --git a/modules/fbx/tools/import_utils.h b/modules/fbx/tools/import_utils.h index 6261138812..bea28ffeda 100644 --- a/modules/fbx/tools/import_utils.h +++ b/modules/fbx/tools/import_utils.h @@ -339,7 +339,7 @@ public: // } else { // Ref<Texture> texture = ResourceLoader::load(p_path); // ERR_FAIL_COND_V(texture.is_null(), Ref<Image>()); - // Ref<Image> image = texture->get_data(); + // Ref<Image> image = texture->get_image(); // ERR_FAIL_COND_V(image.is_null(), Ref<Image>()); // state.path_to_image_cache.insert(p_path, image); // return image; diff --git a/modules/fbx/tools/validation_tools.h b/modules/fbx/tools/validation_tools.h index ced100aed2..fe0c92b22f 100644 --- a/modules/fbx/tools/validation_tools.h +++ b/modules/fbx/tools/validation_tools.h @@ -65,8 +65,9 @@ protected: Error err; FileAccess *file = FileAccess::open(path, FileAccess::WRITE, &err); if (!file || err) { - if (file) + if (file) { memdelete(file); + } print_error("ValidationTracker Error - failed to create file - path: %s\n" + path); return; } diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp index 86bd8b820d..0de6b27d27 100644 --- a/modules/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative.cpp @@ -159,6 +159,8 @@ void GDNativeLibrary::_get_property_list(List<PropertyInfo> *p_list) const { } void GDNativeLibrary::set_config_file(Ref<ConfigFile> p_config_file) { + ERR_FAIL_COND(p_config_file.is_null()); + set_singleton(p_config_file->get_value("general", "singleton", default_singleton)); set_load_once(p_config_file->get_value("general", "load_once", default_load_once)); set_symbol_prefix(p_config_file->get_value("general", "symbol_prefix", default_symbol_prefix)); diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index 59b078f2b6..489083e795 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -5716,7 +5716,7 @@ ] }, { - "name": "godot_packed_glyph_array_invert", + "name": "godot_packed_glyph_array_reverse", "return_type": "void", "arguments": [ [ diff --git a/modules/gdnative/include/pluginscript/godot_pluginscript.h b/modules/gdnative/include/pluginscript/godot_pluginscript.h index cbd65e3772..b76f89cc99 100644 --- a/modules/gdnative/include/pluginscript/godot_pluginscript.h +++ b/modules/gdnative/include/pluginscript/godot_pluginscript.h @@ -56,6 +56,7 @@ typedef struct { int p_argcount, godot_variant_call_error *r_error); void (*notification)(godot_pluginscript_instance_data *p_data, int p_notification); + godot_string (*to_string)(godot_pluginscript_instance_data *p_data, godot_bool *r_valid); //this is used by script languages that keep a reference counter of their own //you can make make Ref<> not die when it reaches zero, so deleting the reference diff --git a/modules/gdnative/include/text/godot_text.h b/modules/gdnative/include/text/godot_text.h index 86fc745134..f3c50e6f87 100644 --- a/modules/gdnative/include/text/godot_text.h +++ b/modules/gdnative/include/text/godot_text.h @@ -118,6 +118,7 @@ typedef struct { godot_vector2 (*font_get_glyph_kerning)(void *, godot_rid *, uint32_t, uint32_t, int); godot_vector2 (*font_draw_glyph)(void *, godot_rid *, godot_rid *, int, const godot_vector2 *, uint32_t, const godot_color *); godot_vector2 (*font_draw_glyph_outline)(void *, godot_rid *, godot_rid *, int, int, const godot_vector2 *, uint32_t, const godot_color *); + bool (*font_get_glyph_contours)(void *, godot_rid *, int, uint32_t, godot_packed_vector3_array *, godot_packed_int32_array *, bool *); float (*font_get_oversampling)(void *); void (*font_set_oversampling)(void *, float); godot_packed_string_array (*get_system_fonts)(void *); @@ -213,7 +214,7 @@ godot_bool GDAPI godot_packed_glyph_array_has(godot_packed_glyph_array *p_self, void GDAPI godot_packed_glyph_array_sort(godot_packed_glyph_array *p_self); -void GDAPI godot_packed_glyph_array_invert(godot_packed_glyph_array *p_self); +void GDAPI godot_packed_glyph_array_reverse(godot_packed_glyph_array *p_self); void GDAPI godot_packed_glyph_array_push_back(godot_packed_glyph_array *p_self, const godot_glyph *p_data); diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index 0025f4bb06..f795bef59f 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -1729,6 +1729,46 @@ void NativeScriptLanguage::unregister_script(NativeScript *script) { Map<String, Ref<GDNative>>::Element *G = library_gdnatives.find(script->lib_path); if (G && G->get()->get_library()->is_reloadable()) { + // ONLY if the library is marked as reloadable, and no more instances of its scripts exist do we unload the library + + // First remove meta data related to the library + Map<String, Map<StringName, NativeScriptDesc>>::Element *L = library_classes.find(script->lib_path); + if (L) { + Map<StringName, NativeScriptDesc> classes = L->get(); + + for (Map<StringName, NativeScriptDesc>::Element *C = classes.front(); C; C = C->next()) { + // free property stuff first + for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element P = C->get().properties.front(); P; P = P.next()) { + if (P.get().getter.free_func) { + P.get().getter.free_func(P.get().getter.method_data); + } + + if (P.get().setter.free_func) { + P.get().setter.free_func(P.get().setter.method_data); + } + } + + // free method stuff + for (Map<StringName, NativeScriptDesc::Method>::Element *M = C->get().methods.front(); M; M = M->next()) { + if (M->get().method.free_func) { + M->get().method.free_func(M->get().method.method_data); + } + } + + // free constructor/destructor + if (C->get().create_func.free_func) { + C->get().create_func.free_func(C->get().create_func.method_data); + } + + if (C->get().destroy_func.free_func) { + C->get().destroy_func.free_func(C->get().destroy_func.method_data); + } + } + + library_classes.erase(script->lib_path); + } + + // now unload the library G->get()->terminate(); library_gdnatives.erase(G); } diff --git a/modules/gdnative/pluginscript/pluginscript_instance.cpp b/modules/gdnative/pluginscript/pluginscript_instance.cpp index 432aa80325..7f8dba0906 100644 --- a/modules/gdnative/pluginscript/pluginscript_instance.cpp +++ b/modules/gdnative/pluginscript/pluginscript_instance.cpp @@ -93,6 +93,13 @@ void PluginScriptInstance::notification(int p_notification) { _desc->notification(_data, p_notification); } +String PluginScriptInstance::to_string(bool *r_valid) { + godot_string ret = _desc->to_string(_data, r_valid); + String str_ret = *(String *)&ret; + godot_string_destroy(&ret); + return str_ret; +} + Vector<ScriptNetData> PluginScriptInstance::get_rpc_methods() const { return _script->get_rpc_methods(); } diff --git a/modules/gdnative/pluginscript/pluginscript_instance.h b/modules/gdnative/pluginscript/pluginscript_instance.h index 536eb550e0..b263c0e62c 100644 --- a/modules/gdnative/pluginscript/pluginscript_instance.h +++ b/modules/gdnative/pluginscript/pluginscript_instance.h @@ -63,6 +63,7 @@ public: virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error); virtual void notification(int p_notification); + virtual String to_string(bool *r_valid); virtual Ref<Script> get_script() const; diff --git a/modules/gdnative/text/text_server_gdnative.cpp b/modules/gdnative/text/text_server_gdnative.cpp index 7cd8de5f2e..bc4b1ac134 100644 --- a/modules/gdnative/text/text_server_gdnative.cpp +++ b/modules/gdnative/text/text_server_gdnative.cpp @@ -359,6 +359,12 @@ Vector2 TextServerGDNative::font_draw_glyph_outline(RID p_font, RID p_canvas, in return advance; } +bool TextServerGDNative::font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const { + ERR_FAIL_COND_V(interface == nullptr, false); + ERR_FAIL_COND_V(interface->font_get_glyph_contours == nullptr, false); + return interface->font_get_glyph_contours(data, (godot_rid *)&p_font, p_size, p_index, (godot_packed_vector3_array *)&r_points, (godot_packed_int32_array *)&r_contours, (bool *)&r_orientation); +} + float TextServerGDNative::font_get_oversampling() const { ERR_FAIL_COND_V(interface == nullptr, 1.f); return interface->font_get_oversampling(data); @@ -841,9 +847,9 @@ void GDAPI godot_packed_glyph_array_sort(godot_packed_glyph_array *p_self) { self->sort(); } -void GDAPI godot_packed_glyph_array_invert(godot_packed_glyph_array *p_self) { +void GDAPI godot_packed_glyph_array_reverse(godot_packed_glyph_array *p_self) { Vector<TextServer::Glyph> *self = (Vector<TextServer::Glyph> *)p_self; - self->invert(); + self->reverse(); } void GDAPI godot_packed_glyph_array_push_back(godot_packed_glyph_array *p_self, const godot_glyph *p_data) { diff --git a/modules/gdnative/text/text_server_gdnative.h b/modules/gdnative/text/text_server_gdnative.h index 931bb44885..7e42b16fe1 100644 --- a/modules/gdnative/text/text_server_gdnative.h +++ b/modules/gdnative/text/text_server_gdnative.h @@ -126,6 +126,8 @@ public: virtual Vector2 font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const override; virtual Vector2 font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const override; + virtual bool font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const override; + virtual float font_get_oversampling() const override; virtual void font_set_oversampling(float p_oversampling) override; diff --git a/modules/gdnative/xr/xr_interface_gdnative.cpp b/modules/gdnative/xr/xr_interface_gdnative.cpp index 5bbf70174c..122cb5849b 100644 --- a/modules/gdnative/xr/xr_interface_gdnative.cpp +++ b/modules/gdnative/xr/xr_interface_gdnative.cpp @@ -301,7 +301,8 @@ godot_int GDAPI godot_xr_add_controller(char *p_device_name, godot_int p_hand, g Input *input = Input::get_singleton(); ERR_FAIL_NULL_V(input, 0); - XRPositionalTracker *new_tracker = memnew(XRPositionalTracker); + Ref<XRPositionalTracker> new_tracker; + new_tracker.instance(); new_tracker->set_tracker_name(p_device_name); new_tracker->set_tracker_type(XRServer::TRACKER_CONTROLLER); if (p_hand == 1) { @@ -340,8 +341,8 @@ void GDAPI godot_xr_remove_controller(godot_int p_controller_id) { Input *input = Input::get_singleton(); ERR_FAIL_NULL(input); - XRPositionalTracker *remove_tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id); - if (remove_tracker != nullptr) { + Ref<XRPositionalTracker> remove_tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id); + if (remove_tracker.is_valid()) { // unset our joystick if applicable int joyid = remove_tracker->get_joy_id(); if (joyid != -1) { @@ -351,7 +352,7 @@ void GDAPI godot_xr_remove_controller(godot_int p_controller_id) { // remove our tracker from our server xr_server->remove_tracker(remove_tracker); - memdelete(remove_tracker); + remove_tracker.unref(); } } @@ -359,8 +360,8 @@ void GDAPI godot_xr_set_controller_transform(godot_int p_controller_id, godot_tr XRServer *xr_server = XRServer::get_singleton(); ERR_FAIL_NULL(xr_server); - XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id); - if (tracker != nullptr) { + Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id); + if (tracker.is_valid()) { Transform *transform = (Transform *)p_transform; if (p_tracks_orientation) { tracker->set_orientation(transform->basis); @@ -378,8 +379,8 @@ void GDAPI godot_xr_set_controller_button(godot_int p_controller_id, godot_int p Input *input = Input::get_singleton(); ERR_FAIL_NULL(input); - XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id); - if (tracker != nullptr) { + Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id); + if (tracker.is_valid()) { int joyid = tracker->get_joy_id(); if (joyid != -1) { input->joy_button(joyid, p_button, p_is_pressed); @@ -394,11 +395,11 @@ void GDAPI godot_xr_set_controller_axis(godot_int p_controller_id, godot_int p_a Input *input = Input::get_singleton(); ERR_FAIL_NULL(input); - XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id); - if (tracker != nullptr) { + Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id); + if (tracker.is_valid()) { int joyid = tracker->get_joy_id(); if (joyid != -1) { - Input::JoyAxis jx; + Input::JoyAxisValue jx; jx.min = p_can_be_negative ? -1 : 0; jx.value = p_value; input->joy_axis(joyid, p_axis, jx); @@ -410,8 +411,8 @@ godot_float GDAPI godot_xr_get_controller_rumble(godot_int p_controller_id) { XRServer *xr_server = XRServer::get_singleton(); ERR_FAIL_NULL_V(xr_server, 0.0); - XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id); - if (tracker != nullptr) { + Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id); + if (tracker.is_valid()) { return tracker->get_rumble(); } diff --git a/modules/gdnavigation/nav_map.cpp b/modules/gdnavigation/nav_map.cpp index 80f367f3a6..464082221f 100644 --- a/modules/gdnavigation/nav_map.cpp +++ b/modules/gdnavigation/nav_map.cpp @@ -351,7 +351,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p path.push_back(begin_point); } - path.invert(); + path.reverse(); } else { path.push_back(end_point); @@ -363,7 +363,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p np_id = navigation_polys[np_id].back_navigation_poly_id; } - path.invert(); + path.reverse(); } return path; diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index a129b73c1a..c9c5d00aa5 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -276,7 +276,7 @@ void GDScript::_get_script_property_list(List<PropertyInfo> *r_list, bool p_incl } msort.sort(); - msort.invert(); + msort.reverse(); for (int i = 0; i < msort.size(); i++) { props.push_front(sptr->member_info[msort[i].name]); } @@ -1310,21 +1310,29 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) { return true; //function exists, call was successful } } else { - if (!member->data_type.is_type(p_value)) { - // Try conversion - Callable::CallError ce; - const Variant *value = &p_value; - Variant converted; - Variant::construct(member->data_type.builtin_type, converted, &value, 1, ce); - if (ce.error == Callable::CallError::CALL_OK) { - members.write[member->index] = converted; - return true; - } else { - return false; + if (member->data_type.has_type) { + if (member->data_type.builtin_type == Variant::ARRAY && member->data_type.has_container_element_type()) { + // Typed array. + if (p_value.get_type() == Variant::ARRAY) { + return VariantInternal::get_array(&members.write[member->index])->typed_assign(p_value); + } else { + return false; + } + } else if (!member->data_type.is_type(p_value)) { + // Try conversion + Callable::CallError ce; + const Variant *value = &p_value; + Variant converted; + Variant::construct(member->data_type.builtin_type, converted, &value, 1, ce); + if (ce.error == Callable::CallError::CALL_OK) { + members.write[member->index] = converted; + return true; + } else { + return false; + } } - } else { - members.write[member->index] = p_value; } + members.write[member->index] = p_value; } return true; } @@ -1494,7 +1502,7 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const } msort.sort(); - msort.invert(); + msort.reverse(); for (int i = 0; i < msort.size(); i++) { props.push_front(sptr->member_info[msort[i].name]); } @@ -2293,7 +2301,7 @@ GDScriptLanguage::~GDScriptLanguage() { script->unreference(); } - singleton = NULL; + singleton = nullptr; } void GDScriptLanguage::add_orphan_subclass(const String &p_qualified_name, const ObjectID &p_subclass) { diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index a6138cc564..bdca64c146 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -39,40 +39,6 @@ #include "gdscript.h" #include "gdscript_utility_functions.h" -// TODO: Move this to a central location (maybe core?). -static HashMap<StringName, StringName> underscore_map; -static const char *underscore_classes[] = { - "ClassDB", - "Directory", - "Engine", - "File", - "Geometry", - "GodotSharp", - "JSON", - "Marshalls", - "Mutex", - "OS", - "ResourceLoader", - "ResourceSaver", - "Semaphore", - "Thread", - "VisualScriptEditor", - nullptr, -}; -static StringName get_real_class_name(const StringName &p_source) { - if (underscore_map.is_empty()) { - const char **class_name = underscore_classes; - while (*class_name != nullptr) { - underscore_map[*class_name] = String("_") + *class_name; - class_name++; - } - } - if (underscore_map.has(p_source)) { - return underscore_map[p_source]; - } - return p_source; -} - static MethodInfo info_from_utility_func(const StringName &p_function) { ERR_FAIL_COND_V(!Variant::has_utility_function(p_function), MethodInfo()); @@ -106,10 +72,6 @@ static MethodInfo info_from_utility_func(const StringName &p_function) { return info; } -void GDScriptAnalyzer::cleanup() { - underscore_map.clear(); -} - static GDScriptParser::DataType make_callable_type(const MethodInfo &p_info) { GDScriptParser::DataType type; type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; @@ -150,7 +112,7 @@ static GDScriptParser::DataType make_native_enum_type(const StringName &p_native type.is_meta_type = true; List<StringName> enum_values; - StringName real_native_name = get_real_class_name(p_native_class); + StringName real_native_name = GDScriptParser::get_real_class_name(p_native_class); ClassDB::get_enum_constants(real_native_name, p_enum_name, &enum_values); for (const List<StringName>::Element *E = enum_values.front(); E != nullptr; E = E->next()) { @@ -267,7 +229,7 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class, push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", name), p_class); return err; } - } else if (class_exists(name) && ClassDB::can_instance(get_real_class_name(name))) { + } else if (class_exists(name) && ClassDB::can_instance(GDScriptParser::get_real_class_name(name))) { base.kind = GDScriptParser::DataType::NATIVE; base.native_type = name; } else { @@ -413,6 +375,14 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type } result.kind = GDScriptParser::DataType::BUILTIN; result.builtin_type = GDScriptParser::get_builtin_type(first); + + if (result.builtin_type == Variant::ARRAY) { + GDScriptParser::DataType container_type = resolve_datatype(p_type->container_type); + + if (container_type.kind != GDScriptParser::DataType::VARIANT) { + result.set_container_element_type(container_type); + } + } } else if (class_exists(first)) { // Native engine classes. result.kind = GDScriptParser::DataType::NATIVE; @@ -436,7 +406,7 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type return GDScriptParser::DataType(); } result = ref->get_parser()->head->get_datatype(); - } else if (ClassDB::has_enum(get_real_class_name(parser->current_class->base_type.native_type), first)) { + } else if (ClassDB::has_enum(GDScriptParser::get_real_class_name(parser->current_class->base_type.native_type), first)) { // Native enum in current class. result = make_native_enum_type(parser->current_class->base_type.native_type, first); } else { @@ -499,7 +469,7 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type } } else if (result.kind == GDScriptParser::DataType::NATIVE) { // Only enums allowed for native. - if (ClassDB::has_enum(get_real_class_name(result.native_type), p_type->type_chain[1]->name)) { + if (ClassDB::has_enum(GDScriptParser::get_real_class_name(result.native_type), p_type->type_chain[1]->name)) { if (p_type->type_chain.size() > 2) { push_error(R"(Enums cannot contain nested types.)", p_type->type_chain[2]); } else { @@ -513,6 +483,10 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type } } + if (result.builtin_type != Variant::ARRAY && p_type->container_type != nullptr) { + push_error("Only arrays can specify the collection element type.", p_type); + } + p_type->set_datatype(result); return result; } @@ -535,9 +509,23 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas datatype.kind = GDScriptParser::DataType::VARIANT; datatype.type_source = GDScriptParser::DataType::UNDETECTED; + GDScriptParser::DataType specified_type; + if (member.variable->datatype_specifier != nullptr) { + specified_type = resolve_datatype(member.variable->datatype_specifier); + specified_type.is_meta_type = false; + } + if (member.variable->initializer != nullptr) { member.variable->set_datatype(datatype); // Allow recursive usage. reduce_expression(member.variable->initializer); + if ((member.variable->infer_datatype || (member.variable->datatype_specifier != nullptr && specified_type.has_container_element_type())) && member.variable->initializer->type == GDScriptParser::Node::ARRAY) { + // Typed array. + GDScriptParser::ArrayNode *array = static_cast<GDScriptParser::ArrayNode *>(member.variable->initializer); + // Can only infer typed array if it has elements. + if ((member.variable->infer_datatype && array->elements.size() > 0) || member.variable->datatype_specifier != nullptr) { + update_array_literal_element_type(specified_type, array); + } + } datatype = member.variable->initializer->get_datatype(); if (datatype.type_source != GDScriptParser::DataType::UNDETECTED) { datatype.type_source = GDScriptParser::DataType::INFERRED; @@ -545,8 +533,7 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas } if (member.variable->datatype_specifier != nullptr) { - datatype = resolve_datatype(member.variable->datatype_specifier); - datatype.is_meta_type = false; + datatype = specified_type; if (member.variable->initializer != nullptr) { if (!is_type_compatible(datatype, member.variable->initializer->get_datatype(), true)) { @@ -582,37 +569,32 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas datatype.is_constant = false; member.variable->set_datatype(datatype); - if (!datatype.has_no_type()) { - // TODO: Move this out into a routine specific to validate annotations. - if (member.variable->export_info.hint == PROPERTY_HINT_TYPE_STRING) { - // @export annotation. - switch (datatype.kind) { - case GDScriptParser::DataType::BUILTIN: - member.variable->export_info.hint_string = Variant::get_type_name(datatype.builtin_type); - break; - case GDScriptParser::DataType::NATIVE: - if (ClassDB::is_parent_class(get_real_class_name(datatype.native_type), "Resource")) { - member.variable->export_info.hint = PROPERTY_HINT_RESOURCE_TYPE; - member.variable->export_info.hint_string = get_real_class_name(datatype.native_type); - } else { - push_error(R"(Export type can only be built-in or a resource.)", member.variable); - } - break; - default: - // TODO: Allow custom user resources. - push_error(R"(Export type can only be built-in or a resource.)", member.variable); - break; - } - } + + // Apply annotations. + for (List<GDScriptParser::AnnotationNode *>::Element *E = member.variable->annotations.front(); E; E = E->next()) { + E->get()->apply(parser, member.variable); } } break; case GDScriptParser::ClassNode::Member::CONSTANT: { reduce_expression(member.constant->initializer); + GDScriptParser::DataType specified_type; + + if (member.constant->datatype_specifier != nullptr) { + specified_type = resolve_datatype(member.constant->datatype_specifier); + specified_type.is_meta_type = false; + } + GDScriptParser::DataType datatype = member.constant->get_datatype(); if (member.constant->initializer) { if (member.constant->initializer->type == GDScriptParser::Node::ARRAY) { - const_fold_array(static_cast<GDScriptParser::ArrayNode *>(member.constant->initializer)); + GDScriptParser::ArrayNode *array = static_cast<GDScriptParser::ArrayNode *>(member.constant->initializer); + const_fold_array(array); + + // Can only infer typed array if it has elements. + if (array->elements.size() > 0 || (member.constant->datatype_specifier != nullptr && specified_type.has_container_element_type())) { + update_array_literal_element_type(specified_type, array); + } } else if (member.constant->initializer->type == GDScriptParser::Node::DICTIONARY) { const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(member.constant->initializer)); } @@ -622,8 +604,7 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas } if (member.constant->datatype_specifier != nullptr) { - datatype = resolve_datatype(member.constant->datatype_specifier); - datatype.is_meta_type = false; + datatype = specified_type; if (!is_type_compatible(datatype, member.constant->initializer->get_datatype(), true)) { push_error(vformat(R"(Value of type "%s" cannot be initialized to constant of type "%s".)", member.constant->initializer->get_datatype().to_string(), datatype.to_string()), member.constant->initializer); @@ -637,6 +618,11 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas datatype.is_constant = true; member.constant->set_datatype(datatype); + + // Apply annotations. + for (List<GDScriptParser::AnnotationNode *>::Element *E = member.constant->annotations.front(); E; E = E->next()) { + E->get()->apply(parser, member.constant); + } } break; case GDScriptParser::ClassNode::Member::SIGNAL: { for (int j = 0; j < member.signal->parameters.size(); j++) { @@ -651,6 +637,11 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas signal_type.builtin_type = Variant::SIGNAL; member.signal->set_datatype(signal_type); + + // Apply annotations. + for (List<GDScriptParser::AnnotationNode *>::Element *E = member.signal->annotations.front(); E; E = E->next()) { + E->get()->apply(parser, member.signal); + } } break; case GDScriptParser::ClassNode::Member::ENUM: { GDScriptParser::DataType enum_type; @@ -693,6 +684,11 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas current_enum = nullptr; member.m_enum->set_datatype(enum_type); + + // Apply annotations. + for (List<GDScriptParser::AnnotationNode *>::Element *E = member.m_enum->annotations.front(); E; E = E->next()) { + E->get()->apply(parser, member.m_enum); + } } break; case GDScriptParser::ClassNode::Member::FUNCTION: resolve_function_signature(member.function); @@ -761,6 +757,11 @@ void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class) { } resolve_function_body(member.function); + + // Apply annotations. + for (List<GDScriptParser::AnnotationNode *>::Element *E = member.function->annotations.front(); E; E = E->next()) { + E->get()->apply(parser, member.function); + } } parser->current_class = previous_class; @@ -1092,8 +1093,23 @@ void GDScriptAnalyzer::resolve_variable(GDScriptParser::VariableNode *p_variable GDScriptParser::DataType type; type.kind = GDScriptParser::DataType::VARIANT; // By default. + GDScriptParser::DataType specified_type; + if (p_variable->datatype_specifier != nullptr) { + specified_type = resolve_datatype(p_variable->datatype_specifier); + specified_type.is_meta_type = false; + } + if (p_variable->initializer != nullptr) { reduce_expression(p_variable->initializer); + if ((p_variable->infer_datatype || (p_variable->datatype_specifier != nullptr && specified_type.has_container_element_type())) && p_variable->initializer->type == GDScriptParser::Node::ARRAY) { + // Typed array. + GDScriptParser::ArrayNode *array = static_cast<GDScriptParser::ArrayNode *>(p_variable->initializer); + // Can only infer typed array if it has elements. + if ((p_variable->infer_datatype && array->elements.size() > 0) || p_variable->datatype_specifier != nullptr) { + update_array_literal_element_type(specified_type, array); + } + } + type = p_variable->initializer->get_datatype(); if (p_variable->infer_datatype) { @@ -1117,7 +1133,7 @@ void GDScriptAnalyzer::resolve_variable(GDScriptParser::VariableNode *p_variable } if (p_variable->datatype_specifier != nullptr) { - type = resolve_datatype(p_variable->datatype_specifier); + type = specified_type; type.is_meta_type = false; if (p_variable->initializer != nullptr) { @@ -1362,6 +1378,12 @@ void GDScriptAnalyzer::resolve_return(GDScriptParser::ReturnNode *p_return) { if (p_return->return_value != nullptr) { reduce_expression(p_return->return_value); + if (p_return->return_value->type == GDScriptParser::Node::ARRAY) { + // Check if assigned value is an array literal, so we can make it a typed array too if appropriate. + if (parser->current_function->get_datatype().has_container_element_type() && p_return->return_value->type == GDScriptParser::Node::ARRAY) { + update_array_literal_element_type(parser->current_function->get_datatype(), static_cast<GDScriptParser::ArrayNode *>(p_return->return_value)); + } + } result = p_return->return_value->get_datatype(); } else { // Return type is null by default. @@ -1498,6 +1520,52 @@ void GDScriptAnalyzer::reduce_array(GDScriptParser::ArrayNode *p_array) { p_array->set_datatype(arr_type); } +// When an array literal is stored (or passed as function argument) to a typed context, we then assume the array is typed. +// This function determines which type is that (if any). +void GDScriptAnalyzer::update_array_literal_element_type(const GDScriptParser::DataType &p_base_type, GDScriptParser::ArrayNode *p_array_literal) { + GDScriptParser::DataType array_type = p_array_literal->get_datatype(); + if (p_array_literal->elements.size() == 0) { + // Empty array literal, just make the same type as the storage. + array_type.set_container_element_type(p_base_type.get_container_element_type()); + } else { + // Check if elements match. + bool all_same_type = true; + bool all_have_type = true; + + GDScriptParser::DataType element_type; + for (int i = 0; i < p_array_literal->elements.size(); i++) { + if (i == 0) { + element_type = p_array_literal->elements[0]->get_datatype(); + } else { + GDScriptParser::DataType this_element_type = p_array_literal->elements[i]->get_datatype(); + if (this_element_type.has_no_type()) { + all_same_type = false; + all_have_type = false; + break; + } else if (element_type != this_element_type) { + if (!is_type_compatible(element_type, this_element_type, false)) { + if (is_type_compatible(this_element_type, element_type, false)) { + // This element is a super-type to the previous type, so we use the super-type. + element_type = this_element_type; + } else { + // It's incompatible. + all_same_type = false; + break; + } + } + } + } + } + if (all_same_type) { + array_type.set_container_element_type(element_type); + } else if (all_have_type) { + push_error(vformat(R"(Variant array is not compatible with an array of type "%s".)", p_base_type.get_container_element_type().to_string()), p_array_literal); + } + } + // Update the type on the value itself. + p_array_literal->set_datatype(array_type); +} + void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assignment) { reduce_expression(p_assignment->assignee); reduce_expression(p_assignment->assigned_value); @@ -1506,24 +1574,33 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig return; } - if (p_assignment->assignee->get_datatype().is_constant) { + GDScriptParser::DataType assignee_type = p_assignment->assignee->get_datatype(); + + // Check if assigned value is an array literal, so we can make it a typed array too if appropriate. + if (assignee_type.has_container_element_type() && p_assignment->assigned_value->type == GDScriptParser::Node::ARRAY) { + update_array_literal_element_type(assignee_type, static_cast<GDScriptParser::ArrayNode *>(p_assignment->assigned_value)); + } + + GDScriptParser::DataType assigned_value_type = p_assignment->assigned_value->get_datatype(); + + if (assignee_type.is_constant) { push_error("Cannot assign a new value to a constant.", p_assignment->assignee); } - if (!p_assignment->assignee->get_datatype().is_variant() && !p_assignment->assigned_value->get_datatype().is_variant()) { + if (!assignee_type.is_variant() && !assigned_value_type.is_variant()) { bool compatible = true; - GDScriptParser::DataType op_type = p_assignment->assigned_value->get_datatype(); + GDScriptParser::DataType op_type = assigned_value_type; if (p_assignment->operation != GDScriptParser::AssignmentNode::OP_NONE) { - op_type = get_operation_type(p_assignment->variant_op, p_assignment->assignee->get_datatype(), p_assignment->assigned_value->get_datatype(), compatible, p_assignment->assigned_value); + op_type = get_operation_type(p_assignment->variant_op, assignee_type, assigned_value_type, compatible, p_assignment->assigned_value); } if (compatible) { - compatible = is_type_compatible(p_assignment->assignee->get_datatype(), op_type, true); + compatible = is_type_compatible(assignee_type, op_type, true); if (!compatible) { - if (p_assignment->assignee->get_datatype().is_hard_type()) { + if (assignee_type.is_hard_type()) { // Try reverse test since it can be a masked subtype. - if (!is_type_compatible(op_type, p_assignment->assignee->get_datatype(), true)) { - push_error(vformat(R"(Cannot assign a value of type "%s" to a target of type "%s".)", p_assignment->assigned_value->get_datatype().to_string(), p_assignment->assignee->get_datatype().to_string()), p_assignment->assigned_value); + if (!is_type_compatible(op_type, assignee_type, true)) { + push_error(vformat(R"(Cannot assign a value of type "%s" to a target of type "%s".)", assigned_value_type.to_string(), assignee_type.to_string()), p_assignment->assigned_value); } else { // TODO: Add warning. mark_node_unsafe(p_assignment); @@ -1534,11 +1611,11 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig } } } else { - push_error(vformat(R"(Invalid operands "%s" and "%s" for assignment operator.)", p_assignment->assignee->get_datatype().to_string(), p_assignment->assigned_value->get_datatype().to_string()), p_assignment); + push_error(vformat(R"(Invalid operands "%s" and "%s" for assignment operator.)", assignee_type.to_string(), assigned_value_type.to_string()), p_assignment); } } - if (p_assignment->assignee->get_datatype().has_no_type() || p_assignment->assigned_value->get_datatype().is_variant()) { + if (assignee_type.has_no_type() || assigned_value_type.is_variant()) { mark_node_unsafe(p_assignment); } @@ -1558,7 +1635,7 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig case GDScriptParser::IdentifierNode::LOCAL_VARIABLE: { GDScriptParser::DataType id_type = identifier->variable_source->get_datatype(); if (!id_type.is_hard_type()) { - id_type = p_assignment->assigned_value->get_datatype(); + id_type = assigned_value_type; id_type.type_source = GDScriptParser::DataType::INFERRED; id_type.is_constant = false; identifier->variable_source->set_datatype(id_type); @@ -1567,7 +1644,7 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig case GDScriptParser::IdentifierNode::LOCAL_ITERATOR: { GDScriptParser::DataType id_type = identifier->bind_source->get_datatype(); if (!id_type.is_hard_type()) { - id_type = p_assignment->assigned_value->get_datatype(); + id_type = assigned_value_type; id_type.type_source = GDScriptParser::DataType::INFERRED; id_type.is_constant = false; identifier->variable_source->set_datatype(id_type); @@ -1579,12 +1656,10 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig } } - GDScriptParser::DataType assignee_type = p_assignment->assignee->get_datatype(); - GDScriptParser::DataType assigned_type = p_assignment->assigned_value->get_datatype(); #ifdef DEBUG_ENABLED - if (p_assignment->assigned_value->type == GDScriptParser::Node::CALL && assigned_type.kind == GDScriptParser::DataType::BUILTIN && assigned_type.builtin_type == Variant::NIL) { + if (p_assignment->assigned_value->type == GDScriptParser::Node::CALL && assigned_value_type.kind == GDScriptParser::DataType::BUILTIN && assigned_value_type.builtin_type == Variant::NIL) { parser->push_warning(p_assignment->assigned_value, GDScriptWarning::VOID_ASSIGNMENT, static_cast<GDScriptParser::CallNode *>(p_assignment->assigned_value)->function_name); - } else if (assignee_type.is_hard_type() && assignee_type.builtin_type == Variant::INT && assigned_type.builtin_type == Variant::FLOAT) { + } else if (assignee_type.is_hard_type() && assignee_type.builtin_type == Variant::INT && assigned_value_type.builtin_type == Variant::FLOAT) { parser->push_warning(p_assignment->assigned_value, GDScriptWarning::NARROWING_CONVERSION); } #endif @@ -1728,8 +1803,12 @@ void GDScriptAnalyzer::reduce_binary_op(GDScriptParser::BinaryOpNode *p_binary_o void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool is_await) { bool all_is_constant = true; + Map<int, GDScriptParser::ArrayNode *> arrays; // For array literal to potentially type when passing. for (int i = 0; i < p_call->arguments.size(); i++) { reduce_expression(p_call->arguments[i]); + if (p_call->arguments[i]->type == GDScriptParser::Node::ARRAY) { + arrays[i] = static_cast<GDScriptParser::ArrayNode *>(p_call->arguments[i]); + } all_is_constant = all_is_constant && p_call->arguments[i]->is_constant; } @@ -2007,6 +2086,13 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool is_awa List<GDScriptParser::DataType> par_types; if (get_function_signature(p_call, base_type, p_call->function_name, return_type, par_types, default_arg_count, is_static, is_vararg)) { + // If the function require typed arrays we must make literals be typed. + for (Map<int, GDScriptParser::ArrayNode *>::Element *E = arrays.front(); E; E = E->next()) { + int index = E->key(); + if (index < par_types.size() && par_types[index].has_container_element_type()) { + update_array_literal_element_type(par_types[index], E->get()); + } + } validate_call_arg(par_types, default_arg_count, is_vararg, p_call); if (is_self && parser->current_function != nullptr && parser->current_function->is_static && !is_static) { @@ -2131,7 +2217,7 @@ void GDScriptAnalyzer::reduce_get_node(GDScriptParser::GetNodeNode *p_get_node) result.native_type = "Node"; result.builtin_type = Variant::OBJECT; - if (!ClassDB::is_parent_class(get_real_class_name(parser->current_class->base_type.native_type), result.native_type)) { + if (!ClassDB::is_parent_class(GDScriptParser::get_real_class_name(parser->current_class->base_type.native_type), result.native_type)) { push_error(R"*(Cannot use shorthand "get_node()" notation ("$") on a class that isn't a node.)*", p_get_node); } @@ -2297,7 +2383,7 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod } // Check native members. - const StringName &native = get_real_class_name(base.native_type); + const StringName &native = GDScriptParser::get_real_class_name(base.native_type); if (class_exists(native)) { PropertyInfo prop_info; @@ -2752,11 +2838,20 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri case Variant::TRANSFORM: case Variant::PLANE: case Variant::COLOR: - case Variant::ARRAY: case Variant::DICTIONARY: result_type.kind = GDScriptParser::DataType::VARIANT; result_type.type_source = GDScriptParser::DataType::UNDETECTED; break; + // Can have an element type. + case Variant::ARRAY: + if (base_type.has_container_element_type()) { + result_type = base_type.get_container_element_type(); + result_type.type_source = base_type.type_source; + } else { + result_type.kind = GDScriptParser::DataType::VARIANT; + result_type.type_source = GDScriptParser::DataType::UNDETECTED; + } + break; // Here for completeness. case Variant::OBJECT: case Variant::VARIANT_MAX: @@ -2979,6 +3074,34 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_property(const PropertyInfo result.native_type = p_property.class_name == StringName() ? "Object" : p_property.class_name; } else { result.kind = GDScriptParser::DataType::BUILTIN; + result.builtin_type = p_property.type; + if (p_property.type == Variant::ARRAY && p_property.hint == PROPERTY_HINT_ARRAY_TYPE) { + // Check element type. + StringName elem_type_name = p_property.hint_string; + GDScriptParser::DataType elem_type; + elem_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; + + Variant::Type elem_builtin_type = GDScriptParser::get_builtin_type(elem_type_name); + if (elem_builtin_type < Variant::VARIANT_MAX) { + // Builtin type. + elem_type.kind = GDScriptParser::DataType::BUILTIN; + elem_type.builtin_type = elem_builtin_type; + } else if (class_exists(elem_type_name)) { + elem_type.kind = GDScriptParser::DataType::NATIVE; + elem_type.builtin_type = Variant::OBJECT; + elem_type.native_type = p_property.hint_string; + } else if (ScriptServer::is_global_class(elem_type_name)) { + // Just load this as it shouldn't be a GDScript. + Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(elem_type_name)); + elem_type.kind = GDScriptParser::DataType::SCRIPT; + elem_type.builtin_type = Variant::OBJECT; + elem_type.native_type = script->get_instance_base_type(); + elem_type.script_type = script; + } else { + ERR_FAIL_V_MSG(result, "Could not find element type from property hint of a typed array."); + } + result.set_container_element_type(elem_type); + } } return result; } @@ -3084,7 +3207,7 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, GD return true; } - StringName real_native = get_real_class_name(base_native); + StringName real_native = GDScriptParser::get_real_class_name(base_native); MethodInfo info; if (ClassDB::get_method_info(real_native, function_name, &info)) { @@ -3179,7 +3302,7 @@ bool GDScriptAnalyzer::is_shadowing(GDScriptParser::IdentifierNode *p_local, con StringName parent = base_native; while (parent != StringName()) { - StringName real_class_name = get_real_class_name(parent); + StringName real_class_name = GDScriptParser::get_real_class_name(parent); if (ClassDB::has_method(real_class_name, name, true)) { parser->push_warning(p_local, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_local->name, "method", parent); return true; @@ -3257,6 +3380,18 @@ bool GDScriptAnalyzer::is_type_compatible(const GDScriptParser::DataType &p_targ // Enum value is also integer. valid = true; } + if (valid && p_target.builtin_type == Variant::ARRAY && p_source.builtin_type == Variant::ARRAY) { + // Check the element type. + if (p_target.has_container_element_type()) { + if (!p_source.has_container_element_type()) { + // TODO: Maybe this is valid but unsafe? + // Variant array can't be appended to typed array. + valid = false; + } else { + valid = is_type_compatible(p_target.get_container_element_type(), p_source.get_container_element_type(), false); + } + } + } return valid; } @@ -3329,14 +3464,14 @@ bool GDScriptAnalyzer::is_type_compatible(const GDScriptParser::DataType &p_targ } // Get underscore-prefixed version for some classes. - src_native = get_real_class_name(src_native); + src_native = GDScriptParser::get_real_class_name(src_native); switch (p_target.kind) { case GDScriptParser::DataType::NATIVE: { if (p_target.is_meta_type) { return ClassDB::is_parent_class(src_native, GDScriptNativeClass::get_class_static()); } - StringName tgt_native = get_real_class_name(p_target.native_type); + StringName tgt_native = GDScriptParser::get_real_class_name(p_target.native_type); return ClassDB::is_parent_class(src_native, tgt_native); } case GDScriptParser::DataType::SCRIPT: @@ -3385,8 +3520,8 @@ void GDScriptAnalyzer::mark_node_unsafe(const GDScriptParser::Node *p_node) { #endif } -bool GDScriptAnalyzer::class_exists(const StringName &p_class) { - StringName real_name = get_real_class_name(p_class); +bool GDScriptAnalyzer::class_exists(const StringName &p_class) const { + StringName real_name = GDScriptParser::get_real_class_name(p_class); return ClassDB::class_exists(real_name) && ClassDB::is_class_exposed(real_name); } diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h index dab5b032a3..8430d3f4a5 100644 --- a/modules/gdscript/gdscript_analyzer.h +++ b/modules/gdscript/gdscript_analyzer.h @@ -103,10 +103,11 @@ class GDScriptAnalyzer { bool validate_call_arg(const MethodInfo &p_method, const GDScriptParser::CallNode *p_call); GDScriptParser::DataType get_operation_type(Variant::Operator p_operation, const GDScriptParser::DataType &p_a, const GDScriptParser::DataType &p_b, bool &r_valid, const GDScriptParser::Node *p_source); GDScriptParser::DataType get_operation_type(Variant::Operator p_operation, const GDScriptParser::DataType &p_a, bool &r_valid, const GDScriptParser::Node *p_source); + void update_array_literal_element_type(const GDScriptParser::DataType &p_base_type, GDScriptParser::ArrayNode *p_array_literal); bool is_type_compatible(const GDScriptParser::DataType &p_target, const GDScriptParser::DataType &p_source, bool p_allow_implicit_conversion = false) const; void push_error(const String &p_message, const GDScriptParser::Node *p_origin); void mark_node_unsafe(const GDScriptParser::Node *p_node); - bool class_exists(const StringName &p_class); + bool class_exists(const StringName &p_class) const; Ref<GDScriptParserRef> get_parser_for(const String &p_path); #ifdef DEBUG_ENABLED bool is_shadowing(GDScriptParser::IdentifierNode *p_local, const String &p_context); @@ -119,8 +120,6 @@ public: Error analyze(); GDScriptAnalyzer(GDScriptParser *p_parser); - - static void cleanup(); }; #endif // GDSCRIPT_ANALYZER_H diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index 58c6b31a77..ec1116197e 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -100,7 +100,7 @@ void GDScriptByteCodeGenerator::start_parameters() { } void GDScriptByteCodeGenerator::end_parameters() { - function->default_arguments.invert(); + function->default_arguments.reverse(); } void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, MultiplayerAPI::RPCMode p_rpc_mode, const GDScriptDataType &p_return_type) { @@ -599,10 +599,16 @@ void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Addr // Typed assignment. switch (p_target.type.kind) { case GDScriptDataType::BUILTIN: { - append(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN, 2); - append(p_target); - append(p_source); - append(p_target.type.builtin_type); + if (p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type()) { + append(GDScriptFunction::OPCODE_ASSIGN_TYPED_ARRAY, 2); + append(p_target); + append(p_source); + } else { + append(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN, 2); + append(p_target); + append(p_source); + append(p_target.type.builtin_type); + } } break; case GDScriptDataType::NATIVE: { int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[p_target.type.native_type]; @@ -633,7 +639,11 @@ void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Addr } } } else { - if (p_target.type.kind == GDScriptDataType::BUILTIN && p_source.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type != p_source.type.builtin_type) { + if (p_target.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type()) { + append(GDScriptFunction::OPCODE_ASSIGN_TYPED_ARRAY, 2); + append(p_target); + append(p_source); + } else if (p_target.type.kind == GDScriptDataType::BUILTIN && p_source.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type != p_source.type.builtin_type) { // Need conversion.. append(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN, 2); append(p_target); @@ -980,6 +990,25 @@ void GDScriptByteCodeGenerator::write_construct_array(const Address &p_target, c append(p_arguments.size()); } +void GDScriptByteCodeGenerator::write_construct_typed_array(const Address &p_target, const GDScriptDataType &p_element_type, const Vector<Address> &p_arguments) { + append(GDScriptFunction::OPCODE_CONSTRUCT_TYPED_ARRAY, 2 + p_arguments.size()); + for (int i = 0; i < p_arguments.size(); i++) { + append(p_arguments[i]); + } + append(p_target); + if (p_element_type.script_type) { + Variant script_type = Ref<Script>(p_element_type.script_type); + int addr = get_constant_pos(script_type); + addr |= GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS; + append(addr); + } else { + append(Address()); // null. + } + append(p_arguments.size()); + append(p_element_type.builtin_type); + append(p_element_type.native_type); +} + void GDScriptByteCodeGenerator::write_construct_dictionary(const Address &p_target, const Vector<Address> &p_arguments) { append(GDScriptFunction::OPCODE_CONSTRUCT_DICTIONARY, 1 + p_arguments.size()); for (int i = 0; i < p_arguments.size(); i++) { @@ -1257,8 +1286,85 @@ void GDScriptByteCodeGenerator::write_newline(int p_line) { } void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) { - append(GDScriptFunction::OPCODE_RETURN, 1); - append(p_return_value); + if (!function->return_type.has_type || p_return_value.type.has_type) { + // Either the function is untyped or the return value is also typed. + + // If this is a typed function, then we need to check for potential conversions. + if (function->return_type.has_type) { + if (function->return_type.kind == GDScriptDataType::BUILTIN && function->return_type.builtin_type == Variant::ARRAY && function->return_type.has_container_element_type()) { + // Typed array. + const GDScriptDataType &element_type = function->return_type.get_container_element_type(); + + Variant script = function->return_type.script_type; + int script_idx = get_constant_pos(script); + script_idx |= (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS); + + append(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY, 2); + append(p_return_value); + append(script_idx); + append(element_type.kind == GDScriptDataType::BUILTIN ? element_type.builtin_type : Variant::OBJECT); + append(element_type.native_type); + } else if (function->return_type.kind == GDScriptDataType::BUILTIN && p_return_value.type.kind == GDScriptDataType::BUILTIN && function->return_type.builtin_type != p_return_value.type.builtin_type) { + // Add conversion. + append(GDScriptFunction::OPCODE_RETURN_TYPED_BUILTIN, 1); + append(p_return_value); + append(function->return_type.builtin_type); + } else { + // Just assign. + append(GDScriptFunction::OPCODE_RETURN, 1); + append(p_return_value); + } + } else { + append(GDScriptFunction::OPCODE_RETURN, 1); + append(p_return_value); + } + } else { + switch (function->return_type.kind) { + case GDScriptDataType::BUILTIN: { + if (function->return_type.builtin_type == Variant::ARRAY && function->return_type.has_container_element_type()) { + const GDScriptDataType &element_type = function->return_type.get_container_element_type(); + + Variant script = function->return_type.script_type; + int script_idx = get_constant_pos(script); + script_idx |= (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS); + + append(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY, 2); + append(p_return_value); + append(script_idx); + append(element_type.kind == GDScriptDataType::BUILTIN ? element_type.builtin_type : Variant::OBJECT); + append(element_type.native_type); + } else { + append(GDScriptFunction::OPCODE_RETURN_TYPED_BUILTIN, 1); + append(p_return_value); + append(function->return_type.builtin_type); + } + } break; + case GDScriptDataType::NATIVE: { + append(GDScriptFunction::OPCODE_RETURN_TYPED_NATIVE, 2); + append(p_return_value); + int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[function->return_type.native_type]; + class_idx |= (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS); + append(class_idx); + } break; + case GDScriptDataType::GDSCRIPT: + case GDScriptDataType::SCRIPT: { + Variant script = function->return_type.script_type; + int script_idx = get_constant_pos(script); + script_idx |= (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS); + + append(GDScriptFunction::OPCODE_RETURN_TYPED_SCRIPT, 2); + append(p_return_value); + append(script_idx); + } break; + default: { + ERR_PRINT("Compiler bug: unresolved return."); + + // Shouldn't get here, but fail-safe to a regular return; + append(GDScriptFunction::OPCODE_RETURN, 1); + append(p_return_value); + } break; + } + } } void GDScriptByteCodeGenerator::write_assert(const Address &p_test, const Address &p_message) { diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h index 1e66af269a..6eaec91504 100644 --- a/modules/gdscript/gdscript_byte_codegen.h +++ b/modules/gdscript/gdscript_byte_codegen.h @@ -163,64 +163,72 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { } int get_constant_pos(const Variant &p_constant) { - if (constant_map.has(p_constant)) + if (constant_map.has(p_constant)) { return constant_map[p_constant]; + } int pos = constant_map.size(); constant_map[p_constant] = pos; return pos; } int get_operation_pos(const Variant::ValidatedOperatorEvaluator p_operation) { - if (operator_func_map.has(p_operation)) + if (operator_func_map.has(p_operation)) { return operator_func_map[p_operation]; + } int pos = operator_func_map.size(); operator_func_map[p_operation] = pos; return pos; } int get_setter_pos(const Variant::ValidatedSetter p_setter) { - if (setters_map.has(p_setter)) + if (setters_map.has(p_setter)) { return setters_map[p_setter]; + } int pos = setters_map.size(); setters_map[p_setter] = pos; return pos; } int get_getter_pos(const Variant::ValidatedGetter p_getter) { - if (getters_map.has(p_getter)) + if (getters_map.has(p_getter)) { return getters_map[p_getter]; + } int pos = getters_map.size(); getters_map[p_getter] = pos; return pos; } int get_keyed_setter_pos(const Variant::ValidatedKeyedSetter p_keyed_setter) { - if (keyed_setters_map.has(p_keyed_setter)) + if (keyed_setters_map.has(p_keyed_setter)) { return keyed_setters_map[p_keyed_setter]; + } int pos = keyed_setters_map.size(); keyed_setters_map[p_keyed_setter] = pos; return pos; } int get_keyed_getter_pos(const Variant::ValidatedKeyedGetter p_keyed_getter) { - if (keyed_getters_map.has(p_keyed_getter)) + if (keyed_getters_map.has(p_keyed_getter)) { return keyed_getters_map[p_keyed_getter]; + } int pos = keyed_getters_map.size(); keyed_getters_map[p_keyed_getter] = pos; return pos; } int get_indexed_setter_pos(const Variant::ValidatedIndexedSetter p_indexed_setter) { - if (indexed_setters_map.has(p_indexed_setter)) + if (indexed_setters_map.has(p_indexed_setter)) { return indexed_setters_map[p_indexed_setter]; + } int pos = indexed_setters_map.size(); indexed_setters_map[p_indexed_setter] = pos; return pos; } int get_indexed_getter_pos(const Variant::ValidatedIndexedGetter p_indexed_getter) { - if (indexed_getters_map.has(p_indexed_getter)) + if (indexed_getters_map.has(p_indexed_getter)) { return indexed_getters_map[p_indexed_getter]; + } int pos = indexed_getters_map.size(); indexed_getters_map[p_indexed_getter] = pos; return pos; @@ -272,8 +280,9 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { } void alloc_stack(int p_level) { - if (p_level >= stack_max) + if (p_level >= stack_max) { stack_max = p_level + 1; + } } int increase_stack() { @@ -283,8 +292,9 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { } void alloc_ptrcall(int p_params) { - if (p_params >= ptrcall_max) + if (p_params >= ptrcall_max) { ptrcall_max = p_params; + } } int address_of(const Address &p_address) { @@ -445,6 +455,7 @@ public: virtual void write_call_script_function(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) override; virtual void write_construct(const Address &p_target, Variant::Type p_type, const Vector<Address> &p_arguments) override; virtual void write_construct_array(const Address &p_target, const Vector<Address> &p_arguments) override; + virtual void write_construct_typed_array(const Address &p_target, const GDScriptDataType &p_element_type, const Vector<Address> &p_arguments) override; virtual void write_construct_dictionary(const Address &p_target, const Vector<Address> &p_arguments) override; virtual void write_await(const Address &p_target, const Address &p_operand) override; virtual void write_if(const Address &p_condition) override; diff --git a/modules/gdscript/gdscript_codegen.h b/modules/gdscript/gdscript_codegen.h index d72bd12033..3c05f14cf7 100644 --- a/modules/gdscript/gdscript_codegen.h +++ b/modules/gdscript/gdscript_codegen.h @@ -137,6 +137,7 @@ public: virtual void write_call_script_function(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0; virtual void write_construct(const Address &p_target, Variant::Type p_type, const Vector<Address> &p_arguments) = 0; virtual void write_construct_array(const Address &p_target, const Vector<Address> &p_arguments) = 0; + virtual void write_construct_typed_array(const Address &p_target, const GDScriptDataType &p_element_type, const Vector<Address> &p_arguments) = 0; virtual void write_construct_dictionary(const Address &p_target, const Vector<Address> &p_arguments) = 0; virtual void write_await(const Address &p_target, const Address &p_operand) = 0; virtual void write_if(const Address &p_condition) = 0; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 63ca34fc24..1c7a168eba 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -137,22 +137,22 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D } } } break; + case GDScriptParser::DataType::ENUM: case GDScriptParser::DataType::ENUM_VALUE: result.has_type = true; result.kind = GDScriptDataType::BUILTIN; result.builtin_type = Variant::INT; break; - case GDScriptParser::DataType::ENUM: - result.has_type = true; - result.kind = GDScriptDataType::BUILTIN; - result.builtin_type = Variant::DICTIONARY; - break; case GDScriptParser::DataType::UNRESOLVED: { ERR_PRINT("Parser bug: converting unresolved type."); return GDScriptDataType(); } } + if (p_datatype.has_container_element_type()) { + result.set_container_element_type(_gdtype_from_datatype(p_datatype.get_container_element_type())); + } + // Only hold strong reference to the script if it's not the owner of the // element qualified with this type, to avoid cyclic references (leaks). if (result.script_type && result.script_type == p_owner) { @@ -376,10 +376,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code Vector<GDScriptCodeGenerator::Address> values; // Create the result temporary first since it's the last to be killed. - GDScriptDataType array_type; - array_type.has_type = true; - array_type.kind = GDScriptDataType::BUILTIN; - array_type.builtin_type = Variant::ARRAY; + GDScriptDataType array_type = _gdtype_from_datatype(an->get_datatype()); GDScriptCodeGenerator::Address result = codegen.add_temporary(array_type); for (int i = 0; i < an->elements.size(); i++) { @@ -390,7 +387,11 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code values.push_back(val); } - gen->write_construct_array(result, values); + if (array_type.has_container_element_type()) { + gen->write_construct_typed_array(result, array_type.get_container_element_type(), values); + } else { + gen->write_construct_array(result, values); + } for (int i = 0; i < values.size(); i++) { if (values[i].mode == GDScriptCodeGenerator::Address::TEMPORARY) { @@ -777,6 +778,10 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code gen->pop_temporary(); } } + + if (operand.mode == GDScriptCodeGenerator::Address::TEMPORARY) { + gen->pop_temporary(); + } } break; default: { GDScriptCodeGenerator::Address left_operand = _parse_expression(codegen, r_error, binary->left_operand); @@ -1733,8 +1738,17 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui const GDScriptParser::VariableNode *lv = static_cast<const GDScriptParser::VariableNode *>(s); // Should be already in stack when the block began. GDScriptCodeGenerator::Address local = codegen.locals[lv->identifier->name]; + GDScriptParser::DataType local_type = lv->get_datatype(); if (lv->initializer != nullptr) { + // For typed arrays we need to make sure this is already initialized correctly so typed assignment work. + if (local_type.is_hard_type() && local_type.builtin_type == Variant::ARRAY) { + if (local_type.has_container_element_type()) { + codegen.generator->write_construct_typed_array(local, _gdtype_from_datatype(local_type.get_container_element_type(), codegen.script), Vector<GDScriptCodeGenerator::Address>()); + } else { + codegen.generator->write_construct_array(local, Vector<GDScriptCodeGenerator::Address>()); + } + } GDScriptCodeGenerator::Address src_address = _parse_expression(codegen, error, lv->initializer); if (error) { return error; @@ -1743,6 +1757,14 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui if (src_address.mode == GDScriptCodeGenerator::Address::TEMPORARY) { codegen.generator->pop_temporary(); } + } else if (lv->get_datatype().is_hard_type()) { + // Initialize with default for type. + if (local_type.has_container_element_type()) { + codegen.generator->write_construct_typed_array(local, _gdtype_from_datatype(local_type.get_container_element_type(), codegen.script), Vector<GDScriptCodeGenerator::Address>()); + } else if (local_type.kind == GDScriptParser::DataType::BUILTIN) { + codegen.generator->write_construct(local, local_type.builtin_type, Vector<GDScriptCodeGenerator::Address>()); + } + // The `else` branch is for objects, in such case we leave it as `null`. } } break; case GDScriptParser::Node::CONSTANT: { @@ -1844,21 +1866,41 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser continue; } + GDScriptParser::DataType field_type = field->get_datatype(); + + GDScriptCodeGenerator::Address dst_address(GDScriptCodeGenerator::Address::MEMBER, codegen.script->member_indices[field->identifier->name].index, _gdtype_from_datatype(field->get_datatype())); if (field->initializer) { // Emit proper line change. codegen.generator->write_newline(field->initializer->start_line); + // For typed arrays we need to make sure this is already initialized correctly so typed assignment work. + if (field_type.is_hard_type() && field_type.builtin_type == Variant::ARRAY && field_type.has_container_element_type()) { + if (field_type.has_container_element_type()) { + codegen.generator->write_construct_typed_array(dst_address, _gdtype_from_datatype(field_type.get_container_element_type(), codegen.script), Vector<GDScriptCodeGenerator::Address>()); + } else { + codegen.generator->write_construct_array(dst_address, Vector<GDScriptCodeGenerator::Address>()); + } + } GDScriptCodeGenerator::Address src_address = _parse_expression(codegen, error, field->initializer, false, true); if (error) { memdelete(codegen.generator); return error; } - GDScriptCodeGenerator::Address dst_address(GDScriptCodeGenerator::Address::MEMBER, codegen.script->member_indices[field->identifier->name].index, _gdtype_from_datatype(field->get_datatype())); codegen.generator->write_assign(dst_address, src_address); if (src_address.mode == GDScriptCodeGenerator::Address::TEMPORARY) { codegen.generator->pop_temporary(); } + } else if (field->get_datatype().is_hard_type()) { + codegen.generator->write_newline(field->start_line); + + // Initialize with default for type. + if (field_type.has_container_element_type()) { + codegen.generator->write_construct_typed_array(dst_address, _gdtype_from_datatype(field_type.get_container_element_type(), codegen.script), Vector<GDScriptCodeGenerator::Address>()); + } else if (field_type.kind == GDScriptParser::DataType::BUILTIN) { + codegen.generator->write_construct(dst_address, field_type.builtin_type, Vector<GDScriptCodeGenerator::Address>()); + } + // The `else` branch is for objects, in such case we leave it as `null`. } } } @@ -2176,9 +2218,8 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar prop_info.hint = export_info.hint; prop_info.hint_string = export_info.hint_string; prop_info.usage = export_info.usage; - } else { - prop_info.usage = PROPERTY_USAGE_SCRIPT_VARIABLE; } + prop_info.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE; #ifdef TOOLS_ENABLED p_script->doc_variables[name] = variable->doc_description; #endif diff --git a/modules/gdscript/gdscript_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp index 17cb5e3c96..33acbb2a35 100644 --- a/modules/gdscript/gdscript_disassembler.cpp +++ b/modules/gdscript/gdscript_disassembler.cpp @@ -322,6 +322,14 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { incr += 4; } break; + case OPCODE_ASSIGN_TYPED_ARRAY: { + text += "assign typed array "; + text += DADDR(1); + text += " = "; + text += DADDR(2); + + incr += 3; + } break; case OPCODE_ASSIGN_TYPED_NATIVE: { text += "assign typed native ("; text += DADDR(3); @@ -385,8 +393,9 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += Variant::get_type_name(t) + "("; for (int i = 0; i < argc; i++) { - if (i > 0) + if (i > 0) { text += ", "; + } text += DADDR(i + 1); } text += ")"; @@ -402,8 +411,9 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += "<unkown type>("; for (int i = 0; i < argc; i++) { - if (i > 0) + if (i > 0) { text += ", "; + } text += DADDR(i + 1); } text += ")"; @@ -417,8 +427,43 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += " = ["; for (int i = 0; i < argc; i++) { - if (i > 0) + if (i > 0) { text += ", "; + } + text += DADDR(1 + i); + } + + text += "]"; + + incr += 3 + argc; + } break; + case OPCODE_CONSTRUCT_TYPED_ARRAY: { + int argc = _code_ptr[ip + 1 + instr_var_args]; + + Ref<Script> script_type = get_constant(_code_ptr[ip + argc + 2]); + Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + argc + 4]; + StringName native_type = get_global_name(_code_ptr[ip + argc + 5]); + + String type_name; + if (script_type.is_valid() && script_type->is_valid()) { + type_name = script_type->get_path(); + } else if (native_type != StringName()) { + type_name = native_type; + } else { + type_name = Variant::get_type_name(builtin_type); + } + + text += " make_typed_array ("; + text += type_name; + text += ") "; + + text += DADDR(1 + argc); + text += " = ["; + + for (int i = 0; i < argc; i++) { + if (i > 0) { + text += ", "; + } text += DADDR(1 + i); } @@ -433,8 +478,9 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += " = {"; for (int i = 0; i < argc; i++) { - if (i > 0) + if (i > 0) { text += ", "; + } text += DADDR(1 + i * 2 + 0); text += ": "; text += DADDR(1 + i * 2 + 1); @@ -468,8 +514,9 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += "("; for (int i = 0; i < argc; i++) { - if (i > 0) + if (i > 0) { text += ", "; + } text += DADDR(1 + i); } text += ")"; @@ -498,8 +545,9 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += "("; for (int i = 0; i < argc; i++) { - if (i > 0) + if (i > 0) { text += ", "; + } text += DADDR(1 + i); } text += ")"; @@ -518,8 +566,9 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += "("; for (int i = 0; i < argc; i++) { - if (i > 0) + if (i > 0) { text += ", "; + } text += DADDR(1 + i); } text += ")"; @@ -595,8 +644,9 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += "("; for (int i = 0; i < argc; i++) { - if (i > 0) + if (i > 0) { text += ", "; + } text += DADDR(1 + i); } text += ")"; @@ -613,8 +663,9 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += "("; for (int i = 0; i < argc; i++) { - if (i > 0) + if (i > 0) { text += ", "; + } text += DADDR(1 + i); } text += ")"; @@ -631,8 +682,9 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += "("; for (int i = 0; i < argc; i++) { - if (i > 0) + if (i > 0) { text += ", "; + } text += DADDR(1 + i); } text += ")"; @@ -649,8 +701,9 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += "("; for (int i = 0; i < argc; i++) { - if (i > 0) + if (i > 0) { text += ", "; + } text += DADDR(1 + i); } text += ")"; @@ -667,8 +720,9 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += "("; for (int i = 0; i < argc; i++) { - if (i > 0) + if (i > 0) { text += ", "; + } text += DADDR(1 + i); } text += ")"; @@ -720,6 +774,39 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { incr = 2; } break; + case OPCODE_RETURN_TYPED_BUILTIN: { + text += "return typed builtin ("; + text += Variant::get_type_name((Variant::Type)_code_ptr[ip + 2]); + text += ") "; + text += DADDR(1); + + incr += 3; + } break; + case OPCODE_RETURN_TYPED_ARRAY: { + text += "return typed array "; + text += DADDR(1); + + incr += 5; + } break; + case OPCODE_RETURN_TYPED_NATIVE: { + text += "return typed native ("; + text += DADDR(2); + text += ") "; + text += DADDR(1); + + incr += 3; + } break; + case OPCODE_RETURN_TYPED_SCRIPT: { + Variant script = _constants_ptr[_code_ptr[ip + 2]]; + Script *sc = Object::cast_to<Script>(script.operator Object *()); + + text += "return typed script ("; + text += sc->get_path(); + text += ") "; + text += DADDR(1); + + incr += 3; + } break; #define DISASSEMBLE_ITERATE(m_type) \ case OPCODE_ITERATE_##m_type: { \ diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index a9975c8602..9856a1a98a 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -500,36 +500,6 @@ struct GDScriptCompletionIdentifier { const GDScriptParser::ExpressionNode *assigned_expression = nullptr; }; -// TODO: Move this to a central location (maybe core?). -static const char *underscore_classes[] = { - "ClassDB", - "Directory", - "Engine", - "File", - "Geometry", - "GodotSharp", - "JSON", - "Marshalls", - "Mutex", - "OS", - "ResourceLoader", - "ResourceSaver", - "Semaphore", - "Thread", - "VisualScriptEditor", - nullptr, -}; -static StringName _get_real_class_name(const StringName &p_source) { - const char **class_name = underscore_classes; - while (*class_name != nullptr) { - if (p_source == *class_name) { - return String("_") + p_source; - } - class_name++; - } - return p_source; -} - static String _get_visual_datatype(const PropertyInfo &p_info, bool p_is_arg = true) { if (p_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { String enum_name = p_info.class_name; @@ -930,7 +900,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base } } break; case GDScriptParser::DataType::NATIVE: { - StringName type = _get_real_class_name(base_type.native_type); + StringName type = GDScriptParser::get_real_class_name(base_type.native_type); if (!ClassDB::class_exists(type)) { return; } @@ -1067,7 +1037,7 @@ static void _find_identifiers(GDScriptParser::CompletionContext &p_context, bool static const char *_keywords[] = { "false", "PI", "TAU", "INF", "NAN", "self", "true", "breakpoint", "tool", "super", "break", "continue", "pass", "return", - 0 + nullptr }; const char **kw = _keywords; @@ -1080,7 +1050,7 @@ static void _find_identifiers(GDScriptParser::CompletionContext &p_context, bool static const char *_keywords_with_space[] = { "and", "in", "not", "or", "as", "class", "extends", "is", "func", "signal", "await", "const", "enum", "static", "var", "if", "elif", "else", "for", "match", "while", - 0 + nullptr }; const char **kws = _keywords_with_space; @@ -1093,7 +1063,7 @@ static void _find_identifiers(GDScriptParser::CompletionContext &p_context, bool static const char *_keywords_with_args[] = { "assert", "preload", - 0 + nullptr }; const char **kwa = _keywords_with_args; @@ -1783,7 +1753,7 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context, base_type = GDScriptParser::DataType(); break; } - StringName real_native = _get_real_class_name(base_type.native_type); + StringName real_native = GDScriptParser::get_real_class_name(base_type.native_type); MethodInfo info; if (ClassDB::get_method_info(real_native, p_context.current_function->identifier->name, &info)) { for (const List<PropertyInfo>::Element *E = info.arguments.front(); E; E = E->next()) { @@ -1854,7 +1824,7 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context, } // Check ClassDB. - StringName class_name = _get_real_class_name(p_identifier); + StringName class_name = GDScriptParser::get_real_class_name(p_identifier); if (ClassDB::class_exists(class_name) && ClassDB::is_class_exposed(class_name)) { r_type.type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; r_type.type.kind = GDScriptParser::DataType::NATIVE; @@ -1970,7 +1940,7 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext & } } break; case GDScriptParser::DataType::NATIVE: { - StringName class_name = _get_real_class_name(base_type.native_type); + StringName class_name = GDScriptParser::get_real_class_name(base_type.native_type); if (!ClassDB::class_exists(class_name)) { return false; } @@ -2133,7 +2103,7 @@ static bool _guess_method_return_type_from_base(GDScriptParser::CompletionContex } } break; case GDScriptParser::DataType::NATIVE: { - StringName native = _get_real_class_name(base_type.native_type); + StringName native = GDScriptParser::get_real_class_name(base_type.native_type); if (!ClassDB::class_exists(native)) { return false; } @@ -2230,7 +2200,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c base_type = base_type.class_type->base_type; } break; case GDScriptParser::DataType::NATIVE: { - StringName class_name = _get_real_class_name(base_type.native_type); + StringName class_name = GDScriptParser::get_real_class_name(base_type.native_type); if (!ClassDB::class_exists(class_name)) { base_type.kind = GDScriptParser::DataType::UNRESOLVED; break; @@ -2615,7 +2585,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path break; } - StringName class_name = _get_real_class_name(native_type.native_type); + StringName class_name = GDScriptParser::get_real_class_name(native_type.native_type); if (!ClassDB::class_exists(class_name)) { break; } @@ -2844,7 +2814,7 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co } } break; case GDScriptParser::DataType::NATIVE: { - StringName class_name = _get_real_class_name(base_type.native_type); + StringName class_name = GDScriptParser::get_real_class_name(base_type.native_type); if (!ClassDB::class_exists(class_name)) { base_type.kind = GDScriptParser::DataType::UNRESOLVED; break; @@ -2922,7 +2892,7 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co v = v_ref; } else { Callable::CallError err; - Variant::construct(base_type.builtin_type, v, NULL, 0, err); + Variant::construct(base_type.builtin_type, v, nullptr, 0, err); if (err.error != Callable::CallError::CALL_OK) { break; } diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index e64630a743..9fc75b66ce 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -43,7 +43,11 @@ class GDScriptInstance; class GDScript; -struct GDScriptDataType { +class GDScriptDataType { +private: + GDScriptDataType *container_element_type = nullptr; + +public: enum Kind { UNINITIALIZED, BUILTIN, @@ -71,7 +75,24 @@ struct GDScriptDataType { case BUILTIN: { Variant::Type var_type = p_variant.get_type(); bool valid = builtin_type == var_type; - if (!valid && p_allow_implicit_conversion) { + if (valid && builtin_type == Variant::ARRAY && has_container_element_type()) { + Array array = p_variant; + if (array.is_typed()) { + Variant::Type array_builtin_type = (Variant::Type)array.get_typed_builtin(); + StringName array_native_type = array.get_typed_class_name(); + Ref<Script> array_script_type_ref = array.get_typed_script(); + + if (array_script_type_ref.is_valid()) { + valid = (container_element_type->kind == SCRIPT || container_element_type->kind == GDSCRIPT) && container_element_type->script_type == array_script_type_ref.ptr(); + } else if (array_native_type != StringName()) { + valid = container_element_type->kind == NATIVE && container_element_type->native_type == array_native_type; + } else { + valid = container_element_type->kind == BUILTIN && container_element_type->builtin_type == array_builtin_type; + } + } else { + valid = false; + } + } else if (!valid && p_allow_implicit_conversion) { valid = Variant::can_convert_strict(var_type, builtin_type); } return valid; @@ -153,7 +174,49 @@ struct GDScriptDataType { return info; } - GDScriptDataType() {} + void set_container_element_type(const GDScriptDataType &p_element_type) { + container_element_type = memnew(GDScriptDataType(p_element_type)); + } + + GDScriptDataType get_container_element_type() const { + ERR_FAIL_COND_V(container_element_type == nullptr, GDScriptDataType()); + return *container_element_type; + } + + bool has_container_element_type() const { + return container_element_type != nullptr; + } + + void unset_container_element_type() { + if (container_element_type) { + memdelete(container_element_type); + } + container_element_type = nullptr; + } + + GDScriptDataType() = default; + + GDScriptDataType &operator=(const GDScriptDataType &p_other) { + kind = p_other.kind; + has_type = p_other.has_type; + builtin_type = p_other.builtin_type; + native_type = p_other.native_type; + script_type = p_other.script_type; + script_type_ref = p_other.script_type_ref; + unset_container_element_type(); + if (p_other.has_container_element_type()) { + set_container_element_type(p_other.get_container_element_type()); + } + return *this; + } + + GDScriptDataType(const GDScriptDataType &p_other) { + *this = p_other; + } + + ~GDScriptDataType() { + unset_container_element_type(); + } }; class GDScriptFunction { @@ -179,6 +242,7 @@ public: OPCODE_ASSIGN_TRUE, OPCODE_ASSIGN_FALSE, OPCODE_ASSIGN_TYPED_BUILTIN, + OPCODE_ASSIGN_TYPED_ARRAY, OPCODE_ASSIGN_TYPED_NATIVE, OPCODE_ASSIGN_TYPED_SCRIPT, OPCODE_CAST_TO_BUILTIN, @@ -187,6 +251,7 @@ public: OPCODE_CONSTRUCT, // Only for basic types! OPCODE_CONSTRUCT_VALIDATED, // Only for basic types! OPCODE_CONSTRUCT_ARRAY, + OPCODE_CONSTRUCT_TYPED_ARRAY, OPCODE_CONSTRUCT_DICTIONARY, OPCODE_CALL, OPCODE_CALL_RETURN, @@ -241,6 +306,10 @@ public: OPCODE_JUMP_IF_NOT, OPCODE_JUMP_TO_DEF_ARGUMENT, OPCODE_RETURN, + OPCODE_RETURN_TYPED_BUILTIN, + OPCODE_RETURN_TYPED_ARRAY, + OPCODE_RETURN_TYPED_NATIVE, + OPCODE_RETURN_TYPED_SCRIPT, OPCODE_ITERATE_BEGIN, OPCODE_ITERATE_BEGIN_INT, OPCODE_ITERATE_BEGIN_FLOAT, diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 7f3dd6b2e5..695154e9a9 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -94,8 +94,43 @@ Variant::Type GDScriptParser::get_builtin_type(const StringName &p_type) { return Variant::VARIANT_MAX; } +// TODO: Move this to a central location (maybe core?). +static HashMap<StringName, StringName> underscore_map; +static const char *underscore_classes[] = { + "ClassDB", + "Directory", + "Engine", + "File", + "Geometry", + "GodotSharp", + "JSON", + "Marshalls", + "Mutex", + "OS", + "ResourceLoader", + "ResourceSaver", + "Semaphore", + "Thread", + "VisualScriptEditor", + nullptr, +}; +StringName GDScriptParser::get_real_class_name(const StringName &p_source) { + if (underscore_map.is_empty()) { + const char **class_name = underscore_classes; + while (*class_name != nullptr) { + underscore_map[*class_name] = String("_") + *class_name; + class_name++; + } + } + if (underscore_map.has(p_source)) { + return underscore_map[p_source]; + } + return p_source; +} + void GDScriptParser::cleanup() { builtin_types.clear(); + underscore_map.clear(); } void GDScriptParser::get_annotation_list(List<MethodInfo> *r_annotations) const { @@ -109,12 +144,11 @@ void GDScriptParser::get_annotation_list(List<MethodInfo> *r_annotations) const GDScriptParser::GDScriptParser() { // Register valid annotations. // TODO: Should this be static? - // TODO: Validate applicable types (e.g. a VARIABLE annotation that only applies to string variables). register_annotation(MethodInfo("@tool"), AnnotationInfo::SCRIPT, &GDScriptParser::tool_annotation); register_annotation(MethodInfo("@icon", { Variant::STRING, "icon_path" }), AnnotationInfo::SCRIPT, &GDScriptParser::icon_annotation); register_annotation(MethodInfo("@onready"), AnnotationInfo::VARIABLE, &GDScriptParser::onready_annotation); // Export annotations. - register_annotation(MethodInfo("@export"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_TYPE_STRING, Variant::NIL>); + register_annotation(MethodInfo("@export"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_NONE, Variant::NIL>); register_annotation(MethodInfo("@export_enum", { Variant::STRING, "names" }), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_ENUM, Variant::INT>, 0, true); register_annotation(MethodInfo("@export_file", { Variant::STRING, "filter" }), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FILE, Variant::STRING>, 1, true); register_annotation(MethodInfo("@export_dir"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_DIR, Variant::STRING>); @@ -680,7 +714,6 @@ void GDScriptParser::parse_class_member(T *(GDScriptParser::*p_parse_function)() while (!annotation_stack.is_empty()) { AnnotationNode *last_annotation = annotation_stack.back()->get(); if (last_annotation->applies_to(p_target)) { - last_annotation->apply(this, member); member->annotations.push_front(last_annotation); annotation_stack.pop_back(); } else { @@ -811,6 +844,9 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_proper if (match(GDScriptTokenizer::Token::EQUAL)) { // Initializer. variable->initializer = parse_expression(false); + if (variable->initializer == nullptr) { + push_error(R"(Expected expression for variable initial value after "=".)"); + } variable->assignments++; } @@ -2674,6 +2710,19 @@ GDScriptParser::TypeNode *GDScriptParser::parse_type(bool p_allow_void) { type->type_chain.push_back(type_element); + if (match(GDScriptTokenizer::Token::BRACKET_OPEN)) { + // Typed collection (like Array[int]). + type->container_type = parse_type(false); // Don't allow void for array element type. + if (type->container_type == nullptr) { + push_error(R"(Expected type for collection after "[".)"); + type = nullptr; + } else if (type->container_type->container_type != nullptr) { + push_error("Nested typed collections are not supported."); + } + consume(GDScriptTokenizer::Token::BRACKET_CLOSE, R"(Expected closing "]" after collection type.)"); + return type; + } + int chain_index = 1; while (match(GDScriptTokenizer::Token::PERIOD)) { make_completion_context(COMPLETION_TYPE_ATTRIBUTE, type, chain_index++); @@ -3160,29 +3209,10 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node } variable->exported = true; - // TODO: Improving setting type, especially for range hints, which can be int or float. + variable->export_info.type = t_type; variable->export_info.hint = t_hint; - if (p_annotation->name == "@export") { - if (variable->datatype_specifier == nullptr) { - if (variable->initializer == nullptr) { - push_error(R"(Cannot use "@export" annotation with variable without type or initializer, since type can't be inferred.)", p_annotation); - return false; - } - if (variable->initializer->type == Node::LITERAL) { - variable->export_info.type = static_cast<LiteralNode *>(variable->initializer)->value.get_type(); - } else if (variable->initializer->type == Node::ARRAY) { - variable->export_info.type = Variant::ARRAY; - } else if (variable->initializer->type == Node::DICTIONARY) { - variable->export_info.type = Variant::DICTIONARY; - } else { - push_error(R"(To use "@export" annotation with type-less variable, the default value must be a literal.)", p_annotation); - return false; - } - } // else: Actual type will be set by the analyzer, which can infer the proper type. - } - String hint_string; for (int i = 0; i < p_annotation->resolved_arguments.size(); i++) { if (i > 0) { @@ -3193,6 +3223,86 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node variable->export_info.hint_string = hint_string; + // This is called after tne analyzer is done finding the type, so this should be set here. + DataType export_type = variable->get_datatype(); + + if (p_annotation->name == "@export") { + if (variable->datatype_specifier == nullptr && variable->initializer == nullptr) { + push_error(R"(Cannot use simple "@export" annotation with variable without type or initializer, since type can't be inferred.)", p_annotation); + return false; + } + + bool is_array = false; + + if (export_type.builtin_type == Variant::ARRAY && export_type.has_container_element_type()) { + export_type = export_type.get_container_element_type(); // Use inner type for. + is_array = true; + } + + if (export_type.is_variant() || export_type.has_no_type()) { + push_error(R"(Cannot use simple "@export" annotation because the type of the initialized value can't be inferred.)", p_annotation); + return false; + } + + switch (export_type.kind) { + case GDScriptParser::DataType::BUILTIN: + variable->export_info.type = export_type.builtin_type; + variable->export_info.hint = PROPERTY_HINT_NONE; + variable->export_info.hint_string = Variant::get_type_name(export_type.builtin_type); + break; + case GDScriptParser::DataType::NATIVE: + if (ClassDB::is_parent_class(get_real_class_name(export_type.native_type), "Resource")) { + variable->export_info.type = Variant::OBJECT; + variable->export_info.hint = PROPERTY_HINT_RESOURCE_TYPE; + variable->export_info.hint_string = get_real_class_name(export_type.native_type); + } else { + push_error(R"(Export type can only be built-in, a resource, or an enum.)", variable); + return false; + } + break; + case GDScriptParser::DataType::ENUM: { + variable->export_info.type = Variant::INT; + variable->export_info.hint = PROPERTY_HINT_ENUM; + + String enum_hint_string; + for (const Map<StringName, int>::Element *E = export_type.enum_values.front(); E; E = E->next()) { + enum_hint_string += E->key().operator String().camelcase_to_underscore(true).capitalize().xml_escape(); + enum_hint_string += ":"; + enum_hint_string += String::num_int64(E->get()).xml_escape(); + + if (E->next()) { + enum_hint_string += ","; + } + } + + variable->export_info.hint_string = enum_hint_string; + } break; + default: + // TODO: Allow custom user resources. + push_error(R"(Export type can only be built-in, a resource, or an enum.)", variable); + break; + } + + if (is_array) { + String hint_prefix = itos(variable->export_info.type); + if (variable->export_info.hint) { + hint_prefix += "/" + itos(variable->export_info.hint); + } + variable->export_info.hint = PROPERTY_HINT_TYPE_STRING; + variable->export_info.hint_string = hint_prefix + ":" + variable->export_info.hint_string; + variable->export_info.type = Variant::ARRAY; + } + } else { + // Validate variable type with export. + if (!export_type.is_variant() && (export_type.kind != DataType::BUILTIN || export_type.builtin_type != t_type)) { + // Allow float/int conversion. + if ((t_type != Variant::FLOAT || export_type.builtin_type != Variant::INT) && (t_type != Variant::INT || export_type.builtin_type != Variant::FLOAT)) { + push_error(vformat(R"("%s" annotation requires a variable of type "%s" but type "%s" was given instead.)", p_annotation->name.operator String(), Variant::get_type_name(t_type), export_type.to_string()), variable); + return false; + } + } + } + return true; } @@ -3278,6 +3388,9 @@ String GDScriptParser::DataType::to_string() const { if (builtin_type == Variant::NIL) { return "null"; } + if (builtin_type == Variant::ARRAY && has_container_element_type()) { + return vformat("Array[%s]", container_element_type->to_string()); + } return Variant::get_type_name(builtin_type); case NATIVE: if (is_meta_type) { diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index a4b1d4c866..272d21ffce 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -94,7 +94,12 @@ public: struct VariableNode; struct WhileNode; - struct DataType { + class DataType { + private: + // Private access so we can control memory management. + DataType *container_element_type = nullptr; + + public: enum Kind { BUILTIN, NATIVE, @@ -104,7 +109,6 @@ public: ENUM_VALUE, // Value from enumeration. VARIANT, // Can be any type. UNRESOLVED, - // TODO: Enum }; Kind kind = UNRESOLVED; @@ -128,7 +132,7 @@ public: ClassNode *class_type = nullptr; MethodInfo method_info; // For callable/signals. - HashMap<StringName, int> enum_values; // For enums. + Map<StringName, int> enum_values; // For enums. _FORCE_INLINE_ bool is_set() const { return kind != UNRESOLVED; } _FORCE_INLINE_ bool has_no_type() const { return type_source == UNDETECTED; } @@ -136,6 +140,26 @@ public: _FORCE_INLINE_ bool is_hard_type() const { return type_source > INFERRED; } String to_string() const; + _FORCE_INLINE_ void set_container_element_type(const DataType &p_type) { + container_element_type = memnew(DataType(p_type)); + } + + _FORCE_INLINE_ DataType get_container_element_type() const { + ERR_FAIL_COND_V(container_element_type == nullptr, DataType()); + return *container_element_type; + } + + _FORCE_INLINE_ bool has_container_element_type() const { + return container_element_type != nullptr; + } + + _FORCE_INLINE_ void unset_container_element_type() { + if (container_element_type) { + memdelete(container_element_type); + }; + container_element_type = nullptr; + } + bool operator==(const DataType &p_other) const { if (type_source == UNDETECTED || p_other.type_source == UNDETECTED) { return true; // Can be consireded equal for parsing purposes. @@ -173,6 +197,37 @@ public: bool operator!=(const DataType &p_other) const { return !(this->operator==(p_other)); } + + DataType &operator=(const DataType &p_other) { + kind = p_other.kind; + type_source = p_other.type_source; + is_constant = p_other.is_constant; + is_meta_type = p_other.is_meta_type; + is_coroutine = p_other.is_coroutine; + builtin_type = p_other.builtin_type; + native_type = p_other.native_type; + enum_type = p_other.enum_type; + script_type = p_other.script_type; + script_path = p_other.script_path; + class_type = p_other.class_type; + method_info = p_other.method_info; + enum_values = p_other.enum_values; + unset_container_element_type(); + if (p_other.has_container_element_type()) { + set_container_element_type(p_other.get_container_element_type()); + } + return *this; + } + + DataType() = default; + + DataType(const DataType &p_other) { + *this = p_other; + } + + ~DataType() { + unset_container_element_type(); + } }; struct ParserError { @@ -987,6 +1042,7 @@ public: struct TypeNode : public Node { Vector<IdentifierNode *> type_chain; + TypeNode *container_type = nullptr; TypeNode() { type = TYPE; @@ -1313,6 +1369,7 @@ public: ClassNode *get_tree() const { return head; } bool is_tool() const { return _is_tool; } static Variant::Type get_builtin_type(const StringName &p_type); + static StringName get_real_class_name(const StringName &p_source); CompletionContext get_completion_context() const { return completion_context; } CompletionCall get_completion_call() const { return completion_call; } diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 319778daab..e432dfc891 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -898,6 +898,9 @@ GDScriptTokenizer::Token GDScriptTokenizer::string() { _advance(); _advance(); break; + } else { + // Not a multiline string termination, add consumed quote. + result += quote_char; } } else { // Ended single-line string. diff --git a/modules/gdscript/gdscript_utility_functions.cpp b/modules/gdscript/gdscript_utility_functions.cpp index 348d221352..64c629662c 100644 --- a/modules/gdscript/gdscript_utility_functions.cpp +++ b/modules/gdscript/gdscript_utility_functions.cpp @@ -298,7 +298,7 @@ struct GDScriptUtilityFunctionsDefinitions { sname.push_back(p->name); p = p->_owner; } - sname.invert(); + sname.reverse(); if (!p->path.is_resource_file()) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index 2216fcab2d..6b7da4a467 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -127,6 +127,17 @@ Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_insta } #ifdef DEBUG_ENABLED +static String _get_script_name(const Ref<Script> p_script) { + Ref<GDScript> gdscript = p_script; + if (gdscript.is_valid()) { + return gdscript->get_script_class_name(); + } else if (p_script->get_name().is_empty()) { + return p_script->get_path().get_file(); + } else { + return p_script->get_name(); + } +} + static String _get_var_type(const Variant *p_var) { String basestr; @@ -140,15 +151,30 @@ static String _get_var_type(const Variant *p_var) { basestr = "previously freed"; } } else { + basestr = bobj->get_class(); if (bobj->get_script_instance()) { - basestr = bobj->get_class() + " (" + bobj->get_script_instance()->get_script()->get_path().get_file() + ")"; - } else { - basestr = bobj->get_class(); + basestr += " (" + _get_script_name(bobj->get_script_instance()->get_script()) + ")"; } } } else { - basestr = Variant::get_type_name(p_var->get_type()); + if (p_var->get_type() == Variant::ARRAY) { + basestr = "Array"; + const Array *p_array = VariantInternal::get_array(p_var); + Variant::Type builtin_type = (Variant::Type)p_array->get_typed_builtin(); + StringName native_type = p_array->get_typed_class_name(); + Ref<Script> script_type = p_array->get_typed_script(); + + if (script_type.is_valid() && script_type->is_valid()) { + basestr += "[" + _get_script_name(script_type) + "]"; + } else if (native_type != StringName()) { + basestr += "[" + native_type.operator String() + "]"; + } else if (builtin_type != Variant::NIL) { + basestr += "[" + Variant::get_type_name(builtin_type) + "]"; + } + } else { + basestr = Variant::get_type_name(p_var->get_type()); + } } return basestr; @@ -207,6 +233,7 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const &&OPCODE_ASSIGN_TRUE, \ &&OPCODE_ASSIGN_FALSE, \ &&OPCODE_ASSIGN_TYPED_BUILTIN, \ + &&OPCODE_ASSIGN_TYPED_ARRAY, \ &&OPCODE_ASSIGN_TYPED_NATIVE, \ &&OPCODE_ASSIGN_TYPED_SCRIPT, \ &&OPCODE_CAST_TO_BUILTIN, \ @@ -215,6 +242,7 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const &&OPCODE_CONSTRUCT, \ &&OPCODE_CONSTRUCT_VALIDATED, \ &&OPCODE_CONSTRUCT_ARRAY, \ + &&OPCODE_CONSTRUCT_TYPED_ARRAY, \ &&OPCODE_CONSTRUCT_DICTIONARY, \ &&OPCODE_CALL, \ &&OPCODE_CALL_RETURN, \ @@ -268,6 +296,10 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const &&OPCODE_JUMP_IF_NOT, \ &&OPCODE_JUMP_TO_DEF_ARGUMENT, \ &&OPCODE_RETURN, \ + &&OPCODE_RETURN_TYPED_BUILTIN, \ + &&OPCODE_RETURN_TYPED_ARRAY, \ + &&OPCODE_RETURN_TYPED_NATIVE, \ + &&OPCODE_RETURN_TYPED_SCRIPT, \ &&OPCODE_ITERATE_BEGIN, \ &&OPCODE_ITERATE_BEGIN_INT, \ &&OPCODE_ITERATE_BEGIN_FLOAT, \ @@ -544,7 +576,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a #ifdef DEBUG_ENABLED OPCODE_WHILE(ip < _code_size) { - int last_opcode = _code_ptr[ip]; + int last_opcode = _code_ptr[ip] & INSTR_MASK; #else OPCODE_WHILE(true) { #endif @@ -1077,6 +1109,31 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } DISPATCH_OPCODE; + OPCODE(OPCODE_ASSIGN_TYPED_ARRAY) { + CHECK_SPACE(3); + GET_INSTRUCTION_ARG(dst, 0); + GET_INSTRUCTION_ARG(src, 1); + + Array *dst_arr = VariantInternal::get_array(dst); + + if (src->get_type() != Variant::ARRAY) { +#ifdef DEBUG_ENABLED + err_text = "Trying to assign value of type '" + Variant::get_type_name(src->get_type()) + + "' to a variable of type '" + +"'."; +#endif + OPCODE_BREAK; + } + if (!dst_arr->typed_assign(*src)) { +#ifdef DEBUG_ENABLED + err_text = "Trying to assign a typed array with an array of different type.'"; +#endif + OPCODE_BREAK; + } + + ip += 3; + } + DISPATCH_OPCODE; + OPCODE(OPCODE_ASSIGN_TYPED_NATIVE) { CHECK_SPACE(4); GET_INSTRUCTION_ARG(dst, 0); @@ -1308,6 +1365,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } GET_INSTRUCTION_ARG(dst, argc); + *dst = Variant(); // Clear potential previous typed array. *dst = array; @@ -1315,6 +1373,35 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } DISPATCH_OPCODE; + OPCODE(OPCODE_CONSTRUCT_TYPED_ARRAY) { + CHECK_SPACE(3 + instr_arg_count); + ip += instr_arg_count; + + int argc = _code_ptr[ip + 1]; + + GET_INSTRUCTION_ARG(script_type, argc + 1); + Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 2]; + int native_type_idx = _code_ptr[ip + 3]; + GD_ERR_BREAK(native_type_idx < 0 || native_type_idx >= _global_names_count); + const StringName native_type = _global_names_ptr[native_type_idx]; + + Array array; + array.set_typed(builtin_type, native_type, script_type); + array.resize(argc); + + for (int i = 0; i < argc; i++) { + array[i] = *(instruction_args[i]); + } + + GET_INSTRUCTION_ARG(dst, argc); + *dst = Variant(); // Clear potential previous typed array. + + *dst = array; + + ip += 4; + } + DISPATCH_OPCODE; + OPCODE(OPCODE_CONSTRUCT_DICTIONARY) { CHECK_SPACE(2 + instr_arg_count); @@ -2063,6 +2150,183 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_BREAK; } + OPCODE(OPCODE_RETURN_TYPED_BUILTIN) { + CHECK_SPACE(3); + GET_INSTRUCTION_ARG(r, 0); + + Variant::Type ret_type = (Variant::Type)_code_ptr[ip + 2]; + GD_ERR_BREAK(ret_type < 0 || ret_type >= Variant::VARIANT_MAX); + + if (r->get_type() != ret_type) { + if (Variant::can_convert_strict(r->get_type(), ret_type)) { + Callable::CallError ce; + Variant::construct(ret_type, retvalue, const_cast<const Variant **>(&r), 1, ce); + } else { +#ifdef DEBUG_ENABLED + err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)", + Variant::get_type_name(r->get_type()), Variant::get_type_name(ret_type)); +#endif // DEBUG_ENABLED + + // Construct a base type anyway so type constraints are met. + Callable::CallError ce; + Variant::construct(ret_type, retvalue, nullptr, 0, ce); + OPCODE_BREAK; + } + } else { + retvalue = *r; + } +#ifdef DEBUG_ENABLED + exit_ok = true; +#endif // DEBUG_ENABLED + OPCODE_BREAK; + } + + OPCODE(OPCODE_RETURN_TYPED_ARRAY) { + CHECK_SPACE(5); + GET_INSTRUCTION_ARG(r, 0); + + GET_INSTRUCTION_ARG(script_type, 1); + Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 3]; + int native_type_idx = _code_ptr[ip + 4]; + GD_ERR_BREAK(native_type_idx < 0 || native_type_idx >= _global_names_count); + const StringName native_type = _global_names_ptr[native_type_idx]; + + if (r->get_type() != Variant::ARRAY) { +#ifdef DEBUG_ENABLED + err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "Array[%s]".)", + Variant::get_type_name(r->get_type()), Variant::get_type_name(builtin_type)); +#endif + OPCODE_BREAK; + } + + Array array; + array.set_typed(builtin_type, native_type, script_type); + +#ifdef DEBUG_ENABLED + bool valid = array.typed_assign(*VariantInternal::get_array(r)); +#else + array.typed_assign(*VariantInternal::get_array(r)); +#endif // DEBUG_ENABLED + + // Assign the return value anyway since we want it to be the valid type. + retvalue = array; + +#ifdef DEBUG_ENABLED + if (!valid) { + err_text = "Trying to return a typed array with an array of different type.'"; + OPCODE_BREAK; + } + + exit_ok = true; +#endif // DEBUG_ENABLED + OPCODE_BREAK; + } + + OPCODE(OPCODE_RETURN_TYPED_NATIVE) { + CHECK_SPACE(3); + GET_INSTRUCTION_ARG(r, 0); + + GET_INSTRUCTION_ARG(type, 1); + GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(type->operator Object *()); + GD_ERR_BREAK(!nc); + + if (r->get_type() != Variant::OBJECT && r->get_type() != Variant::NIL) { + err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)", + Variant::get_type_name(r->get_type()), nc->get_name()); + OPCODE_BREAK; + } + +#ifdef DEBUG_ENABLED + bool freed = false; + Object *ret_obj = r->get_validated_object_with_check(freed); + + if (freed) { + err_text = "Trying to return a previously freed instance."; + OPCODE_BREAK; + } +#else + Object *ret_obj = r->operator Object *(); +#endif // DEBUG_ENABLED + if (ret_obj && !ClassDB::is_parent_class(ret_obj->get_class_name(), nc->get_name())) { +#ifdef DEBUG_ENABLED + err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)", + ret_obj->get_class_name(), nc->get_name()); +#endif // DEBUG_ENABLED + OPCODE_BREAK; + } + retvalue = *r; + +#ifdef DEBUG_ENABLED + exit_ok = true; +#endif // DEBUG_ENABLED + OPCODE_BREAK; + } + + OPCODE(OPCODE_RETURN_TYPED_SCRIPT) { + CHECK_SPACE(3); + GET_INSTRUCTION_ARG(r, 0); + + GET_INSTRUCTION_ARG(type, 1); + Script *base_type = Object::cast_to<Script>(type->operator Object *()); + GD_ERR_BREAK(!base_type); + + if (r->get_type() != Variant::OBJECT && r->get_type() != Variant::NIL) { +#ifdef DEBUG_ENABLED + err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)", + Variant::get_type_name(r->get_type()), _get_script_name(Ref<Script>(base_type))); +#endif // DEBUG_ENABLED + OPCODE_BREAK; + } + +#ifdef DEBUG_ENABLED + bool freed = false; + Object *ret_obj = r->get_validated_object_with_check(freed); + + if (freed) { + err_text = "Trying to return a previously freed instance."; + OPCODE_BREAK; + } +#else + Object *ret_obj = r->operator Object *(); +#endif // DEBUG_ENABLED + + if (ret_obj) { + ScriptInstance *ret_inst = ret_obj->get_script_instance(); + if (!ret_inst) { +#ifdef DEBUG_ENABLED + err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)", + ret_obj->get_class_name(), _get_script_name(Ref<GDScript>(base_type))); +#endif // DEBUG_ENABLED + OPCODE_BREAK; + } + + Script *ret_type = ret_obj->get_script_instance()->get_script().ptr(); + bool valid = false; + + while (ret_type) { + if (ret_type == base_type) { + valid = true; + break; + } + ret_type = ret_type->get_base_script().ptr(); + } + + if (!valid) { +#ifdef DEBUG_ENABLED + err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)", + _get_script_name(ret_obj->get_script_instance()->get_script()), _get_script_name(Ref<GDScript>(base_type))); +#endif // DEBUG_ENABLED + OPCODE_BREAK; + } + } + retvalue = *r; + +#ifdef DEBUG_ENABLED + exit_ok = true; +#endif // DEBUG_ENABLED + OPCODE_BREAK; + } + OPCODE(OPCODE_ITERATE_BEGIN) { CHECK_SPACE(8); // Space for this and a regular iterate. diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index 93b709a613..19fd3daf20 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -158,7 +158,6 @@ void unregister_gdscript_types() { #endif // TOOLS_ENABLED GDScriptParser::cleanup(); - GDScriptAnalyzer::cleanup(); GDScriptUtilityFunctions::unregister_functions(); } diff --git a/modules/gdscript/tests/test_gdscript.cpp b/modules/gdscript/tests/test_gdscript.cpp index 898ac653f5..3cc0eee672 100644 --- a/modules/gdscript/tests/test_gdscript.cpp +++ b/modules/gdscript/tests/test_gdscript.cpp @@ -118,10 +118,10 @@ static void test_parser(const String &p_code, const String &p_script_path, const print_line(vformat("%02d:%02d: %s", error.line, error.column, error.message)); } } - +#ifdef TOOLS_ENABLED GDScriptParser::TreePrinter printer; - printer.print_tree(parser); +#endif } static void test_compiler(const String &p_code, const String &p_script_path, const Vector<String> &p_lines) { @@ -175,8 +175,9 @@ static void test_compiler(const String &p_code, const String &p_script_path, con signature += func->get_argument_name(i); } print_line(signature + ")"); - +#ifdef TOOLS_ENABLED func->disassemble(p_lines); +#endif print_line(""); print_line(""); } diff --git a/modules/glslang/register_types.cpp b/modules/glslang/register_types.cpp index 545aa68747..14135265b9 100644 --- a/modules/glslang/register_types.cpp +++ b/modules/glslang/register_types.cpp @@ -37,7 +37,7 @@ #include <glslang/Include/Types.h> #include <glslang/Public/ShaderLang.h> -static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage, const String &p_source_code, RenderingDevice::ShaderLanguage p_language, String *r_error) { +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) { Vector<uint8_t> ret; ERR_FAIL_COND_V(p_language == RenderingDevice::SHADER_LANGUAGE_HLSL, ret); @@ -51,20 +51,75 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage }; int ClientInputSemanticsVersion = 100; // maps to, say, #define VULKAN 100 + bool check_subgroup_support = true; // assume we support subgroups - glslang::EShTargetClientVersion VulkanClientVersion = glslang::EShTargetVulkan_1_0; - glslang::EShTargetLanguageVersion TargetVersion = glslang::EShTargetSpv_1_3; + glslang::EShTargetClientVersion ClientVersion = glslang::EShTargetVulkan_1_2; + 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) { + 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) { + ClientVersion = glslang::EShTargetVulkan_1_1; + TargetVersion = glslang::EShTargetSpv_1_3; + } else { + // use defaults + } + } else { + // once we support other backends we'll need to do something here + if (r_error) { + (*r_error) = "GLSLANG - Unsupported device family"; + } + return ret; + } + glslang::TShader shader(stages[p_stage]); CharString cs = p_source_code.ascii(); const char *cs_strings = cs.get_data(); + std::string preamble = ""; shader.setStrings(&cs_strings, 1); shader.setEnvInput(glslang::EShSourceGlsl, stages[p_stage], glslang::EShClientVulkan, ClientInputSemanticsVersion); - shader.setEnvClient(glslang::EShClientVulkan, VulkanClientVersion); + shader.setEnvClient(glslang::EShClientVulkan, ClientVersion); shader.setEnvTarget(glslang::EShTargetSpv, TargetVersion); + if (check_subgroup_support) { + uint32_t stage_bit = 1 << p_stage; + + if ((p_capabilities->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) { + preamble += "#define has_GL_KHR_shader_subgroup_vote 1\n"; + } + if (p_capabilities->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) { + preamble += "#define has_GL_KHR_shader_subgroup_ballot 1\n"; + } + if (p_capabilities->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) { + preamble += "#define has_GL_KHR_shader_subgroup_shuffle_relative 1\n"; + } + if (p_capabilities->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) { + preamble += "#define has_GL_KHR_shader_subgroup_quad 1\n"; + } + } + } + + if (preamble != "") { + shader.setPreamble(preamble.c_str()); + } + EShMessages messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules); const int DefaultVersion = 100; std::string pre_processed_code; diff --git a/modules/gltf/doc_classes/GLTFTexture.xml b/modules/gltf/doc_classes/GLTFTexture.xml index ece5cf3fe3..33bd8fddeb 100644 --- a/modules/gltf/doc_classes/GLTFTexture.xml +++ b/modules/gltf/doc_classes/GLTFTexture.xml @@ -9,7 +9,7 @@ <methods> </methods> <members> - <member name="src_image" type="int" setter="set_src_image" getter="get_src_image" default="212600976"> + <member name="src_image" type="int" setter="set_src_image" getter="get_src_image" default="0"> </member> </members> <constants> diff --git a/modules/gltf/editor_scene_importer_gltf.cpp b/modules/gltf/editor_scene_importer_gltf.cpp index 6ea722a216..35f44ca122 100644 --- a/modules/gltf/editor_scene_importer_gltf.cpp +++ b/modules/gltf/editor_scene_importer_gltf.cpp @@ -99,7 +99,9 @@ Node *PackedSceneGLTF::import_scene(const String &p_path, uint32_t p_flags, Ref<GLTFDocument> gltf_document; gltf_document.instance(); Error err = gltf_document->parse(r_state, p_path); - *r_err = err; + if (r_err) { + *r_err = err; + } ERR_FAIL_COND_V(err != Error::OK, nullptr); Node3D *root = memnew(Node3D); diff --git a/modules/gltf/editor_scene_importer_gltf.h b/modules/gltf/editor_scene_importer_gltf.h index db961e591d..af1a885f2b 100644 --- a/modules/gltf/editor_scene_importer_gltf.h +++ b/modules/gltf/editor_scene_importer_gltf.h @@ -64,8 +64,8 @@ public: virtual void get_extensions(List<String> *r_extensions) const override; virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, - List<String> *r_missing_deps = NULL, - Error *r_err = NULL) override; + List<String> *r_missing_deps = nullptr, + Error *r_err = nullptr) override; virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) override; }; @@ -80,7 +80,7 @@ protected: public: virtual void save_scene(Node *p_node, const String &p_path, const String &p_src_path, uint32_t p_flags, int p_bake_fps, - List<String> *r_missing_deps, Error *r_err = NULL); + List<String> *r_missing_deps, Error *r_err = nullptr); virtual void _build_parent_hierachy(Ref<GLTFState> state); virtual Error export_gltf(Node *p_root, String p_path, int32_t p_flags = 0, real_t p_bake_fps = 1000.0f); diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index caf8e3f48f..0b70175a24 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -554,10 +554,10 @@ Error GLTFDocument::_parse_scenes(Ref<GLTFState> state) { state->root_nodes.push_back(nodes[j]); } - if (s.has("name") && s["name"] != "") { + if (s.has("name") && !String(s["name"]).is_empty() && !((String)s["name"]).begins_with("Scene")) { state->scene_name = _gen_unique_name(state, s["name"]); } else { - state->scene_name = _gen_unique_name(state, "Scene"); + state->scene_name = _gen_unique_name(state, state->filename); } } @@ -940,22 +940,29 @@ String GLTFDocument::_get_accessor_type_name(const GLTFDocument::GLTFType p_type } GLTFDocument::GLTFType GLTFDocument::_get_type_from_str(const String &p_string) { - if (p_string == "SCALAR") + if (p_string == "SCALAR") { return GLTFDocument::TYPE_SCALAR; + } - if (p_string == "VEC2") + if (p_string == "VEC2") { return GLTFDocument::TYPE_VEC2; - if (p_string == "VEC3") + } + if (p_string == "VEC3") { return GLTFDocument::TYPE_VEC3; - if (p_string == "VEC4") + } + if (p_string == "VEC4") { return GLTFDocument::TYPE_VEC4; + } - if (p_string == "MAT2") + if (p_string == "MAT2") { return GLTFDocument::TYPE_MAT2; - if (p_string == "MAT3") + } + if (p_string == "MAT3") { return GLTFDocument::TYPE_MAT3; - if (p_string == "MAT4") + } + if (p_string == "MAT4") { return GLTFDocument::TYPE_MAT4; + } ERR_FAIL_V(GLTFDocument::TYPE_SCALAR); } @@ -1434,8 +1441,9 @@ Vector<double> GLTFDocument::_decode_accessor(Ref<GLTFState> state, const GLTFAc ERR_FAIL_INDEX_V(a->buffer_view, state->buffer_views.size(), Vector<double>()); const Error err = _decode_buffer_view(state, dst, a->buffer_view, skip_every, skip_bytes, element_size, a->count, a->type, component_count, a->component_type, component_size, a->normalized, a->byte_offset, p_for_vertex); - if (err != OK) + if (err != OK) { return Vector<double>(); + } } else { //fill with zeros, as bufferview is not defined. for (int i = 0; i < (a->count * component_count); i++) { @@ -1450,14 +1458,16 @@ Vector<double> GLTFDocument::_decode_accessor(Ref<GLTFState> state, const GLTFAc const int indices_component_size = _get_component_type_size(a->sparse_indices_component_type); Error err = _decode_buffer_view(state, indices.ptrw(), a->sparse_indices_buffer_view, 0, 0, indices_component_size, a->sparse_count, TYPE_SCALAR, 1, a->sparse_indices_component_type, indices_component_size, false, a->sparse_indices_byte_offset, false); - if (err != OK) + if (err != OK) { return Vector<double>(); + } Vector<double> data; data.resize(component_count * a->sparse_count); err = _decode_buffer_view(state, data.ptrw(), a->sparse_values_buffer_view, skip_every, skip_bytes, element_size, a->sparse_count, a->type, component_count, a->component_type, component_size, a->normalized, a->sparse_values_byte_offset, p_for_vertex); - if (err != OK) + if (err != OK) { return Vector<double>(); + } for (int i = 0; i < indices.size(); i++) { const int write_offset = int(indices[i]) * component_count; @@ -1528,8 +1538,9 @@ Vector<int> GLTFDocument::_decode_accessor_as_ints(Ref<GLTFState> state, const G const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); Vector<int> ret; - if (attribs.size() == 0) + if (attribs.size() == 0) { return ret; + } const double *attribs_ptr = attribs.ptr(); const int ret_size = attribs.size(); @@ -1546,8 +1557,9 @@ Vector<float> GLTFDocument::_decode_accessor_as_floats(Ref<GLTFState> state, con const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); Vector<float> ret; - if (attribs.size() == 0) + if (attribs.size() == 0) { return ret; + } const double *attribs_ptr = attribs.ptr(); const int ret_size = attribs.size(); @@ -1820,8 +1832,9 @@ Vector<Vector2> GLTFDocument::_decode_accessor_as_vec2(Ref<GLTFState> state, con const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); Vector<Vector2> ret; - if (attribs.size() == 0) + if (attribs.size() == 0) { return ret; + } ERR_FAIL_COND_V(attribs.size() % 2 != 0, ret); const double *attribs_ptr = attribs.ptr(); @@ -1998,8 +2011,9 @@ Vector<Vector3> GLTFDocument::_decode_accessor_as_vec3(Ref<GLTFState> state, con const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); Vector<Vector3> ret; - if (attribs.size() == 0) + if (attribs.size() == 0) { return ret; + } ERR_FAIL_COND_V(attribs.size() % 3 != 0, ret); const double *attribs_ptr = attribs.ptr(); @@ -2017,8 +2031,9 @@ Vector<Color> GLTFDocument::_decode_accessor_as_color(Ref<GLTFState> state, cons const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); Vector<Color> ret; - if (attribs.size() == 0) + if (attribs.size() == 0) { return ret; + } const int type = state->accessors[p_accessor]->type; ERR_FAIL_COND_V(!(type == TYPE_VEC3 || type == TYPE_VEC4), ret); @@ -2042,8 +2057,9 @@ Vector<Quat> GLTFDocument::_decode_accessor_as_quat(Ref<GLTFState> state, const const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); Vector<Quat> ret; - if (attribs.size() == 0) + if (attribs.size() == 0) { return ret; + } ERR_FAIL_COND_V(attribs.size() % 4 != 0, ret); const double *attribs_ptr = attribs.ptr(); @@ -2060,8 +2076,9 @@ Vector<Transform2D> GLTFDocument::_decode_accessor_as_xform2d(Ref<GLTFState> sta const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); Vector<Transform2D> ret; - if (attribs.size() == 0) + if (attribs.size() == 0) { return ret; + } ERR_FAIL_COND_V(attribs.size() % 4 != 0, ret); ret.resize(attribs.size() / 4); @@ -2076,8 +2093,9 @@ Vector<Basis> GLTFDocument::_decode_accessor_as_basis(Ref<GLTFState> state, cons const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); Vector<Basis> ret; - if (attribs.size() == 0) + if (attribs.size() == 0) { return ret; + } ERR_FAIL_COND_V(attribs.size() % 9 != 0, ret); ret.resize(attribs.size() / 9); @@ -2093,8 +2111,9 @@ Vector<Transform> GLTFDocument::_decode_accessor_as_xform(Ref<GLTFState> state, const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); Vector<Transform> ret; - if (attribs.size() == 0) + if (attribs.size() == 0) { return ret; + } ERR_FAIL_COND_V(attribs.size() % 16 != 0, ret); ret.resize(attribs.size() / 16); @@ -2449,6 +2468,12 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { const Dictionary &extras = d.has("extras") ? (Dictionary)d["extras"] : Dictionary(); Ref<EditorSceneImporterMesh> import_mesh; import_mesh.instance(); + String mesh_name = "mesh"; + if (d.has("name") && !String(d["name"]).is_empty()) { + mesh_name = d["name"]; + } + import_mesh->set_name(_gen_unique_name(state, vformat("%s_%s", state->scene_name, mesh_name))); + for (int j = 0; j < primitives.size(); j++) { Dictionary p = primitives[j]; @@ -2815,7 +2840,7 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path ERR_CONTINUE(state->images[i].is_null()); - Ref<Image> image = state->images[i]->get_data(); + Ref<Image> image = state->images[i]->get_image(); ERR_CONTINUE(image.is_null()); if (p_path.to_lower().ends_with("glb")) { @@ -2832,7 +2857,7 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path Vector<uint8_t> buffer; Ref<ImageTexture> img_tex = image; if (img_tex.is_valid()) { - image = img_tex->get_data(); + image = img_tex->get_image(); } Error err = PNGDriverCommon::image_to_png(image, buffer); ERR_FAIL_COND_V_MSG(err, err, "Can't convert image to PNG."); @@ -3040,8 +3065,9 @@ Error GLTFDocument::_serialize_textures(Ref<GLTFState> state) { } Error GLTFDocument::_parse_textures(Ref<GLTFState> state) { - if (!state->json.has("textures")) + if (!state->json.has("textures")) { return OK; + } const Array &textures = state->json["textures"]; for (GLTFTextureIndex i = 0; i < textures.size(); i++) { @@ -3062,7 +3088,7 @@ GLTFTextureIndex GLTFDocument::_set_texture(Ref<GLTFState> state, Ref<Texture2D> ERR_FAIL_COND_V(p_texture.is_null(), -1); Ref<GLTFTexture> gltf_texture; gltf_texture.instance(); - ERR_FAIL_COND_V(p_texture->get_data().is_null(), -1); + ERR_FAIL_COND_V(p_texture->get_image().is_null(), -1); GLTFImageIndex gltf_src_image_i = state->images.size(); state->images.push_back(p_texture); gltf_texture->set_src_image(gltf_src_image_i); @@ -3109,7 +3135,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { Ref<Texture2D> albedo_texture = material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO); GLTFTextureIndex gltf_texture_index = -1; - if (albedo_texture.is_valid() && albedo_texture->get_data().is_valid()) { + if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) { albedo_texture->set_name(material->get_name() + "_albedo"); gltf_texture_index = _set_texture(state, albedo_texture); } @@ -3122,9 +3148,9 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { mr["metallicFactor"] = material->get_metallic(); mr["roughnessFactor"] = material->get_roughness(); - bool has_roughness = material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS).is_valid() && material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS)->get_data().is_valid(); + bool has_roughness = material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS).is_valid() && material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS)->get_image().is_valid(); bool has_ao = material->get_feature(BaseMaterial3D::FEATURE_AMBIENT_OCCLUSION) && material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION).is_valid(); - bool has_metalness = material->get_texture(BaseMaterial3D::TEXTURE_METALLIC).is_valid() && material->get_texture(BaseMaterial3D::TEXTURE_METALLIC)->get_data().is_valid(); + bool has_metalness = material->get_texture(BaseMaterial3D::TEXTURE_METALLIC).is_valid() && material->get_texture(BaseMaterial3D::TEXTURE_METALLIC)->get_image().is_valid(); if (has_ao || has_roughness || has_metalness) { Dictionary mrt; Ref<Texture2D> roughness_texture = material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS); @@ -3143,10 +3169,10 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { if (has_ao) { height = ao_texture->get_height(); width = ao_texture->get_width(); - ao_image = ao_texture->get_data(); + ao_image = ao_texture->get_image(); Ref<ImageTexture> img_tex = ao_image; if (img_tex.is_valid()) { - ao_image = img_tex->get_data(); + ao_image = img_tex->get_image(); } if (ao_image->is_compressed()) { ao_image->decompress(); @@ -3156,10 +3182,10 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { if (has_roughness) { height = roughness_texture->get_height(); width = roughness_texture->get_width(); - roughness_image = roughness_texture->get_data(); + roughness_image = roughness_texture->get_image(); Ref<ImageTexture> img_tex = roughness_image; if (img_tex.is_valid()) { - roughness_image = img_tex->get_data(); + roughness_image = img_tex->get_image(); } if (roughness_image->is_compressed()) { roughness_image->decompress(); @@ -3169,17 +3195,17 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { if (has_metalness) { height = metallic_texture->get_height(); width = metallic_texture->get_width(); - metallness_image = metallic_texture->get_data(); + metallness_image = metallic_texture->get_image(); Ref<ImageTexture> img_tex = metallness_image; if (img_tex.is_valid()) { - metallness_image = img_tex->get_data(); + metallness_image = img_tex->get_image(); } if (metallness_image->is_compressed()) { metallness_image->decompress(); } } Ref<Texture2D> albedo_texture = material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO); - if (albedo_texture.is_valid() && albedo_texture->get_data().is_valid()) { + if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) { height = albedo_texture->get_height(); width = albedo_texture->get_width(); } @@ -3260,10 +3286,10 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { { Ref<Texture2D> normal_texture = material->get_texture(BaseMaterial3D::TEXTURE_NORMAL); // Code for uncompressing RG normal maps - Ref<Image> img = normal_texture->get_data(); + Ref<Image> img = normal_texture->get_image(); Ref<ImageTexture> img_tex = img; if (img_tex.is_valid()) { - img = img_tex->get_data(); + img = img_tex->get_image(); } img->decompress(); img->convert(Image::FORMAT_RGBA8); @@ -3282,7 +3308,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { } Ref<Texture2D> normal_texture = material->get_texture(BaseMaterial3D::TEXTURE_NORMAL); GLTFTextureIndex gltf_texture_index = -1; - if (tex.is_valid() && tex->get_data().is_valid()) { + if (tex.is_valid() && tex->get_image().is_valid()) { tex->set_name(material->get_name() + "_normal"); gltf_texture_index = _set_texture(state, tex); } @@ -3305,7 +3331,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { Dictionary et; Ref<Texture2D> emission_texture = material->get_texture(BaseMaterial3D::TEXTURE_EMISSION); GLTFTextureIndex gltf_texture_index = -1; - if (emission_texture.is_valid() && emission_texture->get_data().is_valid()) { + if (emission_texture.is_valid() && emission_texture->get_image().is_valid()) { emission_texture->set_name(material->get_name() + "_emission"); gltf_texture_index = _set_texture(state, emission_texture); } @@ -3334,8 +3360,9 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { } Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { - if (!state->json.has("materials")) + if (!state->json.has("materials")) { return OK; + } const Array &materials = state->json["materials"]; for (GLTFMaterialIndex i = 0; i < materials.size(); i++) { @@ -3343,8 +3370,10 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { Ref<StandardMaterial3D> material; material.instance(); - if (d.has("name")) { + if (d.has("name") && !String(d["name"]).is_empty()) { material->set_name(d["name"]); + } else { + material->set_name(vformat("material_%s", itos(i))); } material->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); Dictionary pbr_spec_gloss_extensions; @@ -3362,7 +3391,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { if (diffuse_texture_dict.has("index")) { Ref<Texture2D> diffuse_texture = _get_texture(state, diffuse_texture_dict["index"]); if (diffuse_texture.is_valid()) { - spec_gloss->diffuse_img = diffuse_texture->get_data(); + spec_gloss->diffuse_img = diffuse_texture->get_image(); material->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, diffuse_texture); } } @@ -3390,7 +3419,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { if (spec_gloss_texture.has("index")) { const Ref<Texture2D> orig_texture = _get_texture(state, spec_gloss_texture["index"]); if (orig_texture.is_valid()) { - spec_gloss->spec_gloss_img = orig_texture->get_data(); + spec_gloss->spec_gloss_img = orig_texture->get_image(); } } } @@ -3850,8 +3879,9 @@ Error GLTFDocument::_verify_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) { } Error GLTFDocument::_parse_skins(Ref<GLTFState> state) { - if (!state->json.has("skins")) + if (!state->json.has("skins")) { return OK; + } const Array &skins = state->json["skins"]; @@ -3881,8 +3911,10 @@ Error GLTFDocument::_parse_skins(Ref<GLTFState> state) { state->nodes.write[node]->joint = true; } - if (d.has("name")) { + if (d.has("name") && !String(d["name"]).is_empty()) { skin->set_name(d["name"]); + } else { + skin->set_name(vformat("skin_%s", itos(i))); } if (d.has("skeleton")) { @@ -4098,8 +4130,9 @@ Error GLTFDocument::_reparent_to_fake_joint(Ref<GLTFState> state, Ref<GLTFSkelet state->nodes.push_back(fake_joint); // We better not be a joint, or we messed up in our logic - if (node->joint) + if (node->joint) { return FAILED; + } fake_joint->translation = node->translation; fake_joint->rotation = node->rotation; @@ -4518,8 +4551,9 @@ Error GLTFDocument::_parse_lights(Ref<GLTFState> state) { } Error GLTFDocument::_parse_cameras(Ref<GLTFState> state) { - if (!state->json.has("cameras")) + if (!state->json.has("cameras")) { return OK; + } const Array cameras = state->json["cameras"]; @@ -4720,8 +4754,9 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> state) { } Error GLTFDocument::_parse_animations(Ref<GLTFState> state) { - if (!state->json.has("animations")) + if (!state->json.has("animations")) { return OK; + } const Array &animations = state->json["animations"]; @@ -4731,8 +4766,9 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> state) { Ref<GLTFAnimation> animation; animation.instance(); - if (!d.has("channels") || !d.has("samplers")) + if (!d.has("channels") || !d.has("samplers")) { continue; + } Array channels = d["channels"]; Array samplers = d["samplers"]; @@ -4747,8 +4783,9 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> state) { for (int j = 0; j < channels.size(); j++) { const Dictionary &c = channels[j]; - if (!c.has("target")) + if (!c.has("target")) { continue; + } const Dictionary &t = c["target"]; if (!t.has("node") || !t.has("path")) { @@ -4858,8 +4895,9 @@ void GLTFDocument::_assign_scene_names(Ref<GLTFState> state) { Ref<GLTFNode> n = state->nodes[i]; // Any joints get unique names generated when the skeleton is made, unique to the skeleton - if (n->skeleton >= 0) + if (n->skeleton >= 0) { continue; + } if (n->get_name().is_empty()) { if (n->mesh >= 0) { @@ -5505,8 +5543,9 @@ T GLTFDocument::_interpolate_track(const Vector<float> &p_times, const Vector<T> //could use binary search, worth it? int idx = -1; for (int i = 0; i < p_times.size(); i++) { - if (p_times[i] > p_time) + if (p_times[i] > p_time) { break; + } idx++; } @@ -5633,8 +5672,8 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, animation->track_set_path(track_idx, node_path); //first determine animation length - const float increment = 1.0 / float(bake_fps); - float time = 0.0; + const double increment = 1.0 / bake_fps; + double time = 0.0; Vector3 base_pos; Quat base_rot; @@ -5724,8 +5763,8 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, } } else { // CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies. - const float increment = 1.0 / float(bake_fps); - float time = 0.0; + const double increment = 1.0 / bake_fps; + double time = 0.0; bool last = false; while (true) { _interpolate_track<float>(track.weight_tracks[i].times, track.weight_tracks[i].values, time, gltf_interp); @@ -6346,16 +6385,21 @@ Error GLTFDocument::parse(Ref<GLTFState> state, String p_path, bool p_read_binar //binary file //text file err = _parse_glb(p_path, state); - if (err) + if (err) { return FAILED; + } } else { //text file err = _parse_json(p_path, state); - if (err) + if (err) { return FAILED; + } } f->close(); + // get file's name, use for scene name if none + state->filename = p_path.get_file().get_slice(".", 0); + ERR_FAIL_COND_V(!state->json.has("asset"), Error::FAILED); Dictionary asset = state->json["asset"]; @@ -6369,68 +6413,81 @@ Error GLTFDocument::parse(Ref<GLTFState> state, String p_path, bool p_read_binar /* STEP 0 PARSE SCENE */ err = _parse_scenes(state); - if (err != OK) + if (err != OK) { return Error::FAILED; + } /* STEP 1 PARSE NODES */ err = _parse_nodes(state); - if (err != OK) + if (err != OK) { return Error::FAILED; + } /* STEP 2 PARSE BUFFERS */ err = _parse_buffers(state, p_path.get_base_dir()); - if (err != OK) + if (err != OK) { return Error::FAILED; + } /* STEP 3 PARSE BUFFER VIEWS */ err = _parse_buffer_views(state); - if (err != OK) + if (err != OK) { return Error::FAILED; + } /* STEP 4 PARSE ACCESSORS */ err = _parse_accessors(state); - if (err != OK) + if (err != OK) { return Error::FAILED; + } /* STEP 5 PARSE IMAGES */ err = _parse_images(state, p_path.get_base_dir()); - if (err != OK) + if (err != OK) { return Error::FAILED; + } /* STEP 6 PARSE TEXTURES */ err = _parse_textures(state); - if (err != OK) + if (err != OK) { return Error::FAILED; + } /* STEP 7 PARSE TEXTURES */ err = _parse_materials(state); - if (err != OK) + if (err != OK) { return Error::FAILED; + } /* STEP 9 PARSE SKINS */ err = _parse_skins(state); - if (err != OK) + if (err != OK) { return Error::FAILED; + } /* STEP 10 DETERMINE SKELETONS */ err = _determine_skeletons(state); - if (err != OK) + if (err != OK) { return Error::FAILED; + } /* STEP 11 CREATE SKELETONS */ err = _create_skeletons(state); - if (err != OK) + if (err != OK) { return Error::FAILED; + } /* STEP 12 CREATE SKINS */ err = _create_skins(state); - if (err != OK) + if (err != OK) { return Error::FAILED; + } /* STEP 13 PARSE MESHES (we have enough info now) */ err = _parse_meshes(state); - if (err != OK) + if (err != OK) { return Error::FAILED; + } /* STEP 14 PARSE LIGHTS */ err = _parse_lights(state); @@ -6440,13 +6497,15 @@ Error GLTFDocument::parse(Ref<GLTFState> state, String p_path, bool p_read_binar /* STEP 15 PARSE CAMERAS */ err = _parse_cameras(state); - if (err != OK) + if (err != OK) { return Error::FAILED; + } /* STEP 16 PARSE ANIMATIONS */ err = _parse_animations(state); - if (err != OK) + if (err != OK) { return Error::FAILED; + } /* STEP 17 ASSIGN SCENE NAMES */ _assign_scene_names(state); diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h index 9030962b03..ba6bf8a533 100644 --- a/modules/gltf/gltf_state.h +++ b/modules/gltf/gltf_state.h @@ -53,6 +53,7 @@ class GLTFState : public Resource { friend class GLTFDocument; friend class PackedSceneGLTF; + String filename; Dictionary json; int major_version = 0; int minor_version = 0; diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index da9cdb9bc5..74ae45a46e 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -386,13 +386,13 @@ bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, b } int cell[3]; - float cell_size[3] = { node->get_cell_size().x, node->get_cell_size().y, node->get_cell_size().z }; + Vector3 cell_size = node->get_cell_size(); for (int i = 0; i < 3; i++) { if (i == edit_axis) { cell[i] = edit_floor[i]; } else { - cell[i] = inters[i] / node->get_cell_size()[i]; + cell[i] = inters[i] / cell_size[i]; if (inters[i] < 0) { cell[i] -= 1; // Compensate negative. } @@ -436,6 +436,7 @@ bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, b } return true; } + if (input_action == INPUT_PAINT) { SetItem si; si.position = Vector3i(cell[0], cell[1], cell[2]); @@ -545,7 +546,7 @@ void GridMapEditor::_update_paste_indicator() { return; } - Vector3 center = 0.5 * Vector3(float(node->get_center_x()), float(node->get_center_y()), float(node->get_center_z())); + Vector3 center = 0.5 * Vector3(real_t(node->get_center_x()), real_t(node->get_center_y()), real_t(node->get_center_z())); Vector3 scale = (Vector3(1, 1, 1) + (paste_indicator.end - paste_indicator.begin)) * node->get_cell_size(); Transform xf; xf.scale(scale); @@ -614,13 +615,13 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == BUTTON_WHEEL_UP && (mb->get_command() || mb->get_shift())) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && (mb->get_command() || mb->get_shift())) { if (mb->is_pressed()) { floor->set_value(floor->get_value() + mb->get_factor()); } return true; // Eaten. - } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && (mb->get_command() || mb->get_shift())) { + } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && (mb->get_command() || mb->get_shift())) { if (mb->is_pressed()) { floor->set_value(floor->get_value() - mb->get_factor()); } @@ -631,7 +632,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In Node3DEditorViewport::NavigationScheme nav_scheme = (Node3DEditorViewport::NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); if ((nav_scheme == Node3DEditorViewport::NAVIGATION_MAYA || nav_scheme == Node3DEditorViewport::NAVIGATION_MODO) && mb->get_alt()) { input_action = INPUT_NONE; - } else if (mb->get_button_index() == BUTTON_LEFT) { + } else if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { bool can_edit = (node && node->get_mesh_library().is_valid()); if (input_action == INPUT_PASTE) { _do_paste(); @@ -646,7 +647,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In input_action = INPUT_PAINT; set_items.clear(); } - } else if (mb->get_button_index() == BUTTON_RIGHT) { + } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) { if (input_action == INPUT_PASTE) { _clear_clipboard_data(); input_action = INPUT_NONE; @@ -665,7 +666,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In return do_input_action(p_camera, Point2(mb->get_position().x, mb->get_position().y), true); } else { - if ((mb->get_button_index() == BUTTON_RIGHT && input_action == INPUT_ERASE) || (mb->get_button_index() == BUTTON_LEFT && input_action == INPUT_PAINT)) { + if ((mb->get_button_index() == MOUSE_BUTTON_RIGHT && input_action == INPUT_ERASE) || (mb->get_button_index() == MOUSE_BUTTON_LEFT && input_action == INPUT_PAINT)) { if (set_items.size()) { undo_redo->create_action(TTR("GridMap Paint")); for (List<SetItem>::Element *E = set_items.front(); E; E = E->next()) { @@ -684,19 +685,19 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In return set_items.size() > 0; } - if (mb->get_button_index() == BUTTON_LEFT && input_action == INPUT_SELECT) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT && input_action == INPUT_SELECT) { undo_redo->create_action("GridMap Selection"); undo_redo->add_do_method(this, "_set_selection", selection.active, selection.begin, selection.end); undo_redo->add_undo_method(this, "_set_selection", last_selection.active, last_selection.begin, last_selection.end); undo_redo->commit_action(); } - if (mb->get_button_index() == BUTTON_LEFT && input_action != INPUT_NONE) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT && input_action != INPUT_NONE) { set_items.clear(); input_action = INPUT_NONE; return true; } - if (mb->get_button_index() == BUTTON_RIGHT && (input_action == INPUT_ERASE || input_action == INPUT_PASTE)) { + if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && (input_action == INPUT_ERASE || input_action == INPUT_PASTE)) { input_action = INPUT_NONE; return true; } @@ -810,11 +811,11 @@ void GridMapEditor::_mesh_library_palette_input(const Ref<InputEvent> &p_ie) { // Zoom in/out using Ctrl + mouse wheel if (mb.is_valid() && mb->is_pressed() && mb->get_command()) { - if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { size_slider->set_value(size_slider->get_value() + 0.2); } - if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_DOWN) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { size_slider->set_value(size_slider->get_value() - 0.2); } } diff --git a/modules/minimp3/audio_stream_mp3.cpp b/modules/minimp3/audio_stream_mp3.cpp index b128b81000..aaa05a910c 100644 --- a/modules/minimp3/audio_stream_mp3.cpp +++ b/modules/minimp3/audio_stream_mp3.cpp @@ -99,8 +99,9 @@ float AudioStreamPlaybackMP3::get_playback_position() const { } void AudioStreamPlaybackMP3::seek(float p_time) { - if (!active) + if (!active) { return; + } if (p_time >= mp3_stream->get_length()) { p_time = 0; diff --git a/modules/opensimplex/doc_classes/NoiseTexture.xml b/modules/opensimplex/doc_classes/NoiseTexture.xml index 86e7f9cc08..38c5138482 100644 --- a/modules/opensimplex/doc_classes/NoiseTexture.xml +++ b/modules/opensimplex/doc_classes/NoiseTexture.xml @@ -6,11 +6,12 @@ <description> Uses an [OpenSimplexNoise] to fill the texture data. You can specify the texture size but keep in mind that larger textures will take longer to generate and seamless noise only works with square sized textures. NoiseTexture can also generate normal map textures. - The class uses [Thread]s to generate the texture data internally, so [method Texture2D.get_data] may return [code]null[/code] if the generation process has not completed yet. In that case, you need to wait for the texture to be generated before accessing the data: + The class uses [Thread]s to generate the texture data internally, so [method Texture2D.get_image] may return [code]null[/code] if the generation process has not completed yet. In that case, you need to wait for the texture to be generated before accessing the image and the generated byte data: [codeblock] var texture = preload("res://noise.tres") yield(texture, "changed") - var image = texture.get_data() + var image = texture.get_image() + var data = image.get_data() [/codeblock] </description> <tutorials> diff --git a/modules/opensimplex/noise_texture.cpp b/modules/opensimplex/noise_texture.cpp index f5d401b058..7272d32fac 100644 --- a/modules/opensimplex/noise_texture.cpp +++ b/modules/opensimplex/noise_texture.cpp @@ -81,9 +81,9 @@ void NoiseTexture::_validate_property(PropertyInfo &property) const { } } -void NoiseTexture::_set_texture_data(const Ref<Image> &p_image) { - data = p_image; - if (data.is_valid()) { +void NoiseTexture::_set_texture_image(const Ref<Image> &p_image) { + image = p_image; + if (image.is_valid()) { if (texture.is_valid()) { RID new_texture = RS::get_singleton()->texture_2d_create(p_image); RS::get_singleton()->texture_replace(texture, new_texture); @@ -95,7 +95,7 @@ void NoiseTexture::_set_texture_data(const Ref<Image> &p_image) { } void NoiseTexture::_thread_done(const Ref<Image> &p_image) { - _set_texture_data(p_image); + _set_texture_image(p_image); noise_thread.wait_to_finish(); if (regen_queued) { noise_thread.start(_thread_function, this); @@ -159,7 +159,7 @@ void NoiseTexture::_update_texture() { } else { Ref<Image> image = _generate_texture(); - _set_texture_data(image); + _set_texture_image(image); } update_queued = false; } @@ -253,6 +253,6 @@ RID NoiseTexture::get_rid() const { return texture; } -Ref<Image> NoiseTexture::get_data() const { - return data; +Ref<Image> NoiseTexture::get_image() const { + return image; } diff --git a/modules/opensimplex/noise_texture.h b/modules/opensimplex/noise_texture.h index e89479d962..6983ae18fe 100644 --- a/modules/opensimplex/noise_texture.h +++ b/modules/opensimplex/noise_texture.h @@ -43,7 +43,7 @@ class NoiseTexture : public Texture2D { GDCLASS(NoiseTexture, Texture2D); private: - Ref<Image> data; + Ref<Image> image; Thread noise_thread; @@ -66,7 +66,7 @@ private: void _queue_update(); Ref<Image> _generate_texture(); void _update_texture(); - void _set_texture_data(const Ref<Image> &p_image); + void _set_texture_image(const Ref<Image> &p_image); protected: static void _bind_methods(); @@ -94,7 +94,7 @@ public: virtual RID get_rid() const override; virtual bool has_alpha() const override { return false; } - virtual Ref<Image> get_data() const override; + virtual Ref<Image> get_image() const override; NoiseTexture(); virtual ~NoiseTexture(); diff --git a/modules/text_server_adv/dynamic_font_adv.cpp b/modules/text_server_adv/dynamic_font_adv.cpp index 2521e68dda..326af7f0ee 100644 --- a/modules/text_server_adv/dynamic_font_adv.cpp +++ b/modules/text_server_adv/dynamic_font_adv.cpp @@ -231,7 +231,7 @@ Dictionary DynamicFontDataAdvanced::get_feature_list() const { Dictionary out; // Read feature flags. - unsigned int count = hb_ot_layout_table_get_feature_tags(hb_font_get_face(fds->hb_handle), HB_OT_TAG_GSUB, 0, NULL, NULL); + unsigned int count = hb_ot_layout_table_get_feature_tags(hb_font_get_face(fds->hb_handle), HB_OT_TAG_GSUB, 0, nullptr, nullptr); if (count != 0) { hb_tag_t *feature_tags = (hb_tag_t *)memalloc(count * sizeof(hb_tag_t)); hb_ot_layout_table_get_feature_tags(hb_font_get_face(fds->hb_handle), HB_OT_TAG_GSUB, 0, &count, feature_tags); @@ -240,7 +240,7 @@ Dictionary DynamicFontDataAdvanced::get_feature_list() const { } memfree(feature_tags); } - count = hb_ot_layout_table_get_feature_tags(hb_font_get_face(fds->hb_handle), HB_OT_TAG_GPOS, 0, NULL, NULL); + count = hb_ot_layout_table_get_feature_tags(hb_font_get_face(fds->hb_handle), HB_OT_TAG_GPOS, 0, nullptr, nullptr); if (count != 0) { hb_tag_t *feature_tags = (hb_tag_t *)memalloc(count * sizeof(hb_tag_t)); hb_ot_layout_table_get_feature_tags(hb_font_get_face(fds->hb_handle), HB_OT_TAG_GPOS, 0, &count, feature_tags); @@ -639,7 +639,7 @@ bool DynamicFontDataAdvanced::is_script_supported(uint32_t p_script) const { DataAtSize *fds = const_cast<DynamicFontDataAdvanced *>(this)->get_data_for_size(base_size); ERR_FAIL_COND_V(fds == nullptr, false); - unsigned int count = hb_ot_layout_table_get_script_tags(hb_font_get_face(fds->hb_handle), HB_OT_TAG_GSUB, 0, NULL, NULL); + unsigned int count = hb_ot_layout_table_get_script_tags(hb_font_get_face(fds->hb_handle), HB_OT_TAG_GSUB, 0, nullptr, nullptr); if (count != 0) { hb_tag_t *script_tags = (hb_tag_t *)memalloc(count * sizeof(hb_tag_t)); hb_ot_layout_table_get_script_tags(hb_font_get_face(fds->hb_handle), HB_OT_TAG_GSUB, 0, &count, script_tags); @@ -651,7 +651,7 @@ bool DynamicFontDataAdvanced::is_script_supported(uint32_t p_script) const { } memfree(script_tags); } - count = hb_ot_layout_table_get_script_tags(hb_font_get_face(fds->hb_handle), HB_OT_TAG_GPOS, 0, NULL, NULL); + count = hb_ot_layout_table_get_script_tags(hb_font_get_face(fds->hb_handle), HB_OT_TAG_GPOS, 0, nullptr, nullptr); if (count != 0) { hb_tag_t *script_tags = (hb_tag_t *)memalloc(count * sizeof(hb_tag_t)); hb_ot_layout_table_get_script_tags(hb_font_get_face(fds->hb_handle), HB_OT_TAG_GPOS, 0, &count, script_tags); @@ -997,6 +997,29 @@ Vector2 DynamicFontDataAdvanced::draw_glyph_outline(RID p_canvas, int p_size, in return advance; } +bool DynamicFontDataAdvanced::get_glyph_contours(int p_size, uint32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const { + _THREAD_SAFE_METHOD_ + DataAtSize *fds = const_cast<DynamicFontDataAdvanced *>(this)->get_data_for_size(p_size); + ERR_FAIL_COND_V(fds == nullptr, false); + + int error = FT_Load_Glyph(fds->face, p_index, FT_LOAD_NO_BITMAP | (force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0)); + ERR_FAIL_COND_V(error, false); + + r_points.clear(); + r_contours.clear(); + + float h = fds->ascent; + float scale = (1.0 / 64.0) / oversampling * fds->scale_color_font; + for (short i = 0; i < fds->face->glyph->outline.n_points; i++) { + r_points.push_back(Vector3(fds->face->glyph->outline.points[i].x * scale, h - fds->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fds->face->glyph->outline.tags[i]))); + } + for (short i = 0; i < fds->face->glyph->outline.n_contours; i++) { + r_contours.push_back(fds->face->glyph->outline.contours[i]); + } + r_orientation = (FT_Outline_Get_Orientation(&fds->face->glyph->outline) == FT_ORIENTATION_FILL_RIGHT); + return true; +} + DynamicFontDataAdvanced::~DynamicFontDataAdvanced() { clear_cache(); if (library != nullptr) { diff --git a/modules/text_server_adv/dynamic_font_adv.h b/modules/text_server_adv/dynamic_font_adv.h index d69a30b321..1292966f0c 100644 --- a/modules/text_server_adv/dynamic_font_adv.h +++ b/modules/text_server_adv/dynamic_font_adv.h @@ -186,6 +186,8 @@ public: virtual Vector2 draw_glyph(RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color) const override; virtual Vector2 draw_glyph_outline(RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color) const override; + virtual bool get_glyph_contours(int p_size, uint32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const override; + virtual ~DynamicFontDataAdvanced() override; }; diff --git a/modules/text_server_adv/font_adv.h b/modules/text_server_adv/font_adv.h index 2b6d977451..4fadefc569 100644 --- a/modules/text_server_adv/font_adv.h +++ b/modules/text_server_adv/font_adv.h @@ -92,8 +92,8 @@ struct FontDataAdvanced { virtual bool has_outline() const = 0; virtual float get_base_size() const = 0; - virtual bool is_lang_supported(const String &p_lang) const { return false; }; - virtual bool is_script_supported(uint32_t p_script) const { return false; }; + virtual bool is_lang_supported(const String &p_lang) const { return true; }; + virtual bool is_script_supported(uint32_t p_script) const { return true; }; virtual bool has_char(char32_t p_char) const = 0; virtual String get_supported_chars() const = 0; @@ -107,6 +107,8 @@ struct FontDataAdvanced { virtual Vector2 draw_glyph(RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color) const = 0; virtual Vector2 draw_glyph_outline(RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color) const = 0; + virtual bool get_glyph_contours(int p_size, uint32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const { return false; }; + virtual ~FontDataAdvanced(){}; }; diff --git a/modules/text_server_adv/script_iterator.cpp b/modules/text_server_adv/script_iterator.cpp index 8f23bb9e02..f9bbd25a5f 100644 --- a/modules/text_server_adv/script_iterator.cpp +++ b/modules/text_server_adv/script_iterator.cpp @@ -75,10 +75,12 @@ ScriptIterator::ScriptIterator(const String &p_string, int p_start, int p_length while (paren_sp >= 0 && paren_stack[paren_sp].pair_index != paired_ch) { paren_sp -= 1; } - if (paren_sp < start_sp) + if (paren_sp < start_sp) { start_sp = paren_sp; - if (paren_sp >= 0) + } + if (paren_sp >= 0) { sc = paren_stack[paren_sp].script_code; + } } } diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 43b8f18101..8b8b6b7cd3 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -906,6 +906,13 @@ Vector2 TextServerAdvanced::font_draw_glyph_outline(RID p_font, RID p_canvas, in return fd->draw_glyph_outline(p_canvas, p_size, p_outline_size, p_pos, p_index, p_color); } +bool TextServerAdvanced::font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const { + _THREAD_SAFE_METHOD_ + const FontDataAdvanced *fd = font_owner.getornull(p_font); + ERR_FAIL_COND_V(!fd, false); + return fd->get_glyph_contours(p_size, p_index, r_points, r_contours, r_orientation); +} + float TextServerAdvanced::font_get_oversampling() const { return oversampling; } @@ -1825,8 +1832,9 @@ _FORCE_INLINE_ int _generate_kashida_justification_opportunies(const String &p_d } } } - if (!is_transparent(c)) + if (!is_transparent(c)) { pc = c; + } i++; } diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index b53b5716e5..4ad23ca059 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -188,6 +188,8 @@ public: virtual Vector2 font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const override; virtual Vector2 font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const override; + virtual bool font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const override; + virtual float font_get_oversampling() const override; virtual void font_set_oversampling(float p_oversampling) override; diff --git a/modules/text_server_fb/dynamic_font_fb.cpp b/modules/text_server_fb/dynamic_font_fb.cpp index 66d36bc885..dec1d6f83f 100644 --- a/modules/text_server_fb/dynamic_font_fb.cpp +++ b/modules/text_server_fb/dynamic_font_fb.cpp @@ -680,6 +680,29 @@ Vector2 DynamicFontDataFallback::draw_glyph_outline(RID p_canvas, int p_size, in return advance; } +bool DynamicFontDataFallback::get_glyph_contours(int p_size, uint32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const { + _THREAD_SAFE_METHOD_ + DataAtSize *fds = const_cast<DynamicFontDataFallback *>(this)->get_data_for_size(p_size); + ERR_FAIL_COND_V(fds == nullptr, false); + + int error = FT_Load_Glyph(fds->face, p_index, FT_LOAD_NO_BITMAP | (force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0)); + ERR_FAIL_COND_V(error, false); + + r_points.clear(); + r_contours.clear(); + + float h = fds->ascent; + float scale = (1.0 / 64.0) / oversampling * fds->scale_color_font; + for (short i = 0; i < fds->face->glyph->outline.n_points; i++) { + r_points.push_back(Vector3(fds->face->glyph->outline.points[i].x * scale, h - fds->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fds->face->glyph->outline.tags[i]))); + } + for (short i = 0; i < fds->face->glyph->outline.n_contours; i++) { + r_contours.push_back(fds->face->glyph->outline.contours[i]); + } + r_orientation = (FT_Outline_Get_Orientation(&fds->face->glyph->outline) == FT_ORIENTATION_FILL_RIGHT); + return true; +} + DynamicFontDataFallback::~DynamicFontDataFallback() { clear_cache(); if (library != nullptr) { diff --git a/modules/text_server_fb/dynamic_font_fb.h b/modules/text_server_fb/dynamic_font_fb.h index eb70f46666..b34c8cbed5 100644 --- a/modules/text_server_fb/dynamic_font_fb.h +++ b/modules/text_server_fb/dynamic_font_fb.h @@ -164,6 +164,8 @@ public: virtual Vector2 draw_glyph(RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color) const override; virtual Vector2 draw_glyph_outline(RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color) const override; + virtual bool get_glyph_contours(int p_size, uint32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const override; + virtual ~DynamicFontDataFallback() override; }; diff --git a/modules/text_server_fb/font_fb.h b/modules/text_server_fb/font_fb.h index 218f3df03a..fe9888b7f4 100644 --- a/modules/text_server_fb/font_fb.h +++ b/modules/text_server_fb/font_fb.h @@ -93,6 +93,8 @@ struct FontDataFallback { virtual Vector2 draw_glyph(RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color) const = 0; virtual Vector2 draw_glyph_outline(RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color) const = 0; + virtual bool get_glyph_contours(int p_size, uint32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const { return false; }; + virtual ~FontDataFallback(){}; }; diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index f46f96d30d..98a67ef309 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -452,6 +452,13 @@ Vector2 TextServerFallback::font_draw_glyph_outline(RID p_font, RID p_canvas, in return fd->draw_glyph_outline(p_canvas, p_size, p_outline_size, p_pos, p_index, p_color); } +bool TextServerFallback::font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const { + _THREAD_SAFE_METHOD_ + const FontDataFallback *fd = font_owner.getornull(p_font); + ERR_FAIL_COND_V(!fd, false); + return fd->get_glyph_contours(p_size, p_index, r_points, r_contours, r_orientation); +} + float TextServerFallback::font_get_oversampling() const { return oversampling; } diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h index b10369d172..8f5eb1d315 100644 --- a/modules/text_server_fb/text_server_fb.h +++ b/modules/text_server_fb/text_server_fb.h @@ -137,6 +137,8 @@ public: virtual Vector2 font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const override; virtual Vector2 font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const override; + virtual bool font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const override; + virtual float font_get_oversampling() const override; virtual void font_set_oversampling(float p_oversampling) override; diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index e91ae46a57..6d5fff88d9 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -784,8 +784,9 @@ ScriptInstance *VisualScript::instance_create(Object *p_this) { variables.get_key_list(&keys); for (const List<StringName>::Element *E = keys.front(); E; E = E->next()) { - if (!variables[E->get()]._export) + if (!variables[E->get()]._export) { continue; + } PropertyInfo p = variables[E->get()].info; p.name = String(E->get()); @@ -2050,12 +2051,12 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o instance->id = F->get(); instance->input_port_count = node->get_input_value_port_count(); - instance->input_ports = NULL; + instance->input_ports = nullptr; instance->output_port_count = node->get_output_value_port_count(); - instance->output_ports = NULL; + instance->output_ports = nullptr; instance->sequence_output_count = node->get_output_sequence_port_count(); instance->sequence_index = function.node_count++; - instance->sequence_outputs = NULL; + instance->sequence_outputs = nullptr; instance->pass_idx = -1; if (instance->input_port_count) { @@ -2075,7 +2076,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o if (instance->sequence_output_count) { instance->sequence_outputs = memnew_arr(VisualScriptNodeInstance *, instance->sequence_output_count); for (int i = 0; i < instance->sequence_output_count; i++) { - instance->sequence_outputs[i] = NULL; // If it remains null, flow ends here. + instance->sequence_outputs[i] = nullptr; // If it remains null, flow ends here. } } @@ -2085,10 +2086,11 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o StringName var_name; - if (Object::cast_to<VisualScriptLocalVar>(*node)) + if (Object::cast_to<VisualScriptLocalVar>(*node)) { var_name = String(Object::cast_to<VisualScriptLocalVar>(*node)->get_var_name()).strip_edges(); - else + } else { var_name = String(Object::cast_to<VisualScriptLocalVarSet>(*node)->get_var_name()).strip_edges(); + } if (!local_var_indices.has(var_name)) { local_var_indices[var_name] = function.max_stack; @@ -2252,6 +2254,7 @@ Variant VisualScriptFunctionState::_signal_callback(const Variant **p_args, int } void VisualScriptFunctionState::connect_to_signal(Object *p_obj, const String &p_signal, Array p_binds) { + ERR_FAIL_NULL(p_obj); Vector<Variant> binds; for (int i = 0; i < p_binds.size(); i++) { binds.push_back(p_binds[i]); diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 3b2cd50544..3cdf60708b 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -1826,6 +1826,8 @@ void VisualScriptEditor::_generic_search(String p_base_type, Vector2 pos, bool n } void VisualScriptEditor::_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + // GUI input for VS Editor Plugin Ref<InputEventMouseButton> key = p_event; @@ -1837,7 +1839,7 @@ void VisualScriptEditor::_input(const Ref<InputEvent> &p_event) { void VisualScriptEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> key = p_event; - if (key.is_valid() && key->is_pressed() && key->get_button_mask() == BUTTON_RIGHT) { + if (key.is_valid() && key->is_pressed() && key->get_button_mask() == MOUSE_BUTTON_RIGHT) { saved_position = graph->get_local_mouse_position(); Point2 gpos = Input::get_singleton()->get_mouse_position(); @@ -3015,9 +3017,9 @@ void VisualScriptEditor::_graph_connect_to_empty(const String &p_from, int p_fro if (!vsn.is_valid()) { return; } - if (vsn->get_output_value_port_count()) - + if (vsn->get_output_value_port_count()) { port_action_pos = p_release_pos; + } if (p_from_slot < vsn->get_output_sequence_port_count()) { port_action_node = p_from.to_int(); diff --git a/modules/webxr/webxr_interface.h b/modules/webxr/webxr_interface.h index c5b2dc8d73..366235fcd5 100644 --- a/modules/webxr/webxr_interface.h +++ b/modules/webxr/webxr_interface.h @@ -57,7 +57,7 @@ public: virtual void set_requested_reference_space_types(String p_requested_reference_space_types) = 0; virtual String get_requested_reference_space_types() const = 0; virtual String get_reference_space_type() const = 0; - virtual XRPositionalTracker *get_controller(int p_controller_id) const = 0; + virtual Ref<XRPositionalTracker> get_controller(int p_controller_id) const = 0; virtual String get_visibility_state() const = 0; virtual PackedVector3Array get_bounds_geometry() const = 0; }; diff --git a/modules/webxr/webxr_interface_js.cpp b/modules/webxr/webxr_interface_js.cpp index 74789fc98e..4dce2c2b23 100644 --- a/modules/webxr/webxr_interface_js.cpp +++ b/modules/webxr/webxr_interface_js.cpp @@ -160,7 +160,7 @@ String WebXRInterfaceJS::get_reference_space_type() const { return reference_space_type; } -XRPositionalTracker *WebXRInterfaceJS::get_controller(int p_controller_id) const { +Ref<XRPositionalTracker> WebXRInterfaceJS::get_controller(int p_controller_id) const { XRServer *xr_server = XRServer::get_singleton(); ERR_FAIL_NULL_V(xr_server, nullptr); @@ -380,10 +380,10 @@ void WebXRInterfaceJS::_update_tracker(int p_controller_id) { XRServer *xr_server = XRServer::get_singleton(); ERR_FAIL_NULL(xr_server); - XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id + 1); + Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id + 1); if (godot_webxr_is_controller_connected(p_controller_id)) { - if (tracker == nullptr) { - tracker = memnew(XRPositionalTracker); + if (tracker.is_null()) { + tracker.instance(); tracker->set_tracker_type(XRServer::TRACKER_CONTROLLER); // Controller id's 0 and 1 are always the left and right hands. if (p_controller_id < 2) { @@ -416,14 +416,14 @@ void WebXRInterfaceJS::_update_tracker(int p_controller_id) { int *axes = godot_webxr_get_controller_axes(p_controller_id); if (axes) { for (int i = 0; i < axes[0]; i++) { - Input::JoyAxis joy_axis; + Input::JoyAxisValue joy_axis; joy_axis.min = -1; joy_axis.value = *((float *)axes + (i + 1)); input->joy_axis(p_controller_id + 100, i, joy_axis); } free(axes); } - } else if (tracker) { + } else if (tracker.is_valid()) { xr_server->remove_tracker(tracker); } } diff --git a/modules/webxr/webxr_interface_js.h b/modules/webxr/webxr_interface_js.h index 49299b252f..7c841c1911 100644 --- a/modules/webxr/webxr_interface_js.h +++ b/modules/webxr/webxr_interface_js.h @@ -71,7 +71,7 @@ public: virtual String get_requested_reference_space_types() const override; void _set_reference_space_type(String p_reference_space_type); virtual String get_reference_space_type() const override; - virtual XRPositionalTracker *get_controller(int p_controller_id) const override; + virtual Ref<XRPositionalTracker> get_controller(int p_controller_id) const override; virtual String get_visibility_state() const override; virtual PackedVector3Array get_bounds_geometry() const override; diff --git a/platform/android/detect.py b/platform/android/detect.py index 5f0fcc9b77..996b6dcf41 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -197,12 +197,11 @@ def configure(env): if env["optimize"] == "speed": # optimize for speed (default) env.Append(LINKFLAGS=["-O2"]) env.Append(CCFLAGS=["-O2", "-fomit-frame-pointer"]) - env.Append(CPPDEFINES=["NDEBUG"]) - else: # optimize for size + elif env["optimize"] == "size": # optimize for size env.Append(CCFLAGS=["-Os"]) - env.Append(CPPDEFINES=["NDEBUG"]) env.Append(LINKFLAGS=["-Os"]) + env.Append(CPPDEFINES=["NDEBUG"]) if can_vectorize: env.Append(CCFLAGS=["-ftree-vectorize"]) if env["target"] == "release_debug": diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index 5f7e5eaa83..dd001baba9 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -477,7 +477,7 @@ void DisplayServerAndroid::process_joy_event(DisplayServerAndroid::JoypadEvent p Input::get_singleton()->joy_button(p_event.device, p_event.index, p_event.pressed); break; case JOY_EVENT_AXIS: - Input::JoyAxis value; + Input::JoyAxisValue value; value.min = -1; value.value = p_event.value; Input::get_singleton()->joy_axis(p_event.device, p_event.index, value); @@ -741,15 +741,15 @@ void DisplayServerAndroid::process_mouse_event(int input_device, int event_actio ev->set_pressed(true); buttons_state = event_buttons_mask; if (event_vertical_factor > 0) { - _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_UP, event_vertical_factor); + _wheel_button_click(event_buttons_mask, ev, MOUSE_BUTTON_WHEEL_UP, event_vertical_factor); } else if (event_vertical_factor < 0) { - _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_DOWN, -event_vertical_factor); + _wheel_button_click(event_buttons_mask, ev, MOUSE_BUTTON_WHEEL_DOWN, -event_vertical_factor); } if (event_horizontal_factor > 0) { - _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_RIGHT, event_horizontal_factor); + _wheel_button_click(event_buttons_mask, ev, MOUSE_BUTTON_WHEEL_RIGHT, event_horizontal_factor); } else if (event_horizontal_factor < 0) { - _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_LEFT, -event_horizontal_factor); + _wheel_button_click(event_buttons_mask, ev, MOUSE_BUTTON_WHEEL_LEFT, -event_horizontal_factor); } } break; } @@ -784,16 +784,16 @@ void DisplayServerAndroid::process_double_tap(int event_android_button_mask, Poi int DisplayServerAndroid::_button_index_from_mask(int button_mask) { switch (button_mask) { - case BUTTON_MASK_LEFT: - return BUTTON_LEFT; - case BUTTON_MASK_RIGHT: - return BUTTON_RIGHT; - case BUTTON_MASK_MIDDLE: - return BUTTON_MIDDLE; - case BUTTON_MASK_XBUTTON1: - return BUTTON_XBUTTON1; - case BUTTON_MASK_XBUTTON2: - return BUTTON_XBUTTON2; + case MOUSE_BUTTON_MASK_LEFT: + return MOUSE_BUTTON_LEFT; + case MOUSE_BUTTON_MASK_RIGHT: + return MOUSE_BUTTON_RIGHT; + case MOUSE_BUTTON_MASK_MIDDLE: + return MOUSE_BUTTON_MIDDLE; + case MOUSE_BUTTON_MASK_XBUTTON1: + return MOUSE_BUTTON_XBUTTON1; + case MOUSE_BUTTON_MASK_XBUTTON2: + return MOUSE_BUTTON_XBUTTON2; default: return 0; } @@ -854,19 +854,19 @@ int DisplayServerAndroid::mouse_get_button_state() const { int DisplayServerAndroid::_android_button_mask_to_godot_button_mask(int android_button_mask) { int godot_button_mask = 0; if (android_button_mask & AMOTION_EVENT_BUTTON_PRIMARY) { - godot_button_mask |= BUTTON_MASK_LEFT; + godot_button_mask |= MOUSE_BUTTON_MASK_LEFT; } if (android_button_mask & AMOTION_EVENT_BUTTON_SECONDARY) { - godot_button_mask |= BUTTON_MASK_RIGHT; + godot_button_mask |= MOUSE_BUTTON_MASK_RIGHT; } if (android_button_mask & AMOTION_EVENT_BUTTON_TERTIARY) { - godot_button_mask |= BUTTON_MASK_MIDDLE; + godot_button_mask |= MOUSE_BUTTON_MASK_MIDDLE; } if (android_button_mask & AMOTION_EVENT_BUTTON_BACK) { - godot_button_mask |= BUTTON_MASK_XBUTTON1; + godot_button_mask |= MOUSE_BUTTON_MASK_XBUTTON1; } if (android_button_mask & AMOTION_EVENT_BUTTON_SECONDARY) { - godot_button_mask |= BUTTON_MASK_XBUTTON2; + godot_button_mask |= MOUSE_BUTTON_MASK_XBUTTON2; } return godot_button_mask; diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 326e513261..5f9f420b59 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -2262,8 +2262,9 @@ public: CharString command_line_argument = command_line_strings[i].utf8(); int base = r_command_line_flags.size(); int length = command_line_argument.length(); - if (length == 0) + if (length == 0) { continue; + } r_command_line_flags.resize(base + 4 + length); encode_uint32(length, &r_command_line_flags.write[base]); copymem(&r_command_line_flags.write[base + 4], command_line_argument.ptr(), length); @@ -2484,7 +2485,7 @@ public: _clear_assets_directory(); if (!apk_expansion) { print_verbose("Exporting project files.."); - err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, NULL, ignore_so_file); + err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, nullptr, ignore_so_file); if (err != OK) { EditorNode::add_io_error("Could not export project files to gradle project\n"); return err; @@ -2615,10 +2616,11 @@ public: } // This is the start of the Legacy build system print_verbose("Starting legacy build system.."); - if (p_debug) + if (p_debug) { src_apk = p_preset->get("custom_template/debug"); - else + } else { src_apk = p_preset->get("custom_template/release"); + } src_apk = src_apk.strip_edges(); if (src_apk == "") { if (p_debug) { @@ -2813,11 +2815,11 @@ public: zipOpenNewFileInZip(unaligned_apk, "assets/_cl_", &zipfi, - NULL, + nullptr, 0, - NULL, + nullptr, 0, - NULL, + nullptr, 0, // No compress (little size gain and potentially slower startup) Z_DEFAULT_COMPRESSION); zipWriteInFileInZip(unaligned_apk, command_line_flags.ptr(), command_line_flags.size()); diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h index 097a2391ee..40b8e90c6f 100644 --- a/platform/android/export/gradle_export_util.h +++ b/platform/android/export/gradle_export_util.h @@ -47,20 +47,21 @@ const String godot_project_name_xml_string = R"(<?xml version="1.0" encoding="ut DisplayServer::ScreenOrientation _get_screen_orientation() { String orientation_settings = ProjectSettings::get_singleton()->get("display/window/handheld/orientation"); DisplayServer::ScreenOrientation screen_orientation; - if (orientation_settings == "portrait") + if (orientation_settings == "portrait") { screen_orientation = DisplayServer::SCREEN_PORTRAIT; - else if (orientation_settings == "reverse_landscape") + } else if (orientation_settings == "reverse_landscape") { screen_orientation = DisplayServer::SCREEN_REVERSE_LANDSCAPE; - else if (orientation_settings == "reverse_portrait") + } else if (orientation_settings == "reverse_portrait") { screen_orientation = DisplayServer::SCREEN_REVERSE_PORTRAIT; - else if (orientation_settings == "sensor_landscape") + } else if (orientation_settings == "sensor_landscape") { screen_orientation = DisplayServer::SCREEN_SENSOR_LANDSCAPE; - else if (orientation_settings == "sensor_portrait") + } else if (orientation_settings == "sensor_portrait") { screen_orientation = DisplayServer::SCREEN_SENSOR_PORTRAIT; - else if (orientation_settings == "sensor") + } else if (orientation_settings == "sensor") { screen_orientation = DisplayServer::SCREEN_SENSOR; - else + } else { screen_orientation = DisplayServer::SCREEN_LANDSCAPE; + } return screen_orientation; } diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java index c601864880..0c16214c8a 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java @@ -268,7 +268,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC GodotLib.setup(command_line); - final String videoDriver = GodotLib.getGlobal("rendering/quality/driver/driver_name"); + final String videoDriver = GodotLib.getGlobal("rendering/driver/driver_name"); if (videoDriver.equals("Vulkan")) { mRenderView = new GodotVulkanRenderView(activity, this); } else { diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp index ab03599dc3..f49b0e843a 100644 --- a/platform/android/java_class_wrapper.cpp +++ b/platform/android/java_class_wrapper.cpp @@ -38,6 +38,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method, return false; JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, false); MethodInfo *method = nullptr; for (List<MethodInfo>::Element *E = M->get().front(); E; E = E->next()) { @@ -965,6 +966,7 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) { return class_cache[p_class]; JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, Ref<JavaClass>()); jclass bclass = env->FindClass(p_class.utf8().get_data()); ERR_FAIL_COND_V(!bclass, Ref<JavaClass>()); @@ -1149,6 +1151,7 @@ JavaClassWrapper::JavaClassWrapper(jobject p_activity) { singleton = this; JNIEnv *env = get_jni_env(); + ERR_FAIL_COND(env == nullptr); jclass activityClass = env->FindClass("android/app/Activity"); jmethodID getClassLoader = env->GetMethodID(activityClass, "getClassLoader", "()Ljava/lang/ClassLoader;"); diff --git a/platform/android/java_godot_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp index 41201db32b..ec3b6f8ac0 100644 --- a/platform/android/java_godot_io_wrapper.cpp +++ b/platform/android/java_godot_io_wrapper.cpp @@ -73,6 +73,7 @@ jobject GodotIOJavaWrapper::get_instance() { Error GodotIOJavaWrapper::open_uri(const String &p_uri) { if (_open_URI) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, ERR_UNAVAILABLE); jstring jStr = env->NewStringUTF(p_uri.utf8().get_data()); return env->CallIntMethod(godot_io_instance, _open_URI, jStr) ? ERR_CANT_OPEN : OK; } else { @@ -83,6 +84,7 @@ Error GodotIOJavaWrapper::open_uri(const String &p_uri) { String GodotIOJavaWrapper::get_user_data_dir() { if (_get_data_dir) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, String()); jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_data_dir); return jstring_to_string(s, env); } else { @@ -93,6 +95,7 @@ String GodotIOJavaWrapper::get_user_data_dir() { String GodotIOJavaWrapper::get_locale() { if (_get_locale) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, String()); jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_locale); return jstring_to_string(s, env); } else { @@ -103,6 +106,7 @@ String GodotIOJavaWrapper::get_locale() { String GodotIOJavaWrapper::get_model() { if (_get_model) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, String()); jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_model); return jstring_to_string(s, env); } else { @@ -113,6 +117,7 @@ String GodotIOJavaWrapper::get_model() { int GodotIOJavaWrapper::get_screen_dpi() { if (_get_screen_DPI) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, 160); return env->CallIntMethod(godot_io_instance, _get_screen_DPI); } else { return 160; @@ -122,6 +127,7 @@ int GodotIOJavaWrapper::get_screen_dpi() { void GodotIOJavaWrapper::screen_get_usable_rect(int (&p_rect_xywh)[4]) { if (_screen_get_usable_rect) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND(env == nullptr); jintArray returnArray = (jintArray)env->CallObjectMethod(godot_io_instance, _screen_get_usable_rect); ERR_FAIL_COND(env->GetArrayLength(returnArray) != 4); jint *arrayBody = env->GetIntArrayElements(returnArray, JNI_FALSE); @@ -135,6 +141,7 @@ void GodotIOJavaWrapper::screen_get_usable_rect(int (&p_rect_xywh)[4]) { String GodotIOJavaWrapper::get_unique_id() { if (_get_unique_id) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, String()); jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_unique_id); return jstring_to_string(s, env); } else { @@ -149,6 +156,7 @@ bool GodotIOJavaWrapper::has_vk() { void GodotIOJavaWrapper::show_vk(const String &p_existing, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { if (_show_keyboard) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND(env == nullptr); 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); } @@ -157,6 +165,7 @@ void GodotIOJavaWrapper::show_vk(const String &p_existing, bool p_multiline, int void GodotIOJavaWrapper::hide_vk() { if (_hide_keyboard) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND(env == nullptr); env->CallVoidMethod(godot_io_instance, _hide_keyboard); } } @@ -164,6 +173,7 @@ void GodotIOJavaWrapper::hide_vk() { void GodotIOJavaWrapper::set_screen_orientation(int p_orient) { if (_set_screen_orientation) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND(env == nullptr); env->CallVoidMethod(godot_io_instance, _set_screen_orientation, p_orient); } } @@ -171,6 +181,7 @@ void GodotIOJavaWrapper::set_screen_orientation(int p_orient) { int GodotIOJavaWrapper::get_screen_orientation() { if (_get_screen_orientation) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, 0); return env->CallIntMethod(godot_io_instance, _get_screen_orientation); } else { return 0; @@ -180,6 +191,7 @@ int GodotIOJavaWrapper::get_screen_orientation() { String GodotIOJavaWrapper::get_system_dir(int p_dir) { if (_get_system_dir) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, String(".")); jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_system_dir, p_dir); return jstring_to_string(s, env); } else { diff --git a/platform/android/java_godot_view_wrapper.cpp b/platform/android/java_godot_view_wrapper.cpp index 5b638300ef..6b5e44f371 100644 --- a/platform/android/java_godot_view_wrapper.cpp +++ b/platform/android/java_godot_view_wrapper.cpp @@ -34,6 +34,7 @@ GodotJavaViewWrapper::GodotJavaViewWrapper(jobject godot_view) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND(env == nullptr); _godot_view = env->NewGlobalRef(godot_view); @@ -48,6 +49,8 @@ GodotJavaViewWrapper::GodotJavaViewWrapper(jobject godot_view) { void GodotJavaViewWrapper::request_pointer_capture() { if (_request_pointer_capture != 0) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND(env == nullptr); + env->CallVoidMethod(_godot_view, _request_pointer_capture); } } @@ -55,12 +58,16 @@ void GodotJavaViewWrapper::request_pointer_capture() { void GodotJavaViewWrapper::release_pointer_capture() { if (_request_pointer_capture != 0) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND(env == nullptr); + env->CallVoidMethod(_godot_view, _release_pointer_capture); } } GodotJavaViewWrapper::~GodotJavaViewWrapper() { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND(env == nullptr); + env->DeleteGlobalRef(_godot_view); env->DeleteGlobalRef(_cls); } diff --git a/platform/android/java_godot_view_wrapper.h b/platform/android/java_godot_view_wrapper.h index 548c278292..bfb4369fb8 100644 --- a/platform/android/java_godot_view_wrapper.h +++ b/platform/android/java_godot_view_wrapper.h @@ -34,6 +34,8 @@ #include <android/log.h> #include <jni.h> +#include "string_android.h" + // Class that makes functions in java/src/org/godotengine/godot/GodotView.java callable from C++ class GodotJavaViewWrapper { private: diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp index ff1bbec40d..bfd93345f3 100644 --- a/platform/android/java_godot_wrapper.cpp +++ b/platform/android/java_godot_wrapper.cpp @@ -94,6 +94,8 @@ jobject GodotJavaWrapper::get_member_object(const char *p_name, const char *p_cl if (p_env == nullptr) p_env = get_jni_env(); + ERR_FAIL_COND_V(p_env == nullptr, nullptr); + jfieldID fid = p_env->GetStaticFieldID(godot_class, p_name, p_class); return p_env->GetStaticObjectField(godot_class, fid); } else { @@ -104,6 +106,8 @@ jobject GodotJavaWrapper::get_member_object(const char *p_name, const char *p_cl jobject GodotJavaWrapper::get_class_loader() { if (_get_class_loader) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, nullptr); + return env->CallObjectMethod(activity, _get_class_loader); } else { return nullptr; @@ -115,6 +119,8 @@ GodotJavaViewWrapper *GodotJavaWrapper::get_godot_view() { return _godot_view; } JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, nullptr); + jmethodID godot_view_getter = env->GetMethodID(godot_class, "getRenderView", "()Lorg/godotengine/godot/GodotRenderView;"); _godot_view = new GodotJavaViewWrapper(env->CallObjectMethod(godot_instance, godot_view_getter)); return _godot_view; @@ -124,6 +130,7 @@ void GodotJavaWrapper::on_video_init(JNIEnv *p_env) { if (_on_video_init) { if (p_env == nullptr) p_env = get_jni_env(); + ERR_FAIL_COND(p_env == nullptr); p_env->CallVoidMethod(godot_instance, _on_video_init); } @@ -143,6 +150,7 @@ void GodotJavaWrapper::on_godot_main_loop_started(JNIEnv *p_env) { if (p_env == nullptr) { p_env = get_jni_env(); } + ERR_FAIL_COND(p_env == nullptr); p_env->CallVoidMethod(godot_instance, _on_godot_main_loop_started); } } @@ -151,6 +159,7 @@ void GodotJavaWrapper::restart(JNIEnv *p_env) { if (_restart) { if (p_env == nullptr) p_env = get_jni_env(); + ERR_FAIL_COND(p_env == nullptr); p_env->CallVoidMethod(godot_instance, _restart); } @@ -160,6 +169,7 @@ void GodotJavaWrapper::force_quit(JNIEnv *p_env) { if (_finish) { if (p_env == nullptr) p_env = get_jni_env(); + ERR_FAIL_COND(p_env == nullptr); p_env->CallVoidMethod(godot_instance, _finish); } @@ -168,6 +178,8 @@ void GodotJavaWrapper::force_quit(JNIEnv *p_env) { void GodotJavaWrapper::set_keep_screen_on(bool p_enabled) { if (_set_keep_screen_on) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND(env == nullptr); + env->CallVoidMethod(godot_instance, _set_keep_screen_on, p_enabled); } } @@ -175,6 +187,8 @@ void GodotJavaWrapper::set_keep_screen_on(bool p_enabled) { void GodotJavaWrapper::alert(const String &p_message, const String &p_title) { if (_alert) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND(env == nullptr); + jstring jStrMessage = env->NewStringUTF(p_message.utf8().get_data()); jstring jStrTitle = env->NewStringUTF(p_title.utf8().get_data()); env->CallVoidMethod(godot_instance, _alert, jStrMessage, jStrTitle); @@ -183,6 +197,8 @@ void GodotJavaWrapper::alert(const String &p_message, const String &p_title) { int GodotJavaWrapper::get_gles_version_code() { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, 0); + if (_get_GLES_version_code) { return env->CallIntMethod(godot_instance, _get_GLES_version_code); } @@ -197,6 +213,8 @@ bool GodotJavaWrapper::has_get_clipboard() { String GodotJavaWrapper::get_clipboard() { if (_get_clipboard) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, String()); + jstring s = (jstring)env->CallObjectMethod(godot_instance, _get_clipboard); return jstring_to_string(s, env); } else { @@ -207,6 +225,8 @@ String GodotJavaWrapper::get_clipboard() { String GodotJavaWrapper::get_input_fallback_mapping() { if (_get_input_fallback_mapping) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, String()); + jstring fallback_mapping = (jstring)env->CallObjectMethod(godot_instance, _get_input_fallback_mapping); return jstring_to_string(fallback_mapping, env); } else { @@ -221,6 +241,8 @@ bool GodotJavaWrapper::has_set_clipboard() { void GodotJavaWrapper::set_clipboard(const String &p_text) { if (_set_clipboard) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND(env == nullptr); + jstring jStr = env->NewStringUTF(p_text.utf8().get_data()); env->CallVoidMethod(godot_instance, _set_clipboard, jStr); } @@ -229,6 +251,8 @@ void GodotJavaWrapper::set_clipboard(const String &p_text) { bool GodotJavaWrapper::request_permission(const String &p_name) { if (_request_permission) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, false); + jstring jStrName = env->NewStringUTF(p_name.utf8().get_data()); return env->CallBooleanMethod(godot_instance, _request_permission, jStrName); } else { @@ -239,6 +263,8 @@ bool GodotJavaWrapper::request_permission(const String &p_name) { bool GodotJavaWrapper::request_permissions() { if (_request_permissions) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, false); + return env->CallBooleanMethod(godot_instance, _request_permissions); } else { return false; @@ -249,6 +275,8 @@ Vector<String> GodotJavaWrapper::get_granted_permissions() const { Vector<String> permissions_list; if (_get_granted_permissions) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, permissions_list); + jobject permissions_object = env->CallObjectMethod(godot_instance, _get_granted_permissions); jobjectArray *arr = reinterpret_cast<jobjectArray *>(&permissions_object); @@ -267,6 +295,8 @@ Vector<String> GodotJavaWrapper::get_granted_permissions() const { void GodotJavaWrapper::init_input_devices() { if (_init_input_devices) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND(env == nullptr); + env->CallVoidMethod(godot_instance, _init_input_devices); } } @@ -274,6 +304,8 @@ void GodotJavaWrapper::init_input_devices() { jobject GodotJavaWrapper::get_surface() { if (_get_surface) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, nullptr); + return env->CallObjectMethod(godot_instance, _get_surface); } else { return nullptr; @@ -283,6 +315,8 @@ jobject GodotJavaWrapper::get_surface() { bool GodotJavaWrapper::is_activity_resumed() { if (_is_activity_resumed) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, false); + return env->CallBooleanMethod(godot_instance, _is_activity_resumed); } else { return false; @@ -292,6 +326,8 @@ bool GodotJavaWrapper::is_activity_resumed() { void GodotJavaWrapper::vibrate(int p_duration_ms) { if (_vibrate) { JNIEnv *env = get_jni_env(); + ERR_FAIL_COND(env == nullptr); + env->CallVoidMethod(godot_instance, _vibrate, p_duration_ms); } } diff --git a/platform/android/thread_jandroid.cpp b/platform/android/thread_jandroid.cpp index afcc7294f2..ba379c8d43 100644 --- a/platform/android/thread_jandroid.cpp +++ b/platform/android/thread_jandroid.cpp @@ -30,17 +30,34 @@ #include "thread_jandroid.h" +#include <android/log.h> + #include "core/os/thread.h" static JavaVM *java_vm = nullptr; static thread_local JNIEnv *env = nullptr; +// The logic here need to improve, init_thread/term_tread are designed to work with Thread::callback +// Calling init_thread from setup_android_thread and get_jni_env to setup an env we're keeping and not detaching +// could cause issues on app termination. +// +// We should be making sure that any thread started calls a nice cleanup function when it's done, +// especially now that we use many more threads. + static void init_thread() { + if (env) { + // thread never detached! just keep using... + return; + } + java_vm->AttachCurrentThread(&env, nullptr); } static void term_thread() { java_vm->DetachCurrentThread(); + + // this is no longer valid, must called init_thread to re-establish + env = nullptr; } void init_thread_jandroid(JavaVM *p_jvm, JNIEnv *p_env) { @@ -50,9 +67,17 @@ void init_thread_jandroid(JavaVM *p_jvm, JNIEnv *p_env) { } void setup_android_thread() { - init_thread(); + if (!env) { + // !BAS! see remarks above + init_thread(); + } } JNIEnv *get_jni_env() { + if (!env) { + // !BAS! see remarks above + init_thread(); + } + return env; } diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py index 17796beb6f..cf358e0878 100644 --- a/platform/iphone/detect.py +++ b/platform/iphone/detect.py @@ -54,7 +54,7 @@ def configure(env): if env["optimize"] == "speed": # optimize for speed (default) env.Append(CCFLAGS=["-O2", "-ftree-vectorize", "-fomit-frame-pointer"]) env.Append(LINKFLAGS=["-O2"]) - else: # optimize for size + elif env["optimize"] == "size": # optimize for size env.Append(CCFLAGS=["-Os", "-ftree-vectorize"]) env.Append(LINKFLAGS=["-Os"]) diff --git a/platform/iphone/joypad_iphone.mm b/platform/iphone/joypad_iphone.mm index a0f0eee5d3..45842b38aa 100644 --- a/platform/iphone/joypad_iphone.mm +++ b/platform/iphone/joypad_iphone.mm @@ -287,7 +287,7 @@ void JoypadIPhone::start_processing() { gamepad.dpad.right.isPressed); }; - Input::JoyAxis jx; + Input::JoyAxisValue jx; jx.min = -1; if (element == gamepad.leftThumbstick) { jx.value = gamepad.leftThumbstick.xAxis.value; diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index e80ef374ec..ac8d8de7e0 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -64,21 +64,21 @@ def configure(env): sys.exit(255) ## Build type - if env["target"] == "release": + if env["target"].startswith("release"): # Use -Os to prioritize optimizing for reduced file size. This is # particularly valuable for the web platform because it directly # decreases download time. # -Os reduces file size by around 5 MiB over -O3. -Oz only saves about # 100 KiB over -Os, which does not justify the negative impact on # run-time performance. - env.Append(CCFLAGS=["-Os"]) - env.Append(LINKFLAGS=["-Os"]) - elif env["target"] == "release_debug": - env.Append(CCFLAGS=["-Os"]) - env.Append(LINKFLAGS=["-Os"]) - env.Append(CPPDEFINES=["DEBUG_ENABLED"]) - # Retain function names for backtraces at the cost of file size. - env.Append(LINKFLAGS=["--profiling-funcs"]) + if env["optimize"] != "none": + env.Append(CCFLAGS=["-Os"]) + env.Append(LINKFLAGS=["-Os"]) + + if env["target"] == "release_debug": + env.Append(CPPDEFINES=["DEBUG_ENABLED"]) + # Retain function names for backtraces at the cost of file size. + env.Append(LINKFLAGS=["--profiling-funcs"]) else: # "debug" env.Append(CPPDEFINES=["DEBUG_ENABLED"]) env.Append(CCFLAGS=["-O1", "-g"]) diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp index e2c0a3d763..fa6f5c1e9e 100644 --- a/platform/javascript/display_server_javascript.cpp +++ b/platform/javascript/display_server_javascript.cpp @@ -189,19 +189,19 @@ EM_BOOL DisplayServerJavaScript::mouse_button_callback(int p_event_type, const E switch (p_event->button) { case DOM_BUTTON_LEFT: - ev->set_button_index(BUTTON_LEFT); + ev->set_button_index(MOUSE_BUTTON_LEFT); break; case DOM_BUTTON_MIDDLE: - ev->set_button_index(BUTTON_MIDDLE); + ev->set_button_index(MOUSE_BUTTON_MIDDLE); break; case DOM_BUTTON_RIGHT: - ev->set_button_index(BUTTON_RIGHT); + ev->set_button_index(MOUSE_BUTTON_RIGHT); break; case DOM_BUTTON_XBUTTON1: - ev->set_button_index(BUTTON_XBUTTON1); + ev->set_button_index(MOUSE_BUTTON_XBUTTON1); break; case DOM_BUTTON_XBUTTON2: - ev->set_button_index(BUTTON_XBUTTON2); + ev->set_button_index(MOUSE_BUTTON_XBUTTON2); break; default: return false; @@ -341,7 +341,7 @@ void DisplayServerJavaScript::cursor_set_custom_image(const RES &p_cursor, Curso Rect2 atlas_rect; if (texture.is_valid()) { - image = texture->get_data(); + image = texture->get_image(); } if (!image.is_valid() && atlas_texture.is_valid()) { @@ -364,7 +364,7 @@ void DisplayServerJavaScript::cursor_set_custom_image(const RES &p_cursor, Curso ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256); ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height); - image = texture->get_data(); + image = texture->get_image(); ERR_FAIL_COND(!image.is_valid()); @@ -461,13 +461,13 @@ EM_BOOL DisplayServerJavaScript::wheel_callback(int p_event_type, const Emscript ev->set_metakey(input->is_key_pressed(KEY_META)); if (p_event->deltaY < 0) - ev->set_button_index(BUTTON_WHEEL_UP); + ev->set_button_index(MOUSE_BUTTON_WHEEL_UP); else if (p_event->deltaY > 0) - ev->set_button_index(BUTTON_WHEEL_DOWN); + ev->set_button_index(MOUSE_BUTTON_WHEEL_DOWN); else if (p_event->deltaX > 0) - ev->set_button_index(BUTTON_WHEEL_LEFT); + ev->set_button_index(MOUSE_BUTTON_WHEEL_LEFT); else if (p_event->deltaX < 0) - ev->set_button_index(BUTTON_WHEEL_RIGHT); + ev->set_button_index(MOUSE_BUTTON_WHEEL_RIGHT); else return false; @@ -601,7 +601,7 @@ void DisplayServerJavaScript::process_joypads() { // Buttons 6 and 7 in the standard mapping need to be // axis to be handled as JOY_AXIS_TRIGGER by Godot. if (s_standard && (b == 6 || b == 7)) { - Input::JoyAxis joy_axis; + Input::JoyAxisValue joy_axis; joy_axis.min = 0; joy_axis.value = value; int a = b == 6 ? JOY_AXIS_TRIGGER_LEFT : JOY_AXIS_TRIGGER_RIGHT; @@ -611,7 +611,7 @@ void DisplayServerJavaScript::process_joypads() { } } for (int a = 0; a < s_axes_num; a++) { - Input::JoyAxis joy_axis; + Input::JoyAxisValue joy_axis; joy_axis.min = -1; joy_axis.value = s_axes[a]; input->joy_axis(idx, a, joy_axis); diff --git a/platform/javascript/emscripten_helpers.py b/platform/javascript/emscripten_helpers.py index 04fbba8a41..b3b15a1574 100644 --- a/platform/javascript/emscripten_helpers.py +++ b/platform/javascript/emscripten_helpers.py @@ -21,7 +21,11 @@ def get_build_version(): name = "custom_build" if os.getenv("BUILD_NAME") != None: name = os.getenv("BUILD_NAME") - return "%d.%d.%d.%s.%s" % (version.major, version.minor, version.patch, version.status, name) + v = "%d.%d" % (version.major, version.minor) + if version.patch > 0: + v += ".%d" % version.patch + v += ".%s.%s" % (version.status, name) + return v def create_engine_file(env, target, source, externs): diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index 1e89e144cc..3f04bedea2 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -550,7 +550,7 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese if (f) { file_sizes[pck_path.get_file()] = (uint64_t)f->get_len(); memdelete(f); - f = NULL; + f = nullptr; } _fix_html(html, p_preset, p_path.get_file().get_basename(), p_debug, p_flags, shared_objects, file_sizes); f = FileAccess::open(p_path, FileAccess::WRITE); diff --git a/platform/javascript/js/engine/engine.js b/platform/javascript/js/engine/engine.js index 19a0552c8c..17a8df9e29 100644 --- a/platform/javascript/js/engine/engine.js +++ b/platform/javascript/js/engine/engine.js @@ -101,19 +101,23 @@ const Engine = (function () { } const me = this; function doInit(promise) { - return promise.then(function (response) { - return Godot(me.config.getModuleConfig(loadPath, response.clone())); - }).then(function (module) { - const paths = me.config.persistentPaths; - return module['initFS'](paths).then(function (err) { - return Promise.resolve(module); + // Care! Promise chaining is bogus with old emscripten versions. + // This caused a regression with the Mono build (which uses an older emscripten version). + // Make sure to test that when refactoring. + return new Promise(function (resolve, reject) { + promise.then(function (response) { + const cloned = new Response(response.clone().body, { 'headers': [['content-type', 'application/wasm']] }); + Godot(me.config.getModuleConfig(loadPath, cloned)).then(function (module) { + const paths = me.config.persistentPaths; + module['initFS'](paths).then(function (err) { + me.rtenv = module; + if (me.config.unloadAfterInit) { + Engine.unload(); + } + resolve(); + }); + }); }); - }).then(function (module) { - me.rtenv = module; - if (me.config.unloadAfterInit) { - Engine.unload(); - } - return Promise.resolve(); }); } preloader.setProgressFunc(this.config.onProgress); diff --git a/platform/javascript/js/engine/preloader.js b/platform/javascript/js/engine/preloader.js index 3535fdb361..564c68d264 100644 --- a/platform/javascript/js/engine/preloader.js +++ b/platform/javascript/js/engine/preloader.js @@ -1,22 +1,5 @@ const Preloader = /** @constructor */ function () { // eslint-disable-line no-unused-vars function getTrackedResponse(response, load_status) { - let clen = 0; - let compressed = false; - response.headers.forEach(function (value, header) { - const h = header.toLowerCase().trim(); - // We can't accurately compute compressed stream length. - if (h === 'content-encoding') { - compressed = true; - } else if (h === 'content-length') { - const length = parseInt(value, 10); - if (!Number.isNaN(length) && length > 0) { - clen = length; - } - } - }); - if (!compressed && clen) { - load_status.total = clen; - } function onloadprogress(reader, controller) { return reader.read().then(function (result) { if (load_status.done) { diff --git a/platform/javascript/js/libs/library_godot_display.js b/platform/javascript/js/libs/library_godot_display.js index 99aa4793d9..00e6a01679 100644 --- a/platform/javascript/js/libs/library_godot_display.js +++ b/platform/javascript/js/libs/library_godot_display.js @@ -858,7 +858,7 @@ const GodotDisplay = { const notif = [p_enter, p_exit, p_in, p_out]; ['mouseover', 'mouseleave', 'focus', 'blur'].forEach(function (evt_name, idx) { GodotDisplayListeners.add(canvas, evt_name, function () { - func.bind(null, notif[idx]); + func(notif[idx]); }, true); }); }, diff --git a/platform/javascript/js/libs/library_godot_fetch.js b/platform/javascript/js/libs/library_godot_fetch.js index 4ae6a23593..de5ae2b1ae 100644 --- a/platform/javascript/js/libs/library_godot_fetch.js +++ b/platform/javascript/js/libs/library_godot_fetch.js @@ -49,25 +49,14 @@ const GodotFetch = { if (!obj) { return; } - let size = -1; - let compressed = false; let chunked = false; response.headers.forEach(function (value, header) { const v = value.toLowerCase().trim(); const h = header.toLowerCase().trim(); - if (h === 'content-encoding') { - compressed = true; - size = -1; - } else if (h === 'content-length') { - const len = Number.parseInt(value, 10); - if (!Number.isNaN(len) && !compressed) { - size = len; - } - } else if (h === 'transfer-encoding' && v === 'chunked') { + if (h === 'transfer-encoding' && v === 'chunked') { chunked = true; } }); - obj.bodySize = size; obj.status = response.status; obj.response = response; obj.reader = response.body.getReader(); diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index 09d185ae2b..6b527c6fb5 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -90,7 +90,7 @@ def configure(env): if env["target"] == "release": if env["optimize"] == "speed": # optimize for speed (default) env.Prepend(CCFLAGS=["-O3"]) - else: # optimize for size + elif env["optimize"] == "size": # optimize for size env.Prepend(CCFLAGS=["-Os"]) if env["debug_symbols"]: @@ -99,7 +99,7 @@ def configure(env): elif env["target"] == "release_debug": if env["optimize"] == "speed": # optimize for speed (default) env.Prepend(CCFLAGS=["-O2"]) - else: # optimize for size + elif env["optimize"] == "size": # optimize for size env.Prepend(CCFLAGS=["-Os"]) env.Prepend(CPPDEFINES=["DEBUG_ENABLED"]) diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index 3bc859e17d..8dc1b41702 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -1917,7 +1917,7 @@ void DisplayServerX11::cursor_set_custom_image(const RES &p_cursor, CursorShape Rect2i atlas_rect; if (texture.is_valid()) { - image = texture->get_data(); + image = texture->get_image(); } if (!image.is_valid() && atlas_texture.is_valid()) { @@ -1940,7 +1940,7 @@ void DisplayServerX11::cursor_set_custom_image(const RES &p_cursor, CursorShape ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256); ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height); - image = texture->get_data(); + image = texture->get_image(); ERR_FAIL_COND(!image.is_valid()); @@ -2012,7 +2012,7 @@ int DisplayServerX11::keyboard_get_layout_count() const { XkbGetNames(x11_display, XkbSymbolsNameMask, kbd); const Atom *groups = kbd->names->groups; - if (kbd->ctrls != NULL) { + if (kbd->ctrls != nullptr) { _group_count = kbd->ctrls->num_groups; } else { while (_group_count < XkbNumKbdGroups && groups[_group_count] != None) { @@ -2046,7 +2046,7 @@ String DisplayServerX11::keyboard_get_layout_language(int p_index) const { int _group_count = 0; const Atom *groups = kbd->names->groups; - if (kbd->ctrls != NULL) { + if (kbd->ctrls != nullptr) { _group_count = kbd->ctrls->num_groups; } else { while (_group_count < XkbNumKbdGroups && groups[_group_count] != None) { @@ -2085,7 +2085,7 @@ String DisplayServerX11::keyboard_get_layout_name(int p_index) const { int _group_count = 0; const Atom *groups = kbd->names->groups; - if (kbd->ctrls != NULL) { + if (kbd->ctrls != nullptr) { _group_count = kbd->ctrls->num_groups; } else { while (_group_count < XkbNumKbdGroups && groups[_group_count] != None) { @@ -2684,7 +2684,7 @@ bool DisplayServerX11::_wait_for_events() const { tv.tv_sec = 1; // Wait for next event or timeout. - int num_ready_fds = select(x11_fd + 1, &in_fds, NULL, NULL, &tv); + int num_ready_fds = select(x11_fd + 1, &in_fds, nullptr, nullptr, &tv); if (num_ready_fds > 0) { // Event received. @@ -3298,7 +3298,7 @@ void DisplayServerX11::process_events() { if (xi.pressure_supported) { mm->set_pressure(xi.pressure); } else { - mm->set_pressure((mouse_get_button_state() & (1 << (BUTTON_LEFT - 1))) ? 1.0f : 0.0f); + mm->set_pressure((mouse_get_button_state() & (1 << (MOUSE_BUTTON_LEFT - 1))) ? 1.0f : 0.0f); } mm->set_tilt(xi.tilt); diff --git a/platform/linuxbsd/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp index 471259e50f..e8f4352dff 100644 --- a/platform/linuxbsd/joypad_linux.cpp +++ b/platform/linuxbsd/joypad_linux.cpp @@ -62,7 +62,7 @@ void JoypadLinux::Joypad::reset() { dpad = 0; fd = -1; - Input::JoyAxis jx; + Input::JoyAxisValue jx; jx.min = -1; jx.value = 0.0f; for (int i = 0; i < MAX_ABS; i++) { @@ -178,17 +178,18 @@ void JoypadLinux::monitor_joypads(udev *p_udev) { select() ensured that this will not block. */ dev = udev_monitor_receive_device(mon); - if (dev && udev_device_get_devnode(dev) != 0) { + if (dev && udev_device_get_devnode(dev) != nullptr) { MutexLock lock(joy_mutex); String action = udev_device_get_action(dev); const char *devnode = udev_device_get_devnode(dev); if (devnode) { String devnode_str = devnode; if (devnode_str.find(ignore_str) == -1) { - if (action == "add") + if (action == "add") { open_joypad(devnode); - else if (String(action) == "remove") + } else if (String(action) == "remove") { close_joypad(get_joy_from_path(devnode)); + } } } @@ -212,7 +213,7 @@ void JoypadLinux::monitor_joypads() { struct dirent *current; char fname[64]; - while ((current = readdir(input_directory)) != NULL) { + while ((current = readdir(input_directory)) != nullptr) { if (strncmp(current->d_name, "event", 5) != 0) { continue; } @@ -428,10 +429,10 @@ void JoypadLinux::joypad_vibration_stop(int p_id, uint64_t p_timestamp) { joy.ff_effect_timestamp = p_timestamp; } -Input::JoyAxis JoypadLinux::axis_correct(const input_absinfo *p_abs, int p_value) const { +Input::JoyAxisValue JoypadLinux::axis_correct(const input_absinfo *p_abs, int p_value) const { int min = p_abs->minimum; int max = p_abs->maximum; - Input::JoyAxis jx; + Input::JoyAxisValue jx; if (min < 0) { jx.min = -1; @@ -513,7 +514,7 @@ void JoypadLinux::process_joypads() { return; } if (joy->abs_map[ev.code] != -1 && joy->abs_info[ev.code]) { - Input::JoyAxis value = axis_correct(joy->abs_info[ev.code], ev.value); + Input::JoyAxisValue value = axis_correct(joy->abs_info[ev.code], ev.value); joy->curr_axis[joy->abs_map[ev.code]] = value; } break; diff --git a/platform/linuxbsd/joypad_linux.h b/platform/linuxbsd/joypad_linux.h index b0d0db047b..177d7a51ce 100644 --- a/platform/linuxbsd/joypad_linux.h +++ b/platform/linuxbsd/joypad_linux.h @@ -53,7 +53,7 @@ private: }; struct Joypad { - Input::JoyAxis curr_axis[MAX_ABS]; + Input::JoyAxisValue curr_axis[MAX_ABS]; int key_map[MAX_KEY]; int abs_map[MAX_ABS]; int dpad = 0; @@ -97,7 +97,7 @@ private: void joypad_vibration_start(int p_id, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp); void joypad_vibration_stop(int p_id, uint64_t p_timestamp); - Input::JoyAxis axis_correct(const input_absinfo *p_abs, int p_value) const; + Input::JoyAxisValue axis_correct(const input_absinfo *p_abs, int p_value) const; }; #endif diff --git a/platform/osx/detect.py b/platform/osx/detect.py index c39a4426be..5b320da82f 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -50,7 +50,7 @@ def configure(env): if env["target"] == "release": if env["optimize"] == "speed": # optimize for speed (default) env.Prepend(CCFLAGS=["-O3", "-fomit-frame-pointer", "-ftree-vectorize"]) - else: # optimize for size + elif env["optimize"] == "size": # optimize for size env.Prepend(CCFLAGS=["-Os", "-ftree-vectorize"]) if env["arch"] != "arm64": env.Prepend(CCFLAGS=["-msse2"]) @@ -61,7 +61,7 @@ def configure(env): elif env["target"] == "release_debug": if env["optimize"] == "speed": # optimize for speed (default) env.Prepend(CCFLAGS=["-O2"]) - else: # optimize for size + elif env["optimize"] == "size": # optimize for size env.Prepend(CCFLAGS=["-Os"]) env.Prepend(CPPDEFINES=["DEBUG_ENABLED"]) if env["debug_symbols"]: diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm index ed7d89009f..6b838b6d14 100644 --- a/platform/osx/display_server_osx.mm +++ b/platform/osx/display_server_osx.mm @@ -829,7 +829,7 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i mb->set_position(pos); mb->set_global_position(pos); mb->set_button_mask(DS_OSX->last_button_state); - if (index == BUTTON_LEFT && pressed) { + if (index == MOUSE_BUTTON_LEFT && pressed) { mb->set_doubleclick([event clickCount] == 2); } @@ -842,10 +842,10 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i if (([event modifierFlags] & NSEventModifierFlagControl)) { wd.mouse_down_control = true; - _mouseDownEvent(window_id, event, BUTTON_RIGHT, BUTTON_MASK_RIGHT, true); + _mouseDownEvent(window_id, event, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MASK_RIGHT, true); } else { wd.mouse_down_control = false; - _mouseDownEvent(window_id, event, BUTTON_LEFT, BUTTON_MASK_LEFT, true); + _mouseDownEvent(window_id, event, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_MASK_LEFT, true); } } @@ -858,9 +858,9 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; if (wd.mouse_down_control) { - _mouseDownEvent(window_id, event, BUTTON_RIGHT, BUTTON_MASK_RIGHT, false); + _mouseDownEvent(window_id, event, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MASK_RIGHT, false); } else { - _mouseDownEvent(window_id, event, BUTTON_LEFT, BUTTON_MASK_LEFT, false); + _mouseDownEvent(window_id, event, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_MASK_LEFT, false); } } @@ -946,7 +946,7 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i } - (void)rightMouseDown:(NSEvent *)event { - _mouseDownEvent(window_id, event, BUTTON_RIGHT, BUTTON_MASK_RIGHT, true); + _mouseDownEvent(window_id, event, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MASK_RIGHT, true); } - (void)rightMouseDragged:(NSEvent *)event { @@ -954,16 +954,16 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i } - (void)rightMouseUp:(NSEvent *)event { - _mouseDownEvent(window_id, event, BUTTON_RIGHT, BUTTON_MASK_RIGHT, false); + _mouseDownEvent(window_id, event, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MASK_RIGHT, false); } - (void)otherMouseDown:(NSEvent *)event { if ((int)[event buttonNumber] == 2) { - _mouseDownEvent(window_id, event, BUTTON_MIDDLE, BUTTON_MASK_MIDDLE, true); + _mouseDownEvent(window_id, event, MOUSE_BUTTON_MIDDLE, MOUSE_BUTTON_MASK_MIDDLE, true); } else if ((int)[event buttonNumber] == 3) { - _mouseDownEvent(window_id, event, BUTTON_XBUTTON1, BUTTON_MASK_XBUTTON1, true); + _mouseDownEvent(window_id, event, MOUSE_BUTTON_XBUTTON1, MOUSE_BUTTON_MASK_XBUTTON1, true); } else if ((int)[event buttonNumber] == 4) { - _mouseDownEvent(window_id, event, BUTTON_XBUTTON2, BUTTON_MASK_XBUTTON2, true); + _mouseDownEvent(window_id, event, MOUSE_BUTTON_XBUTTON2, MOUSE_BUTTON_MASK_XBUTTON2, true); } else { return; } @@ -975,11 +975,11 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i - (void)otherMouseUp:(NSEvent *)event { if ((int)[event buttonNumber] == 2) { - _mouseDownEvent(window_id, event, BUTTON_MIDDLE, BUTTON_MASK_MIDDLE, false); + _mouseDownEvent(window_id, event, MOUSE_BUTTON_MIDDLE, MOUSE_BUTTON_MASK_MIDDLE, false); } else if ((int)[event buttonNumber] == 3) { - _mouseDownEvent(window_id, event, BUTTON_XBUTTON1, BUTTON_MASK_XBUTTON1, false); + _mouseDownEvent(window_id, event, MOUSE_BUTTON_XBUTTON1, MOUSE_BUTTON_MASK_XBUTTON1, false); } else if ((int)[event buttonNumber] == 4) { - _mouseDownEvent(window_id, event, BUTTON_XBUTTON2, BUTTON_MASK_XBUTTON2, false); + _mouseDownEvent(window_id, event, MOUSE_BUTTON_XBUTTON2, MOUSE_BUTTON_MASK_XBUTTON2, false); } else { return; } @@ -1558,10 +1558,10 @@ inline void sendPanEvent(DisplayServer::WindowID window_id, double dx, double dy sendPanEvent(window_id, deltaX, deltaY, [event modifierFlags]); } else { if (fabs(deltaX)) { - sendScrollEvent(window_id, 0 > deltaX ? BUTTON_WHEEL_RIGHT : BUTTON_WHEEL_LEFT, fabs(deltaX * 0.3), [event modifierFlags]); + sendScrollEvent(window_id, 0 > deltaX ? MOUSE_BUTTON_WHEEL_RIGHT : MOUSE_BUTTON_WHEEL_LEFT, fabs(deltaX * 0.3), [event modifierFlags]); } if (fabs(deltaY)) { - sendScrollEvent(window_id, 0 < deltaY ? BUTTON_WHEEL_UP : BUTTON_WHEEL_DOWN, fabs(deltaY * 0.3), [event modifierFlags]); + sendScrollEvent(window_id, 0 < deltaY ? MOUSE_BUTTON_WHEEL_UP : MOUSE_BUTTON_WHEEL_DOWN, fabs(deltaY * 0.3), [event modifierFlags]); } } } @@ -3117,7 +3117,7 @@ void DisplayServerOSX::cursor_set_custom_image(const RES &p_cursor, CursorShape Rect2 atlas_rect; if (texture.is_valid()) { - image = texture->get_data(); + image = texture->get_image(); } if (!image.is_valid() && atlas_texture.is_valid()) { @@ -3140,7 +3140,7 @@ void DisplayServerOSX::cursor_set_custom_image(const RES &p_cursor, CursorShape ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256); ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height); - image = texture->get_data(); + image = texture->get_image(); ERR_FAIL_COND(!image.is_valid()); diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp index f31d8b9b81..aca9471849 100644 --- a/platform/osx/export/export.cpp +++ b/platform/osx/export/export.cpp @@ -155,10 +155,11 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), "")); #ifdef OSX_ENABLED - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_PLACEHOLDER_TEXT, "Type: Name (ID)"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/timestamp"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/hardened_runtime"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/replace_existing_signature"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/entitlements/custom_file", PROPERTY_HINT_GLOBAL_FILE, "*.plist"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_jit_code_execution"), false)); @@ -486,10 +487,18 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese } args.push_back("-s"); - args.push_back(p_preset->get("codesign/identity")); + if (p_preset->get("codesign/identity") == "") { + args.push_back("-"); + } else { + args.push_back(p_preset->get("codesign/identity")); + } args.push_back("-v"); /* provide some more feedback */ + if (p_preset->get("codesign/replace_existing_signature")) { + args.push_back("-f"); + } + args.push_back(p_path); String str; @@ -1055,12 +1064,6 @@ bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset } bool sign_enabled = p_preset->get("codesign/enable"); - if (sign_enabled) { - if (p_preset->get("codesign/identity") == "") { - err += TTR("Codesign: identity not specified.") + "\n"; - valid = false; - } - } bool noto_enabled = p_preset->get("notarization/enable"); if (noto_enabled) { if (!sign_enabled) { diff --git a/platform/osx/joypad_osx.cpp b/platform/osx/joypad_osx.cpp index 0b6a0e20a6..b12526915f 100644 --- a/platform/osx/joypad_osx.cpp +++ b/platform/osx/joypad_osx.cpp @@ -433,8 +433,8 @@ void JoypadOSX::poll_joypads() const { } } -static const Input::JoyAxis axis_correct(int p_value, int p_min, int p_max) { - Input::JoyAxis jx; +static const Input::JoyAxisValue axis_correct(int p_value, int p_min, int p_max) { + Input::JoyAxisValue jx; if (p_min < 0) { jx.min = -1; if (p_value < 0) { diff --git a/platform/server/detect.py b/platform/server/detect.py index c799ce03e1..16ddbe1768 100644 --- a/platform/server/detect.py +++ b/platform/server/detect.py @@ -56,7 +56,7 @@ def configure(env): if env["target"] == "release": if env["optimize"] == "speed": # optimize for speed (default) env.Prepend(CCFLAGS=["-O3"]) - else: # optimize for size + elif env["optimize"] == "size": # optimize for size env.Prepend(CCFLAGS=["-Os"]) if env["debug_symbols"]: @@ -65,7 +65,7 @@ def configure(env): elif env["target"] == "release_debug": if env["optimize"] == "speed": # optimize for speed (default) env.Prepend(CCFLAGS=["-O2"]) - else: # optimize for size + elif env["optimize"] == "size": # optimize for size env.Prepend(CCFLAGS=["-Os"]) env.Prepend(CPPDEFINES=["DEBUG_ENABLED"]) diff --git a/platform/uwp/app.cpp b/platform/uwp/app.cpp index dc4238bdd4..b7e4361831 100644 --- a/platform/uwp/app.cpp +++ b/platform/uwp/app.cpp @@ -149,28 +149,28 @@ static int _get_button(Windows::UI::Input::PointerPoint ^ pt) { using namespace Windows::UI::Input; #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP - return BUTTON_LEFT; + return MOUSE_BUTTON_LEFT; #else switch (pt->Properties->PointerUpdateKind) { case PointerUpdateKind::LeftButtonPressed: case PointerUpdateKind::LeftButtonReleased: - return BUTTON_LEFT; + return MOUSE_BUTTON_LEFT; case PointerUpdateKind::RightButtonPressed: case PointerUpdateKind::RightButtonReleased: - return BUTTON_RIGHT; + return MOUSE_BUTTON_RIGHT; case PointerUpdateKind::MiddleButtonPressed: case PointerUpdateKind::MiddleButtonReleased: - return BUTTON_MIDDLE; + return MOUSE_BUTTON_MIDDLE; case PointerUpdateKind::XButton1Pressed: case PointerUpdateKind::XButton1Released: - return BUTTON_WHEEL_UP; + return MOUSE_BUTTON_WHEEL_UP; case PointerUpdateKind::XButton2Pressed: case PointerUpdateKind::XButton2Released: - return BUTTON_WHEEL_DOWN; + return MOUSE_BUTTON_WHEEL_DOWN; default: break; @@ -265,9 +265,9 @@ void App::pointer_event(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Cor if (p_is_wheel) { if (point->Properties->MouseWheelDelta > 0) { - mouse_button->set_button_index(point->Properties->IsHorizontalMouseWheel ? BUTTON_WHEEL_RIGHT : BUTTON_WHEEL_UP); + mouse_button->set_button_index(point->Properties->IsHorizontalMouseWheel ? MOUSE_BUTTON_WHEEL_RIGHT : MOUSE_BUTTON_WHEEL_UP); } else if (point->Properties->MouseWheelDelta < 0) { - mouse_button->set_button_index(point->Properties->IsHorizontalMouseWheel ? BUTTON_WHEEL_LEFT : BUTTON_WHEEL_DOWN); + mouse_button->set_button_index(point->Properties->IsHorizontalMouseWheel ? MOUSE_BUTTON_WHEEL_LEFT : MOUSE_BUTTON_WHEEL_DOWN); } } diff --git a/platform/uwp/detect.py b/platform/uwp/detect.py index fda8fdec66..28922a4f59 100644 --- a/platform/uwp/detect.py +++ b/platform/uwp/detect.py @@ -54,16 +54,19 @@ def configure(env): ## Build type if env["target"] == "release": - env.Append(CCFLAGS=["/O2", "/GL"]) env.Append(CCFLAGS=["/MD"]) - env.Append(LINKFLAGS=["/SUBSYSTEM:WINDOWS", "/LTCG"]) + env.Append(LINKFLAGS=["/SUBSYSTEM:WINDOWS"]) + if env["optimize"] != "none": + env.Append(CCFLAGS=["/O2", "/GL"]) + env.Append(LINKFLAGS=["/LTCG"]) elif env["target"] == "release_debug": - env.Append(CCFLAGS=["/O2", "/Zi"]) env.Append(CCFLAGS=["/MD"]) - env.Append(CPPDEFINES=["DEBUG_ENABLED"]) env.Append(LINKFLAGS=["/SUBSYSTEM:CONSOLE"]) env.AppendUnique(CPPDEFINES=["WINDOWS_SUBSYSTEM_CONSOLE"]) + env.Append(CPPDEFINES=["DEBUG_ENABLED"]) + if env["optimize"] != "none": + env.Append(CCFLAGS=["/O2", "/Zi"]) elif env["target"] == "debug": env.Append(CCFLAGS=["/Zi"]) diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp index 1aad2bfa1a..2a0bc78440 100644 --- a/platform/uwp/export/export.cpp +++ b/platform/uwp/export/export.cpp @@ -855,33 +855,33 @@ class EditorExportPlatformUWP : public EditorExportPlatform { Vector<uint8_t> _get_image_data(const Ref<EditorExportPreset> &p_preset, const String &p_path) { Vector<uint8_t> data; - StreamTexture2D *image = nullptr; + StreamTexture2D *texture = nullptr; if (p_path.find("StoreLogo") != -1) { - image = p_preset->get("images/store_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/store_logo"))); + texture = p_preset->get("images/store_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/store_logo"))); } else if (p_path.find("Square44x44Logo") != -1) { - image = p_preset->get("images/square44x44_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/square44x44_logo"))); + texture = p_preset->get("images/square44x44_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/square44x44_logo"))); } else if (p_path.find("Square71x71Logo") != -1) { - image = p_preset->get("images/square71x71_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/square71x71_logo"))); + texture = p_preset->get("images/square71x71_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/square71x71_logo"))); } else if (p_path.find("Square150x150Logo") != -1) { - image = p_preset->get("images/square150x150_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/square150x150_logo"))); + texture = p_preset->get("images/square150x150_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/square150x150_logo"))); } else if (p_path.find("Square310x310Logo") != -1) { - image = p_preset->get("images/square310x310_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/square310x310_logo"))); + texture = p_preset->get("images/square310x310_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/square310x310_logo"))); } else if (p_path.find("Wide310x150Logo") != -1) { - image = p_preset->get("images/wide310x150_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/wide310x150_logo"))); + texture = p_preset->get("images/wide310x150_logo").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/wide310x150_logo"))); } else if (p_path.find("SplashScreen") != -1) { - image = p_preset->get("images/splash_screen").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/splash_screen"))); + texture = p_preset->get("images/splash_screen").is_zero() ? nullptr : Object::cast_to<StreamTexture2D>(((Object *)p_preset->get("images/splash_screen"))); } else { ERR_PRINT("Unable to load logo"); } - if (!image) { + if (!texture) { return data; } String tmp_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("uwp_tmp_logo.png"); - Error err = image->get_data()->save_png(tmp_path); + Error err = texture->get_image()->save_png(tmp_path); if (err != OK) { String err_string = "Couldn't save temp logo file."; diff --git a/platform/uwp/joypad_uwp.cpp b/platform/uwp/joypad_uwp.cpp index 5da90db49d..b419fb4fae 100644 --- a/platform/uwp/joypad_uwp.cpp +++ b/platform/uwp/joypad_uwp.cpp @@ -134,8 +134,8 @@ void JoypadUWP::OnGamepadRemoved(Platform::Object ^ sender, Windows::Gaming::Inp input->joy_connection_changed(idx, false, "Xbox Controller"); } -InputDefault::JoyAxis JoypadUWP::axis_correct(double p_val, bool p_negate, bool p_trigger) const { - InputDefault::JoyAxis jx; +InputDefault::JoyAxisValue JoypadUWP::axis_correct(double p_val, bool p_negate, bool p_trigger) const { + InputDefault::JoyAxisValue jx; jx.min = p_trigger ? 0 : -1; jx.value = (float)(p_negate ? -p_val : p_val); diff --git a/platform/uwp/joypad_uwp.h b/platform/uwp/joypad_uwp.h index 5df4a211ac..d760d9e2fe 100644 --- a/platform/uwp/joypad_uwp.h +++ b/platform/uwp/joypad_uwp.h @@ -73,7 +73,7 @@ private: void OnGamepadAdded(Platform::Object ^ sender, Windows::Gaming::Input::Gamepad ^ value); void OnGamepadRemoved(Platform::Object ^ sender, Windows::Gaming::Input::Gamepad ^ value); - InputDefault::JoyAxis axis_correct(double p_val, bool p_negate = false, bool p_trigger = false) const; + InputDefault::JoyAxisValue axis_correct(double p_val, bool p_negate = false, bool p_trigger = false) const; void joypad_vibration_start(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp); void joypad_vibration_stop(int p_device, uint64_t p_timestamp); }; diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 0b2145a92b..7772ba2dbe 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -191,18 +191,20 @@ def configure_msvc(env, manual_msvc_config): if env["target"] == "release": if env["optimize"] == "speed": # optimize for speed (default) env.Append(CCFLAGS=["/O2"]) - else: # optimize for size + env.Append(LINKFLAGS=["/OPT:REF"]) + elif env["optimize"] == "size": # optimize for size env.Append(CCFLAGS=["/O1"]) + env.Append(LINKFLAGS=["/OPT:REF"]) env.Append(LINKFLAGS=["/ENTRY:mainCRTStartup"]) - env.Append(LINKFLAGS=["/OPT:REF"]) elif env["target"] == "release_debug": if env["optimize"] == "speed": # optimize for speed (default) env.Append(CCFLAGS=["/O2"]) - else: # optimize for size + env.Append(LINKFLAGS=["/OPT:REF"]) + elif env["optimize"] == "size": # optimize for size env.Append(CCFLAGS=["/O1"]) + env.Append(LINKFLAGS=["/OPT:REF"]) env.AppendUnique(CPPDEFINES=["DEBUG_ENABLED"]) - env.Append(LINKFLAGS=["/OPT:REF"]) elif env["target"] == "debug": env.AppendUnique(CCFLAGS=["/Zi", "/FS", "/Od", "/EHsc"]) diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index e29faf4f3c..86f20f1dd7 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -1299,7 +1299,7 @@ void DisplayServerWindows::cursor_set_custom_image(const RES &p_cursor, CursorSh Rect2 atlas_rect; if (texture.is_valid()) { - image = texture->get_data(); + image = texture->get_image(); } if (!image.is_valid() && atlas_texture.is_valid()) { @@ -1322,7 +1322,7 @@ void DisplayServerWindows::cursor_set_custom_image(const RES &p_cursor, CursorSh ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256); ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height); - image = texture->get_data(); + image = texture->get_image(); ERR_FAIL_COND(!image.is_valid()); @@ -2431,9 +2431,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA return 0; if (motion > 0) - mb->set_button_index(BUTTON_WHEEL_UP); + mb->set_button_index(MOUSE_BUTTON_WHEEL_UP); else - mb->set_button_index(BUTTON_WHEEL_DOWN); + mb->set_button_index(MOUSE_BUTTON_WHEEL_DOWN); } break; case WM_MOUSEHWHEEL: { @@ -2443,33 +2443,33 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA return 0; if (motion < 0) { - mb->set_button_index(BUTTON_WHEEL_LEFT); + mb->set_button_index(MOUSE_BUTTON_WHEEL_LEFT); mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA)); } else { - mb->set_button_index(BUTTON_WHEEL_RIGHT); + mb->set_button_index(MOUSE_BUTTON_WHEEL_RIGHT); mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA)); } } break; case WM_XBUTTONDOWN: { mb->set_pressed(true); if (HIWORD(wParam) == XBUTTON1) - mb->set_button_index(BUTTON_XBUTTON1); + mb->set_button_index(MOUSE_BUTTON_XBUTTON1); else - mb->set_button_index(BUTTON_XBUTTON2); + mb->set_button_index(MOUSE_BUTTON_XBUTTON2); } break; case WM_XBUTTONUP: { mb->set_pressed(false); if (HIWORD(wParam) == XBUTTON1) - mb->set_button_index(BUTTON_XBUTTON1); + mb->set_button_index(MOUSE_BUTTON_XBUTTON1); else - mb->set_button_index(BUTTON_XBUTTON2); + mb->set_button_index(MOUSE_BUTTON_XBUTTON2); } break; case WM_XBUTTONDBLCLK: { mb->set_pressed(true); if (HIWORD(wParam) == XBUTTON1) - mb->set_button_index(BUTTON_XBUTTON1); + mb->set_button_index(MOUSE_BUTTON_XBUTTON1); else - mb->set_button_index(BUTTON_XBUTTON2); + mb->set_button_index(MOUSE_BUTTON_XBUTTON2); mb->set_doubleclick(true); } break; default: { @@ -2566,6 +2566,8 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA windows[window_id].preserve_window_size = false; window_set_size(Size2(windows[window_id].width, windows[window_id].height), window_id); } + } else { + windows[window_id].preserve_window_size = true; } if (!windows[window_id].rect_changed_callback.is_null()) { diff --git a/platform/windows/joypad_windows.cpp b/platform/windows/joypad_windows.cpp index b8679a87fe..da36dc1f2b 100644 --- a/platform/windows/joypad_windows.cpp +++ b/platform/windows/joypad_windows.cpp @@ -446,8 +446,8 @@ void JoypadWindows::post_hat(int p_device, DWORD p_dpad) { input->joy_hat(p_device, dpad_val); }; -Input::JoyAxis JoypadWindows::axis_correct(int p_val, bool p_xinput, bool p_trigger, bool p_negate) const { - Input::JoyAxis jx; +Input::JoyAxisValue JoypadWindows::axis_correct(int p_val, bool p_xinput, bool p_trigger, bool p_negate) const { + Input::JoyAxisValue jx; if (Math::abs(p_val) < MIN_JOY_AXIS) { jx.min = p_trigger ? 0 : -1; jx.value = 0.0f; diff --git a/platform/windows/joypad_windows.h b/platform/windows/joypad_windows.h index 4727b4a14c..757fb54fb3 100644 --- a/platform/windows/joypad_windows.h +++ b/platform/windows/joypad_windows.h @@ -132,7 +132,7 @@ private: void joypad_vibration_start_xinput(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp); void joypad_vibration_stop_xinput(int p_device, uint64_t p_timestamp); - Input::JoyAxis axis_correct(int p_val, bool p_xinput = false, bool p_trigger = false, bool p_negate = false) const; + Input::JoyAxisValue axis_correct(int p_val, bool p_xinput = false, bool p_trigger = false, bool p_negate = false) const; XInputGetState_t xinput_get_state; XInputSetState_t xinput_set_state; }; diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp index dfc08583f2..4aa079b013 100644 --- a/scene/2d/animated_sprite_2d.cpp +++ b/scene/2d/animated_sprite_2d.cpp @@ -382,12 +382,11 @@ bool AnimatedSprite2D::_is_playing() const { } void AnimatedSprite2D::play(const StringName &p_animation, const bool p_backwards) { - ERR_FAIL_NULL_MSG(frames, "Can't play AnimatedSprite2D without a valid SpriteFrames resource."); backwards = p_backwards; if (p_animation) { set_animation(p_animation); - if (backwards && get_frame() == 0) { + if (frames.is_valid() && backwards && get_frame() == 0) { set_frame(frames->get_frame_count(p_animation) - 1); } } diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index 9030cc4263..01045502d5 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -157,7 +157,7 @@ Transform2D Camera2D::get_camera_transform() { } if (smoothing_enabled && !Engine::get_singleton()->is_editor_hint()) { - float c = smoothing * (process_callback == CAMERA2D_PROCESS_PHYSICS ? get_physics_process_delta_time() : get_process_delta_time()); + real_t c = smoothing * (process_callback == CAMERA2D_PROCESS_PHYSICS ? get_physics_process_delta_time() : get_process_delta_time()); smoothed_camera_pos = ((camera_pos - smoothed_camera_pos) * c) + smoothed_camera_pos; ret_camera_pos = smoothed_camera_pos; //camera_pos=camera_pos*(1.0-smoothing)+new_camera_pos*smoothing; @@ -172,7 +172,7 @@ Transform2D Camera2D::get_camera_transform() { Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom) : Point2()); - float angle = get_global_transform().get_rotation(); + real_t angle = get_global_transform().get_rotation(); if (rotating) { screen_offset = screen_offset.rotated(angle); } @@ -271,7 +271,7 @@ void Camera2D::_notification(int p_what) { if (screen_drawing_enabled) { Color area_axis_color(0.5, 0.42, 0.87, 0.63); - float area_axis_width = 1; + real_t area_axis_width = 1; if (is_current()) { area_axis_width = 3; area_axis_color.a = 0.83; @@ -296,7 +296,7 @@ void Camera2D::_notification(int p_what) { if (limit_drawing_enabled) { Color limit_drawing_color(1, 1, 0, 0.63); - float limit_drawing_width = 1; + real_t limit_drawing_width = 1; if (is_current()) { limit_drawing_color.a = 0.83; limit_drawing_width = 3; @@ -318,7 +318,7 @@ void Camera2D::_notification(int p_what) { if (margin_drawing_enabled) { Color margin_drawing_color(0, 1, 1, 0.63); - float margin_drawing_width = 1; + real_t margin_drawing_width = 1; if (is_current()) { margin_drawing_width = 3; margin_drawing_color.a = 0.83; @@ -446,13 +446,13 @@ bool Camera2D::is_limit_smoothing_enabled() const { return limit_smoothing_enabled; } -void Camera2D::set_drag_margin(Side p_side, float p_drag_margin) { +void Camera2D::set_drag_margin(Side p_side, real_t p_drag_margin) { ERR_FAIL_INDEX((int)p_side, 4); drag_margin[p_side] = p_drag_margin; update(); } -float Camera2D::get_drag_margin(Side p_side) const { +real_t Camera2D::get_drag_margin(Side p_side) const { ERR_FAIL_INDEX_V((int)p_side, 4, 0); return drag_margin[p_side]; } @@ -494,7 +494,7 @@ void Camera2D::align() { _update_scroll(); } -void Camera2D::set_follow_smoothing(float p_speed) { +void Camera2D::set_follow_smoothing(real_t p_speed) { smoothing = p_speed; if (smoothing > 0 && !(is_inside_tree() && Engine::get_singleton()->is_editor_hint())) { set_process_internal(true); @@ -503,7 +503,7 @@ void Camera2D::set_follow_smoothing(float p_speed) { } } -float Camera2D::get_follow_smoothing() const { +real_t Camera2D::get_follow_smoothing() const { return smoothing; } @@ -535,7 +535,7 @@ bool Camera2D::is_drag_vertical_enabled() const { return drag_vertical_enabled; } -void Camera2D::set_drag_vertical_offset(float p_offset) { +void Camera2D::set_drag_vertical_offset(real_t p_offset) { drag_vertical_offset = p_offset; drag_vertical_offset_changed = true; Point2 old_smoothed_camera_pos = smoothed_camera_pos; @@ -543,11 +543,11 @@ void Camera2D::set_drag_vertical_offset(float p_offset) { smoothed_camera_pos = old_smoothed_camera_pos; } -float Camera2D::get_drag_vertical_offset() const { +real_t Camera2D::get_drag_vertical_offset() const { return drag_vertical_offset; } -void Camera2D::set_drag_horizontal_offset(float p_offset) { +void Camera2D::set_drag_horizontal_offset(real_t p_offset) { drag_horizontal_offset = p_offset; drag_horizontal_offset_changed = true; Point2 old_smoothed_camera_pos = smoothed_camera_pos; @@ -555,11 +555,11 @@ void Camera2D::set_drag_horizontal_offset(float p_offset) { smoothed_camera_pos = old_smoothed_camera_pos; } -float Camera2D::get_drag_horizontal_offset() const { +real_t Camera2D::get_drag_horizontal_offset() const { return drag_horizontal_offset; } -void Camera2D::_set_old_smoothing(float p_enable) { +void Camera2D::_set_old_smoothing(real_t p_enable) { //compatibility if (p_enable > 0) { smoothing_enabled = true; diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h index 220e208eb0..7494e526cc 100644 --- a/scene/2d/camera_2d.h +++ b/scene/2d/camera_2d.h @@ -65,16 +65,16 @@ protected: AnchorMode anchor_mode = ANCHOR_MODE_DRAG_CENTER; bool rotating = false; bool current = false; - float smoothing = 5.0; + real_t smoothing = 5.0; bool smoothing_enabled = false; int limit[4]; bool limit_smoothing_enabled = false; - float drag_margin[4]; + real_t drag_margin[4]; bool drag_horizontal_enabled = false; bool drag_vertical_enabled = false; - float drag_horizontal_offset = 0.0; - float drag_vertical_offset = 0.0; + real_t drag_horizontal_offset = 0.0; + real_t drag_vertical_offset = 0.0; bool drag_horizontal_offset_changed = false; bool drag_vertical_offset_changed = false; @@ -85,7 +85,7 @@ protected: void _make_current(Object *p_which); void _set_current(bool p_current); - void _set_old_smoothing(float p_enable); + void _set_old_smoothing(real_t p_enable); bool screen_drawing_enabled = true; bool limit_drawing_enabled = false; @@ -124,20 +124,20 @@ public: void set_drag_vertical_enabled(bool p_enabled); bool is_drag_vertical_enabled() const; - void set_drag_margin(Side p_side, float p_drag_margin); - float get_drag_margin(Side p_side) const; + void set_drag_margin(Side p_side, real_t p_drag_margin); + real_t get_drag_margin(Side p_side) const; - void set_drag_horizontal_offset(float p_offset); - float get_drag_horizontal_offset() const; + void set_drag_horizontal_offset(real_t p_offset); + real_t get_drag_horizontal_offset() const; - void set_drag_vertical_offset(float p_offset); - float get_drag_vertical_offset() const; + void set_drag_vertical_offset(real_t p_offset); + real_t get_drag_vertical_offset() const; void set_enable_follow_smoothing(bool p_enabled); bool is_follow_smoothing_enabled() const; - void set_follow_smoothing(float p_speed); - float get_follow_smoothing() const; + void set_follow_smoothing(real_t p_speed); + real_t get_follow_smoothing() const; void set_process_callback(Camera2DProcessCallback p_mode); Camera2DProcessCallback get_process_callback() const; diff --git a/scene/2d/canvas_group.cpp b/scene/2d/canvas_group.cpp index 0f0e583ea7..ee025b6dfc 100644 --- a/scene/2d/canvas_group.cpp +++ b/scene/2d/canvas_group.cpp @@ -30,7 +30,7 @@ #include "canvas_group.h" -void CanvasGroup::set_fit_margin(float p_fit_margin) { +void CanvasGroup::set_fit_margin(real_t p_fit_margin) { ERR_FAIL_COND(p_fit_margin < 0.0); fit_margin = p_fit_margin; @@ -39,11 +39,11 @@ void CanvasGroup::set_fit_margin(float p_fit_margin) { update(); } -float CanvasGroup::get_fit_margin() const { +real_t CanvasGroup::get_fit_margin() const { return fit_margin; } -void CanvasGroup::set_clear_margin(float p_clear_margin) { +void CanvasGroup::set_clear_margin(real_t p_clear_margin) { ERR_FAIL_COND(p_clear_margin < 0.0); clear_margin = p_clear_margin; @@ -52,7 +52,7 @@ void CanvasGroup::set_clear_margin(float p_clear_margin) { update(); } -float CanvasGroup::get_clear_margin() const { +real_t CanvasGroup::get_clear_margin() const { return clear_margin; } diff --git a/scene/2d/canvas_group.h b/scene/2d/canvas_group.h index cecf7c24f4..b487d7a098 100644 --- a/scene/2d/canvas_group.h +++ b/scene/2d/canvas_group.h @@ -35,19 +35,19 @@ class CanvasGroup : public Node2D { GDCLASS(CanvasGroup, Node2D) - float fit_margin = 10.0; - float clear_margin = 10.0; + real_t fit_margin = 10.0; + real_t clear_margin = 10.0; bool use_mipmaps = false; protected: static void _bind_methods(); public: - void set_fit_margin(float p_fit_margin); - float get_fit_margin() const; + void set_fit_margin(real_t p_fit_margin); + real_t get_fit_margin() const; - void set_clear_margin(float p_clear_margin); - float get_clear_margin() const; + void set_clear_margin(real_t p_clear_margin); + real_t get_clear_margin() const; void set_use_mipmaps(bool p_use_mipmaps); bool is_using_mipmaps() const; diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index 48acee1bc4..6a69a4c618 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -78,11 +78,11 @@ void CPUParticles2D::set_pre_process_time(float p_time) { pre_process_time = p_time; } -void CPUParticles2D::set_explosiveness_ratio(float p_ratio) { +void CPUParticles2D::set_explosiveness_ratio(real_t p_ratio) { explosiveness_ratio = p_ratio; } -void CPUParticles2D::set_randomness_ratio(float p_ratio) { +void CPUParticles2D::set_randomness_ratio(real_t p_ratio) { randomness_ratio = p_ratio; } @@ -95,7 +95,7 @@ void CPUParticles2D::set_use_local_coordinates(bool p_enable) { set_notify_transform(!p_enable); } -void CPUParticles2D::set_speed_scale(float p_scale) { +void CPUParticles2D::set_speed_scale(real_t p_scale) { speed_scale = p_scale; } @@ -119,11 +119,11 @@ float CPUParticles2D::get_pre_process_time() const { return pre_process_time; } -float CPUParticles2D::get_explosiveness_ratio() const { +real_t CPUParticles2D::get_explosiveness_ratio() const { return explosiveness_ratio; } -float CPUParticles2D::get_randomness_ratio() const { +real_t CPUParticles2D::get_randomness_ratio() const { return randomness_ratio; } @@ -135,7 +135,7 @@ bool CPUParticles2D::get_use_local_coordinates() const { return local_coords; } -float CPUParticles2D::get_speed_scale() const { +real_t CPUParticles2D::get_speed_scale() const { return speed_scale; } @@ -289,39 +289,39 @@ Vector2 CPUParticles2D::get_direction() const { return direction; } -void CPUParticles2D::set_spread(float p_spread) { +void CPUParticles2D::set_spread(real_t p_spread) { spread = p_spread; } -float CPUParticles2D::get_spread() const { +real_t CPUParticles2D::get_spread() const { return spread; } -void CPUParticles2D::set_param(Parameter p_param, float p_value) { +void CPUParticles2D::set_param(Parameter p_param, real_t p_value) { ERR_FAIL_INDEX(p_param, PARAM_MAX); parameters[p_param] = p_value; } -float CPUParticles2D::get_param(Parameter p_param) const { +real_t CPUParticles2D::get_param(Parameter p_param) const { ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); return parameters[p_param]; } -void CPUParticles2D::set_param_randomness(Parameter p_param, float p_value) { +void CPUParticles2D::set_param_randomness(Parameter p_param, real_t p_value) { ERR_FAIL_INDEX(p_param, PARAM_MAX); randomness[p_param] = p_value; } -float CPUParticles2D::get_param_randomness(Parameter p_param) const { +real_t CPUParticles2D::get_param_randomness(Parameter p_param) const { ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); return randomness[p_param]; } -static void _adjust_curve_range(const Ref<Curve> &p_curve, float p_min, float p_max) { +static void _adjust_curve_range(const Ref<Curve> &p_curve, real_t p_min, real_t p_max) { Ref<Curve> curve = p_curve; if (!curve.is_valid()) { return; @@ -413,7 +413,7 @@ void CPUParticles2D::set_emission_shape(EmissionShape p_shape) { notify_property_list_changed(); } -void CPUParticles2D::set_emission_sphere_radius(float p_radius) { +void CPUParticles2D::set_emission_sphere_radius(real_t p_radius) { emission_sphere_radius = p_radius; } @@ -433,7 +433,7 @@ void CPUParticles2D::set_emission_colors(const Vector<Color> &p_colors) { emission_colors = p_colors; } -float CPUParticles2D::get_emission_sphere_radius() const { +real_t CPUParticles2D::get_emission_sphere_radius() const { return emission_sphere_radius; } @@ -502,7 +502,7 @@ static uint32_t idhash(uint32_t x) { return x; } -static float rand_from_seed(uint32_t &seed) { +static real_t rand_from_seed(uint32_t &seed) { int k; int s = int(seed); if (s == 0) { @@ -514,7 +514,7 @@ static float rand_from_seed(uint32_t &seed) { s += 2147483647; } seed = uint32_t(s); - return float(seed % uint32_t(65536)) / 65535.0; + return (seed % uint32_t(65536)) / 65535.0; } void CPUParticles2D::_update_internal() { @@ -625,7 +625,7 @@ void CPUParticles2D::_particles_process(float p_delta) { // The phase is a ratio between 0 (birth) and 1 (end of life) for each particle. // While we use time in tests later on, for randomness we use the phase as done in the // original shader code, and we later multiply by lifetime to get the time. - float restart_phase = float(i) / float(pcount); + real_t restart_phase = real_t(i) / real_t(pcount); if (randomness_ratio > 0.0) { uint32_t seed = cycle; @@ -634,8 +634,8 @@ void CPUParticles2D::_particles_process(float p_delta) { } seed *= uint32_t(pcount); seed += uint32_t(i); - float random = float(idhash(seed) % uint32_t(65536)) / 65536.0; - restart_phase += randomness_ratio * random * 1.0 / float(pcount); + real_t random = (idhash(seed) % uint32_t(65536)) / 65536.0; + restart_phase += randomness_ratio * random * 1.0 / pcount; } restart_phase *= (1.0 - explosiveness_ratio); @@ -680,17 +680,17 @@ void CPUParticles2D::_particles_process(float p_delta) { } p.active = true; - /*float tex_linear_velocity = 0; + /*real_t tex_linear_velocity = 0; if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(0); }*/ - float tex_angle = 0.0; + real_t tex_angle = 0.0; if (curve_parameters[PARAM_ANGLE].is_valid()) { tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(tv); } - float tex_anim_offset = 0.0; + real_t tex_anim_offset = 0.0; if (curve_parameters[PARAM_ANGLE].is_valid()) { tex_anim_offset = curve_parameters[PARAM_ANGLE]->interpolate(tv); } @@ -702,16 +702,16 @@ void CPUParticles2D::_particles_process(float p_delta) { p.hue_rot_rand = Math::randf(); p.anim_offset_rand = Math::randf(); - float angle1_rad = Math::atan2(direction.y, direction.x) + Math::deg2rad((Math::randf() * 2.0 - 1.0) * spread); + real_t angle1_rad = Math::atan2(direction.y, direction.x) + Math::deg2rad((Math::randf() * 2.0 - 1.0) * spread); Vector2 rot = Vector2(Math::cos(angle1_rad), Math::sin(angle1_rad)); - p.velocity = rot * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp(1.0f, float(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]); + p.velocity = rot * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp((real_t)1.0, real_t(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]); - float base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp(1.0f, p.angle_rand, randomness[PARAM_ANGLE]); + real_t base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp((real_t)1.0, p.angle_rand, randomness[PARAM_ANGLE]); p.rotation = Math::deg2rad(base_angle); p.custom[0] = 0.0; // unused p.custom[1] = 0.0; // phase [0..1] - p.custom[2] = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp(1.0f, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]); //animation phase [0..1] + p.custom[2] = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp((real_t)1.0, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]); //animation phase [0..1] p.custom[3] = 0.0; p.transform = Transform2D(); p.time = 0; @@ -723,8 +723,8 @@ void CPUParticles2D::_particles_process(float p_delta) { //do none } break; case EMISSION_SHAPE_SPHERE: { - float s = Math::randf(), t = Math_TAU * Math::randf(); - float radius = emission_sphere_radius * Math::sqrt(1.0 - s * s); + real_t s = Math::randf(), t = Math_TAU * Math::randf(); + real_t radius = emission_sphere_radius * Math::sqrt(1.0 - s * s); p.transform[2] = Vector2(Math::cos(t), Math::sin(t)) * radius; } break; case EMISSION_SHAPE_RECTANGLE: { @@ -775,51 +775,51 @@ void CPUParticles2D::_particles_process(float p_delta) { p.custom[1] = p.time / lifetime; tv = p.time / p.lifetime; - float tex_linear_velocity = 0.0; + real_t tex_linear_velocity = 0.0; if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(tv); } - float tex_orbit_velocity = 0.0; + real_t tex_orbit_velocity = 0.0; if (curve_parameters[PARAM_ORBIT_VELOCITY].is_valid()) { tex_orbit_velocity = curve_parameters[PARAM_ORBIT_VELOCITY]->interpolate(tv); } - float tex_angular_velocity = 0.0; + real_t tex_angular_velocity = 0.0; if (curve_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) { tex_angular_velocity = curve_parameters[PARAM_ANGULAR_VELOCITY]->interpolate(tv); } - float tex_linear_accel = 0.0; + real_t tex_linear_accel = 0.0; if (curve_parameters[PARAM_LINEAR_ACCEL].is_valid()) { tex_linear_accel = curve_parameters[PARAM_LINEAR_ACCEL]->interpolate(tv); } - float tex_tangential_accel = 0.0; + real_t tex_tangential_accel = 0.0; if (curve_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) { tex_tangential_accel = curve_parameters[PARAM_TANGENTIAL_ACCEL]->interpolate(tv); } - float tex_radial_accel = 0.0; + real_t tex_radial_accel = 0.0; if (curve_parameters[PARAM_RADIAL_ACCEL].is_valid()) { tex_radial_accel = curve_parameters[PARAM_RADIAL_ACCEL]->interpolate(tv); } - float tex_damping = 0.0; + real_t tex_damping = 0.0; if (curve_parameters[PARAM_DAMPING].is_valid()) { tex_damping = curve_parameters[PARAM_DAMPING]->interpolate(tv); } - float tex_angle = 0.0; + real_t tex_angle = 0.0; if (curve_parameters[PARAM_ANGLE].is_valid()) { tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(tv); } - float tex_anim_speed = 0.0; + real_t tex_anim_speed = 0.0; if (curve_parameters[PARAM_ANIM_SPEED].is_valid()) { tex_anim_speed = curve_parameters[PARAM_ANIM_SPEED]->interpolate(tv); } - float tex_anim_offset = 0.0; + real_t tex_anim_offset = 0.0; if (curve_parameters[PARAM_ANIM_OFFSET].is_valid()) { tex_anim_offset = curve_parameters[PARAM_ANIM_OFFSET]->interpolate(tv); } @@ -828,20 +828,20 @@ void CPUParticles2D::_particles_process(float p_delta) { Vector2 pos = p.transform[2]; //apply linear acceleration - force += p.velocity.length() > 0.0 ? p.velocity.normalized() * (parameters[PARAM_LINEAR_ACCEL] + tex_linear_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_LINEAR_ACCEL]) : Vector2(); + force += p.velocity.length() > 0.0 ? p.velocity.normalized() * (parameters[PARAM_LINEAR_ACCEL] + tex_linear_accel) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_LINEAR_ACCEL]) : Vector2(); //apply radial acceleration Vector2 org = emission_xform[2]; Vector2 diff = pos - org; - force += diff.length() > 0.0 ? diff.normalized() * (parameters[PARAM_RADIAL_ACCEL] + tex_radial_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_RADIAL_ACCEL]) : Vector2(); + force += diff.length() > 0.0 ? diff.normalized() * (parameters[PARAM_RADIAL_ACCEL] + tex_radial_accel) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_RADIAL_ACCEL]) : Vector2(); //apply tangential acceleration; Vector2 yx = Vector2(diff.y, diff.x); - force += yx.length() > 0.0 ? (yx * Vector2(-1.0, 1.0)).normalized() * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector2(); + force += yx.length() > 0.0 ? (yx * Vector2(-1.0, 1.0)).normalized() * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector2(); //apply attractor forces p.velocity += force * local_delta; //orbit velocity - float orbit_amount = (parameters[PARAM_ORBIT_VELOCITY] + tex_orbit_velocity) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_ORBIT_VELOCITY]); + real_t orbit_amount = (parameters[PARAM_ORBIT_VELOCITY] + tex_orbit_velocity) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_ORBIT_VELOCITY]); if (orbit_amount != 0.0) { - float ang = orbit_amount * local_delta * Math_TAU; + real_t ang = orbit_amount * local_delta * Math_TAU; // Not sure why the ParticlesMaterial code uses a clockwise rotation matrix, // but we use -ang here to reproduce its behavior. Transform2D rot = Transform2D(-ang, Vector2()); @@ -853,8 +853,8 @@ void CPUParticles2D::_particles_process(float p_delta) { } if (parameters[PARAM_DAMPING] + tex_damping > 0.0) { - float v = p.velocity.length(); - float damp = (parameters[PARAM_DAMPING] + tex_damping) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_DAMPING]); + real_t v = p.velocity.length(); + real_t damp = (parameters[PARAM_DAMPING] + tex_damping) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_DAMPING]); v -= damp * local_delta; if (v < 0.0) { p.velocity = Vector2(); @@ -862,28 +862,28 @@ void CPUParticles2D::_particles_process(float p_delta) { p.velocity = p.velocity.normalized() * v; } } - float base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp(1.0f, p.angle_rand, randomness[PARAM_ANGLE]); - base_angle += p.custom[1] * lifetime * (parameters[PARAM_ANGULAR_VELOCITY] + tex_angular_velocity) * Math::lerp(1.0f, rand_from_seed(alt_seed) * 2.0f - 1.0f, randomness[PARAM_ANGULAR_VELOCITY]); + real_t base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp((real_t)1.0, p.angle_rand, randomness[PARAM_ANGLE]); + base_angle += p.custom[1] * lifetime * (parameters[PARAM_ANGULAR_VELOCITY] + tex_angular_velocity) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed) * 2.0f - 1.0f, randomness[PARAM_ANGULAR_VELOCITY]); p.rotation = Math::deg2rad(base_angle); //angle - float animation_phase = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp(1.0f, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]) + p.custom[1] * (parameters[PARAM_ANIM_SPEED] + tex_anim_speed) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_ANIM_SPEED]); + real_t animation_phase = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp((real_t)1.0, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]) + p.custom[1] * (parameters[PARAM_ANIM_SPEED] + tex_anim_speed) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_ANIM_SPEED]); p.custom[2] = animation_phase; } //apply color //apply hue rotation - float tex_scale = 1.0; + real_t tex_scale = 1.0; if (curve_parameters[PARAM_SCALE].is_valid()) { tex_scale = curve_parameters[PARAM_SCALE]->interpolate(tv); } - float tex_hue_variation = 0.0; + real_t tex_hue_variation = 0.0; if (curve_parameters[PARAM_HUE_VARIATION].is_valid()) { tex_hue_variation = curve_parameters[PARAM_HUE_VARIATION]->interpolate(tv); } - float hue_rot_angle = (parameters[PARAM_HUE_VARIATION] + tex_hue_variation) * Math_TAU * Math::lerp(1.0f, p.hue_rot_rand * 2.0f - 1.0f, randomness[PARAM_HUE_VARIATION]); - float hue_rot_c = Math::cos(hue_rot_angle); - float hue_rot_s = Math::sin(hue_rot_angle); + real_t hue_rot_angle = (parameters[PARAM_HUE_VARIATION] + tex_hue_variation) * Math_TAU * Math::lerp(1.0f, p.hue_rot_rand * 2.0f - 1.0f, randomness[PARAM_HUE_VARIATION]); + real_t hue_rot_c = Math::cos(hue_rot_angle); + real_t hue_rot_s = Math::sin(hue_rot_angle); Basis hue_rot_mat; { @@ -921,7 +921,7 @@ void CPUParticles2D::_particles_process(float p_delta) { } //scale by scale - float base_scale = tex_scale * Math::lerp(parameters[PARAM_SCALE], 1.0f, p.scale_rand * randomness[PARAM_SCALE]); + real_t base_scale = tex_scale * Math::lerp(parameters[PARAM_SCALE], (real_t)1.0, p.scale_rand * randomness[PARAM_SCALE]); if (base_scale < 0.000001) { base_scale = 0.000001; } diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h index 7ee165b3e1..ab04ee4a57 100644 --- a/scene/2d/cpu_particles_2d.h +++ b/scene/2d/cpu_particles_2d.h @@ -84,13 +84,13 @@ private: Transform2D transform; Color color; float custom[4] = {}; - float rotation = 0.0; + real_t rotation = 0.0; Vector2 velocity; bool active = false; - float angle_rand = 0.0; - float scale_rand = 0.0; - float hue_rot_rand = 0.0; - float anim_offset_rand = 0.0; + real_t angle_rand = 0.0; + real_t scale_rand = 0.0; + real_t hue_rot_rand = 0.0; + real_t anim_offset_rand = 0.0; float time = 0.0; float lifetime = 0.0; Color base_color; @@ -133,10 +133,10 @@ private: float lifetime = 1.0; float pre_process_time = 0.0; - float explosiveness_ratio = 0.0; - float randomness_ratio = 0.0; - float lifetime_randomness = 0.0; - float speed_scale = 1.0; + real_t explosiveness_ratio = 0.0; + real_t randomness_ratio = 0.0; + real_t lifetime_randomness = 0.0; + real_t speed_scale = 1.0; bool local_coords; int fixed_fps = 0; bool fractional_delta = true; @@ -150,10 +150,10 @@ private: //////// Vector2 direction = Vector2(1, 0); - float spread = 45.0; + real_t spread = 45.0; - float parameters[PARAM_MAX]; - float randomness[PARAM_MAX]; + real_t parameters[PARAM_MAX]; + real_t randomness[PARAM_MAX]; Ref<Curve> curve_parameters[PARAM_MAX]; Color color; @@ -162,7 +162,7 @@ private: bool particle_flags[PARTICLE_FLAG_MAX]; EmissionShape emission_shape = EMISSION_SHAPE_POINT; - float emission_sphere_radius = 1.0; + real_t emission_sphere_radius = 1.0; Vector2 emission_rect_extents = Vector2(1, 1); Vector<Vector2> emission_points; Vector<Vector2> emission_normals; @@ -196,24 +196,24 @@ public: void set_lifetime(float p_lifetime); void set_one_shot(bool p_one_shot); void set_pre_process_time(float p_time); - void set_explosiveness_ratio(float p_ratio); - void set_randomness_ratio(float p_ratio); + void set_explosiveness_ratio(real_t p_ratio); + void set_randomness_ratio(real_t p_ratio); void set_lifetime_randomness(float p_random); void set_visibility_aabb(const Rect2 &p_aabb); void set_use_local_coordinates(bool p_enable); - void set_speed_scale(float p_scale); + void set_speed_scale(real_t p_scale); bool is_emitting() const; int get_amount() const; float get_lifetime() const; bool get_one_shot() const; float get_pre_process_time() const; - float get_explosiveness_ratio() const; - float get_randomness_ratio() const; + real_t get_explosiveness_ratio() const; + real_t get_randomness_ratio() const; float get_lifetime_randomness() const; Rect2 get_visibility_aabb() const; bool get_use_local_coordinates() const; - float get_speed_scale() const; + real_t get_speed_scale() const; void set_fixed_fps(int p_count); int get_fixed_fps() const; @@ -235,14 +235,14 @@ public: void set_direction(Vector2 p_direction); Vector2 get_direction() const; - void set_spread(float p_spread); - float get_spread() const; + void set_spread(real_t p_spread); + real_t get_spread() const; - void set_param(Parameter p_param, float p_value); - float get_param(Parameter p_param) const; + void set_param(Parameter p_param, real_t p_value); + real_t get_param(Parameter p_param) const; - void set_param_randomness(Parameter p_param, float p_value); - float get_param_randomness(Parameter p_param) const; + void set_param_randomness(Parameter p_param, real_t p_value); + real_t get_param_randomness(Parameter p_param) const; void set_param_curve(Parameter p_param, const Ref<Curve> &p_curve); Ref<Curve> get_param_curve(Parameter p_param) const; @@ -257,7 +257,7 @@ public: bool get_particle_flag(ParticleFlags p_particle_flag) const; void set_emission_shape(EmissionShape p_shape); - void set_emission_sphere_radius(float p_radius); + void set_emission_sphere_radius(real_t p_radius); void set_emission_rect_extents(Vector2 p_extents); void set_emission_points(const Vector<Vector2> &p_points); void set_emission_normals(const Vector<Vector2> &p_normals); @@ -265,7 +265,7 @@ public: void set_emission_point_count(int p_count); EmissionShape get_emission_shape() const; - float get_emission_sphere_radius() const; + real_t get_emission_sphere_radius() const; Vector2 get_emission_rect_extents() const; Vector<Vector2> get_emission_points() const; Vector<Vector2> get_emission_normals() const; diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 58e15e3cca..99e35cad1d 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -84,21 +84,21 @@ Color Light2D::get_color() const { return color; } -void Light2D::set_height(float p_height) { +void Light2D::set_height(real_t p_height) { height = p_height; RS::get_singleton()->canvas_light_set_height(canvas_light, height); } -float Light2D::get_height() const { +real_t Light2D::get_height() const { return height; } -void Light2D::set_energy(float p_energy) { +void Light2D::set_energy(real_t p_energy) { energy = p_energy; RS::get_singleton()->canvas_light_set_energy(canvas_light, energy); } -float Light2D::get_energy() const { +real_t Light2D::get_energy() const { return energy; } @@ -213,12 +213,12 @@ void Light2D::_notification(int p_what) { } } -void Light2D::set_shadow_smooth(float p_amount) { +void Light2D::set_shadow_smooth(real_t p_amount) { shadow_smooth = p_amount; RS::get_singleton()->canvas_light_set_shadow_smooth(canvas_light, shadow_smooth); } -float Light2D::get_shadow_smooth() const { +real_t Light2D::get_shadow_smooth() const { return shadow_smooth; } @@ -403,7 +403,7 @@ String PointLight2D::get_configuration_warning() const { return warning; } -void PointLight2D::set_texture_scale(float p_scale) { +void PointLight2D::set_texture_scale(real_t p_scale) { _scale = p_scale; // Avoid having 0 scale values, can lead to errors in physics and rendering. if (_scale == 0) { @@ -413,7 +413,7 @@ void PointLight2D::set_texture_scale(float p_scale) { item_rect_changed(); } -float PointLight2D::get_texture_scale() const { +real_t PointLight2D::get_texture_scale() const { return _scale; } @@ -439,12 +439,12 @@ PointLight2D::PointLight2D() { ////////// -void DirectionalLight2D::set_max_distance(float p_distance) { +void DirectionalLight2D::set_max_distance(real_t p_distance) { max_distance = p_distance; RS::get_singleton()->canvas_light_set_directional_distance(_get_light(), max_distance); } -float DirectionalLight2D::get_max_distance() const { +real_t DirectionalLight2D::get_max_distance() const { return max_distance; } diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index de8a2bb6d0..ae6cf6d0a0 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -57,15 +57,15 @@ private: bool shadow = false; Color color = Color(1, 1, 1); Color shadow_color = Color(0, 0, 0, 0); - float height = 0.0; - float energy = 1.0; + real_t height = 0.0; + real_t energy = 1.0; int z_min = -1024; int z_max = 1024; int layer_min = 0; int layer_max = 0; int item_mask = 1; int item_shadow_mask = 1; - float shadow_smooth = 0.0; + real_t shadow_smooth = 0.0; Ref<Texture2D> texture; Vector2 texture_offset; ShadowFilter shadow_filter = SHADOW_FILTER_NONE; @@ -89,11 +89,11 @@ public: void set_color(const Color &p_color); Color get_color() const; - void set_height(float p_height); - float get_height() const; + void set_height(real_t p_height); + real_t get_height() const; - void set_energy(float p_energy); - float get_energy() const; + void set_energy(real_t p_energy); + real_t get_energy() const; void set_z_range_min(int p_min_z); int get_z_range_min() const; @@ -122,8 +122,8 @@ public: void set_shadow_color(const Color &p_shadow_color); Color get_shadow_color() const; - void set_shadow_smooth(float p_amount); - float get_shadow_smooth() const; + void set_shadow_smooth(real_t p_amount); + real_t get_shadow_smooth() const; void set_blend_mode(BlendMode p_mode); BlendMode get_blend_mode() const; @@ -139,7 +139,7 @@ class PointLight2D : public Light2D { GDCLASS(PointLight2D, Light2D); private: - float _scale = 1.0; + real_t _scale = 1.0; Ref<Texture2D> texture; Vector2 texture_offset; @@ -166,8 +166,8 @@ public: void set_texture_offset(const Vector2 &p_offset); Vector2 get_texture_offset() const; - void set_texture_scale(float p_scale); - float get_texture_scale() const; + void set_texture_scale(real_t p_scale); + real_t get_texture_scale() const; String get_configuration_warning() const override; @@ -177,14 +177,14 @@ public: class DirectionalLight2D : public Light2D { GDCLASS(DirectionalLight2D, Light2D); - float max_distance = 10000.0; + real_t max_distance = 10000.0; protected: static void _bind_methods(); public: - void set_max_distance(float p_distance); - float get_max_distance() const; + void set_max_distance(real_t p_distance); + real_t get_max_distance() const; DirectionalLight2D(); }; diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index bf311632c8..8afc43ddc9 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -71,12 +71,12 @@ Size2 Node2D::_edit_get_scale() const { return _scale; } -void Node2D::_edit_set_rotation(float p_rotation) { +void Node2D::_edit_set_rotation(real_t p_rotation) { angle = p_rotation; _update_transform(); } -float Node2D::_edit_get_rotation() const { +real_t Node2D::_edit_get_rotation() const { return angle; } @@ -148,7 +148,7 @@ void Node2D::set_position(const Point2 &p_pos) { _update_transform(); } -void Node2D::set_rotation(float p_radians) { +void Node2D::set_rotation(real_t p_radians) { if (_xform_dirty) { ((Node2D *)this)->_update_xform_values(); } @@ -156,7 +156,7 @@ void Node2D::set_rotation(float p_radians) { _update_transform(); } -void Node2D::set_skew(float p_radians) { +void Node2D::set_skew(real_t p_radians) { if (_xform_dirty) { ((Node2D *)this)->_update_xform_values(); } @@ -164,11 +164,11 @@ void Node2D::set_skew(float p_radians) { _update_transform(); } -void Node2D::set_rotation_degrees(float p_degrees) { +void Node2D::set_rotation_degrees(real_t p_degrees) { set_rotation(Math::deg2rad(p_degrees)); } -void Node2D::set_skew_degrees(float p_degrees) { +void Node2D::set_skew_degrees(real_t p_degrees) { set_skew(Math::deg2rad(p_degrees)); } @@ -194,7 +194,7 @@ Point2 Node2D::get_position() const { return pos; } -float Node2D::get_rotation() const { +real_t Node2D::get_rotation() const { if (_xform_dirty) { ((Node2D *)this)->_update_xform_values(); } @@ -202,7 +202,7 @@ float Node2D::get_rotation() const { return angle; } -float Node2D::get_skew() const { +real_t Node2D::get_skew() const { if (_xform_dirty) { ((Node2D *)this)->_update_xform_values(); } @@ -210,11 +210,11 @@ float Node2D::get_skew() const { return skew; } -float Node2D::get_rotation_degrees() const { +real_t Node2D::get_rotation_degrees() const { return Math::rad2deg(get_rotation()); } -float Node2D::get_skew_degrees() const { +real_t Node2D::get_skew_degrees() const { return Math::rad2deg(get_skew()); } @@ -230,7 +230,7 @@ Transform2D Node2D::get_transform() const { return _mat; } -void Node2D::rotate(float p_radians) { +void Node2D::rotate(real_t p_radians) { set_rotation(get_rotation() + p_radians); } @@ -246,7 +246,7 @@ void Node2D::apply_scale(const Size2 &p_amount) { set_scale(get_scale() * p_amount); } -void Node2D::move_x(float p_delta, bool p_scaled) { +void Node2D::move_x(real_t p_delta, bool p_scaled) { Transform2D t = get_transform(); Vector2 m = t[0]; if (!p_scaled) { @@ -255,7 +255,7 @@ void Node2D::move_x(float p_delta, bool p_scaled) { set_position(t[2] + m * p_delta); } -void Node2D::move_y(float p_delta, bool p_scaled) { +void Node2D::move_y(real_t p_delta, bool p_scaled) { Transform2D t = get_transform(); Vector2 m = t[1]; if (!p_scaled) { @@ -279,25 +279,25 @@ void Node2D::set_global_position(const Point2 &p_pos) { } } -float Node2D::get_global_rotation() const { +real_t Node2D::get_global_rotation() const { return get_global_transform().get_rotation(); } -void Node2D::set_global_rotation(float p_radians) { +void Node2D::set_global_rotation(real_t p_radians) { CanvasItem *pi = get_parent_item(); if (pi) { - const float parent_global_rot = pi->get_global_transform().get_rotation(); + const real_t parent_global_rot = pi->get_global_transform().get_rotation(); set_rotation(p_radians - parent_global_rot); } else { set_rotation(p_radians); } } -float Node2D::get_global_rotation_degrees() const { +real_t Node2D::get_global_rotation_degrees() const { return Math::rad2deg(get_global_rotation()); } -void Node2D::set_global_rotation_degrees(float p_degrees) { +void Node2D::set_global_rotation_degrees(real_t p_degrees) { set_global_rotation(Math::deg2rad(p_degrees)); } @@ -379,7 +379,7 @@ void Node2D::look_at(const Vector2 &p_pos) { rotate(get_angle_to(p_pos)); } -float Node2D::get_angle_to(const Vector2 &p_pos) const { +real_t Node2D::get_angle_to(const Vector2 &p_pos) const { return (to_local(p_pos) * get_scale()).angle(); } diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h index c27d740b8a..358b7e6520 100644 --- a/scene/2d/node_2d.h +++ b/scene/2d/node_2d.h @@ -37,9 +37,9 @@ class Node2D : public CanvasItem { GDCLASS(Node2D, CanvasItem); Point2 pos; - float angle = 0.0; + real_t angle = 0.0; Size2 _scale = Vector2(1, 1); - float skew = 0.0; + real_t skew = 0.0; int z_index = 0; bool z_relative = true; @@ -65,51 +65,51 @@ public: virtual void _edit_set_scale(const Size2 &p_scale) override; virtual Size2 _edit_get_scale() const override; - virtual void _edit_set_rotation(float p_rotation) override; - virtual float _edit_get_rotation() const override; + virtual void _edit_set_rotation(real_t p_rotation) override; + virtual real_t _edit_get_rotation() const override; virtual bool _edit_use_rotation() const override; virtual void _edit_set_rect(const Rect2 &p_edit_rect) override; #endif void set_position(const Point2 &p_pos); - void set_rotation(float p_radians); - void set_rotation_degrees(float p_degrees); - void set_skew(float p_radians); - void set_skew_degrees(float p_radians); + void set_rotation(real_t p_radians); + void set_rotation_degrees(real_t p_degrees); + void set_skew(real_t p_radians); + void set_skew_degrees(real_t p_radians); void set_scale(const Size2 &p_scale); - void rotate(float p_radians); - void move_x(float p_delta, bool p_scaled = false); - void move_y(float p_delta, bool p_scaled = false); + void rotate(real_t p_radians); + void move_x(real_t p_delta, bool p_scaled = false); + void move_y(real_t p_delta, bool p_scaled = false); void translate(const Vector2 &p_amount); void global_translate(const Vector2 &p_amount); void apply_scale(const Size2 &p_amount); Point2 get_position() const; - float get_rotation() const; - float get_skew() const; - float get_rotation_degrees() const; - float get_skew_degrees() const; + real_t get_rotation() const; + real_t get_skew() const; + real_t get_rotation_degrees() const; + real_t get_skew_degrees() const; Size2 get_scale() const; Point2 get_global_position() const; - float get_global_rotation() const; - float get_global_rotation_degrees() const; + real_t get_global_rotation() const; + real_t get_global_rotation_degrees() const; Size2 get_global_scale() const; void set_transform(const Transform2D &p_transform); void set_global_transform(const Transform2D &p_transform); void set_global_position(const Point2 &p_pos); - void set_global_rotation(float p_radians); - void set_global_rotation_degrees(float p_degrees); + void set_global_rotation(real_t p_radians); + void set_global_rotation_degrees(real_t p_degrees); void set_global_scale(const Size2 &p_scale); void set_z_index(int p_z); int get_z_index() const; void look_at(const Vector2 &p_pos); - float get_angle_to(const Vector2 &p_pos) const; + real_t get_angle_to(const Vector2 &p_pos) const; Point2 to_local(Point2 p_global) const; Point2 to_global(Point2 p_local) const; diff --git a/scene/2d/parallax_background.cpp b/scene/2d/parallax_background.cpp index c93915d1bc..4870ae614b 100644 --- a/scene/2d/parallax_background.cpp +++ b/scene/2d/parallax_background.cpp @@ -51,11 +51,11 @@ void ParallaxBackground::_camera_moved(const Transform2D &p_transform, const Poi set_scroll_offset(p_transform.get_origin()); } -void ParallaxBackground::set_scroll_scale(float p_scale) { +void ParallaxBackground::set_scroll_scale(real_t p_scale) { scale = p_scale; } -float ParallaxBackground::get_scroll_scale() const { +real_t ParallaxBackground::get_scroll_scale() const { return scale; } diff --git a/scene/2d/parallax_background.h b/scene/2d/parallax_background.h index c9991efc9d..27134dab29 100644 --- a/scene/2d/parallax_background.h +++ b/scene/2d/parallax_background.h @@ -39,7 +39,7 @@ class ParallaxBackground : public CanvasLayer { GDCLASS(ParallaxBackground, CanvasLayer); Point2 offset; - float scale = 1.0; + real_t scale = 1.0; Point2 base_offset; Point2 base_scale = Vector2(1, 1); Point2 screen_offset; @@ -61,8 +61,8 @@ public: void set_scroll_offset(const Point2 &p_ofs); Point2 get_scroll_offset() const; - void set_scroll_scale(float p_scale); - float get_scroll_scale() const; + void set_scroll_scale(real_t p_scale); + real_t get_scroll_scale() const; void set_scroll_base_offset(const Point2 &p_ofs); Point2 get_scroll_base_offset() const; diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp index a38338e1e3..725e858a43 100644 --- a/scene/2d/parallax_layer.cpp +++ b/scene/2d/parallax_layer.cpp @@ -39,7 +39,7 @@ void ParallaxLayer::set_motion_scale(const Size2 &p_scale) { ParallaxBackground *pb = Object::cast_to<ParallaxBackground>(get_parent()); if (pb && is_inside_tree()) { Vector2 ofs = pb->get_final_offset(); - float scale = pb->get_scroll_scale(); + real_t scale = pb->get_scroll_scale(); set_base_offset_and_scale(ofs, scale, screen_offset); } } @@ -54,7 +54,7 @@ void ParallaxLayer::set_motion_offset(const Size2 &p_offset) { ParallaxBackground *pb = Object::cast_to<ParallaxBackground>(get_parent()); if (pb && is_inside_tree()) { Vector2 ofs = pb->get_final_offset(); - float scale = pb->get_scroll_scale(); + real_t scale = pb->get_scroll_scale(); set_base_offset_and_scale(ofs, scale, screen_offset); } } @@ -107,7 +107,7 @@ void ParallaxLayer::_notification(int p_what) { } } -void ParallaxLayer::set_base_offset_and_scale(const Point2 &p_offset, float p_scale, const Point2 &p_screen_offset) { +void ParallaxLayer::set_base_offset_and_scale(const Point2 &p_offset, real_t p_scale, const Point2 &p_screen_offset) { screen_offset = p_screen_offset; if (!is_inside_tree()) { diff --git a/scene/2d/parallax_layer.h b/scene/2d/parallax_layer.h index 86694c7724..e826e6da9c 100644 --- a/scene/2d/parallax_layer.h +++ b/scene/2d/parallax_layer.h @@ -59,7 +59,7 @@ public: void set_mirroring(const Size2 &p_mirroring); Size2 get_mirroring() const; - void set_base_offset_and_scale(const Point2 &p_offset, float p_scale, const Point2 &p_screen_offset); + void set_base_offset_and_scale(const Point2 &p_offset, real_t p_scale, const Point2 &p_screen_offset); virtual String get_configuration_warning() const override; ParallaxLayer(); diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index 724998641f..be160ee1dd 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -96,9 +96,9 @@ void Path2D::_notification(int p_what) { } #ifdef TOOLS_ENABLED - const float line_width = 2 * EDSCALE; + const real_t line_width = 2 * EDSCALE; #else - const float line_width = 2; + const real_t line_width = 2; #endif const Color color = Color(0.5, 0.6, 1.0, 0.7); @@ -164,14 +164,14 @@ void PathFollow2D::_update_transform() { return; } - float path_length = c->get_baked_length(); + real_t path_length = c->get_baked_length(); if (path_length == 0) { return; } Vector2 pos = c->interpolate_baked(offset, cubic); if (rotates) { - float ahead = offset + lookahead; + real_t ahead = offset + lookahead; if (loop && ahead >= path_length) { // If our lookahead will loop, we need to check if the path is closed. @@ -240,7 +240,7 @@ bool PathFollow2D::get_cubic_interpolation() const { void PathFollow2D::_validate_property(PropertyInfo &property) const { if (property.name == "offset") { - float max = 10000.0; + real_t max = 10000.0; if (path && path->get_curve().is_valid()) { max = path->get_curve()->get_baked_length(); } @@ -301,11 +301,11 @@ void PathFollow2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lookahead", PROPERTY_HINT_RANGE, "0.001,1024.0,0.001"), "set_lookahead", "get_lookahead"); } -void PathFollow2D::set_offset(float p_offset) { +void PathFollow2D::set_offset(real_t p_offset) { offset = p_offset; if (path) { if (path->get_curve().is_valid()) { - float path_length = path->get_curve()->get_baked_length(); + real_t path_length = path->get_curve()->get_baked_length(); if (loop) { offset = Math::fposmod(offset, path_length); @@ -321,39 +321,39 @@ void PathFollow2D::set_offset(float p_offset) { } } -void PathFollow2D::set_h_offset(float p_h_offset) { +void PathFollow2D::set_h_offset(real_t p_h_offset) { h_offset = p_h_offset; if (path) { _update_transform(); } } -float PathFollow2D::get_h_offset() const { +real_t PathFollow2D::get_h_offset() const { return h_offset; } -void PathFollow2D::set_v_offset(float p_v_offset) { +void PathFollow2D::set_v_offset(real_t p_v_offset) { v_offset = p_v_offset; if (path) { _update_transform(); } } -float PathFollow2D::get_v_offset() const { +real_t PathFollow2D::get_v_offset() const { return v_offset; } -float PathFollow2D::get_offset() const { +real_t PathFollow2D::get_offset() const { return offset; } -void PathFollow2D::set_unit_offset(float p_unit_offset) { +void PathFollow2D::set_unit_offset(real_t p_unit_offset) { if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) { set_offset(p_unit_offset * path->get_curve()->get_baked_length()); } } -float PathFollow2D::get_unit_offset() const { +real_t PathFollow2D::get_unit_offset() const { if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) { return get_offset() / path->get_curve()->get_baked_length(); } else { @@ -361,11 +361,11 @@ float PathFollow2D::get_unit_offset() const { } } -void PathFollow2D::set_lookahead(float p_lookahead) { +void PathFollow2D::set_lookahead(real_t p_lookahead) { lookahead = p_lookahead; } -float PathFollow2D::get_lookahead() const { +real_t PathFollow2D::get_lookahead() const { return lookahead; } diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h index a748817555..671ab493c3 100644 --- a/scene/2d/path_2d.h +++ b/scene/2d/path_2d.h @@ -81,20 +81,20 @@ protected: static void _bind_methods(); public: - void set_offset(float p_offset); - float get_offset() const; + void set_offset(real_t p_offset); + real_t get_offset() const; - void set_h_offset(float p_h_offset); - float get_h_offset() const; + void set_h_offset(real_t p_h_offset); + real_t get_h_offset() const; - void set_v_offset(float p_v_offset); - float get_v_offset() const; + void set_v_offset(real_t p_v_offset); + real_t get_v_offset() const; - void set_unit_offset(float p_unit_offset); - float get_unit_offset() const; + void set_unit_offset(real_t p_unit_offset); + real_t get_unit_offset() const; - void set_lookahead(float p_lookahead); - float get_lookahead() const; + void set_lookahead(real_t p_lookahead); + real_t get_lookahead() const; void set_loop(bool p_loop); bool has_loop() const; diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index 2bb75e5967..1a7038bb80 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -160,8 +160,8 @@ void Polygon2D::_notification(int p_what) { if (invert) { Rect2 bounds; int highest_idx = -1; - float highest_y = -1e20; - float sum = 0.0; + real_t highest_y = -1e20; + real_t sum = 0.0; for (int i = 0; i < len; i++) { if (i == 0) { @@ -279,7 +279,7 @@ void Polygon2D::_notification(int p_what) { //normalize the weights for (int i = 0; i < vc; i++) { - float tw = 0.0; + real_t tw = 0.0; for (int j = 0; j < 4; j++) { tw += weightsw[i * 4 + j]; } @@ -432,20 +432,20 @@ Vector2 Polygon2D::get_texture_offset() const { return tex_ofs; } -void Polygon2D::set_texture_rotation(float p_rot) { +void Polygon2D::set_texture_rotation(real_t p_rot) { tex_rot = p_rot; update(); } -float Polygon2D::get_texture_rotation() const { +real_t Polygon2D::get_texture_rotation() const { return tex_rot; } -void Polygon2D::set_texture_rotation_degrees(float p_rot) { +void Polygon2D::set_texture_rotation_degrees(real_t p_rot) { set_texture_rotation(Math::deg2rad(p_rot)); } -float Polygon2D::get_texture_rotation_degrees() const { +real_t Polygon2D::get_texture_rotation_degrees() const { return Math::rad2deg(get_texture_rotation()); } @@ -477,12 +477,12 @@ bool Polygon2D::get_antialiased() const { return antialiased; } -void Polygon2D::set_invert_border(float p_invert_border) { +void Polygon2D::set_invert_border(real_t p_invert_border) { invert_border = p_invert_border; update(); } -float Polygon2D::get_invert_border() const { +real_t Polygon2D::get_invert_border() const { return invert_border; } diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h index b329251277..c207024a53 100644 --- a/scene/2d/polygon_2d.h +++ b/scene/2d/polygon_2d.h @@ -55,9 +55,9 @@ class Polygon2D : public Node2D { Size2 tex_scale = Vector2(1, 1); Vector2 tex_ofs; bool tex_tile = true; - float tex_rot = 0.0; + real_t tex_rot = 0.0; bool invert = false; - float invert_border = 100.0; + real_t invert_border = 100.0; bool antialiased = false; Vector2 offset; @@ -115,11 +115,11 @@ public: void set_texture_offset(const Vector2 &p_offset); Vector2 get_texture_offset() const; - void set_texture_rotation(float p_rot); - float get_texture_rotation() const; + void set_texture_rotation(real_t p_rot); + real_t get_texture_rotation() const; - void set_texture_rotation_degrees(float p_rot); - float get_texture_rotation_degrees() const; + void set_texture_rotation_degrees(real_t p_rot); + real_t get_texture_rotation_degrees() const; void set_texture_scale(const Size2 &p_scale); Size2 get_texture_scale() const; @@ -130,8 +130,8 @@ public: void set_antialiased(bool p_antialiased); bool get_antialiased() const; - void set_invert_border(float p_invert_border); - float get_invert_border() const; + void set_invert_border(real_t p_invert_border); + real_t get_invert_border() const; void set_offset(const Vector2 &p_offset); Vector2 get_offset() const; diff --git a/scene/2d/position_2d.cpp b/scene/2d/position_2d.cpp index ff7a0dbac3..5c7d65e3e0 100644 --- a/scene/2d/position_2d.cpp +++ b/scene/2d/position_2d.cpp @@ -33,10 +33,10 @@ #include "core/config/engine.h" #include "scene/resources/texture.h" -const float DEFAULT_GIZMO_EXTENTS = 10.0; +const real_t DEFAULT_GIZMO_EXTENTS = 10.0; void Position2D::_draw_cross() { - float extents = get_gizmo_extents(); + real_t extents = get_gizmo_extents(); // Colors taken from `axis_x_color` and `axis_y_color` (defined in `editor/editor_themes.cpp`) draw_line(Point2(-extents, 0), Point2(+extents, 0), Color(0.96, 0.20, 0.32)); draw_line(Point2(0, -extents), Point2(0, +extents), Color(0.53, 0.84, 0.01)); @@ -44,7 +44,7 @@ void Position2D::_draw_cross() { #ifdef TOOLS_ENABLED Rect2 Position2D::_edit_get_rect() const { - float extents = get_gizmo_extents(); + real_t extents = get_gizmo_extents(); return Rect2(Point2(-extents, -extents), Size2(extents * 2, extents * 2)); } @@ -70,7 +70,7 @@ void Position2D::_notification(int p_what) { } } -void Position2D::set_gizmo_extents(float p_extents) { +void Position2D::set_gizmo_extents(real_t p_extents) { if (p_extents == DEFAULT_GIZMO_EXTENTS) { set_meta("_gizmo_extents_", Variant()); } else { @@ -80,7 +80,7 @@ void Position2D::set_gizmo_extents(float p_extents) { update(); } -float Position2D::get_gizmo_extents() const { +real_t Position2D::get_gizmo_extents() const { if (has_meta("_gizmo_extents_")) { return get_meta("_gizmo_extents_"); } else { diff --git a/scene/2d/position_2d.h b/scene/2d/position_2d.h index fcaef0e6a3..9ed622c8f6 100644 --- a/scene/2d/position_2d.h +++ b/scene/2d/position_2d.h @@ -48,8 +48,8 @@ public: virtual bool _edit_use_rect() const override; #endif - void set_gizmo_extents(float p_extents); - float get_gizmo_extents() const; + void set_gizmo_extents(real_t p_extents); + real_t get_gizmo_extents() const; Position2D(); }; diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index e028b5f5b7..2d19d254b1 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -119,11 +119,11 @@ void Bone2D::apply_rest() { set_transform(rest); } -void Bone2D::set_default_length(float p_length) { +void Bone2D::set_default_length(real_t p_length) { default_length = p_length; } -float Bone2D::get_default_length() const { +real_t Bone2D::get_default_length() const { return default_length; } diff --git a/scene/2d/skeleton_2d.h b/scene/2d/skeleton_2d.h index 80ca8c80ac..1f43ea742b 100644 --- a/scene/2d/skeleton_2d.h +++ b/scene/2d/skeleton_2d.h @@ -46,7 +46,7 @@ class Bone2D : public Node2D { Bone2D *parent_bone = nullptr; Skeleton2D *skeleton = nullptr; Transform2D rest; - float default_length = 16.0; + real_t default_length = 16.0; int skeleton_index = -1; @@ -62,8 +62,8 @@ public: String get_configuration_warning() const override; - void set_default_length(float p_length); - float get_default_length() const; + void set_default_length(real_t p_length); + real_t get_default_length() const; int get_index_in_skeleton() const; diff --git a/scene/2d/sprite_2d.cpp b/scene/2d/sprite_2d.cpp index 31040020dd..7c93edbff9 100644 --- a/scene/2d/sprite_2d.cpp +++ b/scene/2d/sprite_2d.cpp @@ -77,14 +77,14 @@ Rect2 Sprite2D::get_anchorable_rect() const { return get_rect(); } -void Sprite2D::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const { +void Sprite2D::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip_enabled) const { Rect2 base_rect; - if (region) { - r_filter_clip = region_filter_clip; + if (region_enabled) { + r_filter_clip_enabled = region_filter_clip_enabled; base_rect = region_rect; } else { - r_filter_clip = false; + r_filter_clip_enabled = false; base_rect = Rect2(0, 0, texture->get_width(), texture->get_height()); } @@ -129,10 +129,10 @@ void Sprite2D::_notification(int p_what) { */ Rect2 src_rect, dst_rect; - bool filter_clip; - _get_rects(src_rect, dst_rect, filter_clip); + bool filter_clip_enabled; + _get_rects(src_rect, dst_rect, filter_clip_enabled); - texture->draw_rect_region(ci, dst_rect, src_rect, Color(1, 1, 1), false, filter_clip); + texture->draw_rect_region(ci, dst_rect, src_rect, Color(1, 1, 1), false, filter_clip_enabled); } break; } } @@ -199,18 +199,18 @@ bool Sprite2D::is_flipped_v() const { return vflip; } -void Sprite2D::set_region(bool p_region) { - if (p_region == region) { +void Sprite2D::set_region_enabled(bool p_region_enabled) { + if (p_region_enabled == region_enabled) { return; } - region = p_region; + region_enabled = p_region_enabled; update(); notify_property_list_changed(); } -bool Sprite2D::is_region() const { - return region; +bool Sprite2D::is_region_enabled() const { + return region_enabled; } void Sprite2D::set_region_rect(const Rect2 &p_region_rect) { @@ -220,7 +220,7 @@ void Sprite2D::set_region_rect(const Rect2 &p_region_rect) { region_rect = p_region_rect; - if (region) { + if (region_enabled) { item_rect_changed(); } } @@ -229,13 +229,13 @@ Rect2 Sprite2D::get_region_rect() const { return region_rect; } -void Sprite2D::set_region_filter_clip(bool p_enable) { - region_filter_clip = p_enable; +void Sprite2D::set_region_filter_clip_enabled(bool p_region_filter_clip_enabled) { + region_filter_clip_enabled = p_region_filter_clip_enabled; update(); } bool Sprite2D::is_region_filter_clip_enabled() const { - return region_filter_clip; + return region_filter_clip_enabled; } void Sprite2D::set_frame(int p_frame) { @@ -299,8 +299,8 @@ bool Sprite2D::is_pixel_opaque(const Point2 &p_point) const { } Rect2 src_rect, dst_rect; - bool filter_clip; - _get_rects(src_rect, dst_rect, filter_clip); + bool filter_clip_enabled; + _get_rects(src_rect, dst_rect, filter_clip_enabled); dst_rect.size = dst_rect.size.abs(); if (!dst_rect.has_point(p_point)) { @@ -350,7 +350,7 @@ Rect2 Sprite2D::get_rect() const { Size2i s; - if (region) { + if (region_enabled) { s = region_rect.size; } else { s = texture->get_size(); @@ -385,7 +385,7 @@ void Sprite2D::_validate_property(PropertyInfo &property) const { property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; } - if (!region && (property.name == "region_rect" || property.name == "region_filter_clip")) { + if (!region_enabled && (property.name == "region_rect" || property.name == "region_filter_clip")) { property.usage = PROPERTY_USAGE_NOEDITOR; } } @@ -414,15 +414,15 @@ void Sprite2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_flip_v", "flip_v"), &Sprite2D::set_flip_v); ClassDB::bind_method(D_METHOD("is_flipped_v"), &Sprite2D::is_flipped_v); - ClassDB::bind_method(D_METHOD("set_region", "enabled"), &Sprite2D::set_region); - ClassDB::bind_method(D_METHOD("is_region"), &Sprite2D::is_region); + ClassDB::bind_method(D_METHOD("set_region_enabled", "enabled"), &Sprite2D::set_region_enabled); + ClassDB::bind_method(D_METHOD("is_region_enabled"), &Sprite2D::is_region_enabled); ClassDB::bind_method(D_METHOD("is_pixel_opaque", "pos"), &Sprite2D::is_pixel_opaque); ClassDB::bind_method(D_METHOD("set_region_rect", "rect"), &Sprite2D::set_region_rect); ClassDB::bind_method(D_METHOD("get_region_rect"), &Sprite2D::get_region_rect); - ClassDB::bind_method(D_METHOD("set_region_filter_clip", "enabled"), &Sprite2D::set_region_filter_clip); + ClassDB::bind_method(D_METHOD("set_region_filter_clip_enabled", "enabled"), &Sprite2D::set_region_filter_clip_enabled); ClassDB::bind_method(D_METHOD("is_region_filter_clip_enabled"), &Sprite2D::is_region_filter_clip_enabled); ClassDB::bind_method(D_METHOD("set_frame", "frame"), &Sprite2D::set_frame); @@ -455,9 +455,9 @@ void Sprite2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords"); ADD_GROUP("Region", "region_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region", "is_region"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region_enabled", "is_region_enabled"); ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_filter_clip"), "set_region_filter_clip", "is_region_filter_clip_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_filter_clip_enabled"), "set_region_filter_clip_enabled", "is_region_filter_clip_enabled"); } Sprite2D::Sprite2D() { diff --git a/scene/2d/sprite_2d.h b/scene/2d/sprite_2d.h index fa765f457d..9db74cfe26 100644 --- a/scene/2d/sprite_2d.h +++ b/scene/2d/sprite_2d.h @@ -39,23 +39,23 @@ class Sprite2D : public Node2D { Ref<Texture2D> texture; Color specular_color; - float shininess = 0.0; + real_t shininess = 0.0; bool centered = true; Point2 offset; bool hflip = false; bool vflip = false; - bool region = false; + bool region_enabled = false; Rect2 region_rect; - bool region_filter_clip = false; + bool region_filter_clip_enabled = false; int frame = 0; int vframes = 1; int hframes = 1; - void _get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const; + void _get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip_enabled) const; void _texture_changed(); @@ -97,10 +97,10 @@ public: void set_flip_v(bool p_flip); bool is_flipped_v() const; - void set_region(bool p_region); - bool is_region() const; + void set_region_enabled(bool p_enabled); + bool is_region_enabled() const; - void set_region_filter_clip(bool p_enable); + void set_region_filter_clip_enabled(bool p_enabled); bool is_region_filter_clip_enabled() const; void set_region_rect(const Rect2 &p_region_rect); diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp index 9d6868a1b2..4e58984b37 100644 --- a/scene/2d/touch_screen_button.cpp +++ b/scene/2d/touch_screen_button.cpp @@ -189,6 +189,8 @@ String TouchScreenButton::get_action() const { } void TouchScreenButton::_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (!get_tree()) { return; } diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index be62fe801f..db5fc7593e 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -439,6 +439,17 @@ String Skeleton3D::get_bone_name(int p_bone) const { return bones[p_bone].name; } +void Skeleton3D::set_bone_name(int p_bone, const String &p_name) { + ERR_FAIL_INDEX(p_bone, bones.size()); + + for (int i = 0; i < bones.size(); i++) { + if (i != p_bone) { + ERR_FAIL_COND(bones[i].name == p_name); + } + } + + bones.write[p_bone].name = p_name; +} bool Skeleton3D::is_bone_parent_of(int p_bone, int p_parent_bone_id) const { int parent_of_bone = get_bone_parent(p_bone); @@ -869,6 +880,7 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("add_bone", "name"), &Skeleton3D::add_bone); ClassDB::bind_method(D_METHOD("find_bone", "name"), &Skeleton3D::find_bone); ClassDB::bind_method(D_METHOD("get_bone_name", "bone_idx"), &Skeleton3D::get_bone_name); + ClassDB::bind_method(D_METHOD("set_bone_name", "bone_idx", "name"), &Skeleton3D::set_bone_name); ClassDB::bind_method(D_METHOD("get_bone_parent", "bone_idx"), &Skeleton3D::get_bone_parent); ClassDB::bind_method(D_METHOD("set_bone_parent", "bone_idx", "parent_idx"), &Skeleton3D::set_bone_parent); diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h index 9772bfcc95..2941ac2c45 100644 --- a/scene/3d/skeleton_3d.h +++ b/scene/3d/skeleton_3d.h @@ -143,6 +143,7 @@ public: void add_bone(const String &p_name); int find_bone(const String &p_name) const; String get_bone_name(int p_bone) const; + void set_bone_name(int p_bone, const String &p_name); bool is_bone_parent_of(int p_bone_id, int p_parent_bone_id) const; diff --git a/scene/3d/skeleton_ik_3d.cpp b/scene/3d/skeleton_ik_3d.cpp index 80c1f0ddb1..85da546430 100644 --- a/scene/3d/skeleton_ik_3d.cpp +++ b/scene/3d/skeleton_ik_3d.cpp @@ -268,6 +268,10 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove p_task->skeleton->set_bone_global_pose_override(p_task->chain.tips[i].chain_item->bone, Transform(), 0.0, true); } + // Update the initial root transform + p_task->chain.chain_root.initial_transform = p_task->skeleton->get_bone_global_pose(p_task->chain.chain_root.bone); + p_task->chain.chain_root.current_pos = p_task->chain.chain_root.initial_transform.origin; + make_goal(p_task, p_task->skeleton->get_global_transform().affine_inverse(), blending_delta); if (p_use_magnet && p_task->chain.middle_chain_item) { diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp index 2d8f22ab37..3fde4d6ef3 100644 --- a/scene/3d/soft_body_3d.cpp +++ b/scene/3d/soft_body_3d.cpp @@ -37,7 +37,6 @@ #include "scene/3d/collision_object_3d.h" #include "scene/3d/physics_body_3d.h" #include "scene/3d/skeleton_3d.h" -#include "servers/physics_server_3d.h" SoftBodyRenderingServerHandler::SoftBodyRenderingServerHandler() {} @@ -48,27 +47,28 @@ void SoftBodyRenderingServerHandler::prepare(RID p_mesh, int p_surface) { mesh = p_mesh; surface = p_surface; -#ifndef _MSC_VER -#warning Softbody is not working, needs to be redone considering that these functions no longer exist -#endif -#if 0 - const uint32_t surface_format = RS::get_singleton()->mesh_surface_get_format(mesh, surface); - const int surface_vertex_len = RS::get_singleton()->mesh_surface_get_array_len(mesh, p_surface); - const int surface_index_len = RS::get_singleton()->mesh_surface_get_array_index_len(mesh, p_surface); + + RS::SurfaceData surface_data = RS::get_singleton()->mesh_get_surface(mesh, surface); + uint32_t surface_offsets[RS::ARRAY_MAX]; + uint32_t vertex_stride; + uint32_t attrib_stride; + uint32_t skin_stride; + RS::get_singleton()->mesh_surface_make_offsets_from_format(surface_data.format, surface_data.vertex_count, surface_data.index_count, surface_offsets, vertex_stride, attrib_stride, skin_stride); - buffer = RS::get_singleton()->mesh_surface_get_array(mesh, surface); - stride = RS::get_singleton()->mesh_surface_make_offsets_from_format(surface_format, surface_vertex_len, surface_index_len, surface_offsets); + buffer = surface_data.vertex_data; + stride = vertex_stride; offset_vertices = surface_offsets[RS::ARRAY_VERTEX]; offset_normal = surface_offsets[RS::ARRAY_NORMAL]; -#endif } void SoftBodyRenderingServerHandler::clear() { - if (mesh.is_valid()) { - buffer.resize(0); - } + buffer.resize(0); + stride = 0; + offset_vertices = 0; + offset_normal = 0; + surface = 0; mesh = RID(); } @@ -77,7 +77,7 @@ void SoftBodyRenderingServerHandler::open() { } void SoftBodyRenderingServerHandler::close() { - //write_buffer.release(); + write_buffer = nullptr; } void SoftBodyRenderingServerHandler::commit_changes() { @@ -309,6 +309,8 @@ void SoftBody3D::_notification(int p_what) { } void SoftBody3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_physics_rid"), &SoftBody3D::get_physics_rid); + ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &SoftBody3D::set_collision_mask); ClassDB::bind_method(D_METHOD("get_collision_mask"), &SoftBody3D::get_collision_mask); @@ -337,18 +339,9 @@ void SoftBody3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_linear_stiffness", "linear_stiffness"), &SoftBody3D::set_linear_stiffness); ClassDB::bind_method(D_METHOD("get_linear_stiffness"), &SoftBody3D::get_linear_stiffness); - ClassDB::bind_method(D_METHOD("set_angular_stiffness", "angular_stiffness"), &SoftBody3D::set_angular_stiffness); - ClassDB::bind_method(D_METHOD("get_angular_stiffness"), &SoftBody3D::get_angular_stiffness); - - ClassDB::bind_method(D_METHOD("set_volume_stiffness", "volume_stiffness"), &SoftBody3D::set_volume_stiffness); - ClassDB::bind_method(D_METHOD("get_volume_stiffness"), &SoftBody3D::get_volume_stiffness); - ClassDB::bind_method(D_METHOD("set_pressure_coefficient", "pressure_coefficient"), &SoftBody3D::set_pressure_coefficient); ClassDB::bind_method(D_METHOD("get_pressure_coefficient"), &SoftBody3D::get_pressure_coefficient); - ClassDB::bind_method(D_METHOD("set_pose_matching_coefficient", "pose_matching_coefficient"), &SoftBody3D::set_pose_matching_coefficient); - ClassDB::bind_method(D_METHOD("get_pose_matching_coefficient"), &SoftBody3D::get_pose_matching_coefficient); - ClassDB::bind_method(D_METHOD("set_damping_coefficient", "damping_coefficient"), &SoftBody3D::set_damping_coefficient); ClassDB::bind_method(D_METHOD("get_damping_coefficient"), &SoftBody3D::get_damping_coefficient); @@ -366,12 +359,9 @@ void SoftBody3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "simulation_precision", PROPERTY_HINT_RANGE, "1,100,1"), "set_simulation_precision", "get_simulation_precision"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_mass", PROPERTY_HINT_RANGE, "0.01,10000,1"), "set_total_mass", "get_total_mass"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_linear_stiffness", "get_linear_stiffness"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_angular_stiffness", "get_angular_stiffness"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_volume_stiffness", "get_volume_stiffness"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure_coefficient"), "set_pressure_coefficient", "get_pressure_coefficient"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_damping_coefficient", "get_damping_coefficient"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "drag_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drag_coefficient", "get_drag_coefficient"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pose_matching_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_pose_matching_coefficient", "get_pose_matching_coefficient"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ray_pickable"), "set_ray_pickable", "is_ray_pickable"); } @@ -612,34 +602,10 @@ real_t SoftBody3D::get_linear_stiffness() { return PhysicsServer3D::get_singleton()->soft_body_get_linear_stiffness(physics_rid); } -void SoftBody3D::set_angular_stiffness(real_t p_angular_stiffness) { - PhysicsServer3D::get_singleton()->soft_body_set_angular_stiffness(physics_rid, p_angular_stiffness); -} - -real_t SoftBody3D::get_angular_stiffness() { - return PhysicsServer3D::get_singleton()->soft_body_get_angular_stiffness(physics_rid); -} - -void SoftBody3D::set_volume_stiffness(real_t p_volume_stiffness) { - PhysicsServer3D::get_singleton()->soft_body_set_volume_stiffness(physics_rid, p_volume_stiffness); -} - -real_t SoftBody3D::get_volume_stiffness() { - return PhysicsServer3D::get_singleton()->soft_body_get_volume_stiffness(physics_rid); -} - real_t SoftBody3D::get_pressure_coefficient() { return PhysicsServer3D::get_singleton()->soft_body_get_pressure_coefficient(physics_rid); } -void SoftBody3D::set_pose_matching_coefficient(real_t p_pose_matching_coefficient) { - PhysicsServer3D::get_singleton()->soft_body_set_pose_matching_coefficient(physics_rid, p_pose_matching_coefficient); -} - -real_t SoftBody3D::get_pose_matching_coefficient() { - return PhysicsServer3D::get_singleton()->soft_body_get_pose_matching_coefficient(physics_rid); -} - void SoftBody3D::set_pressure_coefficient(real_t p_pressure_coefficient) { PhysicsServer3D::get_singleton()->soft_body_set_pressure_coefficient(physics_rid, p_pressure_coefficient); } @@ -768,7 +734,9 @@ void SoftBody3D::_reset_points_offsets() { PinnedPoint *w = pinned_points.ptrw(); for (int i = pinned_points.size() - 1; 0 <= i; --i) { if (!r[i].spatial_attachment) { - w[i].spatial_attachment = Object::cast_to<Node3D>(get_node(r[i].spatial_attachment_path)); + if (!r[i].spatial_attachment_path.is_empty() && has_node(r[i].spatial_attachment_path)) { + w[i].spatial_attachment = Object::cast_to<Node3D>(get_node(r[i].spatial_attachment_path)); + } } if (!r[i].spatial_attachment) { diff --git a/scene/3d/soft_body_3d.h b/scene/3d/soft_body_3d.h index 6e24a530bd..f98df39209 100644 --- a/scene/3d/soft_body_3d.h +++ b/scene/3d/soft_body_3d.h @@ -32,10 +32,11 @@ #define SOFT_PHYSICS_BODY_H #include "scene/3d/mesh_instance_3d.h" +#include "servers/physics_server_3d.h" class SoftBody3D; -class SoftBodyRenderingServerHandler { +class SoftBodyRenderingServerHandler : public RenderingServerHandler { friend class SoftBody3D; RID mesh; @@ -57,9 +58,9 @@ private: void commit_changes(); public: - void set_vertex(int p_vertex_id, const void *p_vector3); - void set_normal(int p_vertex_id, const void *p_vector3); - void set_aabb(const AABB &p_aabb); + void set_vertex(int p_vertex_id, const void *p_vector3) override; + void set_normal(int p_vertex_id, const void *p_vector3) override; + void set_aabb(const AABB &p_aabb) override; }; class SoftBody3D : public MeshInstance3D { @@ -122,6 +123,8 @@ public: void prepare_physics_server(); void become_mesh_owner(); + RID get_physics_rid() const { return physics_rid; } + void set_collision_mask(uint32_t p_mask); uint32_t get_collision_mask() const; @@ -149,18 +152,9 @@ public: void set_linear_stiffness(real_t p_linear_stiffness); real_t get_linear_stiffness(); - void set_angular_stiffness(real_t p_angular_stiffness); - real_t get_angular_stiffness(); - - void set_volume_stiffness(real_t p_volume_stiffness); - real_t get_volume_stiffness(); - void set_pressure_coefficient(real_t p_pressure_coefficient); real_t get_pressure_coefficient(); - void set_pose_matching_coefficient(real_t p_pose_matching_coefficient); - real_t get_pose_matching_coefficient(); - void set_damping_coefficient(real_t p_damping_coefficient); real_t get_damping_coefficient(); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index a3265ffb30..0be54e7243 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -366,7 +366,7 @@ void Sprite3D::_draw() { } Rect2 base_rect; - if (region) { + if (region_enabled) { base_rect = region_rect; } else { base_rect = Rect2(0, 0, texture->get_width(), texture->get_height()); @@ -511,24 +511,24 @@ Ref<Texture2D> Sprite3D::get_texture() const { return texture; } -void Sprite3D::set_region(bool p_region) { - if (p_region == region) { +void Sprite3D::set_region_enabled(bool p_region_enabled) { + if (p_region_enabled == region_enabled) { return; } - region = p_region; + region_enabled = p_region_enabled; _queue_update(); notify_property_list_changed(); } -bool Sprite3D::is_region() const { - return region; +bool Sprite3D::is_region_enabled() const { + return region_enabled; } void Sprite3D::set_region_rect(const Rect2 &p_region_rect) { bool changed = region_rect != p_region_rect; region_rect = p_region_rect; - if (region && changed) { + if (region_enabled && changed) { _queue_update(); } } @@ -595,7 +595,7 @@ Rect2 Sprite3D::get_item_rect() const { Size2i s; - if (region) { + if (region_enabled) { s = region_rect.size; } else { s = texture->get_size(); @@ -625,7 +625,7 @@ void Sprite3D::_validate_property(PropertyInfo &property) const { property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; } - if (!region && property.name == "region_rect") { + if (!region_enabled && property.name == "region_rect") { property.usage = PROPERTY_USAGE_NOEDITOR; } } @@ -634,8 +634,8 @@ void Sprite3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Sprite3D::set_texture); ClassDB::bind_method(D_METHOD("get_texture"), &Sprite3D::get_texture); - ClassDB::bind_method(D_METHOD("set_region", "enabled"), &Sprite3D::set_region); - ClassDB::bind_method(D_METHOD("is_region"), &Sprite3D::is_region); + ClassDB::bind_method(D_METHOD("set_region_enabled", "enabled"), &Sprite3D::set_region_enabled); + ClassDB::bind_method(D_METHOD("is_region_enabled"), &Sprite3D::is_region_enabled); ClassDB::bind_method(D_METHOD("set_region_rect", "rect"), &Sprite3D::set_region_rect); ClassDB::bind_method(D_METHOD("get_region_rect"), &Sprite3D::get_region_rect); @@ -659,14 +659,14 @@ void Sprite3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords"); ADD_GROUP("Region", "region_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region", "is_region"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region_enabled", "is_region_enabled"); ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect"); ADD_SIGNAL(MethodInfo("frame_changed")); } Sprite3D::Sprite3D() { - region = false; + region_enabled = false; frame = 0; vframes = 1; hframes = 1; diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index e46a53da0d..d1bc8dc737 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -107,8 +107,8 @@ public: void set_flip_v(bool p_flip); bool is_flipped_v() const; - void set_region(bool p_region); - bool is_region() const; + void set_region_enabled(bool p_region_enabled); + bool is_region_enabled() const; void set_region_rect(const Rect2 &p_region_rect); Rect2 get_region_rect() const; @@ -147,7 +147,7 @@ class Sprite3D : public SpriteBase3D { GDCLASS(Sprite3D, SpriteBase3D); Ref<Texture2D> texture; - bool region; + bool region_enabled; Rect2 region_rect; int frame; @@ -167,8 +167,8 @@ public: void set_texture(const Ref<Texture2D> &p_texture); Ref<Texture2D> get_texture() const; - void set_region(bool p_region); - bool is_region() const; + void set_region_enabled(bool p_region_enabled); + bool is_region_enabled() const; void set_region_rect(const Rect2 &p_region_rect); Rect2 get_region_rect() const; @@ -203,8 +203,8 @@ class AnimatedSprite3D : public SpriteBase3D { float timeout = 0.0; - bool hflip = 1; - bool vflip = 1; + bool hflip = true; + bool vflip = true; Color modulate; diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp index 16718b956f..1b9ce0201f 100644 --- a/scene/3d/voxelizer.cpp +++ b/scene/3d/voxelizer.cpp @@ -344,7 +344,7 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material Ref<Image> img_albedo; if (albedo_tex.is_valid()) { - img_albedo = albedo_tex->get_data(); + img_albedo = albedo_tex->get_image(); mc.albedo = _get_bake_texture(img_albedo, mat->get_albedo(), Color(0, 0, 0)); // albedo texture, color is multiplicative } else { mc.albedo = _get_bake_texture(img_albedo, Color(1, 1, 1), mat->get_albedo()); // no albedo texture, color is additive @@ -358,7 +358,7 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material Ref<Image> img_emission; if (emission_tex.is_valid()) { - img_emission = emission_tex->get_data(); + img_emission = emission_tex->get_image(); } if (mat->get_emission_operator() == StandardMaterial3D::EMISSION_OP_ADD) { diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp index 7fed34c7c6..63be4352d5 100644 --- a/scene/3d/xr_nodes.cpp +++ b/scene/3d/xr_nodes.cpp @@ -190,8 +190,8 @@ void XRController3D::_notification(int p_what) { ERR_FAIL_NULL(xr_server); // find the tracker for our controller - XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); - if (tracker == nullptr) { + Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); + if (!tracker.is_valid()) { // this controller is currently turned off is_active = false; button_states = 0; @@ -277,8 +277,8 @@ String XRController3D::get_controller_name() const { XRServer *xr_server = XRServer::get_singleton(); ERR_FAIL_NULL_V(xr_server, String()); - XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); - if (tracker == nullptr) { + Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); + if (!tracker.is_valid()) { return String("Not connected"); }; @@ -290,8 +290,8 @@ int XRController3D::get_joystick_id() const { XRServer *xr_server = XRServer::get_singleton(); ERR_FAIL_NULL_V(xr_server, 0); - XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); - if (tracker == nullptr) { + Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); + if (!tracker.is_valid()) { // No tracker? no joystick id... (0 is our first joystick) return -1; }; @@ -322,8 +322,8 @@ real_t XRController3D::get_rumble() const { XRServer *xr_server = XRServer::get_singleton(); ERR_FAIL_NULL_V(xr_server, 0.0); - XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); - if (tracker == nullptr) { + Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); + if (!tracker.is_valid()) { return 0.0; }; @@ -335,8 +335,8 @@ void XRController3D::set_rumble(real_t p_rumble) { XRServer *xr_server = XRServer::get_singleton(); ERR_FAIL_NULL(xr_server); - XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); - if (tracker != nullptr) { + Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); + if (tracker.is_valid()) { tracker->set_rumble(p_rumble); }; }; @@ -354,8 +354,8 @@ XRPositionalTracker::TrackerHand XRController3D::get_tracker_hand() const { XRServer *xr_server = XRServer::get_singleton(); ERR_FAIL_NULL_V(xr_server, XRPositionalTracker::TRACKER_HAND_UNKNOWN); - XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); - if (tracker == nullptr) { + Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); + if (!tracker.is_valid()) { return XRPositionalTracker::TRACKER_HAND_UNKNOWN; }; @@ -404,8 +404,8 @@ void XRAnchor3D::_notification(int p_what) { ERR_FAIL_NULL(xr_server); // find the tracker for our anchor - XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_ANCHOR, anchor_id); - if (tracker == nullptr) { + Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_ANCHOR, anchor_id); + if (!tracker.is_valid()) { // this anchor is currently not available is_active = false; } else { @@ -475,8 +475,8 @@ String XRAnchor3D::get_anchor_name() const { XRServer *xr_server = XRServer::get_singleton(); ERR_FAIL_NULL_V(xr_server, String()); - XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_ANCHOR, anchor_id); - if (tracker == nullptr) { + Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_ANCHOR, anchor_id); + if (!tracker.is_valid()) { return String("Not connected"); }; diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index d46f24752e..246fff6d57 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -281,7 +281,7 @@ bool AnimationNodeStateMachinePlayback::_travel(AnimationNodeStateMachine *p_sta at = cost_map[at].prev; } - path.invert(); + path.reverse(); return true; } diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index db13b9b11f..826fd0189b 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -53,6 +53,8 @@ void BaseButton::_unpress_group() { } void BaseButton::_gui_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (status.disabled) { // no interaction with disabled button return; } @@ -323,6 +325,8 @@ Ref<Shortcut> BaseButton::get_shortcut() const { } void BaseButton::_unhandled_key_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (!_is_focus_owner_in_shorcut_context()) { return; } diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index d54d63cc39..6c7a8f3433 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -45,7 +45,7 @@ public: }; private: - int button_mask = BUTTON_MASK_LEFT; + int button_mask = MOUSE_BUTTON_MASK_LEFT; bool toggle_mode = false; bool shortcut_in_tooltip = true; bool keep_pressed_outside = false; diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp index c570438b6a..7407ad5b8f 100644 --- a/scene/gui/box_container.cpp +++ b/scene/gui/box_container.cpp @@ -313,7 +313,7 @@ BoxContainer::AlignMode BoxContainer::get_alignment() const { return align; } -void BoxContainer::add_spacer(bool p_begin) { +Control *BoxContainer::add_spacer(bool p_begin) { Control *c = memnew(Control); c->set_mouse_filter(MOUSE_FILTER_PASS); //allow spacer to pass mouse events @@ -327,6 +327,8 @@ void BoxContainer::add_spacer(bool p_begin) { if (p_begin) { move_child(c, 0); } + + return c; } BoxContainer::BoxContainer(bool p_vertical) { diff --git a/scene/gui/box_container.h b/scene/gui/box_container.h index 31050d1feb..23feea565c 100644 --- a/scene/gui/box_container.h +++ b/scene/gui/box_container.h @@ -55,7 +55,7 @@ protected: static void _bind_methods(); public: - void add_spacer(bool p_begin = false); + Control *add_spacer(bool p_begin = false); void set_alignment(AlignMode p_align); AlignMode get_alignment() const; diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp index 9df328dd11..c0650a8f3f 100644 --- a/scene/gui/check_box.cpp +++ b/scene/gui/check_box.cpp @@ -34,7 +34,9 @@ Size2 CheckBox::get_icon_size() const { Ref<Texture2D> checked = Control::get_theme_icon("checked"); + Ref<Texture2D> checked_disabled = Control::get_theme_icon("checked_disabled"); Ref<Texture2D> unchecked = Control::get_theme_icon("unchecked"); + Ref<Texture2D> unchecked_disabled = Control::get_theme_icon("unchecked_disabled"); Ref<Texture2D> radio_checked = Control::get_theme_icon("radio_checked"); Ref<Texture2D> radio_unchecked = Control::get_theme_icon("radio_unchecked"); @@ -79,8 +81,8 @@ void CheckBox::_notification(int p_what) { } else if (p_what == NOTIFICATION_DRAW) { RID ci = get_canvas_item(); - Ref<Texture2D> on = Control::get_theme_icon(is_radio() ? "radio_checked" : "checked"); - Ref<Texture2D> off = Control::get_theme_icon(is_radio() ? "radio_unchecked" : "unchecked"); + Ref<Texture2D> on = Control::get_theme_icon(vformat("%s%s", is_radio() ? "radio_checked" : "checked", is_disabled() ? "_disabled" : "")); + Ref<Texture2D> off = Control::get_theme_icon(vformat("%s%s", is_radio() ? "radio_unchecked" : "unchecked", is_disabled() ? "_disabled" : "")); Ref<StyleBox> sb = get_theme_stylebox("normal"); Vector2 ofs; diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index bddbe30f53..1a9ad23434 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -544,7 +544,7 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> bev = p_event; if (bev.is_valid()) { - if (bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) { + if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) { changing_color = true; float x = CLAMP((float)bev->get_position().x, 0, uv_edit->get_size().width); float y = CLAMP((float)bev->get_position().y, 0, uv_edit->get_size().height); @@ -557,7 +557,7 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event) { if (!deferred_mode_enabled) { emit_signal("color_changed", color); } - } else if (deferred_mode_enabled && !bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) { + } else if (deferred_mode_enabled && !bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) { emit_signal("color_changed", color); changing_color = false; } else { @@ -589,7 +589,7 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> bev = p_event; if (bev.is_valid()) { - if (bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) { + if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) { changing_color = true; float y = CLAMP((float)bev->get_position().y, 0, w_edit->get_size().height); h = y / w_edit->get_size().height; @@ -602,7 +602,7 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { _update_color(); if (!deferred_mode_enabled) { emit_signal("color_changed", color); - } else if (!bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) { + } else if (!bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) { emit_signal("color_changed", color); } } @@ -630,7 +630,7 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event) { if (bev.is_valid()) { int index = 0; - if (bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) { + if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) { for (int i = 0; i < presets.size(); i++) { int x = (i % presets_per_row) * bt_add_preset->get_size().x; int y = (Math::floor((float)i / presets_per_row)) * bt_add_preset->get_size().y; @@ -641,7 +641,7 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event) { set_pick_color(presets[index]); _update_color(); emit_signal("color_changed", color); - } else if (bev->is_pressed() && bev->get_button_index() == BUTTON_RIGHT && presets_enabled) { + } else if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_RIGHT && presets_enabled) { index = bev->get_position().x / (preset->get_size().x / presets.size()); Color clicked_preset = presets[index]; erase_preset(clicked_preset); @@ -670,7 +670,7 @@ void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseButton> bev = p_event; - if (bev.is_valid() && bev->get_button_index() == BUTTON_LEFT && !bev->is_pressed()) { + if (bev.is_valid() && bev->get_button_index() == MOUSE_BUTTON_LEFT && !bev->is_pressed()) { emit_signal("color_changed", color); screen->hide(); } @@ -682,7 +682,7 @@ void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) { return; } - Ref<Image> img = r->get_texture()->get_data(); + Ref<Image> img = r->get_texture()->get_image(); if (img.is_valid() && !img->is_empty()) { Vector2 ofs = mev->get_global_position() - r->get_visible_rect().get_position(); Color c = img->get_pixel(ofs.x, r->get_visible_rect().size.height - ofs.y); @@ -847,7 +847,7 @@ ColorPicker::ColorPicker() : btn_pick->set_flat(true); hb_smpl->add_child(btn_pick); btn_pick->set_toggle_mode(true); - btn_pick->set_tooltip(TTR("Pick a color from the editor window.")); + btn_pick->set_tooltip(RTR("Pick a color from the editor window.")); btn_pick->connect("pressed", callable_mp(this, &ColorPicker::_screen_pick_pressed)); VBoxContainer *vbl = memnew(VBoxContainer); @@ -899,12 +899,12 @@ ColorPicker::ColorPicker() : btn_hsv = memnew(CheckButton); hhb->add_child(btn_hsv); - btn_hsv->set_text(TTR("HSV")); + btn_hsv->set_text(RTR("HSV")); btn_hsv->connect("toggled", callable_mp(this, &ColorPicker::set_hsv_mode)); btn_raw = memnew(CheckButton); hhb->add_child(btn_raw); - btn_raw->set_text(TTR("Raw")); + btn_raw->set_text(RTR("Raw")); btn_raw->connect("toggled", callable_mp(this, &ColorPicker::set_raw_mode)); text_type = memnew(Button); @@ -950,7 +950,7 @@ ColorPicker::ColorPicker() : add_child(preset_container2); bt_add_preset = memnew(Button); preset_container2->add_child(bt_add_preset); - bt_add_preset->set_tooltip(TTR("Add current color as a preset.")); + bt_add_preset->set_tooltip(RTR("Add current color as a preset.")); bt_add_preset->connect("pressed", callable_mp(this, &ColorPicker::_add_preset_pressed)); } diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index c13bce5e0c..300201c0db 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -136,11 +136,11 @@ bool Control::_edit_use_rect() const { return true; } -void Control::_edit_set_rotation(float p_rotation) { +void Control::_edit_set_rotation(real_t p_rotation) { set_rotation(p_rotation); } -float Control::_edit_get_rotation() const { +real_t Control::_edit_get_rotation() const { return get_rotation(); } @@ -290,15 +290,11 @@ void Control::_update_minimum_size() { } Size2 minsize = get_combined_minimum_size(); - if (minsize.x > data.size_cache.x || - minsize.y > data.size_cache.y) { - _size_changed(); - } - 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); } } @@ -327,7 +323,6 @@ bool Control::_get(const StringName &p_name, Variant &r_ret) const { r_ret = data.color_override.has(name) ? Variant(data.color_override[name]) : Variant(); } else if (sname.begins_with("custom_constants/")) { String name = sname.get_slicec('/', 1); - r_ret = data.constant_override.has(name) ? Variant(data.constant_override[name]) : Variant(); } else { return false; @@ -1238,10 +1233,10 @@ Size2 Control::get_parent_area_size() const { void Control::_size_changed() { Rect2 parent_rect = get_parent_anchorable_rect(); - float edge_pos[4]; + real_t edge_pos[4]; for (int i = 0; i < 4; i++) { - float area = parent_rect.size[i & 1]; + real_t area = parent_rect.size[i & 1]; edge_pos[i] = data.offset[i] + (data.anchor[i] * area); } @@ -1295,13 +1290,13 @@ void Control::_size_changed() { } } -void Control::set_anchor(Side p_side, float p_anchor, bool p_keep_offset, bool p_push_opposite_anchor) { +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(); - float parent_range = (p_side == SIDE_LEFT || p_side == SIDE_RIGHT) ? parent_rect.size.x : parent_rect.size.y; - float previous_pos = data.offset[p_side] + data.anchor[p_side] * parent_range; - float previous_opposite_pos = data.offset[(p_side + 2) % 4] + data.anchor[(p_side + 2) % 4] * parent_range; + 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; @@ -1327,11 +1322,11 @@ void Control::set_anchor(Side p_side, float p_anchor, bool p_keep_offset, bool p update(); } -void Control::_set_anchor(Side p_side, float p_anchor) { +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, float p_anchor, float p_pos, bool p_push_opposite_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); } @@ -1468,7 +1463,7 @@ void Control::set_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz Rect2 parent_rect = get_parent_anchorable_rect(); - float x = parent_rect.size.x; + real_t x = parent_rect.size.x; if (is_layout_rtl()) { x = parent_rect.size.x - x - new_size.x; } @@ -1592,13 +1587,13 @@ void Control::set_anchors_and_offsets_preset(LayoutPreset p_preset, LayoutPreset set_offsets_preset(p_preset, p_resize_mode, p_margin); } -float Control::get_anchor(Side p_side) const { +real_t Control::get_anchor(Side p_side) const { ERR_FAIL_INDEX_V(int(p_side), 4, 0.0); return data.anchor[p_side]; } -void Control::set_offset(Side p_side, float p_value) { +void Control::set_offset(Side p_side, real_t p_value) { ERR_FAIL_INDEX((int)p_side, 4); data.offset[p_side] = p_value; @@ -1617,7 +1612,7 @@ void Control::set_end(const Size2 &p_point) { _size_changed(); } -float Control::get_offset(Side p_side) const { +real_t Control::get_offset(Side p_side) const { ERR_FAIL_INDEX_V((int)p_side, 4, 0); return data.offset[p_side]; @@ -1660,12 +1655,12 @@ void Control::set_global_position(const Point2 &p_point, bool p_keep_offsets) { set_position(inv.xform(p_point), p_keep_offsets); } -void Control::_compute_anchors(Rect2 p_rect, const float p_offsets[4], float (&r_anchors)[4]) { +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); - float x = p_rect.position.x; + real_t x = p_rect.position.x; if (is_layout_rtl()) { x = parent_rect_size.x - x - p_rect.size.x; } @@ -1675,10 +1670,10 @@ void Control::_compute_anchors(Rect2 p_rect, const float p_offsets[4], float (&r 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 float p_anchors[4], float (&r_offsets)[4]) { +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; - float x = p_rect.position.x; + real_t x = p_rect.position.x; if (is_layout_rtl()) { x = parent_rect_size.x - x - p_rect.size.x; } @@ -1780,53 +1775,38 @@ Rect2 Control::get_anchorable_rect() const { } 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::_override_changed)); } - // clear if "null" is passed instead of an icon - if (p_icon.is_null()) { - data.icon_override.erase(p_name); - } else { - data.icon_override[p_name] = p_icon; - if (data.icon_override[p_name].is_valid()) { - data.icon_override[p_name]->connect("changed", callable_mp(this, &Control::_override_changed), Vector<Variant>(), CONNECT_REFERENCE_COUNTED); - } - } + 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); notification(NOTIFICATION_THEME_CHANGED); } 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::_override_changed)); } - // clear if "null" is passed instead of a style - if (p_style.is_null()) { - data.style_override.erase(p_name); - } else { - data.style_override[p_name] = p_style; - if (data.style_override[p_name].is_valid()) { - data.style_override[p_name]->connect("changed", callable_mp(this, &Control::_override_changed), Vector<Variant>(), CONNECT_REFERENCE_COUNTED); - } - } + 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); notification(NOTIFICATION_THEME_CHANGED); } 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::_override_changed)); } - // clear if "null" is passed instead of a font - if (p_font.is_null()) { - data.font_override.erase(p_name); - } else { - data.font_override[p_name] = p_font; - if (data.font_override[p_name].is_valid()) { - data.font_override[p_name]->connect("changed", callable_mp(this, &Control::_override_changed), Vector<Variant>(), CONNECT_REFERENCE_COUNTED); - } - } + 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); notification(NOTIFICATION_THEME_CHANGED); } @@ -1845,6 +1825,48 @@ void Control::add_theme_constant_override(const StringName &p_name, int p_consta notification(NOTIFICATION_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::_override_changed)); + } + + data.icon_override.erase(p_name); + notification(NOTIFICATION_THEME_CHANGED); +} + +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)); + } + + data.style_override.erase(p_name); + notification(NOTIFICATION_THEME_CHANGED); +} + +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)); + } + + data.font_override.erase(p_name); + notification(NOTIFICATION_THEME_CHANGED); +} + +void Control::remove_theme_font_size_override(const StringName &p_name) { + data.font_size_override.erase(p_name); + notification(NOTIFICATION_THEME_CHANGED); +} + +void Control::remove_theme_color_override(const StringName &p_name) { + data.color_override.erase(p_name); + notification(NOTIFICATION_THEME_CHANGED); +} + +void Control::remove_theme_constant_override(const StringName &p_name) { + data.constant_override.erase(p_name); + notification(NOTIFICATION_THEME_CHANGED); +} + void Control::set_focus_mode(FocusMode p_focus_mode) { ERR_FAIL_INDEX((int)p_focus_mode, 3); @@ -2257,7 +2279,7 @@ Control *Control::_get_focus_neighbor(Side p_side, int p_count) { return c; } - float dist = 1e7; + real_t dist = 1e7; Control *result = nullptr; Point2 points[4]; @@ -2278,10 +2300,10 @@ Control *Control::_get_focus_neighbor(Side p_side, int p_count) { Vector2 vdir = dir[p_side]; - float maxd = -1e7; + real_t maxd = -1e7; for (int i = 0; i < 4; i++) { - float d = vdir.dot(points[i]); + real_t d = vdir.dot(points[i]); if (d > maxd) { maxd = d; } @@ -2308,7 +2330,7 @@ Control *Control::_get_focus_neighbor(Side p_side, int p_count) { return result; } -void Control::_window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, const Point2 *p_points, float p_min, float &r_closest_dist, Control **r_closest) { +void Control::_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) { if (Object::cast_to<Viewport>(p_at)) { return; //bye } @@ -2325,10 +2347,10 @@ void Control::_window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, cons points[2] = xform.xform(c->get_size()); points[3] = xform.xform(Point2(0, c->get_size().y)); - float min = 1e7; + real_t min = 1e7; for (int i = 0; i < 4; i++) { - float d = p_dir.dot(points[i]); + real_t d = p_dir.dot(points[i]); if (d < min) { min = d; } @@ -2344,8 +2366,8 @@ void Control::_window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, cons Vector2 fb = points[(j + 1) % 4]; Vector2 pa, pb; - float d = Geometry2D::get_closest_points_between_segments(la, lb, fa, fb, pa, pb); - //float d = Geometry2D::get_closest_distance_between_segments(Vector3(la.x,la.y,0),Vector3(lb.x,lb.y,0),Vector3(fa.x,fa.y,0),Vector3(fb.x,fb.y,0)); + real_t d = Geometry2D::get_closest_points_between_segments(la, lb, fa, fb, pa, pb); + //real_t d = Geometry2D::get_closest_distance_between_segments(Vector3(la.x,la.y,0),Vector3(lb.x,lb.y,0),Vector3(fa.x,fa.y,0),Vector3(fb.x,fb.y,0)); if (d < r_closest_dist) { r_closest_dist = d; *r_closest = c; @@ -2385,7 +2407,7 @@ void Control::set_v_size_flags(int p_flags) { emit_signal(SceneStringNames::get_singleton()->size_flags_changed); } -void Control::set_stretch_ratio(float p_ratio) { +void Control::set_stretch_ratio(real_t p_ratio) { if (data.expand == p_ratio) { return; } @@ -2394,7 +2416,7 @@ void Control::set_stretch_ratio(float p_ratio) { emit_signal(SceneStringNames::get_singleton()->size_flags_changed); } -float Control::get_stretch_ratio() const { +real_t Control::get_stretch_ratio() const { return data.expand; } @@ -2566,21 +2588,21 @@ Vector<Vector2i> Control::structured_text_parser(StructuredTextParser p_node_typ return ret; } -void Control::set_rotation(float p_radians) { +void Control::set_rotation(real_t p_radians) { data.rotation = p_radians; update(); _notify_transform(); } -float Control::get_rotation() const { +real_t Control::get_rotation() const { return data.rotation; } -void Control::set_rotation_degrees(float p_degrees) { +void Control::set_rotation_degrees(real_t p_degrees) { set_rotation(Math::deg2rad(p_degrees)); } -float Control::get_rotation_degrees() const { +real_t Control::get_rotation_degrees() const { return Math::rad2deg(get_rotation()); } @@ -2799,6 +2821,13 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("add_theme_color_override", "name", "color"), &Control::add_theme_color_override); ClassDB::bind_method(D_METHOD("add_theme_constant_override", "name", "constant"), &Control::add_theme_constant_override); + ClassDB::bind_method(D_METHOD("remove_theme_icon_override", "name"), &Control::remove_theme_icon_override); + ClassDB::bind_method(D_METHOD("remove_theme_stylebox_override", "name"), &Control::remove_theme_style_override); + ClassDB::bind_method(D_METHOD("remove_theme_font_override", "name"), &Control::remove_theme_font_override); + ClassDB::bind_method(D_METHOD("remove_theme_font_size_override", "name"), &Control::remove_theme_font_size_override); + ClassDB::bind_method(D_METHOD("remove_theme_color_override", "name"), &Control::remove_theme_color_override); + ClassDB::bind_method(D_METHOD("remove_theme_constant_override", "name"), &Control::remove_theme_constant_override); + ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "node_type"), &Control::get_theme_icon, DEFVAL("")); ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "node_type"), &Control::get_theme_stylebox, DEFVAL("")); ClassDB::bind_method(D_METHOD("get_theme_font", "name", "node_type"), &Control::get_theme_font, DEFVAL("")); diff --git a/scene/gui/control.h b/scene/gui/control.h index 8981e05872..184b2df6d3 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -171,22 +171,22 @@ private: Size2 last_minimum_size; bool updating_last_minimum_size = false; - float offset[4] = { 0.0, 0.0, 0.0, 0.0 }; - float anchor[4] = { ANCHOR_BEGIN, ANCHOR_BEGIN, ANCHOR_BEGIN, ANCHOR_BEGIN }; + real_t offset[4] = { 0.0, 0.0, 0.0, 0.0 }; + real_t anchor[4] = { ANCHOR_BEGIN, ANCHOR_BEGIN, ANCHOR_BEGIN, ANCHOR_BEGIN }; FocusMode focus_mode = FOCUS_NONE; GrowDirection h_grow = GROW_DIRECTION_END; GrowDirection v_grow = GROW_DIRECTION_END; LayoutDirection layout_dir = LAYOUT_DIRECTION_INHERITED; - float rotation = 0.0; + real_t rotation = 0.0; Vector2 scale = Vector2(1, 1); Vector2 pivot_offset; bool size_warning = true; int h_size_flags = SIZE_FILL; int v_size_flags = SIZE_FILL; - float expand = 1.0; + real_t expand = 1.0; Point2 custom_minimum_size; MouseFilter mouse_filter = MOUSE_FILTER_STOP; @@ -224,10 +224,10 @@ private: // used internally Control *_find_control_at_pos(CanvasItem *p_node, const Point2 &p_pos, const Transform2D &p_xform, Transform2D &r_inv_xform); - void _window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, const Point2 *p_points, float p_min, float &r_closest_dist, Control **r_closest); + 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); - void _set_anchor(Side p_side, float p_anchor); + 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); @@ -239,8 +239,8 @@ private: void _clear_size_warning(); void _update_scroll(); - void _compute_offsets(Rect2 p_rect, const float p_anchors[4], float (&r_offsets)[4]); - void _compute_anchors(Rect2 p_rect, const float p_offsets[4], float (&r_anchors)[4]); + 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; @@ -325,8 +325,8 @@ public: virtual Rect2 _edit_get_rect() const override; virtual bool _edit_use_rect() const override; - virtual void _edit_set_rotation(float p_rotation) override; - virtual float _edit_get_rotation() const override; + virtual void _edit_set_rotation(real_t p_rotation) override; + virtual real_t _edit_get_rotation() const override; virtual bool _edit_use_rotation() const override; virtual void _edit_set_pivot(const Point2 &p_pivot) override; @@ -364,13 +364,13 @@ public: 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_anchor(Side p_side, float p_anchor, bool p_keep_offset = true, bool p_push_opposite_anchor = true); - float get_anchor(Side p_side) const; + 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, float p_value); - float get_offset(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, float p_anchor, float p_pos, bool p_push_opposite_anchor = true); + 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 @@ -395,10 +395,10 @@ public: void set_rect(const Rect2 &p_rect); // Reset anchors to begin and set rect, for faster container children sorting. - void set_rotation(float p_radians); - void set_rotation_degrees(float p_degrees); - float get_rotation() const; - float get_rotation_degrees() const; + void set_rotation(real_t p_radians); + void set_rotation_degrees(real_t p_degrees); + real_t get_rotation() const; + real_t get_rotation_degrees() const; void set_h_grow_direction(GrowDirection p_direction); GrowDirection get_h_grow_direction() const; @@ -421,8 +421,8 @@ public: void set_v_size_flags(int p_flags); int get_v_size_flags() const; - void set_stretch_ratio(float p_ratio); - float get_stretch_ratio() const; + void set_stretch_ratio(real_t p_ratio); + real_t get_stretch_ratio() const; void minimum_size_changed(); @@ -459,6 +459,13 @@ public: void add_theme_color_override(const StringName &p_name, const Color &p_color); void add_theme_constant_override(const StringName &p_name, int p_constant); + void remove_theme_icon_override(const StringName &p_name); + void remove_theme_style_override(const StringName &p_name); + void remove_theme_font_override(const StringName &p_name); + void remove_theme_font_size_override(const StringName &p_name); + void remove_theme_color_override(const StringName &p_name); + void remove_theme_constant_override(const StringName &p_name); + Ref<Texture2D> get_theme_icon(const StringName &p_name, const StringName &p_node_type = StringName()) const; Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_node_type = StringName()) const; Ref<Font> get_theme_font(const StringName &p_name, const StringName &p_node_type = StringName()) const; diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index fdfbf9eafc..b6884bd37d 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -256,7 +256,7 @@ Button *AcceptDialog::add_button(const String &p_text, bool p_right, const Strin Button *AcceptDialog::add_cancel_button(const String &p_cancel) { String c = p_cancel; if (p_cancel == "") { - c = RTR("Cancel"); + c = TTRC("Cancel"); } Button *b = swap_cancel_ok ? add_button(c, true) : add_button(c); b->connect("pressed", callable_mp(this, &AcceptDialog::_cancel_pressed)); @@ -317,13 +317,13 @@ AcceptDialog::AcceptDialog() { hbc->add_spacer(); ok = memnew(Button); - ok->set_text(RTR("OK")); + ok->set_text(TTRC("OK")); hbc->add_child(ok); hbc->add_spacer(); ok->connect("pressed", callable_mp(this, &AcceptDialog::_ok_pressed)); - set_title(RTR("Alert!")); + set_title(TTRC("Alert!")); connect("window_input", callable_mp(this, &AcceptDialog::_input_from_window)); } @@ -342,7 +342,7 @@ Button *ConfirmationDialog::get_cancel_button() { } ConfirmationDialog::ConfirmationDialog() { - set_title(RTR("Please Confirm...")); + set_title(TTRC("Please Confirm...")); #ifdef TOOLS_ENABLED set_min_size(Size2(200, 70) * EDSCALE); #endif diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 7fb5113130..5409b44b9e 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -57,6 +57,14 @@ void FileDialog::_theme_changed() { dir_up->add_theme_color_override("icon_hover_color", font_hover_color); dir_up->add_theme_color_override("icon_pressed_color", font_pressed_color); + dir_prev->add_theme_color_override("icon_color_normal", font_color); + dir_prev->add_theme_color_override("icon_color_hover", font_hover_color); + dir_prev->add_theme_color_override("icon_color_pressed", font_pressed_color); + + dir_next->add_theme_color_override("icon_color_normal", font_color); + dir_next->add_theme_color_override("icon_color_hover", font_hover_color); + dir_next->add_theme_color_override("icon_color_pressed", font_pressed_color); + refresh->add_theme_color_override("icon_normal_color", font_color); refresh->add_theme_color_override("icon_hover_color", font_hover_color); refresh->add_theme_color_override("icon_pressed_color", font_pressed_color); @@ -74,6 +82,13 @@ void FileDialog::_notification(int p_what) { } if (p_what == NOTIFICATION_ENTER_TREE) { dir_up->set_icon(vbox->get_theme_icon("parent_folder", "FileDialog")); + if (vbox->is_layout_rtl()) { + dir_prev->set_icon(vbox->get_theme_icon("forward_folder", "FileDialog")); + dir_next->set_icon(vbox->get_theme_icon("back_folder", "FileDialog")); + } else { + dir_prev->set_icon(vbox->get_theme_icon("back_folder", "FileDialog")); + dir_next->set_icon(vbox->get_theme_icon("forward_folder", "FileDialog")); + } refresh->set_icon(vbox->get_theme_icon("reload", "FileDialog")); show_hidden->set_icon(vbox->get_theme_icon("toggle_hidden", "FileDialog")); _theme_changed(); @@ -81,6 +96,8 @@ void FileDialog::_notification(int p_what) { } void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventKey> k = p_event; if (k.is_valid() && has_focus()) { if (k->is_pressed()) { @@ -144,6 +161,7 @@ void FileDialog::_dir_entered(String p_dir) { file->set_text(""); invalidate(); update_dir(); + _push_history(); } void FileDialog::_file_entered(const String &p_file) { @@ -177,6 +195,21 @@ void FileDialog::_post_popup() { } else { file_box->set_visible(true); } + + local_history.clear(); + local_history_pos = -1; + _push_history(); +} + +void FileDialog::_push_history() { + local_history.resize(local_history_pos + 1); + String new_path = dir_access->get_current_dir(); + if (local_history.size() == 0 || new_path != local_history[local_history_pos]) { + local_history.push_back(new_path); + local_history_pos++; + dir_prev->set_disabled(local_history_pos == 0); + dir_next->set_disabled(true); + } } void FileDialog::_action_pressed() { @@ -272,7 +305,7 @@ void FileDialog::_action_pressed() { } if (dir_access->file_exists(f)) { - confirm_save->set_text(RTR("File exists, overwrite?")); + confirm_save->set_text(TTRC("File exists, overwrite?")); confirm_save->popup_centered(Size2(200, 80)); } else { emit_signal("file_selected", f); @@ -316,6 +349,35 @@ void FileDialog::_go_up() { dir_access->change_dir(".."); update_file_list(); update_dir(); + _push_history(); +} + +void FileDialog::_go_back() { + if (local_history_pos <= 0) { + return; + } + + local_history_pos--; + dir_access->change_dir(local_history[local_history_pos]); + update_file_list(); + update_dir(); + + dir_prev->set_disabled(local_history_pos == 0); + dir_next->set_disabled(local_history_pos == local_history.size() - 1); +} + +void FileDialog::_go_forward() { + if (local_history_pos == local_history.size() - 1) { + return; + } + + local_history_pos++; + dir_access->change_dir(local_history[local_history_pos]); + update_file_list(); + update_dir(); + + dir_prev->set_disabled(local_history_pos == 0); + dir_next->set_disabled(local_history_pos == local_history.size() - 1); } void FileDialog::deselect_all() { @@ -329,10 +391,10 @@ void FileDialog::deselect_all() { switch (mode) { case FILE_MODE_OPEN_FILE: case FILE_MODE_OPEN_FILES: - get_ok_button()->set_text(RTR("Open")); + get_ok_button()->set_text(TTRC("Open")); break; case FILE_MODE_OPEN_DIR: - get_ok_button()->set_text(RTR("Select Current Folder")); + get_ok_button()->set_text(TTRC("Select Current Folder")); break; case FILE_MODE_OPEN_ANY: case FILE_MODE_SAVE_FILE: @@ -356,7 +418,7 @@ void FileDialog::_tree_selected() { if (!d["dir"]) { file->set_text(d["name"]); } else if (mode == FILE_MODE_OPEN_DIR) { - get_ok_button()->set_text(RTR("Select This Folder")); + get_ok_button()->set_text(TTRC("Select This Folder")); } get_ok_button()->set_disabled(_is_open_should_be_disabled()); @@ -377,6 +439,7 @@ void FileDialog::_tree_item_activated() { } call_deferred("_update_file_list"); call_deferred("_update_dir"); + _push_history(); } else { _action_pressed(); } @@ -415,6 +478,13 @@ void FileDialog::update_file_list() { bool is_hidden; String item; + if (dir_access->is_readable(dir_access->get_current_dir().utf8().get_data())) { + message->hide(); + } else { + message->set_text(TTRC("You don't have permission to access contents of this folder.")); + message->show(); + } + while ((item = dir_access->get_next()) != "") { if (item == "." || item == "..") { continue; @@ -549,7 +619,7 @@ void FileDialog::update_filters() { all_filters += ", ..."; } - filter->add_item(RTR("All Recognized") + " (" + all_filters + ")"); + filter->add_item(String(TTRC("All Recognized")) + " (" + all_filters + ")"); } for (int i = 0; i < filters.size(); i++) { String flt = filters[i].get_slice(";", 0).strip_edges(); @@ -561,7 +631,7 @@ void FileDialog::update_filters() { } } - filter->add_item(RTR("All Files (*)")); + filter->add_item(TTRC("All Files (*)")); } void FileDialog::clear_filters() { @@ -602,6 +672,7 @@ void FileDialog::set_current_dir(const String &p_dir) { dir_access->change_dir(p_dir); update_dir(); invalidate(); + _push_history(); } void FileDialog::set_current_file(const String &p_file) { @@ -646,37 +717,37 @@ void FileDialog::set_file_mode(FileMode p_mode) { mode = p_mode; switch (mode) { case FILE_MODE_OPEN_FILE: - get_ok_button()->set_text(RTR("Open")); + get_ok_button()->set_text(TTRC("Open")); if (mode_overrides_title) { - set_title(RTR("Open a File")); + set_title(TTRC("Open a File")); } makedir->hide(); break; case FILE_MODE_OPEN_FILES: - get_ok_button()->set_text(RTR("Open")); + get_ok_button()->set_text(TTRC("Open")); if (mode_overrides_title) { - set_title(RTR("Open File(s)")); + set_title(TTRC("Open File(s)")); } makedir->hide(); break; case FILE_MODE_OPEN_DIR: - get_ok_button()->set_text(RTR("Select Current Folder")); + get_ok_button()->set_text(TTRC("Select Current Folder")); if (mode_overrides_title) { - set_title(RTR("Open a Directory")); + set_title(TTRC("Open a Directory")); } makedir->show(); break; case FILE_MODE_OPEN_ANY: - get_ok_button()->set_text(RTR("Open")); + get_ok_button()->set_text(TTRC("Open")); if (mode_overrides_title) { - set_title(RTR("Open a File or Directory")); + set_title(TTRC("Open a File or Directory")); } makedir->show(); break; case FILE_MODE_SAVE_FILE: - get_ok_button()->set_text(RTR("Save")); + get_ok_button()->set_text(TTRC("Save")); if (mode_overrides_title) { - set_title(RTR("Save a File")); + set_title(TTRC("Save a File")); } makedir->show(); break; @@ -737,6 +808,7 @@ void FileDialog::_make_dir_confirm() { invalidate(); update_filters(); update_dir(); + _push_history(); } else { mkdirerr->popup_centered(Size2(250, 50)); } @@ -754,6 +826,7 @@ void FileDialog::_select_drive(int p_idx) { file->set_text(""); invalidate(); update_dir(); + _push_history(); } void FileDialog::_update_drives() { @@ -857,17 +930,27 @@ FileDialog::FileDialog() { vbox->connect("theme_changed", callable_mp(this, &FileDialog::_theme_changed)); mode = FILE_MODE_SAVE_FILE; - set_title(RTR("Save a File")); + set_title(TTRC("Save a File")); HBoxContainer *hbc = memnew(HBoxContainer); + dir_prev = memnew(Button); + dir_prev->set_flat(true); + dir_prev->set_tooltip(TTRC("Go to previous folder.")); + dir_next = memnew(Button); + dir_next->set_flat(true); + dir_next->set_tooltip(TTRC("Go to next folder.")); dir_up = memnew(Button); dir_up->set_flat(true); - dir_up->set_tooltip(RTR("Go to parent folder.")); + dir_up->set_tooltip(TTRC("Go to parent folder.")); + hbc->add_child(dir_prev); + hbc->add_child(dir_next); hbc->add_child(dir_up); + dir_prev->connect("pressed", callable_mp(this, &FileDialog::_go_back)); + dir_next->connect("pressed", callable_mp(this, &FileDialog::_go_forward)); dir_up->connect("pressed", callable_mp(this, &FileDialog::_go_up)); - hbc->add_child(memnew(Label(RTR("Path:")))); + hbc->add_child(memnew(Label(TTRC("Path:")))); drives_container = memnew(HBoxContainer); hbc->add_child(drives_container); @@ -883,7 +966,7 @@ FileDialog::FileDialog() { refresh = memnew(Button); refresh->set_flat(true); - refresh->set_tooltip(RTR("Refresh files.")); + refresh->set_tooltip(TTRC("Refresh files.")); refresh->connect("pressed", callable_mp(this, &FileDialog::update_file_list)); hbc->add_child(refresh); @@ -891,7 +974,7 @@ FileDialog::FileDialog() { show_hidden->set_flat(true); show_hidden->set_toggle_mode(true); show_hidden->set_pressed(is_showing_hidden_files()); - show_hidden->set_tooltip(RTR("Toggle the visibility of hidden files.")); + show_hidden->set_tooltip(TTRC("Toggle the visibility of hidden files.")); show_hidden->connect("toggled", callable_mp(this, &FileDialog::set_show_hidden_files)); hbc->add_child(show_hidden); @@ -899,17 +982,24 @@ FileDialog::FileDialog() { hbc->add_child(shortcuts_container); makedir = memnew(Button); - makedir->set_text(RTR("Create Folder")); + makedir->set_text(TTRC("Create Folder")); makedir->connect("pressed", callable_mp(this, &FileDialog::_make_dir)); hbc->add_child(makedir); vbox->add_child(hbc); tree = memnew(Tree); tree->set_hide_root(true); - vbox->add_margin_child(RTR("Directories & Files:"), tree, true); + vbox->add_margin_child(TTRC("Directories & Files:"), tree, true); + + message = memnew(Label); + message->hide(); + message->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + message->set_align(Label::ALIGN_CENTER); + message->set_valign(Label::VALIGN_CENTER); + tree->add_child(message); file_box = memnew(HBoxContainer); - file_box->add_child(memnew(Label(RTR("File:")))); + file_box->add_child(memnew(Label(TTRC("File:")))); file = memnew(LineEdit); file->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE); file->set_stretch_ratio(4); @@ -941,22 +1031,22 @@ FileDialog::FileDialog() { confirm_save->connect("confirmed", callable_mp(this, &FileDialog::_save_confirm_pressed)); makedialog = memnew(ConfirmationDialog); - makedialog->set_title(RTR("Create Folder")); + makedialog->set_title(TTRC("Create Folder")); VBoxContainer *makevb = memnew(VBoxContainer); makedialog->add_child(makevb); makedirname = memnew(LineEdit); makedirname->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE); - makevb->add_margin_child(RTR("Name:"), makedirname); + makevb->add_margin_child(TTRC("Name:"), makedirname); add_child(makedialog); makedialog->register_text_enter(makedirname); makedialog->connect("confirmed", callable_mp(this, &FileDialog::_make_dir_confirm)); mkdirerr = memnew(AcceptDialog); - mkdirerr->set_text(RTR("Could not create folder.")); + mkdirerr->set_text(TTRC("Could not create folder.")); add_child(mkdirerr); exterr = memnew(AcceptDialog); - exterr->set_text(RTR("Must use a valid extension.")); + exterr->set_text(TTRC("Must use a valid extension.")); add_child(exterr); update_filters(); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 25b742c234..4996f00cb3 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -86,6 +86,10 @@ private: DirAccess *dir_access; ConfirmationDialog *confirm_save; + Label *message; + + Button *dir_prev; + Button *dir_next; Button *dir_up; Button *refresh; @@ -93,6 +97,10 @@ private: Vector<String> filters; + Vector<String> local_history; + int local_history_pos = 0; + void _push_history(); + bool mode_overrides_title = true; static bool default_show_hidden_files; @@ -119,6 +127,8 @@ private: void _make_dir(); void _make_dir_confirm(); void _go_up(); + void _go_back(); + void _go_forward(); void _update_drives(); diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp index 36b383f16c..e72709e847 100644 --- a/scene/gui/gradient_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -92,6 +92,8 @@ GradientEdit::~GradientEdit() { } void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventKey> k = p_event; if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_DELETE && grabbed != -1) { diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 331f0380c5..06c9cf1b63 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -154,6 +154,8 @@ Vector2 GraphEditMinimap::_convert_to_graph_position(const Vector2 &p_position) } void GraphEditMinimap::_gui_input(const Ref<InputEvent> &p_ev) { + ERR_FAIL_COND(p_ev.is_null()); + if (!ge->is_minimap_enabled()) { return; } @@ -161,7 +163,7 @@ void GraphEditMinimap::_gui_input(const Ref<InputEvent> &p_ev) { Ref<InputEventMouseButton> mb = p_ev; Ref<InputEventMouseMotion> mm = p_ev; - if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->is_pressed()) { is_pressing = true; @@ -180,7 +182,12 @@ void GraphEditMinimap::_gui_input(const Ref<InputEvent> &p_ev) { accept_event(); } else if (mm.is_valid() && is_pressing) { if (is_resizing) { - ge->set_minimap_size(ge->get_minimap_size() - mm->get_relative()); + // Prevent setting minimap wider than GraphEdit + Vector2 new_minimap_size; + new_minimap_size.x = MIN(get_size().x - mm->get_relative().x, ge->get_size().x - 2.0 * minimap_padding.x); + new_minimap_size.y = MIN(get_size().y - mm->get_relative().y, ge->get_size().y - 2.0 * minimap_padding.y); + ge->set_minimap_size(new_minimap_size); + update(); } else { Vector2 click_position = _convert_to_graph_position(mm->get_position() - minimap_padding) - graph_padding; @@ -548,7 +555,7 @@ bool GraphEdit::_filter_input(const Point2 &p_point) { void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { Ref<InputEventMouseButton> mb = p_ev; - if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) { connecting_valid = false; Ref<Texture2D> port = get_theme_icon("port", "GraphNode"); click_pos = mb->get_position() / zoom; @@ -691,7 +698,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { } } - if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && !mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && !mb->is_pressed()) { if (connecting_valid) { if (connecting && connecting_target) { String from = connecting_from; @@ -1061,8 +1068,10 @@ void GraphEdit::set_selected(Node *p_child) { } void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { + ERR_FAIL_COND(p_ev.is_null()); + Ref<InputEventMouseMotion> mm = p_ev; - if (mm.is_valid() && (mm->get_button_mask() & BUTTON_MASK_MIDDLE || (mm->get_button_mask() & BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE)))) { + if (mm.is_valid() && (mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE || (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE)))) { h_scroll->set_value(h_scroll->get_value() - mm->get_relative().x); v_scroll->set_value(v_scroll->get_value() - mm->get_relative().y); } @@ -1118,7 +1127,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { } gn->set_selected(box_selection_mode_additive); } else { - bool select = (previus_selected.find(gn) != nullptr); + bool select = (previous_selected.find(gn) != nullptr); if (gn->is_selected() && !select) { emit_signal("node_deselected", gn); } else if (!gn->is_selected() && select) { @@ -1134,7 +1143,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { Ref<InputEventMouseButton> b = p_ev; if (b.is_valid()) { - if (b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) { + if (b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) { if (box_selecting) { box_selecting = false; for (int i = get_child_count() - 1; i >= 0; i--) { @@ -1143,7 +1152,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { continue; } - bool select = (previus_selected.find(gn) != nullptr); + bool select = (previous_selected.find(gn) != nullptr); if (gn->is_selected() && !select) { emit_signal("node_deselected", gn); } else if (!gn->is_selected() && select) { @@ -1164,7 +1173,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { } } - if (b->get_button_index() == BUTTON_LEFT && !b->is_pressed() && dragging) { + if (b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed() && dragging) { if (!just_selected && drag_accum == Vector2() && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { //deselect current node for (int i = get_child_count() - 1; i >= 0; i--) { @@ -1203,7 +1212,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { connections_layer->update(); } - if (b->get_button_index() == BUTTON_LEFT && b->is_pressed()) { + if (b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed()) { GraphNode *gn = nullptr; for (int i = get_child_count() - 1; i >= 0; i--) { @@ -1268,29 +1277,29 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { box_selecting_from = b->get_position(); if (b->get_control()) { box_selection_mode_additive = true; - previus_selected.clear(); + previous_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { GraphNode *gn2 = Object::cast_to<GraphNode>(get_child(i)); if (!gn2 || !gn2->is_selected()) { continue; } - previus_selected.push_back(gn2); + previous_selected.push_back(gn2); } } else if (b->get_shift()) { box_selection_mode_additive = false; - previus_selected.clear(); + previous_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { GraphNode *gn2 = Object::cast_to<GraphNode>(get_child(i)); if (!gn2 || !gn2->is_selected()) { continue; } - previus_selected.push_back(gn2); + previous_selected.push_back(gn2); } } else { box_selection_mode_additive = true; - previus_selected.clear(); + previous_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { GraphNode *gn2 = Object::cast_to<GraphNode>(get_child(i)); if (!gn2) { @@ -1305,32 +1314,25 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { } } - if (b->get_button_index() == BUTTON_LEFT && !b->is_pressed() && box_selecting) { + if (b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed() && box_selecting) { box_selecting = false; - previus_selected.clear(); + box_selecting_rect = Rect2(); + previous_selected.clear(); top_layer->update(); minimap->update(); } - if (b->get_button_index() == BUTTON_WHEEL_UP && b->is_pressed()) { - //too difficult to get right - //set_zoom(zoom*ZOOM_SCALE); - } - - if (b->get_button_index() == BUTTON_WHEEL_DOWN && b->is_pressed()) { - //too difficult to get right - //set_zoom(zoom/ZOOM_SCALE); - } - if (b->get_button_index() == BUTTON_WHEEL_UP && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + set_zoom_custom(zoom * ZOOM_SCALE, b->get_position()); + } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + set_zoom_custom(zoom / ZOOM_SCALE, b->get_position()); + } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8); - } - if (b->get_button_index() == BUTTON_WHEEL_DOWN && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * b->get_factor() / 8); - } - if (b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_button_index() == BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { + } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT || (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * b->get_factor() / 8); - } - if (b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_button_index() == BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { + } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT || (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * b->get_factor() / 8); } } diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index 8fdf975319..fa3b113705 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -150,7 +150,7 @@ private: Point2 box_selecting_from; Point2 box_selecting_to; Rect2 box_selecting_rect; - List<GraphNode *> previus_selected; + List<GraphNode *> previous_selected; bool setting_scroll_ofs = false; bool right_disconnects = false; diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index c80fc516e8..7d5c53effe 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -804,11 +804,13 @@ Color GraphNode::get_connection_output_color(int p_idx) { } void GraphNode::_gui_input(const Ref<InputEvent> &p_ev) { + ERR_FAIL_COND(p_ev.is_null()); + Ref<InputEventMouseButton> mb = p_ev; if (mb.is_valid()) { ERR_FAIL_COND_MSG(get_parent_control() == nullptr, "GraphNode must be the child of a GraphEdit node."); - if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { Vector2 mpos = Vector2(mb->get_position().x, mb->get_position().y); if (close_rect.size != Size2() && close_rect.has_point(mpos)) { //send focus to parent @@ -831,7 +833,7 @@ void GraphNode::_gui_input(const Ref<InputEvent> &p_ev) { emit_signal("raise_request"); } - if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (!mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { resizing = false; } } diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index fa72599fb3..86d070f9b1 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -530,6 +530,8 @@ Size2 ItemList::Item::get_icon_size() const { } void ItemList::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + double prev_scroll = scroll_bar->get_value(); Ref<InputEventMouseMotion> mm = p_event; @@ -540,7 +542,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (defer_select_single >= 0 && mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && !mb->is_pressed()) { + if (defer_select_single >= 0 && mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && !mb->is_pressed()) { select(defer_select_single, true); emit_signal("multi_selected", defer_select_single, true); @@ -548,7 +550,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { return; } - if (mb.is_valid() && (mb->get_button_index() == BUTTON_LEFT || (allow_rmb_select && mb->get_button_index() == BUTTON_RIGHT)) && mb->is_pressed()) { + if (mb.is_valid() && (mb->get_button_index() == MOUSE_BUTTON_LEFT || (allow_rmb_select && mb->get_button_index() == MOUSE_BUTTON_RIGHT)) && mb->is_pressed()) { search_string = ""; //any mousepress cancels Vector2 pos = mb->get_position(); Ref<StyleBox> bg = get_theme_stylebox("bg"); @@ -594,16 +596,16 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { } } - if (mb->get_button_index() == BUTTON_RIGHT) { + if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) { emit_signal("item_rmb_selected", i, get_local_mouse_position()); } } else { - if (!mb->is_doubleclick() && !mb->get_command() && select_mode == SELECT_MULTI && items[i].selectable && !items[i].disabled && items[i].selected && mb->get_button_index() == BUTTON_LEFT) { + if (!mb->is_doubleclick() && !mb->get_command() && select_mode == SELECT_MULTI && items[i].selectable && !items[i].disabled && items[i].selected && mb->get_button_index() == MOUSE_BUTTON_LEFT) { defer_select_single = i; return; } - if (items[i].selected && mb->get_button_index() == BUTTON_RIGHT) { + if (items[i].selected && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { emit_signal("item_rmb_selected", i, get_local_mouse_position()); } else { bool selected = items[i].selected; @@ -618,7 +620,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { } } - if (mb->get_button_index() == BUTTON_RIGHT) { + if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) { emit_signal("item_rmb_selected", i, get_local_mouse_position()); } else if (/*select_mode==SELECT_SINGLE &&*/ mb->is_doubleclick()) { emit_signal("item_activated", i); @@ -628,7 +630,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { return; } - if (mb->get_button_index() == BUTTON_RIGHT) { + if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) { emit_signal("rmb_clicked", mb->get_position()); return; @@ -637,10 +639,10 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { // Since closest is null, more likely we clicked on empty space, so send signal to interested controls. Allows, for example, implement items deselecting. emit_signal("nothing_selected"); } - if (mb.is_valid() && mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed()) { scroll_bar->set_value(scroll_bar->get_value() - scroll_bar->get_page() * mb->get_factor() / 8); } - if (mb.is_valid() && mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed()) { scroll_bar->set_value(scroll_bar->get_value() + scroll_bar->get_page() * mb->get_factor() / 8); } diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index ce371e3b56..2d8eb3191c 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -215,6 +215,8 @@ void LineEdit::_delete(bool p_word, bool p_all_to_right) { } void LineEdit::_gui_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventMouseButton> b = p_event; if (b.is_valid()) { @@ -222,7 +224,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { // Ignore mouse clicks in IME input mode. return; } - if (b->is_pressed() && b->get_button_index() == BUTTON_RIGHT && context_menu_enabled) { + if (b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_RIGHT && context_menu_enabled) { menu->set_position(get_screen_transform().xform(get_local_mouse_position())); menu->set_size(Vector2(1, 1)); _generate_context_menu(); @@ -232,7 +234,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { return; } - if (b->get_button_index() != BUTTON_LEFT) { + if (b->get_button_index() != MOUSE_BUTTON_LEFT) { return; } @@ -327,7 +329,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { } } - if (m->get_button_mask() & BUTTON_LEFT) { + if (m->get_button_mask() & MOUSE_BUTTON_LEFT) { if (selection.creating) { set_cursor_at_pixel_pos(m->get_position().x); selection_fill_at_cursor(); diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 5acc7e808a..1e9baa77fc 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -34,6 +34,8 @@ #include "scene/main/window.h" void MenuButton::_unhandled_key_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (!_is_focus_owner_in_shorcut_context()) { return; } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index d733c33c5f..44df8eafdc 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -252,6 +252,8 @@ void PopupMenu::_submenu_timeout() { } void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (p_event->is_action("ui_down") && p_event->is_pressed()) { int search_from = mouse_over + 1; if (search_from >= items.size()) { @@ -359,7 +361,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { if (b->is_pressed() || (!b->is_pressed() && during_grabbed_click)) { // Allow activating item by releasing the LMB or any that was down when the popup appeared. // However, if button was not held when opening menu, do not allow release to activate item. - if (button_idx == BUTTON_LEFT || (initial_button_mask & (1 << (button_idx - 1)))) { + if (button_idx == MOUSE_BUTTON_LEFT || (initial_button_mask & (1 << (button_idx - 1)))) { bool was_during_grabbed_click = during_grabbed_click; during_grabbed_click = false; initial_button_mask = 0; @@ -722,6 +724,7 @@ void PopupMenu::_notification(int p_what) { for (int i = 0; i < items.size(); i++) { items.write[i].xl_text = tr(items[i].text); items.write[i].dirty = true; + _shape_item(i); } child_controls_changed(); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index bce30e7cd3..c763ae6bd6 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -760,7 +760,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o //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); + off.y += TS->shaped_text_get_ascent(rid) + l.text_buf->get_spacing_top(); // Draw inlined objects. Array objects = TS->shaped_text_get_objects(rid); for (int i = 0; i < objects.size(); i++) { @@ -1079,7 +1079,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o off.x += glyphs[i].advance; } } - off.y += TS->shaped_text_get_descent(rid); + off.y += TS->shaped_text_get_descent(rid) + l.text_buf->get_spacing_bottom(); } return line_count; @@ -1174,7 +1174,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V } break; } - off.y += TS->shaped_text_get_ascent(rid); + off.y += TS->shaped_text_get_ascent(rid) + l.text_buf->get_spacing_top(); Array objects = TS->shaped_text_get_objects(rid); for (int i = 0; i < objects.size(); i++) { @@ -1238,7 +1238,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V if (rect.has_point(p_click) && !table_hit) { char_pos = TS->shaped_text_hit_test_position(rid, p_click.x - rect.position.x); } - off.y += TS->shaped_text_get_descent(rid); + off.y += TS->shaped_text_get_descent(rid) + l.text_buf->get_spacing_bottom(); } if (char_pos >= 0) { @@ -1469,6 +1469,8 @@ Control::CursorShape RichTextLabel::get_cursor_shape(const Point2 &p_pos) const } void RichTextLabel::_gui_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventMouseButton> b = p_event; if (b.is_valid()) { @@ -1479,7 +1481,7 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) { return; } - if (b->get_button_index() == BUTTON_LEFT) { + if (b->get_button_index() == MOUSE_BUTTON_LEFT) { if (b->is_pressed() && !b->is_doubleclick()) { scroll_updated = false; ItemFrame *c_frame = nullptr; @@ -1564,12 +1566,12 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) { } } - if (b->get_button_index() == BUTTON_WHEEL_UP) { + if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { if (scroll_active) { vscroll->set_value(vscroll->get_value() - vscroll->get_page() * b->get_factor() * 0.5 / 8); } } - if (b->get_button_index() == BUTTON_WHEEL_DOWN) { + if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { if (scroll_active) { vscroll->set_value(vscroll->get_value() + vscroll->get_page() * b->get_factor() * 0.5 / 8); } @@ -3756,7 +3758,9 @@ void RichTextLabel::set_effects(const Vector<Variant> &effects) { custom_effects.push_back(effect); } - parse_bbcode(bbcode); + if ((bbcode != "") && use_bbcode) { + parse_bbcode(bbcode); + } } Vector<Variant> RichTextLabel::get_effects() { @@ -3773,7 +3777,9 @@ void RichTextLabel::install_effect(const Variant effect) { if (rteffect.is_valid()) { custom_effects.push_back(effect); - parse_bbcode(bbcode); + if ((bbcode != "") && use_bbcode) { + parse_bbcode(bbcode); + } } } @@ -3999,14 +4005,16 @@ void RichTextLabel::set_fixed_size_to_width(int p_width) { } Size2 RichTextLabel::get_minimum_size() const { - Size2 size(0, 0); + Ref<StyleBox> style = get_theme_stylebox("normal"); + Size2 size = style->get_minimum_size(); + if (fixed_width != -1) { - size.x = fixed_width; + size.x += fixed_width; } if (fixed_width != -1 || fit_content_height) { const_cast<RichTextLabel *>(this)->_validate_line_caches(main); - size.y = get_content_height(); + size.y += get_content_height(); } return size; diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index f2516e76a5..62276e3af0 100644 --- a/scene/gui/scroll_bar.cpp +++ b/scene/gui/scroll_bar.cpp @@ -42,6 +42,8 @@ void ScrollBar::set_can_focus_by_default(bool p_can_focus) { } void ScrollBar::_gui_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventMouseMotion> m = p_event; if (!m.is_valid() || drag.active) { emit_signal("scrolling"); @@ -52,17 +54,17 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) { if (b.is_valid()) { accept_event(); - if (b->get_button_index() == BUTTON_WHEEL_DOWN && b->is_pressed()) { + if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && b->is_pressed()) { set_value(get_value() + get_page() / 4.0); accept_event(); } - if (b->get_button_index() == BUTTON_WHEEL_UP && b->is_pressed()) { + if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && b->is_pressed()) { set_value(get_value() - get_page() / 4.0); accept_event(); } - if (b->get_button_index() != BUTTON_LEFT) { + if (b->get_button_index() != MOUSE_BUTTON_LEFT) { return; } diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 411891ece8..757a0841ea 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -88,13 +88,15 @@ void ScrollContainer::_cancel_drag() { } void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) { + ERR_FAIL_COND(p_gui_input.is_null()); + double prev_v_scroll = v_scroll->get_value(); double prev_h_scroll = h_scroll->get_value(); Ref<InputEventMouseButton> mb = p_gui_input; if (mb.is_valid()) { - if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed()) { // only horizontal is enabled, scroll horizontally if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->get_shift())) { h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() / 8 * mb->get_factor()); @@ -103,7 +105,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) { } } - if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed()) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed()) { // only horizontal is enabled, scroll horizontally if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->get_shift())) { h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() / 8 * mb->get_factor()); @@ -112,13 +114,13 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) { } } - if (mb->get_button_index() == BUTTON_WHEEL_LEFT && mb->is_pressed()) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT && mb->is_pressed()) { if (h_scroll->is_visible_in_tree()) { h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * mb->get_factor() / 8); } } - if (mb->get_button_index() == BUTTON_WHEEL_RIGHT && mb->is_pressed()) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT && mb->is_pressed()) { if (h_scroll->is_visible_in_tree()) { h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * mb->get_factor() / 8); } @@ -132,7 +134,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) { return; } - if (mb->get_button_index() != BUTTON_LEFT) { + if (mb->get_button_index() != MOUSE_BUTTON_LEFT) { return; } diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index 2239226c78..a407ef21cb 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -46,6 +46,8 @@ Size2 Slider::get_minimum_size() const { } void Slider::_gui_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (!editable) { return; } @@ -53,7 +55,7 @@ void Slider::_gui_input(Ref<InputEvent> p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == BUTTON_LEFT) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->is_pressed()) { Ref<Texture2D> grabber = get_theme_icon(mouse_inside || has_focus() ? "grabber_highlight" : "grabber"); grab.pos = orientation == VERTICAL ? mb->get_position().y : mb->get_position().x; @@ -72,10 +74,10 @@ void Slider::_gui_input(Ref<InputEvent> p_event) { grab.active = false; } } else if (scrollable) { - if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { grab_focus(); set_value(get_value() + get_step()); - } else if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_DOWN) { + } else if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { grab_focus(); set_value(get_value() - get_step()); } diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index d82cc98e01..9dc2afdb2d 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -76,7 +76,7 @@ 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(BUTTON_LEFT)) { + if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT)) { bool up = get_local_mouse_position().y < (get_size().height / 2); set_value(get_value() + (up ? get_step() : -get_step())); @@ -100,6 +100,8 @@ void SpinBox::_release_mouse() { } void SpinBox::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (!is_editable()) { return; } @@ -110,7 +112,7 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) { bool up = mb->get_position().y < (get_size().height / 2); switch (mb->get_button_index()) { - case BUTTON_LEFT: { + case MOUSE_BUTTON_LEFT: { line_edit->grab_focus(); set_value(get_value() + (up ? get_step() : -get_step())); @@ -122,17 +124,17 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) { drag.allowed = true; drag.capture_pos = mb->get_position(); } break; - case BUTTON_RIGHT: { + case MOUSE_BUTTON_RIGHT: { line_edit->grab_focus(); set_value((up ? get_max() : get_min())); } break; - case BUTTON_WHEEL_UP: { + case MOUSE_BUTTON_WHEEL_UP: { if (line_edit->has_focus()) { set_value(get_value() + get_step() * mb->get_factor()); accept_event(); } } break; - case BUTTON_WHEEL_DOWN: { + case MOUSE_BUTTON_WHEEL_DOWN: { if (line_edit->has_focus()) { set_value(get_value() - get_step() * mb->get_factor()); accept_event(); @@ -141,7 +143,7 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) { } } - if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { //set_default_cursor_shape(CURSOR_ARROW); range_click_timer->stop(); _release_mouse(); @@ -150,7 +152,7 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) { + if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { if (drag.enabled) { drag.diff_y += mm->get_relative().y; float diff_y = -0.01 * Math::pow(ABS(drag.diff_y), 1.8f) * SGN(drag.diff_y); diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index d43e195df1..13ff2c5b86 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -207,6 +207,8 @@ void SplitContainer::_notification(int p_what) { } void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (collapsed || !_getch(0) || !_getch(1) || dragger_visibility != DRAGGER_VISIBLE) { return; } @@ -214,7 +216,7 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == BUTTON_LEFT) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->is_pressed()) { int sep = get_theme_constant("separation"); diff --git a/scene/gui/subviewport_container.cpp b/scene/gui/subviewport_container.cpp index 8ffdd269a4..bfc7e29f9c 100644 --- a/scene/gui/subviewport_container.cpp +++ b/scene/gui/subviewport_container.cpp @@ -140,6 +140,8 @@ void SubViewportContainer::_notification(int p_what) { } void SubViewportContainer::_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (Engine::get_singleton()->is_editor_hint()) { return; } @@ -165,6 +167,8 @@ void SubViewportContainer::_input(const Ref<InputEvent> &p_event) { } void SubViewportContainer::_unhandled_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + if (Engine::get_singleton()->is_editor_hint()) { return; } diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 3bf163f670..ff9dafa0f9 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -72,11 +72,13 @@ int TabContainer::_get_top_margin() const { } void TabContainer::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventMouseButton> mb = p_event; Popup *popup = get_popup(); - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { Point2 pos(mb->get_position().x, mb->get_position().y); Size2 size = get_size(); diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp index da1a9698d0..6cbc5890ce 100644 --- a/scene/gui/tabs.cpp +++ b/scene/gui/tabs.cpp @@ -83,11 +83,16 @@ Size2 Tabs::get_minimum_size() const { } } - ms.width = 0; //TODO: should make this optional + if (clip_tabs) { + ms.width = 0; + } + return ms; } void Tabs::_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventMouseMotion> mm = p_event; if (mm.is_valid()) { @@ -105,10 +110,10 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) { highlight_arrow = 0; } } else { - int limit = get_size().width - incr->get_width() - decr->get_width(); - if (pos.x > limit + decr->get_width()) { + int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width(); + if (pos.x > limit_minus_buttons + decr->get_width()) { highlight_arrow = 1; - } else if (pos.x > limit) { + } else if (pos.x > limit_minus_buttons) { highlight_arrow = 0; } } @@ -122,7 +127,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP && !mb->get_command()) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->get_command()) { if (scrolling_enabled && buttons_visible) { if (offset > 0) { offset--; @@ -131,7 +136,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) { } } - if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_DOWN && !mb->get_command()) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->get_command()) { if (scrolling_enabled && buttons_visible) { if (missing_right) { offset++; @@ -140,7 +145,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) { } } - if (rb_pressing && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (rb_pressing && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (rb_hover != -1) { //pressed emit_signal("right_button_pressed", rb_hover); @@ -150,7 +155,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) { update(); } - if (cb_pressing && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (cb_pressing && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (cb_hover != -1) { //pressed emit_signal("tab_closed", cb_hover); @@ -160,7 +165,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) { update(); } - if (mb->is_pressed() && (mb->get_button_index() == BUTTON_LEFT || (select_with_rmb && mb->get_button_index() == BUTTON_RIGHT))) { + if (mb->is_pressed() && (mb->get_button_index() == MOUSE_BUTTON_LEFT || (select_with_rmb && mb->get_button_index() == MOUSE_BUTTON_RIGHT))) { // clicks Point2 pos(mb->get_position().x, mb->get_position().y); @@ -305,7 +310,8 @@ void Tabs::_notification(int p_what) { Ref<Texture2D> incr_hl = get_theme_icon("increment_highlight"); Ref<Texture2D> decr_hl = get_theme_icon("decrement_highlight"); - int limit = get_size().width - incr->get_size().width - decr->get_size().width; + int limit = get_size().width; + int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width(); missing_right = false; @@ -328,7 +334,8 @@ void Tabs::_notification(int p_what) { col = font_unselected_color; } - if (w + lsize > limit) { + int new_width = w + lsize; + if (new_width > limit || (i < tabs.size() - 1 && new_width > limit_minus_buttons)) { // For the last tab, we accept if the tab covers the buttons. max_drawn_tab = i - 1; missing_right = true; break; @@ -459,15 +466,15 @@ void Tabs::_notification(int p_what) { } } else { if (offset > 0) { - draw_texture(highlight_arrow == 0 ? decr_hl : decr, Point2(limit, vofs)); + draw_texture(highlight_arrow == 0 ? decr_hl : decr, Point2(limit_minus_buttons, vofs)); } else { - draw_texture(decr, Point2(limit, vofs), Color(1, 1, 1, 0.5)); + draw_texture(decr, Point2(limit_minus_buttons, vofs), Color(1, 1, 1, 0.5)); } if (missing_right) { - draw_texture(highlight_arrow == 1 ? incr_hl : incr, Point2(limit + decr->get_size().width, vofs)); + draw_texture(highlight_arrow == 1 ? incr_hl : incr, Point2(limit_minus_buttons + decr->get_size().width, vofs)); } else { - draw_texture(incr, Point2(limit + decr->get_size().width, vofs), Color(1, 1, 1, 0.5)); + draw_texture(incr, Point2(limit_minus_buttons + decr->get_size().width, vofs), Color(1, 1, 1, 0.5)); } } @@ -666,7 +673,7 @@ void Tabs::_update_cache() { Ref<StyleBox> tab_selected = get_theme_stylebox("tab_selected"); Ref<Texture2D> incr = get_theme_icon("increment"); Ref<Texture2D> decr = get_theme_icon("decrement"); - int limit = get_size().width - incr->get_width() - decr->get_width(); + int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width(); int w = 0; int mw = 0; @@ -686,7 +693,7 @@ void Tabs::_update_cache() { } int m_width = min_width; if (count_resize > 0) { - m_width = MAX((limit - size_fixed) / count_resize, min_width); + m_width = MAX((limit_minus_buttons - size_fixed) / count_resize, min_width); } for (int i = offset; i < tabs.size(); i++) { Ref<StyleBox> sb; @@ -699,7 +706,7 @@ void Tabs::_update_cache() { } int lsize = tabs[i].size_cache; int slen = tabs[i].size_text; - if (min_width > 0 && mw > limit && i != current) { + if (min_width > 0 && mw > limit_minus_buttons && i != current) { if (lsize > m_width) { slen = m_width - (sb->get_margin(SIDE_LEFT) + sb->get_margin(SIDE_RIGHT)); if (tabs[i].icon.is_valid()) { @@ -909,6 +916,19 @@ Tabs::TabAlign Tabs::get_tab_align() const { return tab_align; } +void Tabs::set_clip_tabs(bool p_clip_tabs) { + if (clip_tabs == p_clip_tabs) { + return; + } + clip_tabs = p_clip_tabs; + update(); + minimum_size_changed(); +} + +bool Tabs::get_clip_tabs() const { + return clip_tabs; +} + void Tabs::move_tab(int from, int to) { if (from == to) { return; @@ -975,7 +995,8 @@ void Tabs::_ensure_no_over_offset() { Ref<Texture2D> incr = get_theme_icon("increment"); Ref<Texture2D> decr = get_theme_icon("decrement"); - int limit = get_size().width - incr->get_width() - decr->get_width(); + int limit = get_size().width; + int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width(); while (offset > 0) { int total_w = 0; @@ -983,7 +1004,7 @@ void Tabs::_ensure_no_over_offset() { total_w += tabs[i].size_cache; } - if (total_w < limit) { + if ((buttons_visible && total_w < limit_minus_buttons) || total_w < limit) { // For the last tab, we accept if the tab covers the buttons. offset--; update(); } else { @@ -1014,9 +1035,12 @@ void Tabs::ensure_tab_visible(int p_idx) { int prev_offset = offset; Ref<Texture2D> incr = get_theme_icon("increment"); Ref<Texture2D> decr = get_theme_icon("decrement"); - int limit = get_size().width - incr->get_width() - decr->get_width(); + int limit = get_size().width; + int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width(); + for (int i = offset; i <= p_idx; i++) { - if (tabs[i].ofs_cache + tabs[i].size_cache > limit) { + int total_w = tabs[i].ofs_cache + tabs[i].size_cache; + if (total_w > limit || (buttons_visible && total_w > limit_minus_buttons)) { offset++; } } @@ -1105,6 +1129,8 @@ void Tabs::_bind_methods() { ClassDB::bind_method(D_METHOD("add_tab", "title", "icon"), &Tabs::add_tab, DEFVAL(""), DEFVAL(Ref<Texture2D>())); ClassDB::bind_method(D_METHOD("set_tab_align", "align"), &Tabs::set_tab_align); ClassDB::bind_method(D_METHOD("get_tab_align"), &Tabs::get_tab_align); + ClassDB::bind_method(D_METHOD("set_clip_tabs", "clip_tabs"), &Tabs::set_clip_tabs); + ClassDB::bind_method(D_METHOD("get_clip_tabs"), &Tabs::get_clip_tabs); ClassDB::bind_method(D_METHOD("get_tab_offset"), &Tabs::get_tab_offset); ClassDB::bind_method(D_METHOD("get_offset_buttons_visible"), &Tabs::get_offset_buttons_visible); ClassDB::bind_method(D_METHOD("ensure_tab_visible", "idx"), &Tabs::ensure_tab_visible); @@ -1131,6 +1157,7 @@ void Tabs::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab"); ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_align", "get_tab_align"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_tabs"), "set_clip_tabs", "get_clip_tabs"); ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrolling_enabled"), "set_scrolling_enabled", "get_scrolling_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_to_rearrange_enabled"), "set_drag_to_rearrange_enabled", "get_drag_to_rearrange_enabled"); diff --git a/scene/gui/tabs.h b/scene/gui/tabs.h index 86877f4d80..61c9a5d96a 100644 --- a/scene/gui/tabs.h +++ b/scene/gui/tabs.h @@ -85,6 +85,7 @@ private: int previous = 0; int _get_top_margin() const; TabAlign tab_align = ALIGN_CENTER; + bool clip_tabs = true; int rb_hover = -1; bool rb_pressing = false; @@ -148,6 +149,9 @@ public: void set_tab_align(TabAlign p_align); TabAlign get_tab_align() const; + void set_clip_tabs(bool p_clip_tabs); + bool get_clip_tabs() const; + void move_tab(int from, int to); void set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 61266f6d22..f54ab004c6 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -357,10 +357,10 @@ void TextEdit::_update_scrollbars() { } void TextEdit::_click_selection_held() { - // Warning: is_mouse_button_pressed(BUTTON_LEFT) returns false for double+ clicks, so this doesn't work for MODE_WORD + // Warning: is_mouse_button_pressed(MOUSE_BUTTON_LEFT) returns false for double+ clicks, so this doesn't work for MODE_WORD // and MODE_LINE. However, moving the mouse triggers _gui_input, which calls these functions too, so that's not a huge problem. // I'm unsure if there's an actual fix that doesn't have a ton of side effects. - if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT) && selection.selecting_mode != SelectionMode::SELECTION_MODE_NONE) { + if (Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT) && selection.selecting_mode != SelectionMode::SELECTION_MODE_NONE) { switch (selection.selecting_mode) { case SelectionMode::SELECTION_MODE_POINTER: { _update_selection_mode_pointer(); @@ -1557,7 +1557,7 @@ void TextEdit::_notification(int p_what) { completion_rect.position.x = rect_left_border_x; } - if (cursor_pos.y + row_height + total_height > get_size().height) { + if (cursor_pos.y + row_height + total_height > get_size().height && cursor_pos.y > total_height) { // Completion panel above the cursor line completion_rect.position.y = cursor_pos.y - total_height; } else { @@ -2854,6 +2854,8 @@ void TextEdit::_get_minimap_mouse_row(const Point2i &p_mouse, int &r_row) const } void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { + ERR_FAIL_COND(p_gui_input.is_null()); + double prev_v_scroll = v_scroll->get_value(); double prev_h_scroll = h_scroll->get_value(); @@ -2873,14 +2875,14 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { return; } - if (mb->get_button_index() == BUTTON_WHEEL_UP) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { if (completion_index > 0) { completion_index--; completion_current = completion_options[completion_index]; update(); } } - if (mb->get_button_index() == BUTTON_WHEEL_DOWN) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { if (completion_index < completion_options.size() - 1) { completion_index++; completion_current = completion_options[completion_index]; @@ -2888,7 +2890,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } } - if (mb->get_button_index() == BUTTON_LEFT) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { completion_index = CLAMP(completion_line_ofs + (mpos.y - completion_rect.position.y) / get_row_height(), 0, completion_options.size() - 1); completion_current = completion_options[completion_index]; @@ -2904,27 +2906,27 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } if (mb->is_pressed()) { - if (mb->get_button_index() == BUTTON_WHEEL_UP && !mb->get_command()) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->get_command()) { if (mb->get_shift()) { h_scroll->set_value(h_scroll->get_value() - (100 * mb->get_factor())); } else if (v_scroll->is_visible()) { _scroll_up(3 * mb->get_factor()); } } - if (mb->get_button_index() == BUTTON_WHEEL_DOWN && !mb->get_command()) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->get_command()) { if (mb->get_shift()) { h_scroll->set_value(h_scroll->get_value() + (100 * mb->get_factor())); } else if (v_scroll->is_visible()) { _scroll_down(3 * mb->get_factor()); } } - if (mb->get_button_index() == BUTTON_WHEEL_LEFT) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT) { h_scroll->set_value(h_scroll->get_value() - (100 * mb->get_factor())); } - if (mb->get_button_index() == BUTTON_WHEEL_RIGHT) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT) { h_scroll->set_value(h_scroll->get_value() + (100 * mb->get_factor())); } - if (mb->get_button_index() == BUTTON_LEFT) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { _reset_caret_blink_timer(); int row, col; @@ -3031,7 +3033,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { update(); } - if (mb->get_button_index() == BUTTON_RIGHT && context_menu_enabled) { + if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && context_menu_enabled) { _reset_caret_blink_timer(); int row, col; @@ -3062,7 +3064,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { grab_focus(); } } else { - if (mb->get_button_index() == BUTTON_LEFT) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->get_command() && highlighted_word != String()) { int row, col; _get_mouse_pos(Point2i(mpos.x, mpos.y), row, col); @@ -3118,7 +3120,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } } - if (mm->get_button_mask() & BUTTON_MASK_LEFT && get_viewport()->gui_get_drag_data() == Variant()) { // Ignore if dragging. + if (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT && get_viewport()->gui_get_drag_data() == Variant()) { // Ignore if dragging. _reset_caret_blink_timer(); if (draw_minimap && !dragging_selection) { diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 6ac4d7fd2f..73fd9dbcd7 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -410,6 +410,14 @@ bool TreeItem::is_collapsed() { return collapsed; } +void TreeItem::uncollapse_tree() { + TreeItem *t = this; + while (t) { + t->set_collapsed(false); + t = t->parent; + } +} + void TreeItem::set_custom_minimum_height(int p_height) { custom_min_height = p_height; _changed_notify(); @@ -842,6 +850,8 @@ void TreeItem::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collapsed", "enable"), &TreeItem::set_collapsed); ClassDB::bind_method(D_METHOD("is_collapsed"), &TreeItem::is_collapsed); + ClassDB::bind_method(D_METHOD("uncollapse_tree"), &TreeItem::uncollapse_tree); + ClassDB::bind_method(D_METHOD("set_custom_minimum_height", "height"), &TreeItem::set_custom_minimum_height); ClassDB::bind_method(D_METHOD("get_custom_minimum_height"), &TreeItem::get_custom_minimum_height); @@ -1578,7 +1588,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 if (p_item->cells[i].custom_button) { if (cache.hover_item == p_item && cache.hover_cell == i) { - if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) { + if (Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT)) { draw_style_box(cache.custom_button_pressed, ir); } else { draw_style_box(cache.custom_button_hover, ir); @@ -1815,7 +1825,7 @@ Rect2 Tree::search_item_rect(TreeItem *p_from, TreeItem *p_item) { } void Tree::_range_click_timeout() { - if (range_item_last && !range_drag_enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) { + if (range_item_last && !range_drag_enabled && Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT)) { Point2 pos = get_local_mouse_position() - cache.bg->get_offset(); if (show_column_titles) { pos.y -= _get_title_button_height(); @@ -1833,7 +1843,7 @@ void Tree::_range_click_timeout() { propagate_mouse_activated = false; // done from outside, so signal handler can't clear the tree in the middle of emit (which is a common case) blocked++; - propagate_mouse_event(pos + cache.offset, 0, 0, false, root, BUTTON_LEFT, mb); + propagate_mouse_event(pos + cache.offset, 0, 0, false, root, MOUSE_BUTTON_LEFT, mb); blocked--; if (range_click_timer->is_one_shot()) { @@ -1950,7 +1960,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool col_width -= w + cache.button_margin; } - if (p_button == BUTTON_LEFT || (p_button == BUTTON_RIGHT && allow_rmb_select)) { + if (p_button == MOUSE_BUTTON_LEFT || (p_button == MOUSE_BUTTON_RIGHT && allow_rmb_select)) { /* process selection */ if (p_doubleclick && (!c.editable || c.mode == TreeItem::CELL_MODE_CUSTOM || c.mode == TreeItem::CELL_MODE_ICON /*|| c.mode==TreeItem::CELL_MODE_CHECK*/)) { //it's confusing for check @@ -1962,10 +1972,10 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool } if (select_mode == SELECT_MULTI && p_mod->get_command() && c.selectable) { - if (!c.selected || p_button == BUTTON_RIGHT) { + if (!c.selected || p_button == MOUSE_BUTTON_RIGHT) { p_item->select(col); emit_signal("multi_selected", p_item, col, true); - if (p_button == BUTTON_RIGHT) { + if (p_button == MOUSE_BUTTON_RIGHT) { emit_signal("item_rmb_selected", get_local_mouse_position()); } @@ -1982,21 +1992,21 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool bool inrange = false; select_single_item(p_item, root, col, selected_item, &inrange); - if (p_button == BUTTON_RIGHT) { + if (p_button == MOUSE_BUTTON_RIGHT) { emit_signal("item_rmb_selected", get_local_mouse_position()); } } else { int icount = _count_selected_items(root); - if (select_mode == SELECT_MULTI && icount > 1 && p_button != BUTTON_RIGHT) { + if (select_mode == SELECT_MULTI && icount > 1 && p_button != MOUSE_BUTTON_RIGHT) { single_select_defer = p_item; single_select_defer_column = col; } else { - if (p_button != BUTTON_RIGHT || !c.selected) { + if (p_button != MOUSE_BUTTON_RIGHT || !c.selected) { select_single_item(p_item, root, col); } - if (p_button == BUTTON_RIGHT) { + if (p_button == MOUSE_BUTTON_RIGHT) { emit_signal("item_rmb_selected", get_local_mouse_position()); } } @@ -2066,7 +2076,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool /* touching the combo */ bool up = p_pos.y < (item_h / 2); - if (p_button == BUTTON_LEFT) { + if (p_button == MOUSE_BUTTON_LEFT) { if (range_click_timer->get_time_left() == 0) { range_item_last = p_item; range_up_last = up; @@ -2083,13 +2093,13 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool item_edited(col, p_item); - } else if (p_button == BUTTON_RIGHT) { + } else if (p_button == MOUSE_BUTTON_RIGHT) { p_item->set_range(col, (up ? c.max : c.min)); item_edited(col, p_item); - } else if (p_button == BUTTON_WHEEL_UP) { + } else if (p_button == MOUSE_BUTTON_WHEEL_UP) { p_item->set_range(col, c.val + c.step); item_edited(col, p_item); - } else if (p_button == BUTTON_WHEEL_DOWN) { + } else if (p_button == MOUSE_BUTTON_WHEEL_DOWN) { p_item->set_range(col, c.val - c.step); item_edited(col, p_item); } @@ -2122,14 +2132,14 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool } if (!p_item->cells[col].custom_button || !on_arrow) { - item_edited(col, p_item, p_button == BUTTON_LEFT); + item_edited(col, p_item, p_button == MOUSE_BUTTON_LEFT); } click_handled = true; return -1; } break; }; - if (!bring_up_editor || p_button != BUTTON_LEFT) { + if (!bring_up_editor || p_button != MOUSE_BUTTON_LEFT) { return -1; } @@ -2169,7 +2179,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool item_h += child_h; } } - if (p_item == root && p_button == BUTTON_RIGHT) { + if (p_item == root && p_button == MOUSE_BUTTON_RIGHT) { emit_signal("empty_rmb", get_local_mouse_position()); } } @@ -2392,6 +2402,8 @@ void Tree::_go_down() { } void Tree::_gui_input(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + Ref<InputEventKey> k = p_event; bool is_command = k.is_valid() && k->get_command(); @@ -2710,7 +2722,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { bool rtl = is_layout_rtl(); if (!b->is_pressed()) { - if (b->get_button_index() == BUTTON_LEFT) { + if (b->get_button_index() == MOUSE_BUTTON_LEFT) { Point2 pos = b->get_position(); if (rtl) { pos.x = get_size().width - pos.x; @@ -2791,8 +2803,8 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { } switch (b->get_button_index()) { - case BUTTON_RIGHT: - case BUTTON_LEFT: { + case MOUSE_BUTTON_RIGHT: + case MOUSE_BUTTON_LEFT: { Ref<StyleBox> bg = cache.bg; Point2 pos = b->get_position(); @@ -2805,7 +2817,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { pos.y -= _get_title_button_height(); if (pos.y < 0) { - if (b->get_button_index() == BUTTON_LEFT) { + if (b->get_button_index() == MOUSE_BUTTON_LEFT) { pos.x += cache.offset.x; int len = 0; for (int i = 0; i < columns.size(); i++) { @@ -2823,7 +2835,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { } } if (!root || (!root->get_children() && hide_root)) { - if (b->get_button_index() == BUTTON_RIGHT && allow_rmb_select) { + if (b->get_button_index() == MOUSE_BUTTON_RIGHT && allow_rmb_select) { emit_signal("empty_tree_rmb_selected", get_local_mouse_position()); } break; @@ -2844,7 +2856,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { } } - if (b->get_button_index() == BUTTON_RIGHT) { + if (b->get_button_index() == MOUSE_BUTTON_RIGHT) { break; } @@ -2867,7 +2879,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { set_physics_process_internal(true); } - if (b->get_button_index() == BUTTON_LEFT) { + if (b->get_button_index() == MOUSE_BUTTON_LEFT) { if (get_item_at_position(b->get_position()) == nullptr && !b->get_shift() && !b->get_control() && !b->get_command()) { emit_signal("nothing_selected"); } @@ -2880,7 +2892,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { } } break; - case BUTTON_WHEEL_UP: { + case MOUSE_BUTTON_WHEEL_UP: { double prev_value = v_scroll->get_value(); v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8); if (v_scroll->get_value() != prev_value) { @@ -2888,7 +2900,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { } } break; - case BUTTON_WHEEL_DOWN: { + case MOUSE_BUTTON_WHEEL_DOWN: { double prev_value = v_scroll->get_value(); v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * b->get_factor() / 8); if (v_scroll->get_value() != prev_value) { @@ -3506,9 +3518,13 @@ int Tree::get_column_width(int p_column) const { return columns[p_column].min_width; } + int expand_area = get_size().width; + Ref<StyleBox> bg = cache.bg; - int expand_area = get_size().width - (bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT)); + if (bg.is_valid()) { + expand_area -= bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT); + } if (v_scroll->is_visible_in_tree()) { expand_area -= v_scroll->get_combined_minimum_size().width; diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 1be21cb4a4..d1407e24d4 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -229,6 +229,8 @@ public: void set_collapsed(bool p_collapsed); bool is_collapsed(); + void uncollapse_tree(); + void set_custom_minimum_height(int p_height); int get_custom_minimum_height() const; diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 90bc99a941..55529517f1 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -729,13 +729,13 @@ void CanvasItem::item_rect_changed(bool p_size_changed) { emit_signal(SceneStringNames::get_singleton()->item_rect_changed); } -void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width) { +void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width); } -void CanvasItem::draw_polyline(const Vector<Point2> &p_points, const Color &p_color, float p_width, bool p_antialiased) { +void CanvasItem::draw_polyline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width, bool p_antialiased) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); Vector<Color> colors; @@ -743,25 +743,25 @@ void CanvasItem::draw_polyline(const Vector<Point2> &p_points, const Color &p_co RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, colors, p_width, p_antialiased); } -void CanvasItem::draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) { +void CanvasItem::draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width, bool p_antialiased) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, p_colors, p_width, p_antialiased); } -void CanvasItem::draw_arc(const Vector2 &p_center, float p_radius, float p_start_angle, float p_end_angle, int p_point_count, const Color &p_color, float p_width, bool p_antialiased) { +void CanvasItem::draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_start_angle, real_t p_end_angle, int p_point_count, const Color &p_color, real_t p_width, bool p_antialiased) { Vector<Point2> points; points.resize(p_point_count); - const float delta_angle = p_end_angle - p_start_angle; + const real_t delta_angle = p_end_angle - p_start_angle; for (int i = 0; i < p_point_count; i++) { - float theta = (i / (p_point_count - 1.0f)) * delta_angle + p_start_angle; + real_t theta = (i / (p_point_count - 1.0f)) * delta_angle + p_start_angle; points.set(i, p_center + Vector2(Math::cos(theta), Math::sin(theta)) * p_radius); } draw_polyline(points, p_color, p_width, p_antialiased); } -void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_color, float p_width) { +void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); Vector<Color> colors; @@ -769,13 +769,13 @@ void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_c RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, colors, p_width); } -void CanvasItem::draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) { +void CanvasItem::draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, p_colors, p_width); } -void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled, float p_width) { +void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled, real_t p_width) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); if (p_filled) { @@ -787,7 +787,7 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil } else { // Thick lines are offset depending on their width to avoid partial overlapping. // Thin lines don't require an offset, so don't apply one in this case - float offset; + real_t offset; if (p_width >= 2) { offset = p_width / 2.0; } else { @@ -821,7 +821,7 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil } } -void CanvasItem::draw_circle(const Point2 &p_pos, float p_radius, const Color &p_color) { +void CanvasItem::draw_circle(const Point2 &p_pos, real_t p_radius, const Color &p_color) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius, p_color); @@ -856,14 +856,14 @@ void CanvasItem::draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p p_style_box->draw(canvas_item, p_rect); } -void CanvasItem::draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture, float p_width) { +void CanvasItem::draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture, real_t p_width) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); RenderingServer::get_singleton()->canvas_item_add_primitive(canvas_item, p_points, p_colors, p_uvs, rid, p_width); } -void CanvasItem::draw_set_transform(const Point2 &p_offset, float p_rot, const Size2 &p_scale) { +void CanvasItem::draw_set_transform(const Point2 &p_offset, real_t p_rot, const Size2 &p_scale) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); Transform2D xform(p_rot, p_offset); @@ -907,19 +907,19 @@ 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, HAlign p_align, float p_width, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint8_t p_flags) const { +void CanvasItem::draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align, real_t p_width, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint8_t p_flags) 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_align, p_width, p_size, p_modulate, p_outline_size, p_outline_modulate, p_flags); } -void CanvasItem::draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align, float p_width, int p_max_lines, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint8_t p_flags) const { +void CanvasItem::draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align, real_t p_width, int p_max_lines, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint8_t p_flags) 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_align, p_width, p_max_lines, p_size, p_modulate, p_outline_size, p_outline_modulate, p_flags); } -float CanvasItem::draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate) const { +real_t CanvasItem::draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate) const { ERR_FAIL_COND_V_MSG(!drawing, 0.f, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND_V(p_font.is_null(), 0.f); ERR_FAIL_COND_V(p_char.length() != 1, 0.f); @@ -1441,6 +1441,7 @@ void CanvasTexture::set_specular_texture(const Ref<Texture2D> &p_specular) { RID tex_rid = specular_texture.is_valid() ? specular_texture->get_rid() : RID(); RS::get_singleton()->canvas_texture_set_channel(canvas_texture, RS::CANVAS_TEXTURE_CHANNEL_SPECULAR, tex_rid); } + Ref<Texture2D> CanvasTexture::get_specular_texture() const { return specular_texture; } @@ -1449,15 +1450,17 @@ void CanvasTexture::set_specular_color(const Color &p_color) { specular = p_color; RS::get_singleton()->canvas_texture_set_shading_parameters(canvas_texture, specular, shininess); } + Color CanvasTexture::get_specular_color() const { return specular; } -void CanvasTexture::set_specular_shininess(float p_shininess) { +void CanvasTexture::set_specular_shininess(real_t p_shininess) { shininess = p_shininess; RS::get_singleton()->canvas_texture_set_shading_parameters(canvas_texture, specular, shininess); } -float CanvasTexture::get_specular_shininess() const { + +real_t CanvasTexture::get_specular_shininess() const { return shininess; } @@ -1508,9 +1511,9 @@ bool CanvasTexture::has_alpha() const { } } -Ref<Image> CanvasTexture::get_data() const { +Ref<Image> CanvasTexture::get_image() const { if (diffuse_texture.is_valid()) { - return diffuse_texture->get_data(); + return diffuse_texture->get_image(); } else { return Ref<Image>(); } diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index e22f93a7ea..1c64cafab8 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -290,8 +290,8 @@ public: // Used to rotate the node virtual bool _edit_use_rotation() const { return false; }; - virtual void _edit_set_rotation(float p_rotation) {} - virtual float _edit_get_rotation() const { return 0.0; }; + virtual void _edit_set_rotation(real_t p_rotation) {} + virtual real_t _edit_get_rotation() const { return 0.0; }; // Used to resize/move the node virtual bool _edit_use_rect() const { return false; }; // MAYBE REPLACE BY A _edit_get_editmode() @@ -331,30 +331,30 @@ public: /* DRAWING API */ - void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0); - void draw_polyline(const Vector<Point2> &p_points, const Color &p_color, float p_width = 1.0, bool p_antialiased = false); - void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false); - void draw_arc(const Vector2 &p_center, float p_radius, float p_start_angle, float p_end_angle, int p_point_count, const Color &p_color, float p_width = 1.0, bool p_antialiased = false); - void draw_multiline(const Vector<Point2> &p_points, const Color &p_color, float p_width = 1.0); - void draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0); - void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true, float p_width = 1.0); - void draw_circle(const Point2 &p_pos, float p_radius, const Color &p_color); + void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = 1.0); + void draw_polyline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width = 1.0, bool p_antialiased = false); + void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width = 1.0, bool p_antialiased = false); + void draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_start_angle, real_t p_end_angle, int p_point_count, const Color &p_color, real_t p_width = 1.0, bool p_antialiased = false); + void draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width = 1.0); + void draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width = 1.0); + void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true, real_t p_width = 1.0); + void draw_circle(const Point2 &p_pos, real_t p_radius, const Color &p_color); void draw_texture(const Ref<Texture2D> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1)); void draw_texture_rect(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false); void draw_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false); void draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect); - void draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture = Ref<Texture2D>(), float p_width = 1); + void draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture = Ref<Texture2D>(), real_t p_width = 1); void draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture2D> p_texture = Ref<Texture2D>()); void draw_colored_polygon(const Vector<Point2> &p_points, const Color &p_color, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture2D> p_texture = Ref<Texture2D>()); 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, HAlign p_align = HALIGN_LEFT, float p_width = -1, int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint8_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const; - void draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, float p_width = -1, int p_max_lines = -1, int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint8_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const; - float draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next = "", int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0)) const; + void draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint8_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const; + void draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_max_lines = -1, int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint8_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const; + real_t draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next = "", int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0)) const; - void draw_set_transform(const Point2 &p_offset, float p_rot = 0.0, const Size2 &p_scale = Size2(1.0, 1.0)); + void draw_set_transform(const Point2 &p_offset, real_t p_rot = 0.0, const Size2 &p_scale = Size2(1.0, 1.0)); void draw_set_transform_matrix(const Transform2D &p_matrix); static CanvasItem *get_current_item_drawn(); @@ -437,7 +437,7 @@ class CanvasTexture : public Texture2D { Ref<Texture2D> normal_texture; Ref<Texture2D> specular_texture; Color specular = Color(1, 1, 1, 1); - float shininess = 1.0; + real_t shininess = 1.0; RID canvas_texture; @@ -460,8 +460,8 @@ public: void set_specular_color(const Color &p_color); Color get_specular_color() const; - void set_specular_shininess(float p_shininess); - float get_specular_shininess() const; + void set_specular_shininess(real_t p_shininess); + real_t get_specular_shininess() const; void set_texture_filter(CanvasItem::TextureFilter p_filter); CanvasItem::TextureFilter get_texture_filter() const; @@ -475,7 +475,7 @@ public: virtual bool is_pixel_opaque(int p_x, int p_y) const override; virtual bool has_alpha() const override; - virtual Ref<Image> get_data() const override; + virtual Ref<Image> get_image() const override; virtual RID get_rid() const override; diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index e4ed5c6e6c..64df37654b 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -454,7 +454,7 @@ void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArra is_compressed = false; } - const PackedByteArray *data = NULL; + const PackedByteArray *data = nullptr; if (accept_gzip && is_compressed && p_data.size() > 0) { // Decompress request body diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 933f67db68..27712242d1 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1690,7 +1690,7 @@ NodePath Node::get_path_to(const Node *p_node) const { n = n->data.parent; } - path.invert(); + path.reverse(); return NodePath(path, false); } @@ -1711,7 +1711,7 @@ NodePath Node::get_path() const { n = n->data.parent; } - path.invert(); + path.reverse(); data.path_cache = memnew(NodePath(path, true)); @@ -1968,8 +1968,9 @@ Node *Node::get_deepest_editable_node(Node *p_start_node) const { Node *node = p_start_node; while (iterated_item->get_owner() && iterated_item->get_owner() != this) { - if (!is_editable_instance(iterated_item->get_owner())) + if (!is_editable_instance(iterated_item->get_owner())) { node = iterated_item->get_owner(); + } iterated_item = iterated_item->get_owner(); } diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 9aaddfd373..66f3a2ebde 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -389,6 +389,7 @@ void SceneTree::set_group(const StringName &p_group, const String &p_name, const } void SceneTree::initialize() { + ERR_FAIL_COND(!root); initialized = true; root->_set_tree(this); MainLoop::initialize(); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index e4cda4b96f..a2047261f5 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -131,7 +131,7 @@ bool ViewportTexture::has_alpha() const { return false; } -Ref<Image> ViewportTexture::get_data() const { +Ref<Image> ViewportTexture::get_image() const { ERR_FAIL_COND_V_MSG(!vp, Ref<Image>(), "Viewport Texture must be set to use it."); return RS::get_singleton()->texture_2d_get(vp->texture_rid); } @@ -1621,10 +1621,10 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu Ref<InputEventMouseButton> mb = p_input; bool cant_stop_me_now = (mb.is_valid() && - (mb->get_button_index() == BUTTON_WHEEL_DOWN || - mb->get_button_index() == BUTTON_WHEEL_UP || - mb->get_button_index() == BUTTON_WHEEL_LEFT || - mb->get_button_index() == BUTTON_WHEEL_RIGHT)); + (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN || + mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP || + mb->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT || + mb->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT)); Ref<InputEventPanGesture> pn = p_input; cant_stop_me_now = pn.is_valid() || cant_stop_me_now; @@ -1860,7 +1860,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { gui.mouse_focus_mask = 1 << (mb->get_button_index() - 1); - if (mb->get_button_index() == BUTTON_LEFT) { + if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { gui.drag_accum = Vector2(); gui.drag_attempted = false; } @@ -1883,7 +1883,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { } #endif - if (mb->get_button_index() == BUTTON_LEFT) { //assign focus + if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { //assign focus CanvasItem *ci = gui.mouse_focus; while (ci) { Control *control = Object::cast_to<Control>(ci); @@ -1914,7 +1914,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { set_input_as_handled(); - if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == BUTTON_LEFT) { + if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == MOUSE_BUTTON_LEFT) { //alternate drop use (when using force_drag(), as proposed by #5342 if (gui.mouse_focus) { _gui_drop(gui.mouse_focus, pos, false); @@ -1934,7 +1934,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { _gui_cancel_tooltip(); } else { - if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == BUTTON_LEFT) { + if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (gui.drag_mouse_over) { _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, false); } @@ -1978,7 +1978,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { _gui_call_input(mouse_focus, mb); } - /*if (gui.drag_data.get_type()!=Variant::NIL && mb->get_button_index()==BUTTON_LEFT) { + /*if (gui.drag_data.get_type()!=Variant::NIL && mb->get_button_index()==MOUSE_BUTTON_LEFT) { _propagate_viewport_notification(this,NOTIFICATION_DRAG_END); gui.drag_data=Variant(); //always clear }*/ @@ -2022,7 +2022,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { Control *over = nullptr; // D&D - if (!gui.drag_attempted && gui.mouse_focus && mm->get_button_mask() & BUTTON_MASK_LEFT) { + if (!gui.drag_attempted && gui.mouse_focus && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { gui.drag_accum += mm->get_relative(); float len = gui.drag_accum.length(); if (len > 10) { @@ -2266,7 +2266,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { Transform2D localizer = gui.drag_mouse_over->get_global_transform_with_canvas().affine_inverse(); gui.drag_mouse_over_pos = localizer.xform(viewport_pos); - if (mm->get_button_mask() & BUTTON_MASK_LEFT) { + if (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { bool can_drop = _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, true); if (!can_drop) { @@ -2783,7 +2783,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND_V(gui.subwindow_focused == nullptr, false); Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (gui.subwindow_drag == SUB_WINDOW_DRAG_CLOSE) { if (gui.subwindow_drag_close_rect.has_point(mb->get_position())) { //close window @@ -2908,7 +2908,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; //if the event is a mouse button, we need to check whether another window was clicked - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { bool click_on_window = false; for (int i = gui.sub_windows.size() - 1; i >= 0; i--) { SubWindow &sw = gui.sub_windows.write[i]; @@ -3067,6 +3067,7 @@ void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) { } void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords) { + ERR_FAIL_COND(p_event.is_null()); ERR_FAIL_COND(!is_inside_tree()); if (disable_input || !_can_consume_input_events()) { @@ -3227,8 +3228,9 @@ Viewport::ScreenSpaceAA Viewport::get_screen_space_aa() const { } void Viewport::set_use_debanding(bool p_use_debanding) { - if (use_debanding == p_use_debanding) + if (use_debanding == p_use_debanding) { return; + } use_debanding = p_use_debanding; RS::get_singleton()->viewport_set_use_debanding(viewport, p_use_debanding); } diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 0f11e6fb19..8e79b50385 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -77,7 +77,7 @@ public: virtual bool has_alpha() const override; - virtual Ref<Image> get_data() const override; + virtual Ref<Image> get_image() const override; ViewportTexture(); ~ViewportTexture(); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index d697a1a5dd..bacb0030bb 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -232,7 +232,7 @@ void Window::_make_window() { 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_title(title, window_id); + DisplayServer::get_singleton()->window_set_title(tr(title), window_id); DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id); _update_window_size(); @@ -759,6 +759,10 @@ void Window::_notification(int p_what) { } } + if (p_what == NOTIFICATION_TRANSLATION_CHANGED) { + child_controls_changed(); + } + if (p_what == NOTIFICATION_EXIT_TREE) { if (transient) { _clear_transient(); @@ -893,12 +897,13 @@ void Window::_window_input(const Ref<InputEvent> &p_ev) { } if (exclusive_child != nullptr) { + /* Window *focus_target = exclusive_child; focus_target->grab_focus(); while (focus_target->exclusive_child != nullptr) { focus_target = focus_target->exclusive_child; focus_target->grab_focus(); - } + }*/ if (!is_embedding_subwindows()) { //not embedding, no need for event return; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index fe8591e3d9..232ad278dd 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -532,6 +532,7 @@ void register_scene_types() { ClassDB::register_virtual_class<VisualShaderNodeResizableBase>(); ClassDB::register_virtual_class<VisualShaderNodeGroupBase>(); ClassDB::register_virtual_class<VisualShaderNodeConstant>(); + ClassDB::register_class<VisualShaderNodeComment>(); ClassDB::register_class<VisualShaderNodeFloatConstant>(); ClassDB::register_class<VisualShaderNodeIntConstant>(); ClassDB::register_class<VisualShaderNodeBooleanConstant>(); @@ -955,9 +956,9 @@ void register_scene_types() { bool default_theme_hidpi = GLOBAL_DEF("gui/theme/use_hidpi", false); ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/use_hidpi", PropertyInfo(Variant::BOOL, "gui/theme/use_hidpi", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); - String theme_path = GLOBAL_DEF("gui/theme/custom", ""); + String theme_path = GLOBAL_DEF_RST("gui/theme/custom", ""); ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom", PropertyInfo(Variant::STRING, "gui/theme/custom", PROPERTY_HINT_FILE, "*.tres,*.res,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); - String font_path = GLOBAL_DEF("gui/theme/custom_font", ""); + String font_path = GLOBAL_DEF_RST("gui/theme/custom_font", ""); ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res,*.font", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); Ref<Font> font; diff --git a/scene/resources/concave_polygon_shape_3d.cpp b/scene/resources/concave_polygon_shape_3d.cpp index f067695d7d..3fed700383 100644 --- a/scene/resources/concave_polygon_shape_3d.cpp +++ b/scene/resources/concave_polygon_shape_3d.cpp @@ -35,13 +35,12 @@ Vector<Vector3> ConcavePolygonShape3D::get_debug_mesh_lines() const { Set<DrawEdge> edges; - Vector<Vector3> data = get_faces(); - int datalen = data.size(); - ERR_FAIL_COND_V((datalen % 3) != 0, Vector<Vector3>()); + int index_count = faces.size(); + ERR_FAIL_COND_V((index_count % 3) != 0, Vector<Vector3>()); - const Vector3 *r = data.ptr(); + const Vector3 *r = faces.ptr(); - for (int i = 0; i < datalen; i += 3) { + for (int i = 0; i < index_count; i += 3) { for (int j = 0; j < 3; j++) { DrawEdge de(r[i + j], r[i + ((j + 1) % 3)]); edges.insert(de); @@ -71,22 +70,46 @@ real_t ConcavePolygonShape3D::get_enclosing_radius() const { } void ConcavePolygonShape3D::_update_shape() { + Dictionary d; + d["faces"] = faces; + d["backface_collision"] = backface_collision; + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), d); + Shape3D::_update_shape(); } void ConcavePolygonShape3D::set_faces(const Vector<Vector3> &p_faces) { - PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), p_faces); + faces = p_faces; + _update_shape(); notify_change_to_owners(); } Vector<Vector3> ConcavePolygonShape3D::get_faces() const { - return PhysicsServer3D::get_singleton()->shape_get_data(get_shape()); + return faces; +} + +void ConcavePolygonShape3D::set_backface_collision_enabled(bool p_enabled) { + backface_collision = p_enabled; + + if (!faces.is_empty()) { + _update_shape(); + notify_change_to_owners(); + } +} + +bool ConcavePolygonShape3D::is_backface_collision_enabled() const { + return backface_collision; } void ConcavePolygonShape3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_faces", "faces"), &ConcavePolygonShape3D::set_faces); ClassDB::bind_method(D_METHOD("get_faces"), &ConcavePolygonShape3D::get_faces); + + ClassDB::bind_method(D_METHOD("set_backface_collision_enabled", "enabled"), &ConcavePolygonShape3D::set_backface_collision_enabled); + ClassDB::bind_method(D_METHOD("is_backface_collision_enabled"), &ConcavePolygonShape3D::is_backface_collision_enabled); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_faces", "get_faces"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "backface_collision"), "set_backface_collision_enabled", "is_backface_collision_enabled"); } ConcavePolygonShape3D::ConcavePolygonShape3D() : diff --git a/scene/resources/concave_polygon_shape_3d.h b/scene/resources/concave_polygon_shape_3d.h index 391459a3d7..bb28359dcc 100644 --- a/scene/resources/concave_polygon_shape_3d.h +++ b/scene/resources/concave_polygon_shape_3d.h @@ -36,6 +36,9 @@ class ConcavePolygonShape3D : public Shape3D { GDCLASS(ConcavePolygonShape3D, Shape3D); + Vector<Vector3> faces; + bool backface_collision = false; + struct DrawEdge { Vector3 a; Vector3 b; @@ -65,6 +68,9 @@ public: void set_faces(const Vector<Vector3> &p_faces); Vector<Vector3> get_faces() const; + void set_backface_collision_enabled(bool p_enabled); + bool is_backface_collision_enabled() const; + virtual Vector<Vector3> get_debug_mesh_lines() const override; virtual real_t get_enclosing_radius() const override; diff --git a/scene/resources/convex_polygon_shape_2d.cpp b/scene/resources/convex_polygon_shape_2d.cpp index 6e56f6e7fc..ac31315858 100644 --- a/scene/resources/convex_polygon_shape_2d.cpp +++ b/scene/resources/convex_polygon_shape_2d.cpp @@ -41,7 +41,7 @@ bool ConvexPolygonShape2D::_edit_is_selected_on_click(const Point2 &p_point, dou void ConvexPolygonShape2D::_update_shape() { Vector<Vector2> final_points = points; if (Geometry2D::is_polygon_clockwise(final_points)) { //needs to be counter clockwise - final_points.invert(); + final_points.reverse(); } PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), final_points); emit_changed(); diff --git a/scene/resources/default_theme/checked_disabled.png b/scene/resources/default_theme/checked_disabled.png Binary files differnew file mode 100644 index 0000000000..70549e2edc --- /dev/null +++ b/scene/resources/default_theme/checked_disabled.png diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 0c661cc17d..85d097aa19 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -114,7 +114,7 @@ static Ref<Texture2D> flip_icon(Ref<Texture2D> p_texture, bool p_flip_y = false, } Ref<ImageTexture> texture(memnew(ImageTexture)); - Ref<Image> img = p_texture->get_data(); + Ref<Image> img = p_texture->get_image(); img = img->duplicate(); if (p_flip_y) { @@ -348,9 +348,13 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("focus", "CheckBox", cbx_focus); theme->set_icon("checked", "CheckBox", make_icon(checked_png)); + theme->set_icon("checked_disabled", "CheckBox", make_icon(checked_disabled_png)); theme->set_icon("unchecked", "CheckBox", make_icon(unchecked_png)); + theme->set_icon("unchecked_disabled", "CheckBox", make_icon(unchecked_disabled_png)); theme->set_icon("radio_checked", "CheckBox", make_icon(radio_checked_png)); + theme->set_icon("radio_checked_disabled", "CheckBox", make_icon(radio_checked_disabled_png)); theme->set_icon("radio_unchecked", "CheckBox", make_icon(radio_unchecked_png)); + theme->set_icon("radio_unchecked_disabled", "CheckBox", make_icon(radio_unchecked_disabled_png)); theme->set_font("font", "CheckBox", Ref<Font>()); theme->set_font_size("font_size", "CheckBox", -1); @@ -628,6 +632,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // File Dialog theme->set_icon("parent_folder", "FileDialog", make_icon(icon_parent_folder_png)); + theme->set_icon("back_folder", "FileDialog", make_icon(arrow_left_png)); + theme->set_icon("forward_folder", "FileDialog", make_icon(arrow_right_png)); theme->set_icon("reload", "FileDialog", make_icon(icon_reload_png)); theme->set_icon("toggle_hidden", "FileDialog", make_icon(icon_visibility_png)); diff --git a/scene/resources/default_theme/radio_checked_disabled.png b/scene/resources/default_theme/radio_checked_disabled.png Binary files differnew file mode 100644 index 0000000000..72f08ecb96 --- /dev/null +++ b/scene/resources/default_theme/radio_checked_disabled.png diff --git a/scene/resources/default_theme/radio_unchecked_disabled.png b/scene/resources/default_theme/radio_unchecked_disabled.png Binary files differnew file mode 100644 index 0000000000..a8f4c1b555 --- /dev/null +++ b/scene/resources/default_theme/radio_unchecked_disabled.png diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h index 6b78ba7933..5d4dbd0758 100644 --- a/scene/resources/default_theme/theme_data.h +++ b/scene/resources/default_theme/theme_data.h @@ -46,6 +46,10 @@ static const unsigned char checked_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x8d, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x58, 0x56, 0x63, 0xb0, 0xaf, 0xb5, 0x38, 0x37, 0x40, 0x20, 0x20, 0x24, 0xb6, 0xb6, 0xb9, 0x57, 0x57, 0x5a, 0x20, 0x20, 0x24, 0x38, 0x36, 0x40, 0x20, 0x20, 0x25, 0x1e, 0x1e, 0x22, 0x1f, 0x1f, 0x23, 0x8b, 0x8b, 0x8d, 0xff, 0xff, 0xff, 0x20, 0x20, 0x24, 0x22, 0x22, 0x27, 0x23, 0x23, 0x28, 0x42, 0x42, 0x47, 0xf8, 0xf8, 0xf8, 0xfe, 0xfe, 0xfe, 0x25, 0x25, 0x2a, 0x4e, 0x4e, 0x52, 0x26, 0x26, 0x2b, 0xc5, 0xc5, 0xc7, 0xaa, 0xaa, 0xab, 0xb8, 0xb8, 0xba, 0x5f, 0x5f, 0x63, 0x74, 0x74, 0x77, 0xed, 0xed, 0xed, 0x33, 0x33, 0x38, 0x8d, 0x8d, 0x8f, 0xb8, 0xb8, 0xb9, 0x35, 0x35, 0x39, 0x3a, 0x3a, 0x3e, 0xfb, 0xfb, 0xfb, 0xfa, 0xfa, 0xfa, 0xb2, 0xb2, 0xb4, 0x45, 0x45, 0x49, 0x61, 0x61, 0x65, 0x8f, 0x8f, 0x92, 0x63, 0x63, 0x66, 0x2a, 0x2a, 0x2f, 0x40, 0x82, 0xb, 0xf6, 0x0, 0x0, 0x0, 0xf, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x7, 0x27, 0x50, 0x66, 0x68, 0x6a, 0x81, 0xb4, 0xfa, 0xdd, 0xfb, 0xfb, 0xb4, 0xfa, 0xb8, 0xf0, 0x7f, 0x59, 0x0, 0x0, 0x0, 0x7e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x5d, 0xca, 0x5, 0xb2, 0x2, 0x30, 0x18, 0x3, 0xe1, 0x4d, 0xed, 0xb9, 0x60, 0xf7, 0x3f, 0x20, 0xee, 0x4e, 0x99, 0xe0, 0xb0, 0x63, 0xfd, 0xbf, 0x86, 0xd7, 0x12, 0x72, 0x38, 0x69, 0x5b, 0x6b, 0x42, 0x45, 0xe5, 0xa, 0xab, 0x95, 0x41, 0x9f, 0x32, 0x20, 0x69, 0x2d, 0xbc, 0x50, 0x46, 0x3a, 0x10, 0x17, 0x5f, 0x49, 0x4, 0x7f, 0x90, 0x57, 0x89, 0xb7, 0xc5, 0x5f, 0x96, 0x17, 0x2e, 0x93, 0xcb, 0x8e, 0x3a, 0x83, 0xb, 0xc4, 0x8e, 0xd4, 0xff, 0x5c, 0x73, 0x83, 0x69, 0x9e, 0x95, 0xfc, 0x3b, 0xf4, 0x33, 0xe0, 0xf8, 0x61, 0xd3, 0xf1, 0x7d, 0x5d, 0x30, 0x7a, 0x6f, 0x89, 0xb, 0xd4, 0x5a, 0xe1, 0x40, 0xf, 0xfc, 0x34, 0x6c, 0xd2, 0x56, 0x80, 0xef, 0xfd, 0x9, 0xd2, 0x3a, 0x5e, 0x41, 0x15, 0x21, 0x77, 0x6, 0xc7, 0x6b, 0x47, 0x4e, 0x3a, 0x2f, 0x53, 0xb4, 0x10, 0xc7, 0x8c, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; +static const unsigned char checked_disabled_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x99, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x73, 0x72, 0x7b, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x82, 0x80, 0x8a, 0x90, 0x90, 0x93, 0x6a, 0x69, 0x70, 0x6a, 0x68, 0x70, 0x93, 0x93, 0x95, 0x58, 0x58, 0x5c, 0x58, 0x58, 0x5b, 0x7d, 0x7d, 0x7f, 0x58, 0x58, 0x5b, 0xa4, 0xa4, 0xa4, 0x9e, 0x9e, 0xa0, 0x9e, 0x9e, 0x9e, 0x9b, 0x9b, 0x9c, 0x9b, 0x9b, 0x9b, 0x9a, 0x9a, 0x9a, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x95, 0x95, 0x95, 0x93, 0x93, 0x94, 0x8f, 0x8f, 0x8f, 0x86, 0x86, 0x88, 0x85, 0x85, 0x86, 0x82, 0x82, 0x83, 0x81, 0x81, 0x83, 0x7f, 0x7f, 0x81, 0x7c, 0x7c, 0x7e, 0x7a, 0x7a, 0x7d, 0x78, 0x78, 0x7b, 0x71, 0x71, 0x74, 0x68, 0x68, 0x6c, 0x66, 0x66, 0x6a, 0x65, 0x65, 0x68, 0x63, 0x63, 0x66, 0x5f, 0x5f, 0x63, 0x5c, 0x5c, 0x60, 0x5c, 0x5c, 0x5f, 0x5a, 0x5a, 0x5e, 0x59, 0x59, 0x5d, 0x59, 0x59, 0x5c, 0x58, 0x58, 0x5b, 0x57, 0x57, 0x5a, 0x56, 0x56, 0x59, 0x10, 0x13, 0xbb, 0xf, 0x0, 0x0, 0x0, 0x10, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x7, 0x27, 0x27, 0x50, 0x66, 0x68, 0x6a, 0x81, 0xb4, 0xb4, 0xdd, 0xfa, 0xfa, 0xfb, 0xfb, 0x5b, 0xd1, 0xf1, 0xe6, 0x0, 0x0, 0x0, 0x96, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5e, 0x5d, 0x8f, 0xc9, 0x12, 0x82, 0x30, 0x14, 0x4, 0x87, 0x18, 0x50, 0x51, 0x44, 0x25, 0x42, 0x4, 0x77, 0xc4, 0x8d, 0x97, 0x0, 0xf9, 0xff, 0x8f, 0xb3, 0x88, 0xa4, 0x4a, 0xed, 0x63, 0x5f, 0xa6, 0x7, 0xf8, 0x7, 0x1e, 0xe3, 0x7e, 0x60, 0x19, 0x4f, 0x46, 0x1e, 0x0, 0x36, 0x8d, 0x4c, 0x67, 0x59, 0x65, 0x33, 0x6, 0x80, 0x47, 0xad, 0x56, 0x3d, 0xb7, 0x3c, 0x5d, 0x70, 0x0, 0xbe, 0xd1, 0x44, 0x65, 0x4d, 0x94, 0xc8, 0xc2, 0xf8, 0x0, 0x82, 0x4e, 0x91, 0x94, 0x15, 0x5d, 0xd2, 0xec, 0xde, 0x5, 0x83, 0x38, 0xc8, 0xe3, 0x63, 0x23, 0xce, 0xca, 0x9, 0x7a, 0x6e, 0xf3, 0x93, 0x48, 0x1a, 0x27, 0x14, 0x35, 0x3b, 0xb9, 0x5e, 0x56, 0xe4, 0x84, 0x22, 0xba, 0xa, 0x51, 0xd0, 0xb7, 0xa8, 0xcb, 0xfd, 0xcb, 0x9, 0x3b, 0xfb, 0x41, 0xdb, 0x59, 0x17, 0xa6, 0x94, 0x6e, 0xe3, 0x3e, 0x8c, 0x85, 0xf1, 0x90, 0x6e, 0xe6, 0x21, 0xfb, 0x39, 0xe7, 0x73, 0xe6, 0xfd, 0x5f, 0x7, 0xde, 0xc3, 0xb5, 0x16, 0x87, 0xb0, 0x9e, 0x42, 0x46, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 +}; + static const unsigned char checker_bg_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0xe1, 0x64, 0xe1, 0x57, 0x0, 0x0, 0x0, 0x14, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xfc, 0xcf, 0xc0, 0xc0, 0xd0, 0x0, 0xc4, 0xf8, 0x18, 0xf5, 0x84, 0x19, 0x0, 0x9f, 0x5f, 0xa, 0x1, 0xf8, 0xef, 0x65, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; @@ -286,10 +290,18 @@ static const unsigned char radio_checked_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x42, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4, 0x3, 0x4, 0x9, 0x9, 0x9, 0x6, 0x6, 0x6, 0xa, 0xa, 0xb, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x7f, 0x7f, 0x82, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0x47, 0x47, 0x48, 0xd3, 0xd3, 0xd3, 0xa2, 0xa2, 0xa2, 0x79, 0x79, 0x79, 0x73, 0x73, 0x73, 0x1c, 0x1c, 0x1c, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0xd1, 0xa7, 0xf5, 0xaa, 0x0, 0x0, 0x0, 0xb, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x88, 0xd1, 0xf7, 0x64, 0xf6, 0x2, 0xb3, 0xed, 0xd7, 0x0, 0x0, 0x0, 0x63, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x6d, 0x4f, 0x55, 0x2, 0x43, 0x31, 0x8, 0x4b, 0xe8, 0x6a, 0xf7, 0xbf, 0xeb, 0xc, 0x9b, 0x6b, 0x1f, 0x9f, 0xc4, 0x89, 0xbf, 0xbb, 0x3f, 0x2a, 0x49, 0x64, 0xa6, 0x3e, 0x1e, 0x1c, 0x7c, 0x3e, 0xf2, 0x14, 0xb7, 0xc7, 0xac, 0xf1, 0x10, 0xa6, 0xe8, 0x1, 0x44, 0xad, 0x42, 0xb9, 0x33, 0x22, 0x43, 0x95, 0x68, 0x55, 0xa4, 0xdc, 0x1f, 0x1e, 0xa1, 0x67, 0xa2, 0x57, 0x96, 0x22, 0x0, 0xc2, 0x3d, 0xf5, 0x44, 0x8c, 0x8a, 0x5d, 0x21, 0x80, 0x74, 0x83, 0x1e, 0x97, 0xc7, 0x22, 0x59, 0x4c, 0xd7, 0xd8, 0xb5, 0x18, 0x4a, 0x7b, 0x57, 0x57, 0xdb, 0x1a, 0xf7, 0x77, 0x17, 0x3a, 0x56, 0x4e, 0x11, 0x6f, 0x82, 0x20, 0xde, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; +static const unsigned char radio_checked_disabled_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x45, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x3, 0x4, 0x9, 0x9, 0x9, 0x6, 0x6, 0x6, 0xa, 0xa, 0xb, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x7f, 0x7f, 0x82, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0x47, 0x47, 0x48, 0xd3, 0xd3, 0xd3, 0xa2, 0xa2, 0xa2, 0x79, 0x79, 0x79, 0x73, 0x73, 0x73, 0x1c, 0x1c, 0x1c, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x83, 0xac, 0xe9, 0xaf, 0x0, 0x0, 0x0, 0x1, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x40, 0xe6, 0xd8, 0x66, 0x0, 0x0, 0x0, 0x3f, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x63, 0x60, 0x20, 0xe, 0xf0, 0x8, 0x2, 0x1, 0xf, 0x9c, 0x2b, 0x2c, 0x8, 0x5, 0xc2, 0x50, 0x1, 0xb0, 0x34, 0x58, 0x11, 0x5c, 0xbd, 0x10, 0x3f, 0x10, 0x8, 0xc1, 0x74, 0x1, 0x65, 0xf8, 0xc1, 0x0, 0xa6, 0x4, 0x28, 0x1, 0x11, 0xe0, 0xc1, 0x2d, 0x80, 0xa6, 0x5, 0xc3, 0x50, 0xc, 0x6b, 0x31, 0x1d, 0x86, 0xe1, 0x74, 0xfc, 0x0, 0x0, 0x1b, 0xc, 0x7, 0xb9, 0xa, 0x5e, 0x2e, 0x12, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 +}; + static const unsigned char radio_unchecked_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x2a, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4, 0x3, 0x4, 0x9, 0x9, 0x9, 0x6, 0x6, 0x6, 0xa, 0xa, 0xb, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x7f, 0x7f, 0x82, 0xd9, 0xd9, 0xd9, 0x47, 0x47, 0x48, 0x2b, 0x6e, 0xf2, 0xbf, 0x0, 0x0, 0x0, 0xb, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x88, 0xd1, 0xf7, 0x64, 0xf6, 0x2, 0xb3, 0xed, 0xd7, 0x0, 0x0, 0x0, 0x49, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x40, 0x2, 0x61, 0x15, 0xed, 0xa9, 0x20, 0x5a, 0x72, 0xf5, 0x99, 0x33, 0xbb, 0x26, 0x1, 0x19, 0x73, 0xcf, 0x0, 0xc1, 0x4d, 0x6, 0x6, 0xd6, 0x35, 0x20, 0xc6, 0xa9, 0x0, 0x6, 0xb6, 0x3d, 0x20, 0xc6, 0xe9, 0x4, 0x6, 0xf6, 0x33, 0x60, 0x50, 0xc0, 0xc0, 0x1, 0x61, 0x34, 0xc0, 0x19, 0x70, 0x29, 0xb8, 0x62, 0xb8, 0x76, 0x84, 0x81, 0xc, 0x96, 0x20, 0x2b, 0xa6, 0xc0, 0x2d, 0x45, 0x0, 0x0, 0x37, 0xca, 0x3d, 0x81, 0xb4, 0x84, 0xb6, 0x80, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; +static const unsigned char radio_unchecked_disabled_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0xf, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x54, 0x54, 0x54, 0xad, 0xad, 0xad, 0x80, 0x80, 0x81, 0x64, 0x64, 0x64, 0xf4, 0x17, 0x36, 0x28, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x1b, 0xfc, 0xf6, 0x4, 0xd4, 0x0, 0x0, 0x0, 0x40, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5e, 0x7d, 0x8d, 0xb1, 0x11, 0x80, 0x40, 0xc, 0xc3, 0x94, 0xd, 0x12, 0x60, 0x1, 0xc4, 0x4, 0xb0, 0x1, 0xfb, 0x2f, 0x45, 0xe5, 0x3b, 0xaa, 0x57, 0xe5, 0xc2, 0xb6, 0x20, 0xc0, 0xcc, 0xc, 0x40, 0xed, 0x7a, 0x37, 0x70, 0xa8, 0xbe, 0x50, 0x9b, 0xea, 0xd9, 0xd4, 0xa3, 0x7a, 0x35, 0xa5, 0xaa, 0xeb, 0x90, 0x72, 0xe6, 0x39, 0xfc, 0x2b, 0x22, 0xd, 0x1f, 0xe7, 0x64, 0xa, 0x5d, 0x6c, 0xfe, 0xc1, 0x3b, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 +}; + static const unsigned char scroll_bg_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x3, 0x0, 0x0, 0x0, 0x61, 0xab, 0xac, 0xd5, 0x0, 0x0, 0x0, 0x45, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x40, 0x3e, 0x4a, 0x2a, 0x29, 0x2f, 0x20, 0x20, 0x24, 0x3f, 0x3e, 0x49, 0x1f, 0x1f, 0x24, 0x20, 0x20, 0x24, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x3f, 0x3e, 0x49, 0x3f, 0x3e, 0x49, 0x1e, 0x1e, 0x23, 0x20, 0x20, 0x25, 0x22, 0x22, 0x27, 0x23, 0x23, 0x27, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2a, 0x14, 0xee, 0x69, 0x20, 0x0, 0x0, 0x0, 0x11, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x4, 0x19, 0x40, 0x5d, 0x66, 0x28, 0x93, 0xf0, 0xfc, 0x94, 0xfc, 0xfd, 0x67, 0x1a, 0x96, 0x95, 0x1c, 0xf0, 0x43, 0x52, 0x0, 0x0, 0x0, 0x55, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x55, 0x8e, 0x45, 0x2, 0x80, 0x50, 0x10, 0x42, 0xc1, 0xee, 0xfb, 0x5f, 0xd4, 0xd6, 0xdf, 0xfd, 0x36, 0xd3, 0x3, 0x4, 0xd, 0x90, 0x6, 0xb2, 0x25, 0x39, 0xe0, 0xd2, 0xf9, 0xcb, 0x6a, 0x60, 0x6f, 0x27, 0xb7, 0xbc, 0x58, 0xb7, 0x53, 0x4d, 0x0, 0xf2, 0x3f, 0x5e, 0x36, 0x43, 0x5f, 0xc3, 0xf0, 0xdf, 0x17, 0xd7, 0xa6, 0xae, 0x60, 0x10, 0xff, 0x57, 0x16, 0xc5, 0x5a, 0xf1, 0x60, 0xe3, 0xe7, 0x5f, 0x37, 0x46, 0x74, 0xba, 0x9a, 0x16, 0xef, 0x37, 0x1c, 0x6f, 0x61, 0x47, 0x1, 0xa5, 0xc7, 0x32, 0x47, 0x38, 0x12, 0x92, 0xb1, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; @@ -434,6 +446,10 @@ static const unsigned char unchecked_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x33, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x38, 0x37, 0x40, 0x20, 0x20, 0x24, 0x20, 0x20, 0x24, 0x38, 0x36, 0x40, 0x20, 0x20, 0x25, 0x1e, 0x1e, 0x22, 0x1f, 0x1f, 0x23, 0x20, 0x20, 0x24, 0x22, 0x22, 0x27, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2a, 0x23, 0xc3, 0x49, 0x39, 0x0, 0x0, 0x0, 0xb, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x7, 0x27, 0x50, 0x66, 0x68, 0xb4, 0xfa, 0xfb, 0xb4, 0xfa, 0xa4, 0x7f, 0xe1, 0x5a, 0x0, 0x0, 0x0, 0x4f, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xb5, 0xcf, 0x45, 0x2, 0x80, 0x40, 0x8, 0x0, 0x40, 0x97, 0x66, 0xfb, 0xff, 0x9f, 0xb5, 0xdb, 0xb3, 0x73, 0xa4, 0x19, 0xbe, 0x2, 0x20, 0xf1, 0x8a, 0x10, 0xc2, 0x1c, 0x0, 0xd1, 0x94, 0x57, 0x49, 0x5, 0xe6, 0x0, 0x6a, 0xa9, 0x6d, 0x55, 0x8b, 0xe2, 0x1c, 0xa0, 0x54, 0xfb, 0xae, 0x26, 0x9a, 0x3, 0x9c, 0xdb, 0x11, 0x68, 0x99, 0xff, 0xa, 0x7c, 0xd6, 0xde, 0xf, 0x33, 0x9c, 0x3, 0xe0, 0x76, 0x9c, 0x1e, 0x1d, 0xbe, 0xcf, 0x7d, 0x4c, 0x93, 0xe2, 0x8, 0xa4, 0x66, 0x3c, 0xec, 0xed, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; +static const unsigned char unchecked_disabled_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x33, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x6a, 0x69, 0x70, 0x6a, 0x68, 0x70, 0x58, 0x58, 0x5c, 0x58, 0x58, 0x5b, 0x58, 0x58, 0x5b, 0x5c, 0x5c, 0x5f, 0x5a, 0x5a, 0x5e, 0x59, 0x59, 0x5d, 0x58, 0x58, 0x5b, 0x57, 0x57, 0x5a, 0x56, 0x56, 0x59, 0x27, 0xa1, 0xa6, 0x53, 0x0, 0x0, 0x0, 0xb, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x7, 0x27, 0x50, 0x66, 0x68, 0xb4, 0xb4, 0xfa, 0xfa, 0xfb, 0xc7, 0x8b, 0xf6, 0x7e, 0x0, 0x0, 0x0, 0x52, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5e, 0xb5, 0xcf, 0x31, 0x12, 0xc0, 0x20, 0x8, 0x44, 0xd1, 0x15, 0x50, 0x83, 0x11, 0xe5, 0xfe, 0xa7, 0xcd, 0xe8, 0xc4, 0x22, 0xf4, 0x79, 0xe5, 0x36, 0x7c, 0x80, 0x8, 0x89, 0x58, 0xf2, 0x26, 0x4c, 0x9, 0x0, 0x15, 0xf5, 0xb9, 0xb9, 0x16, 0x2, 0xc0, 0x3a, 0xac, 0x6f, 0x36, 0x94, 0x1, 0x88, 0xdb, 0xfd, 0x32, 0x17, 0x0, 0x79, 0xf6, 0x33, 0xf4, 0x99, 0xff, 0x1a, 0xe2, 0xd9, 0x4f, 0x58, 0x5b, 0x61, 0x54, 0xdb, 0x49, 0xbf, 0xea, 0x4a, 0x8f, 0xcf, 0x45, 0xf, 0x4, 0x40, 0x7, 0x90, 0xb0, 0x7b, 0x47, 0x4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 +}; + static const unsigned char updown_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0x81, 0x83, 0xf6, 0xf6, 0x0, 0x0, 0x0, 0x57, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x8d, 0x4e, 0xb5, 0x1, 0xc0, 0x30, 0xc, 0xf3, 0x15, 0xfe, 0xff, 0x96, 0x64, 0xa, 0x6c, 0xca, 0x56, 0xd2, 0x25, 0x65, 0xe6, 0xc8, 0x8b, 0x49, 0x20, 0x79, 0x28, 0x95, 0x81, 0xa1, 0xd4, 0x7d, 0x4, 0xbb, 0xa1, 0x50, 0xea, 0x3c, 0xa6, 0x71, 0x98, 0x96, 0x69, 0x58, 0x31, 0xcc, 0xb7, 0xe5, 0x2f, 0x48, 0x63, 0x26, 0xf6, 0xa2, 0xd4, 0x18, 0xf9, 0x7, 0x2d, 0xe3, 0x46, 0x89, 0xb4, 0xd2, 0xf8, 0xa3, 0x68, 0xe3, 0xd7, 0x14, 0x20, 0xe6, 0xc3, 0x3d, 0xd8, 0xca, 0x5e, 0x94, 0x32, 0xd0, 0x3, 0x91, 0xba, 0x5f, 0x1b, 0x4a, 0x9b, 0x12, 0x62, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; diff --git a/scene/resources/default_theme/unchecked_disabled.png b/scene/resources/default_theme/unchecked_disabled.png Binary files differnew file mode 100644 index 0000000000..bef9316f58 --- /dev/null +++ b/scene/resources/default_theme/unchecked_disabled.png diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 1a2b21299a..f8e1ce6a61 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -1238,6 +1238,22 @@ StringName ArrayMesh::get_blend_shape_name(int p_index) const { return blend_shapes[p_index]; } +void ArrayMesh::set_blend_shape_name(int p_index, const StringName &p_name) { + ERR_FAIL_INDEX(p_index, blend_shapes.size()); + + StringName name = p_name; + int found = blend_shapes.find(name); + if (found != -1 && found != p_index) { + int count = 2; + do { + name = String(p_name) + " " + itos(count); + count++; + } while (blend_shapes.find(name) != -1); + } + + blend_shapes.write[p_index] = name; +} + void ArrayMesh::clear_blend_shapes() { ERR_FAIL_COND_MSG(surfaces.size(), "Can't set shape key count if surfaces are already created."); @@ -1590,6 +1606,7 @@ void ArrayMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &ArrayMesh::add_blend_shape); ClassDB::bind_method(D_METHOD("get_blend_shape_count"), &ArrayMesh::get_blend_shape_count); ClassDB::bind_method(D_METHOD("get_blend_shape_name", "index"), &ArrayMesh::get_blend_shape_name); + ClassDB::bind_method(D_METHOD("set_blend_shape_name", "index", "name"), &ArrayMesh::set_blend_shape_name); ClassDB::bind_method(D_METHOD("clear_blend_shapes"), &ArrayMesh::clear_blend_shapes); ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &ArrayMesh::set_blend_shape_mode); ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &ArrayMesh::get_blend_shape_mode); diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 2ce519e644..9a462d5719 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -141,6 +141,7 @@ public: virtual Ref<Material> surface_get_material(int p_idx) const = 0; virtual int get_blend_shape_count() const = 0; virtual StringName get_blend_shape_name(int p_index) const = 0; + virtual void set_blend_shape_name(int p_index, const StringName &p_name) = 0; Vector<Face3> get_faces() const; Ref<TriangleMesh> generate_triangle_mesh() const; @@ -223,6 +224,7 @@ public: void add_blend_shape(const StringName &p_name); int get_blend_shape_count() const override; StringName get_blend_shape_name(int p_index) const override; + void set_blend_shape_name(int p_index, const StringName &p_name) override; void clear_blend_shapes(); void set_blend_shape_mode(BlendShapeMode p_mode); diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index a0f4bf9409..195ce070a7 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -340,14 +340,21 @@ void ParticlesMaterial::_update_shader() { //initiate velocity spread in 3D code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; code += " float angle2_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad * (1.0 - flatness);\n"; - code += " angle1_rad += direction.z != 0.0 ? atan(direction.x, direction.z) : sign(direction.x) * (pi / 2.0);\n"; - code += " angle2_rad += direction.z != 0.0 ? atan(direction.y, abs(direction.z)) : (direction.x != 0.0 ? atan(direction.y, abs(direction.x)) : sign(direction.y) * (pi / 2.0));\n"; code += " vec3 direction_xz = vec3(sin(angle1_rad), 0.0, cos(angle1_rad));\n"; code += " vec3 direction_yz = vec3(0.0, sin(angle2_rad), cos(angle2_rad));\n"; code += " direction_yz.z = direction_yz.z / max(0.0001,sqrt(abs(direction_yz.z))); // better uniform distribution\n"; - code += " vec3 vec_direction = vec3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);\n"; - code += " vec_direction = normalize(vec_direction);\n"; - code += " VELOCITY = vec_direction * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; + code += " vec3 spread_direction = vec3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);\n"; + code += " vec3 direction_nrm = normalize(direction);\n"; + code += " // rotate spread to direction\n"; + code += " vec3 binormal = cross(vec3(0.0, 1.0, 0.0), direction_nrm);\n"; + code += " if (length(binormal) < 0.0001) {\n"; + code += " // direction is parallel to Y. Choose Z as the binormal.\n"; + code += " binormal = vec3(0.0, 0.0, 1.0);\n"; + code += " }\n"; + code += " binormal = normalize(binormal);\n"; + code += " vec3 normal = cross(binormal, direction_nrm);\n"; + code += " spread_direction = binormal * spread_direction.x + normal * spread_direction.y + direction_nrm * spread_direction.z;\n"; + code += " VELOCITY = spread_direction * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; } code += " }\n"; diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp index 536318ed16..a08684a506 100644 --- a/scene/resources/polygon_path_finder.cpp +++ b/scene/resources/polygon_path_finder.cpp @@ -368,7 +368,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector path.push_back(points[at].pos); } while (at != aidx); - path.invert(); + path.reverse(); } for (int i = 0; i < points.size() - 2; i++) { diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index ba6c4591c9..1be511e8f1 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -175,6 +175,9 @@ StringName PrimitiveMesh::get_blend_shape_name(int p_index) const { return StringName(); } +void PrimitiveMesh::set_blend_shape_name(int p_index, const StringName &p_name) { +} + AABB PrimitiveMesh::get_aabb() const { if (pending_request) { _update(); diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index bb3df9d10e..65ecdfc19d 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -81,6 +81,7 @@ public: virtual Ref<Material> surface_get_material(int p_idx) const override; virtual int get_blend_shape_count() const override; virtual StringName get_blend_shape_name(int p_index) const override; + virtual void set_blend_shape_name(int p_index, const StringName &p_name) override; virtual AABB get_aabb() const override; virtual RID get_rid() const override; diff --git a/scene/resources/ray_shape_2d.cpp b/scene/resources/ray_shape_2d.cpp index d2125445fa..fb8f4b9985 100644 --- a/scene/resources/ray_shape_2d.cpp +++ b/scene/resources/ray_shape_2d.cpp @@ -42,17 +42,33 @@ void RayShape2D::_update_shape() { } void RayShape2D::draw(const RID &p_to_rid, const Color &p_color) { - Vector2 tip = Vector2(0, get_length()); - RS::get_singleton()->canvas_item_add_line(p_to_rid, Vector2(), tip, p_color, 3); + const Vector2 target_position = Vector2(0, get_length()); + + const float max_arrow_size = 6; + const float line_width = 1.4; + bool no_line = target_position.length() < line_width; + float arrow_size = CLAMP(target_position.length() * 2 / 3, line_width, max_arrow_size); + + if (no_line) { + arrow_size = target_position.length(); + } else { + RS::get_singleton()->canvas_item_add_line(p_to_rid, Vector2(), target_position - target_position.normalized() * arrow_size, p_color, line_width); + } + + Transform2D xf; + xf.rotate(target_position.angle()); + xf.translate(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0)); + Vector<Vector2> pts; - float tsize = 4.0; - pts.push_back(tip + Vector2(0, tsize)); - pts.push_back(tip + Vector2(Math_SQRT12 * tsize, 0)); - pts.push_back(tip + Vector2(-Math_SQRT12 * tsize, 0)); + pts.push_back(xf.xform(Vector2(arrow_size, 0))); + pts.push_back(xf.xform(Vector2(0, 0.5 * arrow_size))); + pts.push_back(xf.xform(Vector2(0, -0.5 * arrow_size))); + Vector<Color> cols; for (int i = 0; i < 3; i++) { cols.push_back(p_color); } + RS::get_singleton()->canvas_item_add_primitive(p_to_rid, pts, cols, Vector<Point2>(), RID()); } diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 47933bd69a..3d3900ecc5 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -1059,6 +1059,10 @@ void SurfaceTool::set_material(const Ref<Material> &p_material) { material = p_material; } +Ref<Material> SurfaceTool::get_material() const { + return material; +} + void SurfaceTool::clear() { begun = false; primitive = Mesh::PRIMITIVE_LINES; @@ -1088,6 +1092,10 @@ void SurfaceTool::set_custom_format(int p_index, CustomFormat p_format) { ERR_FAIL_COND(begun); last_custom_format[p_index] = p_format; } + +Mesh::PrimitiveType SurfaceTool::get_primitive() const { + return primitive; +} SurfaceTool::CustomFormat SurfaceTool::get_custom_format(int p_index) const { ERR_FAIL_INDEX_V(p_index, RS::ARRAY_CUSTOM_COUNT, CUSTOM_MAX); return last_custom_format[p_index]; @@ -1174,6 +1182,7 @@ void SurfaceTool::_bind_methods() { ClassDB::bind_method(D_METHOD("generate_lod", "nd_threshold", "target_index_count"), &SurfaceTool::generate_lod, DEFVAL(3)); ClassDB::bind_method(D_METHOD("set_material", "material"), &SurfaceTool::set_material); + ClassDB::bind_method(D_METHOD("get_primitive"), &SurfaceTool::get_primitive); ClassDB::bind_method(D_METHOD("clear"), &SurfaceTool::clear); diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index 17efdcba71..28addf2245 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -143,6 +143,8 @@ public: void set_custom_format(int p_index, CustomFormat p_format); CustomFormat get_custom_format(int p_index) const; + Mesh::PrimitiveType get_primitive() const; + void begin(Mesh::PrimitiveType p_primitive); void set_color(Color p_color); @@ -171,6 +173,7 @@ public: Vector<int> generate_lod(float p_threshold, int p_target_index_count = 3); void set_material(const Ref<Material> &p_material); + Ref<Material> get_material() const; void clear(); diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp index 444a4bb22a..341f5abd80 100644 --- a/scene/resources/text_paragraph.cpp +++ b/scene/resources/text_paragraph.cpp @@ -98,6 +98,9 @@ void TextParagraph::_bind_methods() { ClassDB::bind_method(D_METHOD("get_line_underline_position", "line"), &TextParagraph::get_line_underline_position); ClassDB::bind_method(D_METHOD("get_line_underline_thickness", "line"), &TextParagraph::get_line_underline_thickness); + ClassDB::bind_method(D_METHOD("get_spacing_top"), &TextParagraph::get_spacing_top); + ClassDB::bind_method(D_METHOD("get_spacing_bottom"), &TextParagraph::get_spacing_bottom); + ClassDB::bind_method(D_METHOD("get_dropcap_size"), &TextParagraph::get_dropcap_size); ClassDB::bind_method(D_METHOD("get_dropcap_lines"), &TextParagraph::get_dropcap_lines); @@ -266,6 +269,14 @@ bool TextParagraph::add_string(const String &p_text, const Ref<Font> &p_fonts, i return res; } +int TextParagraph::get_spacing_top() const { + return spacing_top; +} + +int TextParagraph::get_spacing_bottom() const { + return spacing_bottom; +} + void TextParagraph::_set_bidi_override(const Array &p_override) { Vector<Vector2i> overrides; for (int i = 0; i < p_override.size(); i++) { @@ -609,11 +620,13 @@ int TextParagraph::hit_test(const Point2 &p_coords) const { const_cast<TextParagraph *>(this)->_shape_lines(); Vector2 ofs; if (TS->shaped_text_get_orientation(rid) == TextServer::ORIENTATION_HORIZONTAL) { - if (ofs.y < 0) + if (ofs.y < 0) { return 0; + } } else { - if (ofs.x < 0) + if (ofs.x < 0) { return 0; + } } for (int i = 0; i < lines.size(); i++) { if (TS->shaped_text_get_orientation(lines[i]) == TextServer::ORIENTATION_HORIZONTAL) { diff --git a/scene/resources/text_paragraph.h b/scene/resources/text_paragraph.h index a16fa8c3c4..4396b07130 100644 --- a/scene/resources/text_paragraph.h +++ b/scene/resources/text_paragraph.h @@ -116,6 +116,9 @@ public: float get_line_underline_position(int p_line) const; float get_line_underline_thickness(int p_line) const; + int get_spacing_top() const; + int get_spacing_bottom() const; + Size2 get_dropcap_size() const; int get_dropcap_lines() const; diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index d2bb1338d8..b6a2f24b8b 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -71,7 +71,7 @@ void Texture2D::_bind_methods() { ClassDB::bind_method(D_METHOD("draw", "canvas_item", "position", "modulate", "transpose"), &Texture2D::draw, DEFVAL(Color(1, 1, 1)), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_rect", "canvas_item", "rect", "tile", "modulate", "transpose"), &Texture2D::draw_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_rect_region", "canvas_item", "rect", "src_rect", "modulate", "transpose", "clip_uv"), &Texture2D::draw_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(true)); - ClassDB::bind_method(D_METHOD("get_data"), &Texture2D::get_data); + ClassDB::bind_method(D_METHOD("get_image"), &Texture2D::get_image); ADD_GROUP("", ""); } @@ -116,7 +116,7 @@ bool ImageTexture::_set(const StringName &p_name, const Variant &p_value) { bool ImageTexture::_get(const StringName &p_name, Variant &r_ret) const { if (p_name == "image") { - r_ret = get_data(); + r_ret = get_image(); } else if (p_name == "size") { r_ret = Size2(w, h); } else { @@ -200,7 +200,7 @@ void ImageTexture::_resource_path_changed() { String path = get_path(); } -Ref<Image> ImageTexture::get_data() const { +Ref<Image> ImageTexture::get_image() const { if (image_stored) { return RenderingServer::get_singleton()->texture_2d_get(texture); } else { @@ -251,7 +251,7 @@ void ImageTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, cons bool ImageTexture::is_pixel_opaque(int p_x, int p_y) const { if (!alpha_cache.is_valid()) { - Ref<Image> img = get_data(); + Ref<Image> img = get_image(); if (img.is_valid()) { if (img->is_compressed()) { //must decompress, if compressed Ref<Image> decom = img->duplicate(); @@ -661,7 +661,7 @@ bool StreamTexture2D::has_alpha() const { return false; } -Ref<Image> StreamTexture2D::get_data() const { +Ref<Image> StreamTexture2D::get_image() const { if (texture.is_valid()) { return RS::get_singleton()->texture_2d_get(texture); } else { @@ -671,7 +671,7 @@ Ref<Image> StreamTexture2D::get_data() const { bool StreamTexture2D::is_pixel_opaque(int p_x, int p_y) const { if (!alpha_cache.is_valid()) { - Ref<Image> img = get_data(); + Ref<Image> img = get_image(); if (img.is_valid()) { if (img->is_compressed()) { //must decompress, if compressed Ref<Image> decom = img->duplicate(); @@ -1495,7 +1495,7 @@ Ref<Texture2D> LargeTexture::get_piece_texture(int p_idx) const { Ref<Image> LargeTexture::to_image() const { Ref<Image> img = memnew(Image(this->get_width(), this->get_height(), false, Image::FORMAT_RGBA8)); for (int i = 0; i < pieces.size(); i++) { - Ref<Image> src_img = pieces[i].texture->get_data(); + Ref<Image> src_img = pieces[i].texture->get_image(); img->blit_rect(src_img, Rect2(0, 0, src_img->get_width(), src_img->get_height()), pieces[i].offset); } @@ -1782,7 +1782,7 @@ int GradientTexture::get_width() const { return width; } -Ref<Image> GradientTexture::get_data() const { +Ref<Image> GradientTexture::get_image() const { if (!texture.is_valid()) { return Ref<Image>(); } @@ -2031,14 +2031,14 @@ bool AnimatedTexture::has_alpha() const { return frames[current_frame].texture->has_alpha(); } -Ref<Image> AnimatedTexture::get_data() const { +Ref<Image> AnimatedTexture::get_image() const { RWLockRead r(rw_lock); if (!frames[current_frame].texture.is_valid()) { return Ref<Image>(); } - return frames[current_frame].texture->get_data(); + return frames[current_frame].texture->get_image(); } bool AnimatedTexture::is_pixel_opaque(int p_x, int p_y) const { @@ -2543,7 +2543,7 @@ uint32_t CameraTexture::get_flags() const { return 0; } -Ref<Image> CameraTexture::get_data() const { +Ref<Image> CameraTexture::get_image() const { // not (yet) supported return Ref<Image>(); } diff --git a/scene/resources/texture.h b/scene/resources/texture.h index a0d917fd86..16c98f2891 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -71,7 +71,7 @@ public: virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = true) const; virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const; - virtual Ref<Image> get_data() const { return Ref<Image>(); } + virtual Ref<Image> get_image() const { return Ref<Image>(); } Texture2D(); }; @@ -108,7 +108,7 @@ public: Image::Format get_format() const; void update(const Ref<Image> &p_image, bool p_immediate = false); - Ref<Image> get_data() const override; + Ref<Image> get_image() const override; int get_width() const override; int get_height() const override; @@ -203,7 +203,7 @@ public: virtual bool has_alpha() const override; bool is_pixel_opaque(int p_x, int p_y) const override; - virtual Ref<Image> get_data() const override; + virtual Ref<Image> get_image() const override; StreamTexture2D(); ~StreamTexture2D(); @@ -716,7 +716,7 @@ public: virtual int get_height() const override { return 1; } virtual bool has_alpha() const override { return true; } - virtual Ref<Image> get_data() const override; + virtual Ref<Image> get_image() const override; GradientTexture(); virtual ~GradientTexture(); @@ -812,7 +812,7 @@ public: virtual bool has_alpha() const override; - virtual Ref<Image> get_data() const override; + virtual Ref<Image> get_image() const override; bool is_pixel_opaque(int p_x, int p_y) const override; @@ -839,7 +839,7 @@ public: virtual void set_flags(uint32_t p_flags); virtual uint32_t get_flags() const; - virtual Ref<Image> get_data() const override; + virtual Ref<Image> get_image() const override; void set_camera_feed_id(int p_new_id); int get_camera_feed_id() const; diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index 0405ea98bb..036d11574c 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -141,6 +141,21 @@ Vector<String> Theme::_get_font_size_list(const String &p_node_type) const { return ilret; } +Vector<String> Theme::_get_font_size_type_list() const { + Vector<String> ilret; + List<StringName> il; + + get_font_size_type_list(&il); + ilret.resize(il.size()); + + int i = 0; + String *w = ilret.ptrw(); + for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { + w[i] = E->get(); + } + return ilret; +} + Vector<String> Theme::_get_color_list(const String &p_node_type) const { Vector<String> ilret; List<StringName> il; @@ -201,6 +216,48 @@ Vector<String> Theme::_get_constant_type_list() const { return ilret; } +Vector<String> Theme::_get_theme_item_list(DataType p_data_type, const String &p_node_type) const { + switch (p_data_type) { + case DATA_TYPE_COLOR: + return _get_color_list(p_node_type); + case DATA_TYPE_CONSTANT: + return _get_constant_list(p_node_type); + case DATA_TYPE_FONT: + return _get_font_list(p_node_type); + case DATA_TYPE_FONT_SIZE: + return _get_font_size_list(p_node_type); + case DATA_TYPE_ICON: + return _get_icon_list(p_node_type); + case DATA_TYPE_STYLEBOX: + return _get_stylebox_list(p_node_type); + case DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } + + return Vector<String>(); +} + +Vector<String> Theme::_get_theme_item_type_list(DataType p_data_type) const { + switch (p_data_type) { + case DATA_TYPE_COLOR: + return _get_color_type_list(); + case DATA_TYPE_CONSTANT: + return _get_constant_type_list(); + case DATA_TYPE_FONT: + return _get_font_type_list(); + case DATA_TYPE_FONT_SIZE: + return _get_font_size_type_list(); + case DATA_TYPE_ICON: + return _get_icon_type_list(); + case DATA_TYPE_STYLEBOX: + return _get_stylebox_type_list(); + case DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } + + return Vector<String>(); +} + Vector<String> Theme::_get_type_list() const { Vector<String> ilret; List<StringName> il; @@ -421,8 +478,6 @@ void Theme::set_default_font_size(int p_font_size) { } void Theme::set_icon(const StringName &p_name, const StringName &p_node_type, const Ref<Texture2D> &p_icon) { - //ERR_FAIL_COND(p_icon.is_null()); - bool new_value = !icon_map.has(p_node_type) || !icon_map[p_node_type].has(p_name); if (icon_map[p_node_type].has(p_name) && icon_map[p_node_type][p_name].is_valid()) { @@ -453,9 +508,21 @@ bool Theme::has_icon(const StringName &p_name, const StringName &p_node_type) co return (icon_map.has(p_node_type) && icon_map[p_node_type].has(p_name) && icon_map[p_node_type][p_name].is_valid()); } +void Theme::rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { + ERR_FAIL_COND_MSG(!icon_map.has(p_node_type), "Cannot rename the icon '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); + ERR_FAIL_COND_MSG(icon_map[p_node_type].has(p_name), "Cannot rename the icon '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); + ERR_FAIL_COND_MSG(!icon_map[p_node_type].has(p_old_name), "Cannot rename the icon '" + String(p_old_name) + "' because it does not exist."); + + icon_map[p_node_type][p_name] = icon_map[p_node_type][p_old_name]; + icon_map[p_node_type].erase(p_old_name); + + notify_property_list_changed(); + emit_changed(); +} + void Theme::clear_icon(const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND(!icon_map.has(p_node_type)); - ERR_FAIL_COND(!icon_map[p_node_type].has(p_name)); + ERR_FAIL_COND_MSG(!icon_map.has(p_node_type), "Cannot clear the icon '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); + ERR_FAIL_COND_MSG(!icon_map[p_node_type].has(p_name), "Cannot clear the icon '" + String(p_name) + "' because it does not exist."); if (icon_map[p_node_type][p_name].is_valid()) { icon_map[p_node_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); @@ -481,6 +548,10 @@ void Theme::get_icon_list(StringName p_node_type, List<StringName> *p_list) cons } } +void Theme::add_icon_type(const StringName &p_node_type) { + icon_map[p_node_type] = HashMap<StringName, Ref<Texture2D>>(); +} + void Theme::get_icon_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); @@ -491,8 +562,6 @@ void Theme::get_icon_type_list(List<StringName> *p_list) const { } void Theme::set_stylebox(const StringName &p_name, const StringName &p_node_type, const Ref<StyleBox> &p_style) { - //ERR_FAIL_COND(p_style.is_null()); - bool new_value = !style_map.has(p_node_type) || !style_map[p_node_type].has(p_name); if (style_map[p_node_type].has(p_name) && style_map[p_node_type][p_name].is_valid()) { @@ -523,9 +592,21 @@ bool Theme::has_stylebox(const StringName &p_name, const StringName &p_node_type return (style_map.has(p_node_type) && style_map[p_node_type].has(p_name) && style_map[p_node_type][p_name].is_valid()); } +void Theme::rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { + ERR_FAIL_COND_MSG(!style_map.has(p_node_type), "Cannot rename the stylebox '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); + ERR_FAIL_COND_MSG(style_map[p_node_type].has(p_name), "Cannot rename the stylebox '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); + ERR_FAIL_COND_MSG(!style_map[p_node_type].has(p_old_name), "Cannot rename the stylebox '" + String(p_old_name) + "' because it does not exist."); + + style_map[p_node_type][p_name] = style_map[p_node_type][p_old_name]; + style_map[p_node_type].erase(p_old_name); + + notify_property_list_changed(); + emit_changed(); +} + void Theme::clear_stylebox(const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND(!style_map.has(p_node_type)); - ERR_FAIL_COND(!style_map[p_node_type].has(p_name)); + ERR_FAIL_COND_MSG(!style_map.has(p_node_type), "Cannot clear the stylebox '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); + ERR_FAIL_COND_MSG(!style_map[p_node_type].has(p_name), "Cannot clear the stylebox '" + String(p_name) + "' because it does not exist."); if (style_map[p_node_type][p_name].is_valid()) { style_map[p_node_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); @@ -551,6 +632,10 @@ void Theme::get_stylebox_list(StringName p_node_type, List<StringName> *p_list) } } +void Theme::add_stylebox_type(const StringName &p_node_type) { + style_map[p_node_type] = HashMap<StringName, Ref<StyleBox>>(); +} + void Theme::get_stylebox_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); @@ -561,8 +646,6 @@ void Theme::get_stylebox_type_list(List<StringName> *p_list) const { } void Theme::set_font(const StringName &p_name, const StringName &p_node_type, const Ref<Font> &p_font) { - //ERR_FAIL_COND(p_font.is_null()); - bool new_value = !font_map.has(p_node_type) || !font_map[p_node_type].has(p_name); if (font_map[p_node_type][p_name].is_valid()) { @@ -595,9 +678,21 @@ bool Theme::has_font(const StringName &p_name, const StringName &p_node_type) co return ((font_map.has(p_node_type) && font_map[p_node_type].has(p_name) && font_map[p_node_type][p_name].is_valid()) || default_theme_font.is_valid()); } +void Theme::rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { + ERR_FAIL_COND_MSG(!font_map.has(p_node_type), "Cannot rename the font '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); + ERR_FAIL_COND_MSG(font_map[p_node_type].has(p_name), "Cannot rename the font '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); + ERR_FAIL_COND_MSG(!font_map[p_node_type].has(p_old_name), "Cannot rename the font '" + String(p_old_name) + "' because it does not exist."); + + font_map[p_node_type][p_name] = font_map[p_node_type][p_old_name]; + font_map[p_node_type].erase(p_old_name); + + notify_property_list_changed(); + emit_changed(); +} + void Theme::clear_font(const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND(!font_map.has(p_node_type)); - ERR_FAIL_COND(!font_map[p_node_type].has(p_name)); + ERR_FAIL_COND_MSG(!font_map.has(p_node_type), "Cannot clear the font '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); + ERR_FAIL_COND_MSG(!font_map[p_node_type].has(p_name), "Cannot clear the font '" + String(p_name) + "' because it does not exist."); if (font_map[p_node_type][p_name].is_valid()) { font_map[p_node_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); @@ -622,6 +717,10 @@ void Theme::get_font_list(StringName p_node_type, List<StringName> *p_list) cons } } +void Theme::add_font_type(const StringName &p_node_type) { + font_map[p_node_type] = HashMap<StringName, Ref<Font>>(); +} + void Theme::get_font_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); @@ -656,9 +755,21 @@ bool Theme::has_font_size(const StringName &p_name, const StringName &p_node_typ return ((font_size_map.has(p_node_type) && font_size_map[p_node_type].has(p_name) && (font_size_map[p_node_type][p_name] > 0)) || (default_theme_font_size > 0)); } +void Theme::rename_font_size(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { + ERR_FAIL_COND_MSG(!font_size_map.has(p_node_type), "Cannot rename the font size '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); + ERR_FAIL_COND_MSG(font_size_map[p_node_type].has(p_name), "Cannot rename the font size '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); + ERR_FAIL_COND_MSG(!font_size_map[p_node_type].has(p_old_name), "Cannot rename the font size '" + String(p_old_name) + "' because it does not exist."); + + font_size_map[p_node_type][p_name] = font_size_map[p_node_type][p_old_name]; + font_size_map[p_node_type].erase(p_old_name); + + notify_property_list_changed(); + emit_changed(); +} + void Theme::clear_font_size(const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND(!font_size_map.has(p_node_type)); - ERR_FAIL_COND(!font_size_map[p_node_type].has(p_name)); + ERR_FAIL_COND_MSG(!font_size_map.has(p_node_type), "Cannot clear the font size '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); + ERR_FAIL_COND_MSG(!font_size_map[p_node_type].has(p_name), "Cannot clear the font size '" + String(p_name) + "' because it does not exist."); font_size_map[p_node_type].erase(p_name); notify_property_list_changed(); @@ -679,6 +790,19 @@ void Theme::get_font_size_list(StringName p_node_type, List<StringName> *p_list) } } +void Theme::add_font_size_type(const StringName &p_node_type) { + font_size_map[p_node_type] = HashMap<StringName, int>(); +} + +void Theme::get_font_size_type_list(List<StringName> *p_list) const { + ERR_FAIL_NULL(p_list); + + const StringName *key = nullptr; + while ((key = font_size_map.next(key))) { + p_list->push_back(*key); + } +} + void Theme::set_color(const StringName &p_name, const StringName &p_node_type, const Color &p_color) { bool new_value = !color_map.has(p_node_type) || !color_map[p_node_type].has(p_name); @@ -702,9 +826,21 @@ bool Theme::has_color(const StringName &p_name, const StringName &p_node_type) c return (color_map.has(p_node_type) && color_map[p_node_type].has(p_name)); } +void Theme::rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { + ERR_FAIL_COND_MSG(!color_map.has(p_node_type), "Cannot rename the color '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); + ERR_FAIL_COND_MSG(color_map[p_node_type].has(p_name), "Cannot rename the color '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); + ERR_FAIL_COND_MSG(!color_map[p_node_type].has(p_old_name), "Cannot rename the color '" + String(p_old_name) + "' because it does not exist."); + + color_map[p_node_type][p_name] = color_map[p_node_type][p_old_name]; + color_map[p_node_type].erase(p_old_name); + + notify_property_list_changed(); + emit_changed(); +} + void Theme::clear_color(const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND(!color_map.has(p_node_type)); - ERR_FAIL_COND(!color_map[p_node_type].has(p_name)); + ERR_FAIL_COND_MSG(!color_map.has(p_node_type), "Cannot clear the color '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); + ERR_FAIL_COND_MSG(!color_map[p_node_type].has(p_name), "Cannot clear the color '" + String(p_name) + "' because it does not exist."); color_map[p_node_type].erase(p_name); notify_property_list_changed(); @@ -725,6 +861,10 @@ void Theme::get_color_list(StringName p_node_type, List<StringName> *p_list) con } } +void Theme::add_color_type(const StringName &p_node_type) { + color_map[p_node_type] = HashMap<StringName, Color>(); +} + void Theme::get_color_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); @@ -756,9 +896,21 @@ bool Theme::has_constant(const StringName &p_name, const StringName &p_node_type return (constant_map.has(p_node_type) && constant_map[p_node_type].has(p_name)); } +void Theme::rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { + ERR_FAIL_COND_MSG(!constant_map.has(p_node_type), "Cannot rename the constant '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); + ERR_FAIL_COND_MSG(constant_map[p_node_type].has(p_name), "Cannot rename the constant '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); + ERR_FAIL_COND_MSG(!constant_map[p_node_type].has(p_old_name), "Cannot rename the constant '" + String(p_old_name) + "' because it does not exist."); + + constant_map[p_node_type][p_name] = constant_map[p_node_type][p_old_name]; + constant_map[p_node_type].erase(p_old_name); + + notify_property_list_changed(); + emit_changed(); +} + void Theme::clear_constant(const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND(!constant_map.has(p_node_type)); - ERR_FAIL_COND(!constant_map[p_node_type].has(p_name)); + ERR_FAIL_COND_MSG(!constant_map.has(p_node_type), "Cannot clear the constant '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); + ERR_FAIL_COND_MSG(!constant_map[p_node_type].has(p_name), "Cannot clear the constant '" + String(p_name) + "' because it does not exist."); constant_map[p_node_type].erase(p_name); notify_property_list_changed(); @@ -779,6 +931,10 @@ void Theme::get_constant_list(StringName p_node_type, List<StringName> *p_list) } } +void Theme::add_constant_type(const StringName &p_node_type) { + constant_map[p_node_type] = HashMap<StringName, int>(); +} + void Theme::get_constant_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); @@ -788,6 +944,216 @@ void Theme::get_constant_type_list(List<StringName> *p_list) const { } } +void Theme::set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type, const Variant &p_value) { + switch (p_data_type) { + case DATA_TYPE_COLOR: { + ERR_FAIL_COND_MSG(p_value.get_type() != Variant::COLOR, "Theme item's data type (Color) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ")."); + + Color color_value = p_value; + set_color(p_name, p_node_type, color_value); + } break; + case DATA_TYPE_CONSTANT: { + ERR_FAIL_COND_MSG(p_value.get_type() != Variant::INT, "Theme item's data type (int) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ")."); + + int constant_value = p_value; + set_constant(p_name, p_node_type, constant_value); + } break; + case DATA_TYPE_FONT: { + ERR_FAIL_COND_MSG(p_value.get_type() != Variant::OBJECT, "Theme item's data type (Object) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ")."); + + Ref<Font> font_value = Object::cast_to<Font>(p_value.get_validated_object()); + set_font(p_name, p_node_type, font_value); + } break; + case DATA_TYPE_FONT_SIZE: { + ERR_FAIL_COND_MSG(p_value.get_type() != Variant::INT, "Theme item's data type (int) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ")."); + + int font_size_value = p_value; + set_font_size(p_name, p_node_type, font_size_value); + } break; + case DATA_TYPE_ICON: { + ERR_FAIL_COND_MSG(p_value.get_type() != Variant::OBJECT, "Theme item's data type (Object) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ")."); + + Ref<Texture2D> icon_value = Object::cast_to<Texture2D>(p_value.get_validated_object()); + set_icon(p_name, p_node_type, icon_value); + } break; + case DATA_TYPE_STYLEBOX: { + ERR_FAIL_COND_MSG(p_value.get_type() != Variant::OBJECT, "Theme item's data type (Object) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ")."); + + Ref<StyleBox> stylebox_value = Object::cast_to<StyleBox>(p_value.get_validated_object()); + set_stylebox(p_name, p_node_type, stylebox_value); + } break; + case DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } +} + +Variant Theme::get_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const { + switch (p_data_type) { + case DATA_TYPE_COLOR: + return get_color(p_name, p_node_type); + case DATA_TYPE_CONSTANT: + return get_constant(p_name, p_node_type); + case DATA_TYPE_FONT: + return get_font(p_name, p_node_type); + case DATA_TYPE_FONT_SIZE: + return get_font_size(p_name, p_node_type); + case DATA_TYPE_ICON: + return get_icon(p_name, p_node_type); + case DATA_TYPE_STYLEBOX: + return get_stylebox(p_name, p_node_type); + case DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } + + return Variant(); +} + +bool Theme::has_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const { + switch (p_data_type) { + case DATA_TYPE_COLOR: + return has_color(p_name, p_node_type); + case DATA_TYPE_CONSTANT: + return has_constant(p_name, p_node_type); + case DATA_TYPE_FONT: + return has_font(p_name, p_node_type); + case DATA_TYPE_FONT_SIZE: + return has_font_size(p_name, p_node_type); + case DATA_TYPE_ICON: + return has_icon(p_name, p_node_type); + case DATA_TYPE_STYLEBOX: + return has_stylebox(p_name, p_node_type); + case DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } + + return false; +} + +void Theme::rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { + switch (p_data_type) { + case DATA_TYPE_COLOR: + rename_color(p_old_name, p_name, p_node_type); + break; + case DATA_TYPE_CONSTANT: + rename_constant(p_old_name, p_name, p_node_type); + break; + case DATA_TYPE_FONT: + rename_font(p_old_name, p_name, p_node_type); + break; + case DATA_TYPE_FONT_SIZE: + rename_font_size(p_old_name, p_name, p_node_type); + break; + case DATA_TYPE_ICON: + rename_icon(p_old_name, p_name, p_node_type); + break; + case DATA_TYPE_STYLEBOX: + rename_stylebox(p_old_name, p_name, p_node_type); + break; + case DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } +} + +void Theme::clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) { + switch (p_data_type) { + case DATA_TYPE_COLOR: + clear_color(p_name, p_node_type); + break; + case DATA_TYPE_CONSTANT: + clear_constant(p_name, p_node_type); + break; + case DATA_TYPE_FONT: + clear_font(p_name, p_node_type); + break; + case DATA_TYPE_FONT_SIZE: + clear_font_size(p_name, p_node_type); + break; + case DATA_TYPE_ICON: + clear_icon(p_name, p_node_type); + break; + case DATA_TYPE_STYLEBOX: + clear_stylebox(p_name, p_node_type); + break; + case DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } +} + +void Theme::get_theme_item_list(DataType p_data_type, StringName p_node_type, List<StringName> *p_list) const { + switch (p_data_type) { + case DATA_TYPE_COLOR: + get_color_list(p_node_type, p_list); + break; + case DATA_TYPE_CONSTANT: + get_constant_list(p_node_type, p_list); + break; + case DATA_TYPE_FONT: + get_font_list(p_node_type, p_list); + break; + case DATA_TYPE_FONT_SIZE: + get_font_size_list(p_node_type, p_list); + break; + case DATA_TYPE_ICON: + get_icon_list(p_node_type, p_list); + break; + case DATA_TYPE_STYLEBOX: + get_stylebox_list(p_node_type, p_list); + break; + case DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } +} + +void Theme::add_theme_item_type(DataType p_data_type, const StringName &p_node_type) { + switch (p_data_type) { + case DATA_TYPE_COLOR: + add_color_type(p_node_type); + break; + case DATA_TYPE_CONSTANT: + add_constant_type(p_node_type); + break; + case DATA_TYPE_FONT: + add_font_type(p_node_type); + break; + case DATA_TYPE_FONT_SIZE: + add_font_size_type(p_node_type); + break; + case DATA_TYPE_ICON: + add_icon_type(p_node_type); + break; + case DATA_TYPE_STYLEBOX: + add_stylebox_type(p_node_type); + break; + case DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } +} + +void Theme::get_theme_item_type_list(DataType p_data_type, List<StringName> *p_list) const { + switch (p_data_type) { + case DATA_TYPE_COLOR: + get_color_type_list(p_list); + break; + case DATA_TYPE_CONSTANT: + get_constant_type_list(p_list); + break; + case DATA_TYPE_FONT: + get_font_type_list(p_list); + break; + case DATA_TYPE_FONT_SIZE: + get_font_size_type_list(p_list); + break; + case DATA_TYPE_ICON: + get_icon_type_list(p_list); + break; + case DATA_TYPE_STYLEBOX: + get_stylebox_type_list(p_list); + break; + case DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } +} + void Theme::clear() { //these need disconnecting { @@ -847,11 +1213,10 @@ void Theme::copy_default_theme() { void Theme::copy_theme(const Ref<Theme> &p_other) { if (p_other.is_null()) { clear(); - return; } - //these need reconnecting, so add normally + // These items need reconnecting, so add them normally. { const StringName *K = nullptr; while ((K = p_other->icon_map.next(K))) { @@ -882,8 +1247,8 @@ void Theme::copy_theme(const Ref<Theme> &p_other) { } } - //these are ok to just copy - + // These items can be simply copied. + font_size_map = p_other->font_size_map; color_map = p_other->color_map; constant_map = p_other->constant_map; @@ -937,6 +1302,7 @@ void Theme::_bind_methods() { ClassDB::bind_method(D_METHOD("set_icon", "name", "node_type", "texture"), &Theme::set_icon); ClassDB::bind_method(D_METHOD("get_icon", "name", "node_type"), &Theme::get_icon); ClassDB::bind_method(D_METHOD("has_icon", "name", "node_type"), &Theme::has_icon); + ClassDB::bind_method(D_METHOD("rename_icon", "old_name", "name", "node_type"), &Theme::rename_icon); ClassDB::bind_method(D_METHOD("clear_icon", "name", "node_type"), &Theme::clear_icon); ClassDB::bind_method(D_METHOD("get_icon_list", "node_type"), &Theme::_get_icon_list); ClassDB::bind_method(D_METHOD("get_icon_type_list"), &Theme::_get_icon_type_list); @@ -944,6 +1310,7 @@ void Theme::_bind_methods() { ClassDB::bind_method(D_METHOD("set_stylebox", "name", "node_type", "texture"), &Theme::set_stylebox); ClassDB::bind_method(D_METHOD("get_stylebox", "name", "node_type"), &Theme::get_stylebox); ClassDB::bind_method(D_METHOD("has_stylebox", "name", "node_type"), &Theme::has_stylebox); + ClassDB::bind_method(D_METHOD("rename_stylebox", "old_name", "name", "node_type"), &Theme::rename_stylebox); ClassDB::bind_method(D_METHOD("clear_stylebox", "name", "node_type"), &Theme::clear_stylebox); ClassDB::bind_method(D_METHOD("get_stylebox_list", "node_type"), &Theme::_get_stylebox_list); ClassDB::bind_method(D_METHOD("get_stylebox_type_list"), &Theme::_get_stylebox_type_list); @@ -951,6 +1318,7 @@ void Theme::_bind_methods() { ClassDB::bind_method(D_METHOD("set_font", "name", "node_type", "font"), &Theme::set_font); ClassDB::bind_method(D_METHOD("get_font", "name", "node_type"), &Theme::get_font); ClassDB::bind_method(D_METHOD("has_font", "name", "node_type"), &Theme::has_font); + ClassDB::bind_method(D_METHOD("rename_font", "old_name", "name", "node_type"), &Theme::rename_font); ClassDB::bind_method(D_METHOD("clear_font", "name", "node_type"), &Theme::clear_font); ClassDB::bind_method(D_METHOD("get_font_list", "node_type"), &Theme::_get_font_list); ClassDB::bind_method(D_METHOD("get_font_type_list"), &Theme::_get_font_type_list); @@ -958,12 +1326,15 @@ void Theme::_bind_methods() { ClassDB::bind_method(D_METHOD("set_font_size", "name", "node_type", "font_size"), &Theme::set_font_size); ClassDB::bind_method(D_METHOD("get_font_size", "name", "node_type"), &Theme::get_font_size); ClassDB::bind_method(D_METHOD("has_font_size", "name", "node_type"), &Theme::has_font_size); + ClassDB::bind_method(D_METHOD("rename_font_size", "old_name", "name", "node_type"), &Theme::rename_font_size); ClassDB::bind_method(D_METHOD("clear_font_size", "name", "node_type"), &Theme::clear_font_size); ClassDB::bind_method(D_METHOD("get_font_size_list", "node_type"), &Theme::_get_font_size_list); + ClassDB::bind_method(D_METHOD("get_font_size_type_list"), &Theme::_get_font_size_type_list); ClassDB::bind_method(D_METHOD("set_color", "name", "node_type", "color"), &Theme::set_color); ClassDB::bind_method(D_METHOD("get_color", "name", "node_type"), &Theme::get_color); ClassDB::bind_method(D_METHOD("has_color", "name", "node_type"), &Theme::has_color); + ClassDB::bind_method(D_METHOD("rename_color", "old_name", "name", "node_type"), &Theme::rename_color); ClassDB::bind_method(D_METHOD("clear_color", "name", "node_type"), &Theme::clear_color); ClassDB::bind_method(D_METHOD("get_color_list", "node_type"), &Theme::_get_color_list); ClassDB::bind_method(D_METHOD("get_color_type_list"), &Theme::_get_color_type_list); @@ -971,6 +1342,7 @@ void Theme::_bind_methods() { ClassDB::bind_method(D_METHOD("set_constant", "name", "node_type", "constant"), &Theme::set_constant); ClassDB::bind_method(D_METHOD("get_constant", "name", "node_type"), &Theme::get_constant); ClassDB::bind_method(D_METHOD("has_constant", "name", "node_type"), &Theme::has_constant); + ClassDB::bind_method(D_METHOD("rename_constant", "old_name", "name", "node_type"), &Theme::rename_constant); ClassDB::bind_method(D_METHOD("clear_constant", "name", "node_type"), &Theme::clear_constant); ClassDB::bind_method(D_METHOD("get_constant_list", "node_type"), &Theme::_get_constant_list); ClassDB::bind_method(D_METHOD("get_constant_type_list"), &Theme::_get_constant_type_list); @@ -983,6 +1355,14 @@ void Theme::_bind_methods() { ClassDB::bind_method(D_METHOD("set_default_font_size", "font_size"), &Theme::set_default_theme_font_size); ClassDB::bind_method(D_METHOD("get_default_font_size"), &Theme::get_default_theme_font_size); + ClassDB::bind_method(D_METHOD("set_theme_item", "data_type", "name", "node_type", "value"), &Theme::set_theme_item); + ClassDB::bind_method(D_METHOD("get_theme_item", "data_type", "name", "node_type"), &Theme::get_theme_item); + ClassDB::bind_method(D_METHOD("has_theme_item", "data_type", "name", "node_type"), &Theme::has_theme_item); + ClassDB::bind_method(D_METHOD("rename_theme_item", "data_type", "old_name", "name", "node_type"), &Theme::rename_theme_item); + ClassDB::bind_method(D_METHOD("clear_theme_item", "data_type", "name", "node_type"), &Theme::clear_theme_item); + ClassDB::bind_method(D_METHOD("get_theme_item_list", "data_type", "node_type"), &Theme::_get_theme_item_list); + ClassDB::bind_method(D_METHOD("get_theme_item_type_list", "data_type"), &Theme::_get_theme_item_type_list); + ClassDB::bind_method(D_METHOD("get_type_list"), &Theme::_get_type_list); ClassDB::bind_method("copy_default_theme", &Theme::copy_default_theme); @@ -990,6 +1370,14 @@ void Theme::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "default_font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_default_font", "get_default_font"); ADD_PROPERTY(PropertyInfo(Variant::INT, "default_font_size"), "set_default_font_size", "get_default_font_size"); + + BIND_ENUM_CONSTANT(DATA_TYPE_COLOR); + BIND_ENUM_CONSTANT(DATA_TYPE_CONSTANT); + BIND_ENUM_CONSTANT(DATA_TYPE_FONT); + BIND_ENUM_CONSTANT(DATA_TYPE_FONT_SIZE); + BIND_ENUM_CONSTANT(DATA_TYPE_ICON); + BIND_ENUM_CONSTANT(DATA_TYPE_STYLEBOX); + BIND_ENUM_CONSTANT(DATA_TYPE_MAX); } Theme::Theme() { diff --git a/scene/resources/theme.h b/scene/resources/theme.h index 35481126ea..eb918fac69 100644 --- a/scene/resources/theme.h +++ b/scene/resources/theme.h @@ -41,6 +41,18 @@ class Theme : public Resource { GDCLASS(Theme, Resource); RES_BASE_EXTENSION("theme"); +public: + enum DataType { + DATA_TYPE_COLOR, + DATA_TYPE_CONSTANT, + DATA_TYPE_FONT, + DATA_TYPE_FONT_SIZE, + DATA_TYPE_ICON, + DATA_TYPE_STYLEBOX, + DATA_TYPE_MAX + }; + +private: void _emit_theme_changed(); HashMap<StringName, HashMap<StringName, Ref<Texture2D>>> icon_map; @@ -57,10 +69,14 @@ class Theme : public Resource { Vector<String> _get_font_list(const String &p_node_type) const; Vector<String> _get_font_type_list() const; Vector<String> _get_font_size_list(const String &p_node_type) const; + Vector<String> _get_font_size_type_list() const; Vector<String> _get_color_list(const String &p_node_type) const; Vector<String> _get_color_type_list() const; Vector<String> _get_constant_list(const String &p_node_type) const; Vector<String> _get_constant_type_list() const; + + Vector<String> _get_theme_item_list(DataType p_data_type, const String &p_node_type) const; + Vector<String> _get_theme_item_type_list(DataType p_data_type) const; Vector<String> _get_type_list() const; protected: @@ -103,44 +119,66 @@ public: void set_icon(const StringName &p_name, const StringName &p_node_type, const Ref<Texture2D> &p_icon); Ref<Texture2D> get_icon(const StringName &p_name, const StringName &p_node_type) const; bool has_icon(const StringName &p_name, const StringName &p_node_type) const; + void rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void clear_icon(const StringName &p_name, const StringName &p_node_type); void get_icon_list(StringName p_node_type, List<StringName> *p_list) const; + void add_icon_type(const StringName &p_node_type); void get_icon_type_list(List<StringName> *p_list) const; void set_stylebox(const StringName &p_name, const StringName &p_node_type, const Ref<StyleBox> &p_style); Ref<StyleBox> get_stylebox(const StringName &p_name, const StringName &p_node_type) const; bool has_stylebox(const StringName &p_name, const StringName &p_node_type) const; + void rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void clear_stylebox(const StringName &p_name, const StringName &p_node_type); void get_stylebox_list(StringName p_node_type, List<StringName> *p_list) const; + void add_stylebox_type(const StringName &p_node_type); void get_stylebox_type_list(List<StringName> *p_list) const; void set_font(const StringName &p_name, const StringName &p_node_type, const Ref<Font> &p_font); Ref<Font> get_font(const StringName &p_name, const StringName &p_node_type) const; bool has_font(const StringName &p_name, const StringName &p_node_type) const; + void rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void clear_font(const StringName &p_name, const StringName &p_node_type); void get_font_list(StringName p_node_type, List<StringName> *p_list) const; + void add_font_type(const StringName &p_node_type); void get_font_type_list(List<StringName> *p_list) const; void set_font_size(const StringName &p_name, const StringName &p_node_type, int p_font_size); int get_font_size(const StringName &p_name, const StringName &p_node_type) const; bool has_font_size(const StringName &p_name, const StringName &p_node_type) const; + void rename_font_size(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void clear_font_size(const StringName &p_name, const StringName &p_node_type); void get_font_size_list(StringName p_node_type, List<StringName> *p_list) const; + void add_font_size_type(const StringName &p_node_type); + void get_font_size_type_list(List<StringName> *p_list) const; void set_color(const StringName &p_name, const StringName &p_node_type, const Color &p_color); Color get_color(const StringName &p_name, const StringName &p_node_type) const; bool has_color(const StringName &p_name, const StringName &p_node_type) const; + void rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void clear_color(const StringName &p_name, const StringName &p_node_type); void get_color_list(StringName p_node_type, List<StringName> *p_list) const; + void add_color_type(const StringName &p_node_type); void get_color_type_list(List<StringName> *p_list) const; void set_constant(const StringName &p_name, const StringName &p_node_type, int p_constant); int get_constant(const StringName &p_name, const StringName &p_node_type) const; bool has_constant(const StringName &p_name, const StringName &p_node_type) const; + void rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void clear_constant(const StringName &p_name, const StringName &p_node_type); void get_constant_list(StringName p_node_type, List<StringName> *p_list) const; + void add_constant_type(const StringName &p_node_type); void get_constant_type_list(List<StringName> *p_list) const; + void set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type, const Variant &p_value); + Variant get_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const; + bool has_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const; + void rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); + void clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type); + void get_theme_item_list(DataType p_data_type, StringName p_node_type, List<StringName> *p_list) const; + void add_theme_item_type(DataType p_data_type, const StringName &p_node_type); + void get_theme_item_type_list(DataType p_data_type, List<StringName> *p_list) const; + void get_type_list(List<StringName> *p_list) const; void copy_default_theme(); @@ -151,4 +189,6 @@ public: ~Theme(); }; +VARIANT_ENUM_CAST(Theme::DataType); + #endif diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 859546694f..e1e24ddab2 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -2667,6 +2667,70 @@ VisualShaderNodeResizableBase::VisualShaderNodeResizableBase() { set_allow_v_resize(true); } +////////////// Comment + +String VisualShaderNodeComment::get_caption() const { + return title; +} + +int VisualShaderNodeComment::get_input_port_count() const { + return 0; +} + +VisualShaderNodeComment::PortType VisualShaderNodeComment::get_input_port_type(int p_port) const { + return PortType::PORT_TYPE_SCALAR; +} + +String VisualShaderNodeComment::get_input_port_name(int p_port) const { + return String(); +} + +int VisualShaderNodeComment::get_output_port_count() const { + return 0; +} + +VisualShaderNodeComment::PortType VisualShaderNodeComment::get_output_port_type(int p_port) const { + return PortType::PORT_TYPE_SCALAR; +} + +String VisualShaderNodeComment::get_output_port_name(int p_port) const { + return String(); +} + +void VisualShaderNodeComment::set_title(const String &p_title) { + title = p_title; +} + +String VisualShaderNodeComment::get_title() const { + return title; +} + +void VisualShaderNodeComment::set_description(const String &p_description) { + description = p_description; +} + +String VisualShaderNodeComment::get_description() const { + return description; +} + +String VisualShaderNodeComment::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { + return String(); +} + +void VisualShaderNodeComment::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_title", "title"), &VisualShaderNodeComment::set_title); + ClassDB::bind_method(D_METHOD("get_title"), &VisualShaderNodeComment::get_title); + + ClassDB::bind_method(D_METHOD("set_description", "description"), &VisualShaderNodeComment::set_description); + ClassDB::bind_method(D_METHOD("get_description"), &VisualShaderNodeComment::get_description); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "description"), "set_description", "get_description"); +} + +VisualShaderNodeComment::VisualShaderNodeComment() { +} + ////////////// GroupBase void VisualShaderNodeGroupBase::set_inputs(const String &p_inputs) { diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index ef724c7650..54a5c19049 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -421,6 +421,7 @@ public: bool is_global_code_generated() const; virtual bool is_qualifier_supported(Qualifier p_qual) const = 0; + virtual bool is_convertible_to_constant() const = 0; virtual Vector<StringName> get_editable_properties() const override; virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override; @@ -510,6 +511,38 @@ public: VisualShaderNodeResizableBase(); }; +class VisualShaderNodeComment : public VisualShaderNodeResizableBase { + GDCLASS(VisualShaderNodeComment, VisualShaderNodeResizableBase); + +protected: + String title = "Comment"; + String description = ""; + +protected: + static void _bind_methods(); + +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; + + void set_title(const String &p_title); + String get_title() const; + + void set_description(const String &p_description); + String get_description() const; + + VisualShaderNodeComment(); +}; + class VisualShaderNodeGroupBase : public VisualShaderNodeResizableBase { GDCLASS(VisualShaderNodeGroupBase, VisualShaderNodeResizableBase); diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index a99c09e89c..7943b95177 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -3744,6 +3744,10 @@ bool VisualShaderNodeFloatUniform::is_qualifier_supported(Qualifier p_qual) cons return true; // all qualifiers are supported } +bool VisualShaderNodeFloatUniform::is_convertible_to_constant() const { + return true; // conversion is allowed +} + Vector<StringName> VisualShaderNodeFloatUniform::get_editable_properties() const { Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); props.push_back("hint"); @@ -3911,6 +3915,10 @@ bool VisualShaderNodeIntUniform::is_qualifier_supported(Qualifier p_qual) const return true; // all qualifiers are supported } +bool VisualShaderNodeIntUniform::is_convertible_to_constant() const { + return true; // conversion is allowed +} + Vector<StringName> VisualShaderNodeIntUniform::get_editable_properties() const { Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); props.push_back("hint"); @@ -4019,6 +4027,10 @@ bool VisualShaderNodeBooleanUniform::is_qualifier_supported(Qualifier p_qual) co return true; // all qualifiers are supported } +bool VisualShaderNodeBooleanUniform::is_convertible_to_constant() const { + return true; // conversion is allowed +} + Vector<StringName> VisualShaderNodeBooleanUniform::get_editable_properties() const { Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); props.push_back("default_value_enabled"); @@ -4113,6 +4125,10 @@ bool VisualShaderNodeColorUniform::is_qualifier_supported(Qualifier p_qual) cons return true; // all qualifiers are supported } +bool VisualShaderNodeColorUniform::is_convertible_to_constant() const { + return true; // conversion is allowed +} + Vector<StringName> VisualShaderNodeColorUniform::get_editable_properties() const { Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); props.push_back("default_value_enabled"); @@ -4209,6 +4225,10 @@ bool VisualShaderNodeVec3Uniform::is_qualifier_supported(Qualifier p_qual) const return true; // all qualifiers are supported } +bool VisualShaderNodeVec3Uniform::is_convertible_to_constant() const { + return true; // conversion is allowed +} + Vector<StringName> VisualShaderNodeVec3Uniform::get_editable_properties() const { Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); props.push_back("default_value_enabled"); @@ -4309,6 +4329,10 @@ bool VisualShaderNodeTransformUniform::is_qualifier_supported(Qualifier p_qual) return true; // all qualifiers are supported } +bool VisualShaderNodeTransformUniform::is_convertible_to_constant() const { + return true; // conversion is allowed +} + Vector<StringName> VisualShaderNodeTransformUniform::get_editable_properties() const { Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); props.push_back("default_value_enabled"); @@ -4494,6 +4518,10 @@ bool VisualShaderNodeTextureUniform::is_qualifier_supported(Qualifier p_qual) co return false; } +bool VisualShaderNodeTextureUniform::is_convertible_to_constant() const { + return false; // conversion is not allowed +} + VisualShaderNodeTextureUniform::VisualShaderNodeTextureUniform() { simple_decl = false; } @@ -4632,16 +4660,18 @@ String VisualShaderNodeTexture2DArrayUniform::generate_global(Shader::Mode p_mod switch (texture_type) { case TYPE_DATA: - if (color_default == COLOR_DEFAULT_BLACK) + if (color_default == COLOR_DEFAULT_BLACK) { code += " : hint_black;\n"; - else + } else { code += ";\n"; + } break; case TYPE_COLOR: - if (color_default == COLOR_DEFAULT_BLACK) + if (color_default == COLOR_DEFAULT_BLACK) { code += " : hint_black_albedo;\n"; - else + } else { code += " : hint_albedo;\n"; + } break; case TYPE_NORMAL_MAP: code += " : hint_normal;\n"; @@ -4700,16 +4730,18 @@ String VisualShaderNodeTexture3DUniform::generate_global(Shader::Mode p_mode, Vi switch (texture_type) { case TYPE_DATA: - if (color_default == COLOR_DEFAULT_BLACK) + if (color_default == COLOR_DEFAULT_BLACK) { code += " : hint_black;\n"; - else + } else { code += ";\n"; + } break; case TYPE_COLOR: - if (color_default == COLOR_DEFAULT_BLACK) + if (color_default == COLOR_DEFAULT_BLACK) { code += " : hint_black_albedo;\n"; - else + } else { code += " : hint_albedo;\n"; + } break; case TYPE_NORMAL_MAP: code += " : hint_normal;\n"; diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index a5d0fe4649..594a494cf1 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -1574,6 +1574,7 @@ public: float get_default_value() const; bool is_qualifier_supported(Qualifier p_qual) const override; + bool is_convertible_to_constant() const override; virtual Vector<StringName> get_editable_properties() const override; @@ -1639,6 +1640,7 @@ public: int get_default_value() const; bool is_qualifier_supported(Qualifier p_qual) const override; + bool is_convertible_to_constant() const override; virtual Vector<StringName> get_editable_properties() const override; @@ -1683,6 +1685,7 @@ public: bool get_default_value() const; bool is_qualifier_supported(Qualifier p_qual) const override; + bool is_convertible_to_constant() const override; virtual Vector<StringName> get_editable_properties() const override; @@ -1724,6 +1727,7 @@ public: Color get_default_value() const; bool is_qualifier_supported(Qualifier p_qual) const override; + bool is_convertible_to_constant() const override; virtual Vector<StringName> get_editable_properties() const override; @@ -1766,6 +1770,7 @@ public: Vector3 get_default_value() const; bool is_qualifier_supported(Qualifier p_qual) const override; + bool is_convertible_to_constant() const override; virtual Vector<StringName> get_editable_properties() const override; @@ -1808,6 +1813,7 @@ public: Transform get_default_value() const; bool is_qualifier_supported(Qualifier p_qual) const override; + bool is_convertible_to_constant() const override; virtual Vector<StringName> get_editable_properties() const override; @@ -1865,6 +1871,7 @@ public: ColorDefault get_color_default() const; bool is_qualifier_supported(Qualifier p_qual) const override; + bool is_convertible_to_constant() const override; VisualShaderNodeTextureUniform(); }; diff --git a/servers/camera_server.cpp b/servers/camera_server.cpp index b06f32417c..ee4a2e148b 100644 --- a/servers/camera_server.cpp +++ b/servers/camera_server.cpp @@ -99,6 +99,8 @@ Ref<CameraFeed> CameraServer::get_feed_by_id(int p_id) { }; void CameraServer::add_feed(const Ref<CameraFeed> &p_feed) { + ERR_FAIL_COND(p_feed.is_null()); + // add our feed feeds.push_back(p_feed); diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp index 6485c8d1e9..532cb259b3 100644 --- a/servers/physics_2d/area_2d_sw.cpp +++ b/servers/physics_2d/area_2d_sw.cpp @@ -215,7 +215,9 @@ void Area2DSW::call_queries() { for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) { if (E->get().state == 0) { // Nothing happened - E = E->next(); + Map<BodyKey, BodyState>::Element *next = E->next(); + monitored_bodies.erase(E); + E = next; continue; } @@ -250,7 +252,9 @@ void Area2DSW::call_queries() { for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) { if (E->get().state == 0) { // Nothing happened - E = E->next(); + Map<BodyKey, BodyState>::Element *next = E->next(); + monitored_areas.erase(E); + E = next; continue; } diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp index feced36a2b..da70ac7d4b 100644 --- a/servers/physics_2d/body_pair_2d_sw.cpp +++ b/servers/physics_2d/body_pair_2d_sw.cpp @@ -221,11 +221,21 @@ real_t combine_friction(Body2DSW *A, Body2DSW *B) { bool BodyPair2DSW::setup(real_t p_step) { //cannot collide - if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode() <= PhysicsServer2D::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer2D::BODY_MODE_KINEMATIC && A->get_max_contacts_reported() == 0 && B->get_max_contacts_reported() == 0)) { + if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) { collided = false; return false; } + bool report_contacts_only = false; + if ((A->get_mode() <= PhysicsServer2D::BODY_MODE_KINEMATIC) && (B->get_mode() <= PhysicsServer2D::BODY_MODE_KINEMATIC)) { + if ((A->get_max_contacts_reported() > 0) || (B->get_max_contacts_reported() > 0)) { + report_contacts_only = true; + } else { + collided = false; + return false; + } + } + if (A->is_shape_set_as_disabled(shape_A) || B->is_shape_set_as_disabled(shape_B)) { collided = false; return false; @@ -350,51 +360,44 @@ bool BodyPair2DSW::setup(real_t p_step) { for (int i = 0; i < contact_count; i++) { Contact &c = contacts[i]; + c.active = false; + Vector2 global_A = xform_Au.xform(c.local_A); Vector2 global_B = xform_Bu.xform(c.local_B); real_t depth = c.normal.dot(global_A - global_B); if (depth <= 0 || !c.reused) { - c.active = false; continue; } - c.active = true; #ifdef DEBUG_ENABLED if (space->is_debugging_contacts()) { space->add_debug_contact(global_A + offset_A); space->add_debug_contact(global_B + offset_A); } #endif - int gather_A = A->can_report_contacts(); - int gather_B = B->can_report_contacts(); c.rA = global_A; c.rB = global_B - offset_B; - if (gather_A | gather_B) { - //Vector2 crB( -B->get_angular_velocity() * c.rB.y, B->get_angular_velocity() * c.rB.x ); - - global_A += offset_A; - global_B += offset_A; + if (A->can_report_contacts()) { + Vector2 crB(-B->get_angular_velocity() * c.rB.y, B->get_angular_velocity() * c.rB.x); + A->add_contact(global_A + offset_A, -c.normal, depth, shape_A, global_B + offset_A, shape_B, B->get_instance_id(), B->get_self(), crB + B->get_linear_velocity()); + } - if (gather_A) { - Vector2 crB(-B->get_angular_velocity() * c.rB.y, B->get_angular_velocity() * c.rB.x); - A->add_contact(global_A, -c.normal, depth, shape_A, global_B, shape_B, B->get_instance_id(), B->get_self(), crB + B->get_linear_velocity()); - } - if (gather_B) { - Vector2 crA(-A->get_angular_velocity() * c.rA.y, A->get_angular_velocity() * c.rA.x); - B->add_contact(global_B, c.normal, depth, shape_B, global_A, shape_A, A->get_instance_id(), A->get_self(), crA + A->get_linear_velocity()); - } + if (B->can_report_contacts()) { + Vector2 crA(-A->get_angular_velocity() * c.rA.y, A->get_angular_velocity() * c.rA.x); + B->add_contact(global_B + offset_A, c.normal, depth, shape_B, global_A + offset_A, shape_A, A->get_instance_id(), A->get_self(), crA + A->get_linear_velocity()); } - if ((A->get_mode() <= PhysicsServer2D::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer2D::BODY_MODE_KINEMATIC)) { - c.active = false; + if (report_contacts_only) { collided = false; continue; } + c.active = true; + // Precompute normal mass, tangent mass, and bias. real_t rnA = c.rA.dot(c.normal); real_t rnB = c.rB.dot(c.normal); diff --git a/servers/physics_3d/area_3d_sw.cpp b/servers/physics_3d/area_3d_sw.cpp index b6c5b3003c..bb4e0ed752 100644 --- a/servers/physics_3d/area_3d_sw.cpp +++ b/servers/physics_3d/area_3d_sw.cpp @@ -215,7 +215,9 @@ void Area3DSW::call_queries() { for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) { if (E->get().state == 0) { // Nothing happened - E = E->next(); + Map<BodyKey, BodyState>::Element *next = E->next(); + monitored_bodies.erase(E); + E = next; continue; } @@ -250,7 +252,9 @@ void Area3DSW::call_queries() { for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) { if (E->get().state == 0) { // Nothing happened - E = E->next(); + Map<BodyKey, BodyState>::Element *next = E->next(); + monitored_areas.erase(E); + E = next; continue; } diff --git a/servers/physics_3d/body_3d_sw.cpp b/servers/physics_3d/body_3d_sw.cpp index 9eff14bbeb..64ba0cb09d 100644 --- a/servers/physics_3d/body_3d_sw.cpp +++ b/servers/physics_3d/body_3d_sw.cpp @@ -501,20 +501,18 @@ void Body3DSW::integrate_forces(real_t p_step) { if (mode == PhysicsServer3D::BODY_MODE_KINEMATIC) { //compute motion, angular and etc. velocities from prev transform - linear_velocity = (new_transform.origin - get_transform().origin) / p_step; + motion = new_transform.origin - get_transform().origin; + do_motion = true; + linear_velocity = motion / p_step; //compute a FAKE angular velocity, not so easy - Basis rot = new_transform.basis.orthonormalized().transposed() * get_transform().basis.orthonormalized(); + Basis rot = new_transform.basis.orthonormalized() * get_transform().basis.orthonormalized().transposed(); Vector3 axis; real_t angle; rot.get_axis_angle(axis, angle); axis.normalize(); - angular_velocity = axis.normalized() * (angle / p_step); - - motion = new_transform.origin - get_transform().origin; - do_motion = true; - + angular_velocity = axis * (angle / p_step); } else { if (!omit_force_integration && !first_integration) { //overridden by direct state query diff --git a/servers/physics_3d/body_3d_sw.h b/servers/physics_3d/body_3d_sw.h index 8e21003a5f..e87ff2364b 100644 --- a/servers/physics_3d/body_3d_sw.h +++ b/servers/physics_3d/body_3d_sw.h @@ -290,10 +290,10 @@ public: void update_inertias(); _FORCE_INLINE_ real_t get_inv_mass() const { return _inv_mass; } - _FORCE_INLINE_ Vector3 get_inv_inertia() const { return _inv_inertia; } - _FORCE_INLINE_ Basis get_inv_inertia_tensor() const { return _inv_inertia_tensor; } + _FORCE_INLINE_ const Vector3 &get_inv_inertia() const { return _inv_inertia; } + _FORCE_INLINE_ const Basis &get_inv_inertia_tensor() const { return _inv_inertia_tensor; } _FORCE_INLINE_ real_t get_friction() const { return friction; } - _FORCE_INLINE_ Vector3 get_gravity() const { return gravity; } + _FORCE_INLINE_ const Vector3 &get_gravity() const { return gravity; } _FORCE_INLINE_ real_t get_bounce() const { return bounce; } void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock); diff --git a/servers/physics_3d/body_pair_3d_sw.cpp b/servers/physics_3d/body_pair_3d_sw.cpp index 6012ff1522..36114c0c91 100644 --- a/servers/physics_3d/body_pair_3d_sw.cpp +++ b/servers/physics_3d/body_pair_3d_sw.cpp @@ -49,12 +49,12 @@ #define MIN_VELOCITY 0.0001 #define MAX_BIAS_ROTATION (Math_PI / 8) -void BodyPair3DSW::_contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) { +void BodyPair3DSW::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { BodyPair3DSW *pair = (BodyPair3DSW *)p_userdata; - pair->contact_added_callback(p_point_A, p_point_B); + pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B); } -void BodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B) { +void BodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B) { // check if we already have the contact //Vector3 local_A = A->get_inv_transform().xform(p_point_A); @@ -73,6 +73,8 @@ void BodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, const Vector contact.acc_bias_impulse = 0; contact.acc_bias_impulse_center_of_mass = 0; contact.acc_tangent_impulse = Vector3(); + contact.index_A = p_index_A; + contact.index_B = p_index_B; contact.local_A = local_A; contact.local_B = local_B; contact.normal = (p_point_A - p_point_B).normalized(); @@ -211,11 +213,21 @@ real_t combine_friction(Body3DSW *A, Body3DSW *B) { bool BodyPair3DSW::setup(real_t p_step) { //cannot collide - if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode() <= PhysicsServer3D::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer3D::BODY_MODE_KINEMATIC && A->get_max_contacts_reported() == 0 && B->get_max_contacts_reported() == 0)) { + if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) { collided = false; return false; } + bool report_contacts_only = false; + if ((A->get_mode() <= PhysicsServer3D::BODY_MODE_KINEMATIC) && (B->get_mode() <= PhysicsServer3D::BODY_MODE_KINEMATIC)) { + if ((A->get_max_contacts_reported() > 0) || (B->get_max_contacts_reported() > 0)) { + report_contacts_only = true; + } else { + collided = false; + return false; + } + } + if (A->is_shape_set_as_disabled(shape_A) || B->is_shape_set_as_disabled(shape_B)) { collided = false; return false; @@ -279,12 +291,9 @@ bool BodyPair3DSW::setup(real_t p_step) { real_t depth = c.normal.dot(global_A - global_B); if (depth <= 0) { - c.active = false; continue; } - c.active = true; - #ifdef DEBUG_ENABLED if (space->is_debugging_contacts()) { @@ -308,6 +317,11 @@ bool BodyPair3DSW::setup(real_t p_step) { B->add_contact(global_B, c.normal, depth, shape_B, global_A, shape_A, A->get_instance_id(), A->get_self(), crB); } + if (report_contacts_only) { + collided = false; + continue; + } + c.active = true; // Precompute normal mass, tangent mass, and bias. @@ -456,7 +470,7 @@ void BodyPair3DSW::solve(real_t p_step) { } BodyPair3DSW::BodyPair3DSW(Body3DSW *p_A, int p_shape_A, Body3DSW *p_B, int p_shape_B) : - Constraint3DSW(_arr, 2) { + BodyContact3DSW(_arr, 2) { A = p_A; B = p_B; shape_A = p_shape_A; @@ -472,3 +486,305 @@ BodyPair3DSW::~BodyPair3DSW() { A->remove_constraint(this); B->remove_constraint(this); } + +void BodySoftBodyPair3DSW::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { + BodySoftBodyPair3DSW *pair = (BodySoftBodyPair3DSW *)p_userdata; + pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B); +} + +void BodySoftBodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B) { + Vector3 local_A = body->get_inv_transform().xform(p_point_A); + Vector3 local_B = p_point_B - soft_body->get_node_position(p_index_B); + + Contact contact; + contact.index_A = p_index_A; + contact.index_B = p_index_B; + contact.acc_normal_impulse = 0; + contact.acc_bias_impulse = 0; + contact.acc_bias_impulse_center_of_mass = 0; + contact.acc_tangent_impulse = Vector3(); + contact.local_A = local_A; + contact.local_B = local_B; + contact.normal = (p_point_A - p_point_B).normalized(); + contact.mass_normal = 0; + + // Attempt to determine if the contact will be reused. + real_t contact_recycle_radius = space->get_contact_recycle_radius(); + + uint32_t contact_count = contacts.size(); + for (uint32_t contact_index = 0; contact_index < contact_count; ++contact_index) { + Contact &c = contacts[contact_index]; + if (c.index_B == p_index_B) { + if (c.local_A.distance_squared_to(local_A) < (contact_recycle_radius * contact_recycle_radius) && + c.local_B.distance_squared_to(local_B) < (contact_recycle_radius * contact_recycle_radius)) { + contact.acc_normal_impulse = c.acc_normal_impulse; + contact.acc_bias_impulse = c.acc_bias_impulse; + contact.acc_bias_impulse_center_of_mass = c.acc_bias_impulse_center_of_mass; + contact.acc_tangent_impulse = c.acc_tangent_impulse; + } + c = contact; + return; + } + } + + contacts.push_back(contact); +} + +void BodySoftBodyPair3DSW::validate_contacts() { + // Make sure to erase contacts that are no longer valid. + const Transform &transform_A = body->get_transform(); + + real_t contact_max_separation = space->get_contact_max_separation(); + + uint32_t contact_count = contacts.size(); + for (uint32_t contact_index = 0; contact_index < contact_count; ++contact_index) { + Contact &c = contacts[contact_index]; + + Vector3 global_A = transform_A.xform(c.local_A); + Vector3 global_B = soft_body->get_node_position(c.index_B) + c.local_B; + Vector3 axis = global_A - global_B; + real_t depth = axis.dot(c.normal); + + if (depth < -contact_max_separation || (global_B + c.normal * depth - global_A).length() > contact_max_separation) { + // Contact no longer needed, remove. + if ((contact_index + 1) < contact_count) { + // Swap with the last one. + SWAP(c, contacts[contact_count - 1]); + } + + contact_index--; + contact_count--; + } + } + + contacts.resize(contact_count); +} + +bool BodySoftBodyPair3DSW::setup(real_t p_step) { + if (!body->test_collision_mask(soft_body) || body->has_exception(soft_body->get_self()) || soft_body->has_exception(body->get_self())) { + collided = false; + return false; + } + + if (body->is_shape_set_as_disabled(body_shape)) { + collided = false; + return false; + } + + const Transform &xform_Au = body->get_transform(); + Transform xform_A = xform_Au * body->get_shape_transform(body_shape); + + Transform xform_Bu = soft_body->get_transform(); + Transform xform_B = xform_Bu * soft_body->get_shape_transform(0); + + validate_contacts(); + + Shape3DSW *shape_A_ptr = body->get_shape(body_shape); + Shape3DSW *shape_B_ptr = soft_body->get_shape(0); + + bool collided = CollisionSolver3DSW::solve_static(shape_A_ptr, xform_A, shape_B_ptr, xform_B, _contact_added_callback, this, &sep_axis); + this->collided = collided; + + real_t max_penetration = space->get_contact_max_allowed_penetration(); + + real_t bias = (real_t)0.3; + if (shape_A_ptr->get_custom_bias()) { + bias = shape_A_ptr->get_custom_bias(); + } + + real_t inv_dt = 1.0 / p_step; + + uint32_t contact_count = contacts.size(); + for (uint32_t contact_index = 0; contact_index < contact_count; ++contact_index) { + Contact &c = contacts[contact_index]; + c.active = false; + + real_t node_inv_mass = soft_body->get_node_inv_mass(c.index_B); + if (node_inv_mass == 0.0) { + continue; + } + + Vector3 global_A = xform_Au.xform(c.local_A); + Vector3 global_B = soft_body->get_node_position(c.index_B) + c.local_B; + + real_t depth = c.normal.dot(global_A - global_B); + + if (depth <= 0) { + continue; + } + + c.active = true; + +#ifdef DEBUG_ENABLED + + if (space->is_debugging_contacts()) { + space->add_debug_contact(global_A); + space->add_debug_contact(global_B); + } +#endif + + c.rA = global_A - xform_Au.origin - body->get_center_of_mass(); + c.rB = global_B; + + if (body->can_report_contacts()) { + Vector3 crA = body->get_angular_velocity().cross(c.rA) + body->get_linear_velocity(); + body->add_contact(global_A, -c.normal, depth, body_shape, global_B, 0, soft_body->get_instance_id(), soft_body->get_self(), crA); + } + + if (body->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC) { + body->set_active(true); + } + + // Precompute normal mass, tangent mass, and bias. + Vector3 inertia_A = body->get_inv_inertia_tensor().xform(c.rA.cross(c.normal)); + real_t kNormal = body->get_inv_mass() + node_inv_mass; + kNormal += c.normal.dot(inertia_A.cross(c.rA)); + c.mass_normal = 1.0f / kNormal; + + c.bias = -bias * inv_dt * MIN(0.0f, -depth + max_penetration); + c.depth = depth; + + Vector3 j_vec = c.normal * c.acc_normal_impulse + c.acc_tangent_impulse; + body->apply_impulse(c.rA + body->get_center_of_mass(), -j_vec); + soft_body->apply_node_impulse(c.index_B, j_vec); + c.acc_bias_impulse = 0; + c.acc_bias_impulse_center_of_mass = 0; + + c.bounce = body->get_bounce(); + + if (c.bounce) { + Vector3 crA = body->get_angular_velocity().cross(c.rA); + Vector3 dv = soft_body->get_node_velocity(c.index_B) - body->get_linear_velocity() - crA; + + // Normal impulse. + c.bounce = c.bounce * dv.dot(c.normal); + } + } + + return true; +} + +void BodySoftBodyPair3DSW::solve(real_t p_step) { + if (!collided) { + return; + } + + uint32_t contact_count = contacts.size(); + for (uint32_t contact_index = 0; contact_index < contact_count; ++contact_index) { + Contact &c = contacts[contact_index]; + if (!c.active) { + continue; + } + + c.active = false; + + // Bias impulse. + Vector3 crbA = body->get_biased_angular_velocity().cross(c.rA); + Vector3 dbv = soft_body->get_node_biased_velocity(c.index_B) - body->get_biased_linear_velocity() - crbA; + + real_t vbn = dbv.dot(c.normal); + + if (Math::abs(-vbn + c.bias) > MIN_VELOCITY) { + real_t jbn = (-vbn + c.bias) * c.mass_normal; + real_t jbnOld = c.acc_bias_impulse; + c.acc_bias_impulse = MAX(jbnOld + jbn, 0.0f); + + Vector3 jb = c.normal * (c.acc_bias_impulse - jbnOld); + + body->apply_bias_impulse(c.rA + body->get_center_of_mass(), -jb, MAX_BIAS_ROTATION / p_step); + soft_body->apply_node_bias_impulse(c.index_B, jb); + + crbA = body->get_biased_angular_velocity().cross(c.rA); + dbv = soft_body->get_node_biased_velocity(c.index_B) - body->get_biased_linear_velocity() - crbA; + + vbn = dbv.dot(c.normal); + + if (Math::abs(-vbn + c.bias) > MIN_VELOCITY) { + real_t jbn_com = (-vbn + c.bias) / (body->get_inv_mass() + soft_body->get_node_inv_mass(c.index_B)); + real_t jbnOld_com = c.acc_bias_impulse_center_of_mass; + c.acc_bias_impulse_center_of_mass = MAX(jbnOld_com + jbn_com, 0.0f); + + Vector3 jb_com = c.normal * (c.acc_bias_impulse_center_of_mass - jbnOld_com); + + body->apply_bias_impulse(body->get_center_of_mass(), -jb_com, 0.0f); + soft_body->apply_node_bias_impulse(c.index_B, -jb_com); + } + + c.active = true; + } + + Vector3 crA = body->get_angular_velocity().cross(c.rA); + Vector3 dv = soft_body->get_node_velocity(c.index_B) - body->get_linear_velocity() - crA; + + // Normal impulse. + real_t vn = dv.dot(c.normal); + + if (Math::abs(vn) > MIN_VELOCITY) { + real_t jn = -(c.bounce + vn) * c.mass_normal; + real_t jnOld = c.acc_normal_impulse; + c.acc_normal_impulse = MAX(jnOld + jn, 0.0f); + + Vector3 j = c.normal * (c.acc_normal_impulse - jnOld); + + body->apply_impulse(c.rA + body->get_center_of_mass(), -j); + soft_body->apply_node_impulse(c.index_B, j); + + c.active = true; + } + + // Friction impulse. + real_t friction = body->get_friction(); + + Vector3 lvA = body->get_linear_velocity() + body->get_angular_velocity().cross(c.rA); + Vector3 lvB = soft_body->get_node_velocity(c.index_B); + Vector3 dtv = lvB - lvA; + + real_t tn = c.normal.dot(dtv); + + // Tangential velocity. + Vector3 tv = dtv - c.normal * tn; + real_t tvl = tv.length(); + + if (tvl > MIN_VELOCITY) { + tv /= tvl; + + Vector3 temp1 = body->get_inv_inertia_tensor().xform(c.rA.cross(tv)); + + real_t t = -tvl / + (body->get_inv_mass() + soft_body->get_node_inv_mass(c.index_B) + tv.dot(temp1.cross(c.rA))); + + Vector3 jt = t * tv; + + Vector3 jtOld = c.acc_tangent_impulse; + c.acc_tangent_impulse += jt; + + real_t fi_len = c.acc_tangent_impulse.length(); + real_t jtMax = c.acc_normal_impulse * friction; + + if (fi_len > CMP_EPSILON && fi_len > jtMax) { + c.acc_tangent_impulse *= jtMax / fi_len; + } + + jt = c.acc_tangent_impulse - jtOld; + + body->apply_impulse(c.rA + body->get_center_of_mass(), -jt); + soft_body->apply_node_impulse(c.index_B, jt); + + c.active = true; + } + } +} + +BodySoftBodyPair3DSW::BodySoftBodyPair3DSW(Body3DSW *p_A, int p_shape_A, SoftBody3DSW *p_B) { + body = p_A; + soft_body = p_B; + body_shape = p_shape_A; + space = p_A->get_space(); + body->add_constraint(this, 0); + soft_body->add_constraint(this); +} + +BodySoftBodyPair3DSW::~BodySoftBodyPair3DSW() { + body->remove_constraint(this); + soft_body->remove_constraint(this); +} diff --git a/servers/physics_3d/body_pair_3d_sw.h b/servers/physics_3d/body_pair_3d_sw.h index 4d049eafdc..74dddfa6aa 100644 --- a/servers/physics_3d/body_pair_3d_sw.h +++ b/servers/physics_3d/body_pair_3d_sw.h @@ -28,32 +28,20 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BODY_PAIR_SW_H -#define BODY_PAIR_SW_H +#ifndef BODY_PAIR_3D_SW_H +#define BODY_PAIR_3D_SW_H #include "body_3d_sw.h" #include "constraint_3d_sw.h" +#include "core/templates/local_vector.h" +#include "soft_body_3d_sw.h" -class BodyPair3DSW : public Constraint3DSW { - enum { - MAX_CONTACTS = 4 - }; - - union { - struct { - Body3DSW *A; - Body3DSW *B; - }; - - Body3DSW *_arr[2]; - }; - - int shape_A; - int shape_B; - +class BodyContact3DSW : public Constraint3DSW { +protected: struct Contact { Vector3 position; Vector3 normal; + int index_A, index_B; Vector3 local_A, local_B; real_t acc_normal_impulse; // accumulated normal impulse (Pn) Vector3 acc_tangent_impulse; // accumulated tangent impulse (Pt) @@ -68,22 +56,45 @@ class BodyPair3DSW : public Constraint3DSW { Vector3 rA, rB; // Offset in world orientation with respect to center of mass }; + Vector3 sep_axis; + bool collided; + + Space3DSW *space; + + BodyContact3DSW(Body3DSW **p_body_ptr = nullptr, int p_body_count = 0) : + Constraint3DSW(p_body_ptr, p_body_count) { + } +}; + +class BodyPair3DSW : public BodyContact3DSW { + enum { + MAX_CONTACTS = 4 + }; + + union { + struct { + Body3DSW *A; + Body3DSW *B; + }; + + Body3DSW *_arr[2]; + }; + + int shape_A; + int shape_B; + Vector3 offset_B; //use local A coordinates to avoid numerical issues on collision detection - Vector3 sep_axis; Contact contacts[MAX_CONTACTS]; int contact_count; - bool collided; - static void _contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata); + static void _contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata); - void contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B); + void contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B); void validate_contacts(); bool _test_ccd(real_t p_step, Body3DSW *p_A, int p_shape_A, const Transform &p_xform_A, Body3DSW *p_B, int p_shape_B, const Transform &p_xform_B); - Space3DSW *space; - public: bool setup(real_t p_step); void solve(real_t p_step); @@ -92,4 +103,26 @@ public: ~BodyPair3DSW(); }; -#endif // BODY_PAIR__SW_H +class BodySoftBodyPair3DSW : public BodyContact3DSW { + Body3DSW *body; + SoftBody3DSW *soft_body; + + int body_shape; + + LocalVector<Contact> contacts; + + static void _contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata); + + void contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B); + + void validate_contacts(); + +public: + bool setup(real_t p_step); + void solve(real_t p_step); + + BodySoftBodyPair3DSW(Body3DSW *p_A, int p_shape_A, SoftBody3DSW *p_B); + ~BodySoftBodyPair3DSW(); +}; + +#endif // BODY_PAIR_3D_SW_H diff --git a/servers/physics_3d/collision_object_3d_sw.h b/servers/physics_3d/collision_object_3d_sw.h index 3847b81381..85221b7746 100644 --- a/servers/physics_3d/collision_object_3d_sw.h +++ b/servers/physics_3d/collision_object_3d_sw.h @@ -48,7 +48,8 @@ class CollisionObject3DSW : public ShapeOwner3DSW { public: enum Type { TYPE_AREA, - TYPE_BODY + TYPE_BODY, + TYPE_SOFT_BODY, }; private: @@ -129,8 +130,8 @@ public: _FORCE_INLINE_ const AABB &get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; } _FORCE_INLINE_ real_t get_shape_area(int p_index) const { return shapes[p_index].area_cache; } - _FORCE_INLINE_ Transform get_transform() const { return transform; } - _FORCE_INLINE_ Transform get_inv_transform() const { return inv_transform; } + _FORCE_INLINE_ const Transform &get_transform() const { return transform; } + _FORCE_INLINE_ const Transform &get_inv_transform() const { return inv_transform; } _FORCE_INLINE_ Space3DSW *get_space() const { return space; } _FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable = p_enable; } diff --git a/servers/physics_3d/collision_solver_3d_sat.cpp b/servers/physics_3d/collision_solver_3d_sat.cpp index 33075a38be..9d5448dbfa 100644 --- a/servers/physics_3d/collision_solver_3d_sat.cpp +++ b/servers/physics_3d/collision_solver_3d_sat.cpp @@ -74,9 +74,9 @@ struct _CollectorCallback { _FORCE_INLINE_ void call(const Vector3 &p_point_A, const Vector3 &p_point_B) { if (swap) { - callback(p_point_B, p_point_A, userdata); + callback(p_point_B, 0, p_point_A, 0, userdata); } else { - callback(p_point_A, p_point_B, userdata); + callback(p_point_A, 0, p_point_B, 0, userdata); } } }; @@ -626,7 +626,7 @@ public: } } - _FORCE_INLINE_ bool test_axis(const Vector3 &p_axis) { + _FORCE_INLINE_ bool test_axis(const Vector3 &p_axis, bool p_directional = false) { Vector3 axis = p_axis; if (Math::abs(axis.x) < CMP_EPSILON && @@ -662,7 +662,12 @@ public: //use the smallest depth if (min_B < 0.0) { // could be +0.0, we don't want it to become -0.0 - min_B = -min_B; + if (p_directional) { + min_B = max_B; + axis = -axis; + } else { + min_B = -min_B; + } } if (max_B < min_B) { @@ -680,7 +685,7 @@ public: return true; } - static _FORCE_INLINE_ void test_contact_points(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) { + static _FORCE_INLINE_ void test_contact_points(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { SeparatorAxisTest<ShapeA, ShapeB, withMargin> *separator = (SeparatorAxisTest<ShapeA, ShapeB, withMargin> *)p_userdata; Vector3 axis = (p_point_B - p_point_A); real_t depth = axis.length(); @@ -1006,23 +1011,31 @@ static void _collision_sphere_face(const Shape3DSW *p_a, const Transform &p_tran p_transform_b.xform(face_B->vertex[2]), }; - if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) { + Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized(); + + if (!separator.test_axis(normal, !face_B->backface_collision)) { return; } // edges and points of B for (int i = 0; i < 3; i++) { Vector3 n1 = vertex[i] - p_transform_a.origin; + if (n1.dot(normal) < 0.0) { + n1 *= -1.0; + } - if (!separator.test_axis(n1.normalized())) { + if (!separator.test_axis(n1.normalized(), !face_B->backface_collision)) { return; } Vector3 n2 = vertex[(i + 1) % 3] - vertex[i]; Vector3 axis = n1.cross(n2).cross(n2).normalized(); + if (axis.dot(normal) < 0.0) { + axis *= -1.0; + } - if (!separator.test_axis(axis)) { + if (!separator.test_axis(axis, !face_B->backface_collision)) { return; } } @@ -1467,15 +1480,20 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transfo p_transform_b.xform(face_B->vertex[2]), }; - if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) { + Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized(); + + if (!separator.test_axis(normal, !face_B->backface_collision)) { return; } // faces of A for (int i = 0; i < 3; i++) { Vector3 axis = p_transform_a.basis.get_axis(i).normalized(); + if (axis.dot(normal) < 0.0) { + axis *= -1.0; + } - if (!separator.test_axis(axis)) { + if (!separator.test_axis(axis, !face_B->backface_collision)) { return; } } @@ -1486,9 +1504,12 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transfo Vector3 e = vertex[i] - vertex[(i + 1) % 3]; for (int j = 0; j < 3; j++) { - Vector3 axis = p_transform_a.basis.get_axis(j); + Vector3 axis = e.cross(p_transform_a.basis.get_axis(j)).normalized(); + if (axis.dot(normal) < 0.0) { + axis *= -1.0; + } - if (!separator.test_axis(e.cross(axis).normalized())) { + if (!separator.test_axis(axis, !face_B->backface_collision)) { return; } } @@ -1508,8 +1529,11 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transfo (cnormal_a.z < 0) ? -box_A->get_half_extents().z : box_A->get_half_extents().z)); Vector3 axis_ab = support_a - vertex[v]; + if (axis_ab.dot(normal) < 0.0) { + axis_ab *= -1.0; + } - if (!separator.test_axis(axis_ab.normalized())) { + if (!separator.test_axis(axis_ab.normalized(), !face_B->backface_collision)) { return; } @@ -1519,7 +1543,12 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transfo //a ->b Vector3 axis_a = p_transform_a.basis.get_axis(i); - if (!separator.test_axis(axis_ab.cross(axis_a).cross(axis_a).normalized())) { + Vector3 axis = axis_ab.cross(axis_a).cross(axis_a).normalized(); + if (axis.dot(normal) < 0.0) { + axis *= -1.0; + } + + if (!separator.test_axis(axis, !face_B->backface_collision)) { return; } } @@ -1544,7 +1573,12 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transfo Vector3 n = (p2 - p1); - if (!separator.test_axis((point - p2).cross(n).cross(n).normalized())) { + Vector3 axis = (point - p2).cross(n).cross(n).normalized(); + if (axis.dot(normal) < 0.0) { + axis *= -1.0; + } + + if (!separator.test_axis(axis, !face_B->backface_collision)) { return; } } @@ -1759,7 +1793,9 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform &p_tra p_transform_b.xform(face_B->vertex[2]), }; - if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) { + Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized(); + + if (!separator.test_axis(normal, !face_B->backface_collision)) { return; } @@ -1770,13 +1806,22 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform &p_tra for (int i = 0; i < 3; i++) { // edge-cylinder Vector3 edge_axis = vertex[i] - vertex[(i + 1) % 3]; + Vector3 axis = edge_axis.cross(capsule_axis).normalized(); + if (axis.dot(normal) < 0.0) { + axis *= -1.0; + } - if (!separator.test_axis(axis)) { + if (!separator.test_axis(axis, !face_B->backface_collision)) { return; } - if (!separator.test_axis((p_transform_a.origin - vertex[i]).cross(capsule_axis).cross(capsule_axis).normalized())) { + Vector3 dir_axis = (p_transform_a.origin - vertex[i]).cross(capsule_axis).cross(capsule_axis).normalized(); + if (dir_axis.dot(normal) < 0.0) { + dir_axis *= -1.0; + } + + if (!separator.test_axis(dir_axis, !face_B->backface_collision)) { return; } @@ -1785,16 +1830,22 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform &p_tra Vector3 sphere_pos = p_transform_a.origin + ((j == 0) ? capsule_axis : -capsule_axis); Vector3 n1 = sphere_pos - vertex[i]; + if (n1.dot(normal) < 0.0) { + n1 *= -1.0; + } - if (!separator.test_axis(n1.normalized())) { + if (!separator.test_axis(n1.normalized(), !face_B->backface_collision)) { return; } Vector3 n2 = edge_axis; axis = n1.cross(n2).cross(n2); + if (axis.dot(normal) < 0.0) { + axis *= -1.0; + } - if (!separator.test_axis(axis.normalized())) { + if (!separator.test_axis(axis.normalized(), !face_B->backface_collision)) { return; } } @@ -1891,18 +1942,21 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform &p_tr p_transform_b.xform(face_B->vertex[2]), }; + Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized(); + // Face B normal. - if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) { + if (!separator.test_axis(normal, !face_B->backface_collision)) { return; } Vector3 cyl_axis = p_transform_a.basis.get_axis(1).normalized(); + if (cyl_axis.dot(normal) < 0.0) { + cyl_axis *= -1.0; + } // Cylinder end caps. - { - if (!separator.test_axis(cyl_axis)) { - return; - } + if (!separator.test_axis(cyl_axis, !face_B->backface_collision)) { + return; } // Edges of B, cylinder lateral surface. @@ -1913,7 +1967,11 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform &p_tr continue; } - if (!separator.test_axis(axis.normalized())) { + if (axis.dot(normal) < 0.0) { + axis *= -1.0; + } + + if (!separator.test_axis(axis.normalized(), !face_B->backface_collision)) { return; } } @@ -1922,8 +1980,11 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform &p_tr for (int i = 0; i < 3; i++) { const Vector3 &point = vertex[i]; Vector3 axis = Plane(cyl_axis, 0).project(point).normalized(); + if (axis.dot(normal) < 0.0) { + axis *= -1.0; + } - if (!separator.test_axis(axis)) { + if (!separator.test_axis(axis, !face_B->backface_collision)) { return; } } @@ -1956,8 +2017,11 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform &p_tr // Axis is orthogonal both to tangent and edge direction. Vector3 axis = tangent.cross(edge_dir); + if (axis.dot(normal) < 0.0) { + axis *= -1.0; + } - if (!separator.test_axis(axis.normalized())) { + if (!separator.test_axis(axis.normalized(), !face_B->backface_collision)) { return; } } @@ -2097,7 +2161,9 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform p_transform_b.xform(face_B->vertex[2]), }; - if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) { + Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized(); + + if (!separator.test_axis(normal, !face_B->backface_collision)) { return; } @@ -2105,8 +2171,11 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform for (int i = 0; i < face_count; i++) { //Vector3 axis = p_transform_a.xform( faces[i].plane ).normal; Vector3 axis = p_transform_a.basis.xform(faces[i].plane.normal).normalized(); + if (axis.dot(normal) < 0.0) { + axis *= -1.0; + } - if (!separator.test_axis(axis)) { + if (!separator.test_axis(axis, !face_B->backface_collision)) { return; } } @@ -2119,8 +2188,11 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform Vector3 e2 = vertex[j] - vertex[(j + 1) % 3]; Vector3 axis = e1.cross(e2).normalized(); + if (axis.dot(normal) < 0.0) { + axis *= -1.0; + } - if (!separator.test_axis(axis)) { + if (!separator.test_axis(axis, !face_B->backface_collision)) { return; } } @@ -2132,7 +2204,12 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform Vector3 va = p_transform_a.xform(vertices[i]); for (int j = 0; j < 3; j++) { - if (!separator.test_axis((va - vertex[j]).normalized())) { + Vector3 axis = (va - vertex[j]).normalized(); + if (axis.dot(normal) < 0.0) { + axis *= -1.0; + } + + if (!separator.test_axis(axis, !face_B->backface_collision)) { return; } } @@ -2147,7 +2224,12 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform for (int j = 0; j < 3; j++) { Vector3 e3 = vertex[j]; - if (!separator.test_axis((e1 - e3).cross(n).cross(n).normalized())) { + Vector3 axis = (e1 - e3).cross(n).cross(n).normalized(); + if (axis.dot(normal) < 0.0) { + axis *= -1.0; + } + + if (!separator.test_axis(axis, !face_B->backface_collision)) { return; } } @@ -2161,7 +2243,12 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform for (int j = 0; j < vertex_count; j++) { Vector3 e3 = p_transform_a.xform(vertices[j]); - if (!separator.test_axis((e1 - e3).cross(n).cross(n).normalized())) { + Vector3 axis = (e1 - e3).cross(n).cross(n).normalized(); + if (axis.dot(normal) < 0.0) { + axis *= -1.0; + } + + if (!separator.test_axis(axis, !face_B->backface_collision)) { return; } } diff --git a/servers/physics_3d/collision_solver_3d_sw.cpp b/servers/physics_3d/collision_solver_3d_sw.cpp index fd9ea00d92..f655c4626c 100644 --- a/servers/physics_3d/collision_solver_3d_sw.cpp +++ b/servers/physics_3d/collision_solver_3d_sw.cpp @@ -30,6 +30,7 @@ #include "collision_solver_3d_sw.h" #include "collision_solver_3d_sat.h" +#include "soft_body_3d_sw.h" #include "gjk_epa.h" @@ -78,9 +79,9 @@ bool CollisionSolver3DSW::solve_static_plane(const Shape3DSW *p_shape_A, const T if (p_result_callback) { if (p_swap_result) { - p_result_callback(supports[i], support_A, p_userdata); + p_result_callback(supports[i], 0, support_A, 0, p_userdata); } else { - p_result_callback(support_A, supports[i], p_userdata); + p_result_callback(support_A, 0, supports[i], 0, p_userdata); } } } @@ -113,14 +114,148 @@ bool CollisionSolver3DSW::solve_ray(const Shape3DSW *p_shape_A, const Transform if (p_result_callback) { if (p_swap_result) { - p_result_callback(support_B, support_A, p_userdata); + p_result_callback(support_B, 0, support_A, 0, p_userdata); } else { - p_result_callback(support_A, support_B, p_userdata); + p_result_callback(support_A, 0, support_B, 0, p_userdata); } } return true; } +struct _SoftBodyContactCollisionInfo { + int node_index = 0; + CollisionSolver3DSW::CallbackResult result_callback = nullptr; + void *userdata = nullptr; + bool swap_result = false; + int contact_count = 0; +}; + +void CollisionSolver3DSW::soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { + _SoftBodyContactCollisionInfo &cinfo = *(_SoftBodyContactCollisionInfo *)(p_userdata); + + ++cinfo.contact_count; + + if (cinfo.swap_result) { + cinfo.result_callback(p_point_B, cinfo.node_index, p_point_A, p_index_A, cinfo.userdata); + } else { + cinfo.result_callback(p_point_A, p_index_A, p_point_B, cinfo.node_index, cinfo.userdata); + } +} + +struct _SoftBodyQueryInfo { + SoftBody3DSW *soft_body = nullptr; + const Shape3DSW *shape_A = nullptr; + const Shape3DSW *shape_B = nullptr; + Transform transform_A; + Transform node_transform; + _SoftBodyContactCollisionInfo contact_info; +#ifdef DEBUG_ENABLED + int node_query_count = 0; + int convex_query_count = 0; +#endif +}; + +bool CollisionSolver3DSW::soft_body_query_callback(uint32_t p_node_index, void *p_userdata) { + _SoftBodyQueryInfo &query_cinfo = *(_SoftBodyQueryInfo *)(p_userdata); + + Vector3 node_position = query_cinfo.soft_body->get_node_position(p_node_index); + + Transform transform_B; + transform_B.origin = query_cinfo.node_transform.xform(node_position); + + query_cinfo.contact_info.node_index = p_node_index; + solve_static(query_cinfo.shape_A, query_cinfo.transform_A, query_cinfo.shape_B, transform_B, soft_body_contact_callback, &query_cinfo.contact_info); + +#ifdef DEBUG_ENABLED + ++query_cinfo.node_query_count; +#endif + + // Continue with the query. + return false; +} + +void CollisionSolver3DSW::soft_body_concave_callback(void *p_userdata, Shape3DSW *p_convex) { + _SoftBodyQueryInfo &query_cinfo = *(_SoftBodyQueryInfo *)(p_userdata); + + query_cinfo.shape_A = p_convex; + + // Calculate AABB for internal soft body query (in world space). + AABB shape_aabb; + for (int i = 0; i < 3; i++) { + Vector3 axis; + axis[i] = 1.0; + + real_t smin, smax; + p_convex->project_range(axis, query_cinfo.transform_A, smin, smax); + + shape_aabb.position[i] = smin; + shape_aabb.size[i] = smax - smin; + } + + shape_aabb.grow_by(query_cinfo.soft_body->get_collision_margin()); + + query_cinfo.soft_body->query_aabb(shape_aabb, soft_body_query_callback, &query_cinfo); + +#ifdef DEBUG_ENABLED + ++query_cinfo.convex_query_count; +#endif +} + +bool CollisionSolver3DSW::solve_soft_body(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) { + const SoftBodyShape3DSW *soft_body_shape_B = static_cast<const SoftBodyShape3DSW *>(p_shape_B); + + SoftBody3DSW *soft_body = soft_body_shape_B->get_soft_body(); + const Transform &world_to_local = soft_body->get_inv_transform(); + + const real_t collision_margin = soft_body->get_collision_margin(); + + SphereShape3DSW sphere_shape; + sphere_shape.set_data(collision_margin); + + _SoftBodyQueryInfo query_cinfo; + query_cinfo.contact_info.result_callback = p_result_callback; + query_cinfo.contact_info.userdata = p_userdata; + query_cinfo.contact_info.swap_result = p_swap_result; + query_cinfo.soft_body = soft_body; + query_cinfo.node_transform = p_transform_B * world_to_local; + query_cinfo.shape_A = p_shape_A; + query_cinfo.transform_A = p_transform_A; + query_cinfo.shape_B = &sphere_shape; + + if (p_shape_A->is_concave()) { + // In case of concave shape, query convex shapes first. + const ConcaveShape3DSW *concave_shape_A = static_cast<const ConcaveShape3DSW *>(p_shape_A); + + AABB soft_body_aabb = soft_body->get_bounds(); + soft_body_aabb.grow_by(collision_margin); + + // Calculate AABB for internal concave shape query (in local space). + AABB local_aabb; + for (int i = 0; i < 3; i++) { + Vector3 axis(p_transform_A.basis.get_axis(i)); + real_t axis_scale = 1.0 / axis.length(); + + real_t smin = soft_body_aabb.position[i]; + real_t smax = smin + soft_body_aabb.size[i]; + + smin *= axis_scale; + smax *= axis_scale; + + local_aabb.position[i] = smin; + local_aabb.size[i] = smax - smin; + } + + concave_shape_A->cull(local_aabb, soft_body_concave_callback, &query_cinfo); + } else { + AABB shape_aabb = p_transform_A.xform(p_shape_A->get_aabb()); + shape_aabb.grow_by(collision_margin); + + soft_body->query_aabb(shape_aabb, soft_body_query_callback, &query_cinfo); + } + + return (query_cinfo.contact_info.contact_count > 0); +} + struct _ConcaveCollisionInfo { const Transform *transform_A; const Shape3DSW *shape_A; @@ -215,6 +350,9 @@ bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transfo if (type_B == PhysicsServer3D::SHAPE_RAY) { return false; } + if (type_B == PhysicsServer3D::SHAPE_SOFT_BODY) { + return false; + } if (swap) { return solve_static_plane(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true); @@ -233,6 +371,18 @@ bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transfo return solve_ray(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false); } + } else if (type_B == PhysicsServer3D::SHAPE_SOFT_BODY) { + if (type_A == PhysicsServer3D::SHAPE_SOFT_BODY) { + // Soft Body / Soft Body not supported. + return false; + } + + if (swap) { + return solve_soft_body(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true); + } else { + return solve_soft_body(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false); + } + } else if (concave_B) { if (concave_A) { return false; diff --git a/servers/physics_3d/collision_solver_3d_sw.h b/servers/physics_3d/collision_solver_3d_sw.h index 81d87e9773..34ac2c6d3f 100644 --- a/servers/physics_3d/collision_solver_3d_sw.h +++ b/servers/physics_3d/collision_solver_3d_sw.h @@ -35,12 +35,16 @@ class CollisionSolver3DSW { public: - typedef void (*CallbackResult)(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata); + typedef void (*CallbackResult)(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata); private: + static bool soft_body_query_callback(uint32_t p_node_index, void *p_userdata); + static void soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata); + static void soft_body_concave_callback(void *p_userdata, Shape3DSW *p_convex); static void concave_callback(void *p_userdata, Shape3DSW *p_convex); static bool solve_static_plane(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result); static bool solve_ray(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result); + static bool solve_soft_body(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result); static bool solve_concave(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A = 0, real_t p_margin_B = 0); static void concave_distance_callback(void *p_userdata, Shape3DSW *p_convex); static bool solve_distance_plane(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B); diff --git a/servers/physics_3d/gjk_epa.cpp b/servers/physics_3d/gjk_epa.cpp index e44c92da79..1a8c7f704f 100644 --- a/servers/physics_3d/gjk_epa.cpp +++ b/servers/physics_3d/gjk_epa.cpp @@ -1011,9 +1011,9 @@ bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform & if (GjkEpa2::Penetration(p_shape_A, p_transform_A, p_margin_A, p_shape_B, p_transform_B, p_margin_B, p_transform_B.origin - p_transform_A.origin, res)) { if (p_result_callback) { if (p_swap) { - p_result_callback(res.witnesses[1], res.witnesses[0], p_userdata); + p_result_callback(res.witnesses[1], 0, res.witnesses[0], 0, p_userdata); } else { - p_result_callback(res.witnesses[0], res.witnesses[1], p_userdata); + p_result_callback(res.witnesses[0], 0, res.witnesses[1], 0, p_userdata); } } return true; diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp index 6bbef09907..3d0063b0fa 100644 --- a/servers/physics_3d/physics_server_3d_sw.cpp +++ b/servers/physics_3d/physics_server_3d_sw.cpp @@ -611,9 +611,18 @@ uint32_t PhysicsServer3DSW::body_get_collision_mask(RID p_body) const { void PhysicsServer3DSW::body_attach_object_instance_id(RID p_body, ObjectID p_id) { Body3DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); + if (body) { + body->set_instance_id(p_id); + return; + } + + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + if (soft_body) { + soft_body->set_instance_id(p_id); + return; + } - body->set_instance_id(p_id); + ERR_FAIL_MSG("Invalid ID."); }; ObjectID PhysicsServer3DSW::body_get_object_instance_id(RID p_body) const { @@ -893,6 +902,266 @@ PhysicsDirectBodyState3D *PhysicsServer3DSW::body_get_direct_state(RID p_body) { return direct_state; } +/* SOFT BODY */ + +RID PhysicsServer3DSW::soft_body_create() { + SoftBody3DSW *soft_body = memnew(SoftBody3DSW); + RID rid = soft_body_owner.make_rid(soft_body); + soft_body->set_self(rid); + return rid; +} + +void PhysicsServer3DSW::soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->update_rendering_server(p_rendering_server_handler); +} + +void PhysicsServer3DSW::soft_body_set_space(RID p_body, RID p_space) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + Space3DSW *space = nullptr; + if (p_space.is_valid()) { + space = space_owner.getornull(p_space); + ERR_FAIL_COND(!space); + } + + if (soft_body->get_space() == space) { + return; + } + + soft_body->set_space(space); +} + +RID PhysicsServer3DSW::soft_body_get_space(RID p_body) const { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND_V(!soft_body, RID()); + + Space3DSW *space = soft_body->get_space(); + if (!space) { + return RID(); + } + return space->get_self(); +} + +void PhysicsServer3DSW::soft_body_set_collision_layer(RID p_body, uint32_t p_layer) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_collision_layer(p_layer); +} + +uint32_t PhysicsServer3DSW::soft_body_get_collision_layer(RID p_body) const { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND_V(!soft_body, 0); + + return soft_body->get_collision_layer(); +} + +void PhysicsServer3DSW::soft_body_set_collision_mask(RID p_body, uint32_t p_mask) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_collision_mask(p_mask); +} + +uint32_t PhysicsServer3DSW::soft_body_get_collision_mask(RID p_body) const { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND_V(!soft_body, 0); + + return soft_body->get_collision_mask(); +} + +void PhysicsServer3DSW::soft_body_add_collision_exception(RID p_body, RID p_body_b) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->add_exception(p_body_b); +} + +void PhysicsServer3DSW::soft_body_remove_collision_exception(RID p_body, RID p_body_b) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->remove_exception(p_body_b); +} + +void PhysicsServer3DSW::soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + for (int i = 0; i < soft_body->get_exceptions().size(); i++) { + p_exceptions->push_back(soft_body->get_exceptions()[i]); + } +} + +void PhysicsServer3DSW::soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_state(p_state, p_variant); +} + +Variant PhysicsServer3DSW::soft_body_get_state(RID p_body, BodyState p_state) const { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND_V(!soft_body, Variant()); + + return soft_body->get_state(p_state); +} + +void PhysicsServer3DSW::soft_body_set_transform(RID p_body, const Transform &p_transform) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_state(BODY_STATE_TRANSFORM, p_transform); +} + +void PhysicsServer3DSW::soft_body_set_ray_pickable(RID p_body, bool p_enable) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_ray_pickable(p_enable); +} + +void PhysicsServer3DSW::soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_iteration_count(p_simulation_precision); +} + +int PhysicsServer3DSW::soft_body_get_simulation_precision(RID p_body) const { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND_V(!soft_body, 0.f); + + return soft_body->get_iteration_count(); +} + +void PhysicsServer3DSW::soft_body_set_total_mass(RID p_body, real_t p_total_mass) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_total_mass(p_total_mass); +} + +real_t PhysicsServer3DSW::soft_body_get_total_mass(RID p_body) const { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND_V(!soft_body, 0.f); + + return soft_body->get_total_mass(); +} + +void PhysicsServer3DSW::soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_linear_stiffness(p_stiffness); +} + +real_t PhysicsServer3DSW::soft_body_get_linear_stiffness(RID p_body) const { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND_V(!soft_body, 0.f); + + return soft_body->get_linear_stiffness(); +} + +void PhysicsServer3DSW::soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_pressure_coefficient(p_pressure_coefficient); +} + +real_t PhysicsServer3DSW::soft_body_get_pressure_coefficient(RID p_body) const { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND_V(!soft_body, 0.f); + + return soft_body->get_pressure_coefficient(); +} + +void PhysicsServer3DSW::soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_damping_coefficient(p_damping_coefficient); +} + +real_t PhysicsServer3DSW::soft_body_get_damping_coefficient(RID p_body) const { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND_V(!soft_body, 0.f); + + return soft_body->get_damping_coefficient(); +} + +void PhysicsServer3DSW::soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_drag_coefficient(p_drag_coefficient); +} + +real_t PhysicsServer3DSW::soft_body_get_drag_coefficient(RID p_body) const { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND_V(!soft_body, 0.f); + + return soft_body->get_drag_coefficient(); +} + +void PhysicsServer3DSW::soft_body_set_mesh(RID p_body, const REF &p_mesh) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_mesh(p_mesh); +} + +AABB PhysicsServer3DSW::soft_body_get_bounds(RID p_body) const { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND_V(!soft_body, AABB()); + + return soft_body->get_bounds(); +} + +void PhysicsServer3DSW::soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_vertex_position(p_point_index, p_global_position); +} + +Vector3 PhysicsServer3DSW::soft_body_get_point_global_position(RID p_body, int p_point_index) const { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND_V(!soft_body, Vector3()); + + return soft_body->get_vertex_position(p_point_index); +} + +void PhysicsServer3DSW::soft_body_remove_all_pinned_points(RID p_body) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->unpin_all_vertices(); +} + +void PhysicsServer3DSW::soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND(!soft_body); + + if (p_pin) { + soft_body->pin_vertex(p_point_index); + } else { + soft_body->unpin_vertex(p_point_index); + } +} + +bool PhysicsServer3DSW::soft_body_is_point_pinned(RID p_body, int p_point_index) const { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_body); + ERR_FAIL_COND_V(!soft_body, false); + + return soft_body->is_vertex_pinned(p_point_index); +} + /* JOINT API */ RID PhysicsServer3DSW::joint_create() { @@ -1278,7 +1547,13 @@ void PhysicsServer3DSW::free(RID p_rid) { body_owner.free(p_rid); memdelete(body); + } else if (soft_body_owner.owns(p_rid)) { + SoftBody3DSW *soft_body = soft_body_owner.getornull(p_rid); + + soft_body->set_space(nullptr); + soft_body_owner.free(p_rid); + memdelete(soft_body); } else if (area_owner.owns(p_rid)) { Area3DSW *area = area_owner.getornull(p_rid); @@ -1444,7 +1719,7 @@ void PhysicsServer3DSW::_update_shapes() { } } -void PhysicsServer3DSW::_shape_col_cbk(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) { +void PhysicsServer3DSW::_shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { CollCbkData *cbk = (CollCbkData *)p_userdata; if (cbk->max == 0) { diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h index afda161fa8..f92652bfad 100644 --- a/servers/physics_3d/physics_server_3d_sw.h +++ b/servers/physics_3d/physics_server_3d_sw.h @@ -63,6 +63,7 @@ class PhysicsServer3DSW : public PhysicsServer3D { mutable RID_PtrOwner<Space3DSW, true> space_owner; mutable RID_PtrOwner<Area3DSW, true> area_owner; mutable RID_PtrOwner<Body3DSW, true> body_owner; + mutable RID_PtrOwner<SoftBody3DSW, true> soft_body_owner; mutable RID_PtrOwner<Joint3DSW, true> joint_owner; //void _clear_query(QuerySW *p_query); @@ -79,7 +80,7 @@ public: Vector3 *ptr; }; - static void _shape_col_cbk(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata); + static void _shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata); virtual RID plane_shape_create() override; virtual RID ray_shape_create() override; @@ -252,68 +253,58 @@ public: /* SOFT BODY */ - virtual RID soft_body_create() override { return RID(); } + virtual RID soft_body_create() override; - virtual void soft_body_update_rendering_server(RID p_body, class SoftBodyRenderingServerHandler *p_rendering_server_handler) override {} + virtual void soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) override; - virtual void soft_body_set_space(RID p_body, RID p_space) override {} - virtual RID soft_body_get_space(RID p_body) const override { return RID(); } + virtual void soft_body_set_space(RID p_body, RID p_space) override; + virtual RID soft_body_get_space(RID p_body) const override; - virtual void soft_body_set_collision_layer(RID p_body, uint32_t p_layer) override {} - virtual uint32_t soft_body_get_collision_layer(RID p_body) const override { return 0; } + virtual void soft_body_set_collision_layer(RID p_body, uint32_t p_layer) override; + virtual uint32_t soft_body_get_collision_layer(RID p_body) const override; - virtual void soft_body_set_collision_mask(RID p_body, uint32_t p_mask) override {} - virtual uint32_t soft_body_get_collision_mask(RID p_body) const override { return 0; } + virtual void soft_body_set_collision_mask(RID p_body, uint32_t p_mask) override; + virtual uint32_t soft_body_get_collision_mask(RID p_body) const override; - virtual void soft_body_add_collision_exception(RID p_body, RID p_body_b) override {} - virtual void soft_body_remove_collision_exception(RID p_body, RID p_body_b) override {} - virtual void soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) override {} + virtual void soft_body_add_collision_exception(RID p_body, RID p_body_b) override; + virtual void soft_body_remove_collision_exception(RID p_body, RID p_body_b) override; + virtual void soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) override; - virtual void soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) override {} - virtual Variant soft_body_get_state(RID p_body, BodyState p_state) const override { return Variant(); } + virtual void soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) override; + virtual Variant soft_body_get_state(RID p_body, BodyState p_state) const override; - virtual void soft_body_set_transform(RID p_body, const Transform &p_transform) override {} - virtual Vector3 soft_body_get_vertex_position(RID p_body, int vertex_index) const override { return Vector3(); } + virtual void soft_body_set_transform(RID p_body, const Transform &p_transform) override; - virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) override {} + virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) override; - virtual void soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) override {} - virtual int soft_body_get_simulation_precision(RID p_body) const override { return 0; } + virtual void soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) override; + virtual int soft_body_get_simulation_precision(RID p_body) const override; - virtual void soft_body_set_total_mass(RID p_body, real_t p_total_mass) override {} - virtual real_t soft_body_get_total_mass(RID p_body) const override { return 0.; } + virtual void soft_body_set_total_mass(RID p_body, real_t p_total_mass) override; + virtual real_t soft_body_get_total_mass(RID p_body) const override; - virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) override {} - virtual real_t soft_body_get_linear_stiffness(RID p_body) const override { return 0.; } + virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) override; + virtual real_t soft_body_get_linear_stiffness(RID p_body) const override; - virtual void soft_body_set_angular_stiffness(RID p_body, real_t p_stiffness) override {} - virtual real_t soft_body_get_angular_stiffness(RID p_body) const override { return 0.; } + virtual void soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) override; + virtual real_t soft_body_get_pressure_coefficient(RID p_body) const override; - virtual void soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) override {} - virtual real_t soft_body_get_volume_stiffness(RID p_body) const override { return 0.; } + virtual void soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) override; + virtual real_t soft_body_get_damping_coefficient(RID p_body) const override; - virtual void soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) override {} - virtual real_t soft_body_get_pressure_coefficient(RID p_body) const override { return 0.; } + virtual void soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) override; + virtual real_t soft_body_get_drag_coefficient(RID p_body) const override; - virtual void soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) override {} - virtual real_t soft_body_get_pose_matching_coefficient(RID p_body) const override { return 0.; } + virtual void soft_body_set_mesh(RID p_body, const REF &p_mesh) override; - virtual void soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) override {} - virtual real_t soft_body_get_damping_coefficient(RID p_body) const override { return 0.; } + virtual AABB soft_body_get_bounds(RID p_body) const override; - virtual void soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) override {} - virtual real_t soft_body_get_drag_coefficient(RID p_body) const override { return 0.; } + virtual void soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) override; + virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) const override; - virtual void soft_body_set_mesh(RID p_body, const REF &p_mesh) override {} - - virtual void soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) override {} - virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) const override { return Vector3(); } - - virtual Vector3 soft_body_get_point_offset(RID p_body, int p_point_index) const override { return Vector3(); } - - virtual void soft_body_remove_all_pinned_points(RID p_body) override {} - virtual void soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) override {} - virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) const override { return false; } + virtual void soft_body_remove_all_pinned_points(RID p_body) override; + virtual void soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) override; + virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) const override; /* JOINT API */ diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.h b/servers/physics_3d/physics_server_3d_wrap_mt.h index f60e1332d5..49ae60db92 100644 --- a/servers/physics_3d/physics_server_3d_wrap_mt.h +++ b/servers/physics_3d/physics_server_3d_wrap_mt.h @@ -273,7 +273,7 @@ public: FUNCRID(soft_body) - FUNC2(soft_body_update_rendering_server, RID, class SoftBodyRenderingServerHandler *) + FUNC2(soft_body_update_rendering_server, RID, class RenderingServerHandler *) FUNC2(soft_body_set_space, RID, RID) FUNC1RC(RID, soft_body_get_space, RID) @@ -294,7 +294,6 @@ public: FUNC2RC(Variant, soft_body_get_state, RID, BodyState); FUNC2(soft_body_set_transform, RID, const Transform &); - FUNC2RC(Vector3, soft_body_get_vertex_position, RID, int); FUNC2(soft_body_set_simulation_precision, RID, int); FUNC1RC(int, soft_body_get_simulation_precision, RID); @@ -305,18 +304,9 @@ public: FUNC2(soft_body_set_linear_stiffness, RID, real_t); FUNC1RC(real_t, soft_body_get_linear_stiffness, RID); - FUNC2(soft_body_set_angular_stiffness, RID, real_t); - FUNC1RC(real_t, soft_body_get_angular_stiffness, RID); - - FUNC2(soft_body_set_volume_stiffness, RID, real_t); - FUNC1RC(real_t, soft_body_get_volume_stiffness, RID); - FUNC2(soft_body_set_pressure_coefficient, RID, real_t); FUNC1RC(real_t, soft_body_get_pressure_coefficient, RID); - FUNC2(soft_body_set_pose_matching_coefficient, RID, real_t); - FUNC1RC(real_t, soft_body_get_pose_matching_coefficient, RID); - FUNC2(soft_body_set_damping_coefficient, RID, real_t); FUNC1RC(real_t, soft_body_get_damping_coefficient, RID); @@ -325,9 +315,10 @@ public: FUNC2(soft_body_set_mesh, RID, const REF &); + FUNC1RC(AABB, soft_body_get_bounds, RID); + FUNC3(soft_body_move_point, RID, int, const Vector3 &); FUNC2RC(Vector3, soft_body_get_point_global_position, RID, int); - FUNC2RC(Vector3, soft_body_get_point_offset, RID, int); FUNC1(soft_body_remove_all_pinned_points, RID); FUNC3(soft_body_pin_point, RID, int, bool); diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/shape_3d_sw.cpp index 02d0c66215..bf0946a0e2 100644 --- a/servers/physics_3d/shape_3d_sw.cpp +++ b/servers/physics_3d/shape_3d_sw.cpp @@ -627,7 +627,7 @@ Vector3 CapsuleShape3DSW::get_moment_of_inertia(real_t p_mass) const { return Vector3( (p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z), (p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z), - (p_mass / 3.0) * (extents.y * extents.y + extents.y * extents.y)); + (p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y)); } void CapsuleShape3DSW::_setup(real_t p_height, real_t p_radius) { @@ -807,7 +807,7 @@ Vector3 CylinderShape3DSW::get_moment_of_inertia(real_t p_mass) const { return Vector3( (p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z), (p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z), - (p_mass / 3.0) * (extents.y * extents.y + extents.y * extents.y)); + (p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y)); } void CylinderShape3DSW::_setup(real_t p_height, real_t p_radius) { @@ -1064,7 +1064,7 @@ Vector3 ConvexPolygonShape3DSW::get_moment_of_inertia(real_t p_mass) const { return Vector3( (p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z), (p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z), - (p_mass / 3.0) * (extents.y * extents.y + extents.y * extents.y)); + (p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y)); } void ConvexPolygonShape3DSW::_setup(const Vector<Vector3> &p_vertices) { @@ -1134,7 +1134,7 @@ void FaceShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_ Vector3 n = p_normal; /** TEST FACE AS SUPPORT **/ - if (normal.dot(n) > _FACE_IS_VALID_SUPPORT_THRESHOLD) { + if (Math::abs(normal.dot(n)) > _FACE_IS_VALID_SUPPORT_THRESHOLD) { r_amount = 3; r_type = FEATURE_FACE; for (int i = 0; i < 3; i++) { @@ -1187,7 +1187,11 @@ bool FaceShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_e if (c) { r_normal = Plane(vertex[0], vertex[1], vertex[2]).normal; if (r_normal.dot(p_end - p_begin) > 0) { - r_normal = -r_normal; + if (backface_collision) { + r_normal = -r_normal; + } else { + c = false; + } } } @@ -1285,30 +1289,24 @@ void ConcavePolygonShape3DSW::_cull_segment(int p_idx, _SegmentCullParams *p_par } if (bvh->face_index >= 0) { - Vector3 res; - Vector3 vertices[3] = { - p_params->vertices[p_params->faces[bvh->face_index].indices[0]], - p_params->vertices[p_params->faces[bvh->face_index].indices[1]], - p_params->vertices[p_params->faces[bvh->face_index].indices[2]] - }; + const Face *f = &p_params->faces[bvh->face_index]; + FaceShape3DSW *face = p_params->face; + face->normal = f->normal; + face->vertex[0] = p_params->vertices[f->indices[0]]; + face->vertex[1] = p_params->vertices[f->indices[1]]; + face->vertex[2] = p_params->vertices[f->indices[2]]; - if (Geometry3D::segment_intersects_triangle( - p_params->from, - p_params->to, - vertices[0], - vertices[1], - vertices[2], - &res)) { + Vector3 res; + Vector3 normal; + if (face->intersect_segment(p_params->from, p_params->to, res, normal)) { real_t d = p_params->dir.dot(res) - p_params->dir.dot(p_params->from); - //TODO, seems segmen/triangle intersection is broken :( - if (d > 0 && d < p_params->min_d) { + if ((d > 0) && (d < p_params->min_d)) { p_params->min_d = d; p_params->result = res; - p_params->normal = Plane(vertices[0], vertices[1], vertices[2]).normal; + p_params->normal = normal; p_params->collisions++; } } - } else { if (bvh->left >= 0) { _cull_segment(bvh->left, p_params); @@ -1329,17 +1327,20 @@ bool ConcavePolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Ve const Vector3 *vr = vertices.ptr(); const BVH *br = bvh.ptr(); + FaceShape3DSW face; + face.backface_collision = backface_collision; + _SegmentCullParams params; params.from = p_begin; params.to = p_end; - params.collisions = 0; params.dir = (p_end - p_begin).normalized(); params.faces = fr; params.vertices = vr; params.bvh = br; - params.min_d = 1e20; + params.face = &face; + // cull _cull_segment(0, ¶ms); @@ -1401,6 +1402,7 @@ void ConcavePolygonShape3DSW::cull(const AABB &p_local_aabb, Callback p_callback const BVH *br = bvh.ptr(); FaceShape3DSW face; // use this to send in the callback + face.backface_collision = backface_collision; _CullParams params; params.aabb = local_aabb; @@ -1422,7 +1424,7 @@ Vector3 ConcavePolygonShape3DSW::get_moment_of_inertia(real_t p_mass) const { return Vector3( (p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z), (p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z), - (p_mass / 3.0) * (extents.y * extents.y + extents.y * extents.y)); + (p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y)); } struct _VolumeSW_BVH_Element { @@ -1532,7 +1534,7 @@ void ConcavePolygonShape3DSW::_fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_ar memdelete(p_bvh_tree); } -void ConcavePolygonShape3DSW::_setup(Vector<Vector3> p_faces) { +void ConcavePolygonShape3DSW::_setup(const Vector<Vector3> &p_faces, bool p_backface_collision) { int src_face_count = p_faces.size(); if (src_face_count == 0) { configure(AABB()); @@ -1587,15 +1589,24 @@ void ConcavePolygonShape3DSW::_setup(Vector<Vector3> p_faces) { int idx = 0; _fill_bvh(bvh_tree, bvh_arrayw2, idx); + backface_collision = p_backface_collision; + configure(_aabb); // this type of shape has no margin } void ConcavePolygonShape3DSW::set_data(const Variant &p_data) { - _setup(p_data); + Dictionary d = p_data; + ERR_FAIL_COND(!d.has("faces")); + + _setup(d["faces"], d["backface_collision"]); } Variant ConcavePolygonShape3DSW::get_data() const { - return get_faces(); + Dictionary d; + d["faces"] = get_faces(); + d["backface_collision"] = backface_collision; + + return d; } ConcavePolygonShape3DSW::ConcavePolygonShape3DSW() { @@ -1651,7 +1662,7 @@ Vector3 HeightMapShape3DSW::get_moment_of_inertia(real_t p_mass) const { return Vector3( (p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z), (p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z), - (p_mass / 3.0) * (extents.y * extents.y + extents.y * extents.y)); + (p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y)); } void HeightMapShape3DSW::_setup(Vector<real_t> p_heights, int p_width, int p_depth, real_t p_cell_size) { diff --git a/servers/physics_3d/shape_3d_sw.h b/servers/physics_3d/shape_3d_sw.h index cafe978abb..988e76c699 100644 --- a/servers/physics_3d/shape_3d_sw.h +++ b/servers/physics_3d/shape_3d_sw.h @@ -334,34 +334,37 @@ struct ConcavePolygonShape3DSW : public ConcaveShape3DSW { struct _CullParams { AABB aabb; - Callback callback; - void *userdata; - const Face *faces; - const Vector3 *vertices; - const BVH *bvh; - FaceShape3DSW *face; + Callback callback = nullptr; + void *userdata = nullptr; + const Face *faces = nullptr; + const Vector3 *vertices = nullptr; + const BVH *bvh = nullptr; + FaceShape3DSW *face = nullptr; }; struct _SegmentCullParams { Vector3 from; Vector3 to; - const Face *faces; - const Vector3 *vertices; - const BVH *bvh; Vector3 dir; + const Face *faces = nullptr; + const Vector3 *vertices = nullptr; + const BVH *bvh = nullptr; + FaceShape3DSW *face = nullptr; Vector3 result; Vector3 normal; - real_t min_d; - int collisions; + real_t min_d = 1e20; + int collisions = 0; }; + bool backface_collision = false; + void _cull_segment(int p_idx, _SegmentCullParams *p_params) const; void _cull(int p_idx, _CullParams *p_params) const; void _fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_array, int &p_idx); - void _setup(Vector<Vector3> p_faces); + void _setup(const Vector<Vector3> &p_faces, bool p_backface_collision); public: Vector<Vector3> get_faces() const; @@ -424,6 +427,7 @@ public: struct FaceShape3DSW : public Shape3DSW { Vector3 normal; //cache Vector3 vertex[3]; + bool backface_collision = false; virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_CONCAVE_POLYGON; } diff --git a/servers/physics_3d/soft_body_3d_sw.cpp b/servers/physics_3d/soft_body_3d_sw.cpp new file mode 100644 index 0000000000..f63a470cbe --- /dev/null +++ b/servers/physics_3d/soft_body_3d_sw.cpp @@ -0,0 +1,1221 @@ +/*************************************************************************/ +/* soft_body_3d_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 "soft_body_3d_sw.h" +#include "space_3d_sw.h" + +#include "core/math/geometry_3d.h" +#include "core/templates/map.h" + +// Based on Bullet soft body. + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btSoftBody implementation by Nathanael Presson + +SoftBody3DSW::SoftBody3DSW() : + CollisionObject3DSW(TYPE_SOFT_BODY), + active_list(this) { + _set_static(false); +} + +void SoftBody3DSW::_shapes_changed() { +} + +void SoftBody3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant) { + switch (p_state) { + case PhysicsServer3D::BODY_STATE_TRANSFORM: { + _set_transform(p_variant); + _set_inv_transform(get_transform().inverse()); + + apply_nodes_transform(get_transform()); + + } break; + case PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY: { + // Not supported. + ERR_FAIL_MSG("Linear velocity is not supported for Soft bodies."); + } break; + case PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY: { + ERR_FAIL_MSG("Angular velocity is not supported for Soft bodies."); + } break; + case PhysicsServer3D::BODY_STATE_SLEEPING: { + ERR_FAIL_MSG("Sleeping state is not supported for Soft bodies."); + } break; + case PhysicsServer3D::BODY_STATE_CAN_SLEEP: { + ERR_FAIL_MSG("Sleeping state is not supported for Soft bodies."); + } break; + } +} + +Variant SoftBody3DSW::get_state(PhysicsServer3D::BodyState p_state) const { + switch (p_state) { + case PhysicsServer3D::BODY_STATE_TRANSFORM: { + return get_transform(); + } break; + case PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY: { + ERR_FAIL_V_MSG(Vector3(), "Linear velocity is not supported for Soft bodies."); + } break; + case PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY: { + ERR_FAIL_V_MSG(Vector3(), "Angular velocity is not supported for Soft bodies."); + return Vector3(); + } break; + case PhysicsServer3D::BODY_STATE_SLEEPING: { + ERR_FAIL_V_MSG(false, "Sleeping state is not supported for Soft bodies."); + } break; + case PhysicsServer3D::BODY_STATE_CAN_SLEEP: { + ERR_FAIL_V_MSG(false, "Sleeping state is not supported for Soft bodies."); + } break; + } + + return Variant(); +} + +void SoftBody3DSW::set_space(Space3DSW *p_space) { + if (get_space()) { + get_space()->soft_body_remove_from_active_list(&active_list); + + deinitialize_shape(); + } + + _set_space(p_space); + + if (get_space()) { + get_space()->soft_body_add_to_active_list(&active_list); + + if (bounds != AABB()) { + initialize_shape(true); + } + } +} + +void SoftBody3DSW::set_mesh(const Ref<Mesh> &p_mesh) { + destroy(); + + soft_mesh = p_mesh; + + if (soft_mesh.is_null()) { + return; + } + + Array arrays = soft_mesh->surface_get_arrays(0); + ERR_FAIL_COND(!(soft_mesh->surface_get_format(0) & RS::ARRAY_FORMAT_INDEX)); + + bool success = create_from_trimesh(arrays[RS::ARRAY_INDEX], arrays[RS::ARRAY_VERTEX]); + if (!success) { + destroy(); + soft_mesh = Ref<Mesh>(); + } +} + +void SoftBody3DSW::update_rendering_server(RenderingServerHandler *p_rendering_server_handler) { + if (soft_mesh.is_null()) { + return; + } + + const uint32_t vertex_count = map_visual_to_physics.size(); + for (uint32_t i = 0; i < vertex_count; ++i) { + const uint32_t node_index = map_visual_to_physics[i]; + const Node &node = nodes[node_index]; + const Vector3 &vertex_position = node.x; + const Vector3 &vertex_normal = node.n; + + p_rendering_server_handler->set_vertex(i, &vertex_position); + p_rendering_server_handler->set_normal(i, &vertex_normal); + } + + p_rendering_server_handler->set_aabb(bounds); +} + +void SoftBody3DSW::update_normals() { + uint32_t i, ni; + + for (i = 0, ni = nodes.size(); i < ni; ++i) { + nodes[i].n = Vector3(); + } + + for (i = 0, ni = faces.size(); i < ni; ++i) { + Face &face = faces[i]; + const Vector3 n = vec3_cross(face.n[0]->x - face.n[2]->x, face.n[0]->x - face.n[1]->x); + face.n[0]->n += n; + face.n[1]->n += n; + face.n[2]->n += n; + face.normal = n; + face.normal.normalize(); + } + + for (i = 0, ni = nodes.size(); i < ni; ++i) { + Node &node = nodes[i]; + real_t len = node.n.length(); + if (len > CMP_EPSILON) { + node.n /= len; + } + } +} + +void SoftBody3DSW::update_bounds() { + AABB prev_bounds = bounds; + prev_bounds.grow_by(collision_margin); + + bounds = AABB(); + + const uint32_t nodes_count = nodes.size(); + if (nodes_count == 0) { + deinitialize_shape(); + return; + } + + bool first = true; + bool moved = false; + for (uint32_t node_index = 0; node_index < nodes_count; ++node_index) { + const Node &node = nodes[node_index]; + if (!prev_bounds.has_point(node.x)) { + moved = true; + } + if (first) { + bounds.position = node.x; + first = false; + } else { + bounds.expand_to(node.x); + } + } + + if (get_space()) { + initialize_shape(moved); + } +} + +void SoftBody3DSW::update_constants() { + reset_link_rest_lengths(); + update_link_constants(); + update_area(); +} + +void SoftBody3DSW::update_area() { + int i, ni; + + // Face area. + for (i = 0, ni = faces.size(); i < ni; ++i) { + Face &face = faces[i]; + + const Vector3 &x0 = face.n[0]->x; + const Vector3 &x1 = face.n[1]->x; + const Vector3 &x2 = face.n[2]->x; + + const Vector3 a = x1 - x0; + const Vector3 b = x2 - x0; + const Vector3 cr = vec3_cross(a, b); + face.ra = cr.length(); + } + + // Node area. + LocalVector<int> counts; + counts.resize(nodes.size()); + memset(counts.ptr(), 0, counts.size() * sizeof(int)); + + for (i = 0, ni = nodes.size(); i < ni; ++i) { + nodes[i].area = 0.0; + } + + for (i = 0, ni = faces.size(); i < ni; ++i) { + const Face &face = faces[i]; + for (int j = 0; j < 3; ++j) { + const int index = (int)(face.n[j] - &nodes[0]); + counts[index]++; + face.n[j]->area += Math::abs(face.ra); + } + } + + for (i = 0, ni = nodes.size(); i < ni; ++i) { + if (counts[i] > 0) { + nodes[i].area /= (real_t)counts[i]; + } else { + nodes[i].area = 0.0; + } + } +} + +void SoftBody3DSW::reset_link_rest_lengths() { + for (uint32_t i = 0, ni = links.size(); i < ni; ++i) { + Link &link = links[i]; + link.rl = (link.n[0]->x - link.n[1]->x).length(); + link.c1 = link.rl * link.rl; + } +} + +void SoftBody3DSW::update_link_constants() { + real_t inv_linear_stiffness = 1.0 / linear_stiffness; + for (uint32_t i = 0, ni = links.size(); i < ni; ++i) { + Link &link = links[i]; + link.c0 = (link.n[0]->im + link.n[1]->im) * inv_linear_stiffness; + } +} + +void SoftBody3DSW::apply_nodes_transform(const Transform &p_transform) { + if (soft_mesh.is_null()) { + return; + } + + uint32_t node_count = nodes.size(); + Vector3 leaf_size = Vector3(collision_margin, collision_margin, collision_margin) * 2.0; + for (uint32_t node_index = 0; node_index < node_count; ++node_index) { + Node &node = nodes[node_index]; + + node.x = p_transform.xform(node.x); + node.q = node.x; + node.v = Vector3(); + node.bv = Vector3(); + + AABB node_aabb(node.x, leaf_size); + node_tree.update(node.leaf, node_aabb); + } + + face_tree.clear(); + + update_normals(); + update_bounds(); + update_constants(); +} + +Vector3 SoftBody3DSW::get_vertex_position(int p_index) const { + if (soft_mesh.is_null()) { + return Vector3(); + } + + ERR_FAIL_INDEX_V(p_index, (int)map_visual_to_physics.size(), Vector3()); + uint32_t node_index = map_visual_to_physics[p_index]; + + ERR_FAIL_COND_V(node_index >= nodes.size(), Vector3()); + return nodes[node_index].x; +} + +void SoftBody3DSW::set_vertex_position(int p_index, const Vector3 &p_position) { + if (soft_mesh.is_null()) { + return; + } + + ERR_FAIL_INDEX(p_index, (int)map_visual_to_physics.size()); + uint32_t node_index = map_visual_to_physics[p_index]; + + ERR_FAIL_COND(node_index >= nodes.size()); + Node &node = nodes[node_index]; + node.q = node.x; + node.x = p_position; +} + +void SoftBody3DSW::pin_vertex(int p_index) { + if (is_vertex_pinned(p_index)) { + return; + } + + pinned_vertices.push_back(p_index); + + if (!soft_mesh.is_null()) { + ERR_FAIL_INDEX(p_index, (int)map_visual_to_physics.size()); + uint32_t node_index = map_visual_to_physics[p_index]; + + ERR_FAIL_COND(node_index >= nodes.size()); + Node &node = nodes[node_index]; + node.im = 0.0; + } +} + +void SoftBody3DSW::unpin_vertex(int p_index) { + uint32_t pinned_count = pinned_vertices.size(); + for (uint32_t i = 0; i < pinned_count; ++i) { + if (p_index == pinned_vertices[i]) { + pinned_vertices.remove(i); + + if (!soft_mesh.is_null()) { + ERR_FAIL_INDEX(p_index, (int)map_visual_to_physics.size()); + uint32_t node_index = map_visual_to_physics[p_index]; + + ERR_FAIL_COND(node_index >= nodes.size()); + real_t inv_node_mass = nodes.size() * inv_total_mass; + + Node &node = nodes[node_index]; + node.im = inv_node_mass; + } + + return; + } + } +} + +void SoftBody3DSW::unpin_all_vertices() { + if (!soft_mesh.is_null()) { + real_t inv_node_mass = nodes.size() * inv_total_mass; + uint32_t pinned_count = pinned_vertices.size(); + for (uint32_t i = 0; i < pinned_count; ++i) { + uint32_t vertex_index = pinned_vertices[i]; + + ERR_CONTINUE(vertex_index >= map_visual_to_physics.size()); + uint32_t node_index = map_visual_to_physics[vertex_index]; + + ERR_CONTINUE(node_index >= nodes.size()); + Node &node = nodes[node_index]; + node.im = inv_node_mass; + } + } + + pinned_vertices.clear(); +} + +bool SoftBody3DSW::is_vertex_pinned(int p_index) const { + uint32_t pinned_count = pinned_vertices.size(); + for (uint32_t i = 0; i < pinned_count; ++i) { + if (p_index == pinned_vertices[i]) { + return true; + } + } + + return false; +} + +uint32_t SoftBody3DSW::get_node_count() const { + return nodes.size(); +} + +real_t SoftBody3DSW::get_node_inv_mass(uint32_t p_node_index) const { + ERR_FAIL_COND_V(p_node_index >= nodes.size(), 0.0); + return nodes[p_node_index].im; +} + +Vector3 SoftBody3DSW::get_node_position(uint32_t p_node_index) const { + ERR_FAIL_COND_V(p_node_index >= nodes.size(), Vector3()); + return nodes[p_node_index].x; +} + +Vector3 SoftBody3DSW::get_node_velocity(uint32_t p_node_index) const { + ERR_FAIL_COND_V(p_node_index >= nodes.size(), Vector3()); + return nodes[p_node_index].v; +} + +Vector3 SoftBody3DSW::get_node_biased_velocity(uint32_t p_node_index) const { + ERR_FAIL_COND_V(p_node_index >= nodes.size(), Vector3()); + return nodes[p_node_index].bv; +} + +void SoftBody3DSW::apply_node_impulse(uint32_t p_node_index, const Vector3 &p_impulse) { + ERR_FAIL_COND(p_node_index >= nodes.size()); + Node &node = nodes[p_node_index]; + node.v += p_impulse * node.im; +} + +void SoftBody3DSW::apply_node_bias_impulse(uint32_t p_node_index, const Vector3 &p_impulse) { + ERR_FAIL_COND(p_node_index >= nodes.size()); + Node &node = nodes[p_node_index]; + node.bv += p_impulse * node.im; +} + +uint32_t SoftBody3DSW::get_face_count() const { + return faces.size(); +} + +void SoftBody3DSW::get_face_points(uint32_t p_face_index, Vector3 &r_point_1, Vector3 &r_point_2, Vector3 &r_point_3) const { + ERR_FAIL_COND(p_face_index >= faces.size()); + const Face &face = faces[p_face_index]; + r_point_1 = face.n[0]->x; + r_point_2 = face.n[1]->x; + r_point_3 = face.n[2]->x; +} + +Vector3 SoftBody3DSW::get_face_normal(uint32_t p_face_index) const { + ERR_FAIL_COND_V(p_face_index >= faces.size(), Vector3()); + return faces[p_face_index].normal; +} + +bool SoftBody3DSW::create_from_trimesh(const Vector<int> &p_indices, const Vector<Vector3> &p_vertices) { + uint32_t node_count = 0; + LocalVector<Vector3> vertices; + const int visual_vertex_count(p_vertices.size()); + + LocalVector<int> triangles; + const uint32_t triangle_count(p_indices.size() / 3); + triangles.resize(triangle_count * 3); + + // Merge all overlapping vertices and create a map of physical vertices to visual vertices. + { + // Process vertices. + { + uint32_t vertex_count = 0; + Map<Vector3, uint32_t> unique_vertices; + + vertices.resize(visual_vertex_count); + map_visual_to_physics.resize(visual_vertex_count); + + for (int visual_vertex_index = 0; visual_vertex_index < visual_vertex_count; ++visual_vertex_index) { + const Vector3 &vertex = p_vertices[visual_vertex_index]; + + Map<Vector3, uint32_t>::Element *e = unique_vertices.find(vertex); + uint32_t vertex_id; + if (e) { + // Already existing. + vertex_id = e->value(); + } else { + // Create new one. + vertex_id = vertex_count++; + unique_vertices[vertex] = vertex_id; + vertices[vertex_id] = vertex; + } + + map_visual_to_physics[visual_vertex_index] = vertex_id; + } + + vertices.resize(vertex_count); + } + + // Process triangles. + { + for (uint32_t triangle_index = 0; triangle_index < triangle_count; ++triangle_index) { + for (int i = 0; i < 3; ++i) { + int visual_index = 3 * triangle_index + i; + int physics_index = map_visual_to_physics[p_indices[visual_index]]; + triangles[visual_index] = physics_index; + node_count = MAX((int)node_count, physics_index); + } + } + } + } + + ++node_count; + + // Create nodes from vertices. + nodes.resize(node_count); + real_t inv_node_mass = node_count * inv_total_mass; + Vector3 leaf_size = Vector3(collision_margin, collision_margin, collision_margin) * 2.0; + for (uint32_t i = 0; i < node_count; ++i) { + Node &node = nodes[i]; + node.s = vertices[i]; + node.x = node.s; + node.q = node.s; + node.im = inv_node_mass; + + AABB node_aabb(node.x, leaf_size); + node.leaf = node_tree.insert(node_aabb, &node); + + node.index = i; + } + + // Create links and faces from triangles. + LocalVector<bool> chks; + chks.resize(node_count * node_count); + memset(chks.ptr(), 0, chks.size() * sizeof(bool)); + + for (uint32_t i = 0; i < triangle_count * 3; i += 3) { + const int idx[] = { triangles[i], triangles[i + 1], triangles[i + 2] }; + + for (int j = 2, k = 0; k < 3; j = k++) { + int chk = idx[k] * node_count + idx[j]; + if (!chks[chk]) { + chks[chk] = true; + int inv_chk = idx[j] * node_count + idx[k]; + chks[inv_chk] = true; + + append_link(idx[j], idx[k]); + } + } + + append_face(idx[0], idx[1], idx[2]); + } + + // Set pinned nodes. + uint32_t pinned_count = pinned_vertices.size(); + for (uint32_t i = 0; i < pinned_count; ++i) { + int pinned_vertex = pinned_vertices[i]; + + ERR_CONTINUE(pinned_vertex >= visual_vertex_count); + uint32_t node_index = map_visual_to_physics[pinned_vertex]; + + ERR_CONTINUE(node_index >= node_count); + Node &node = nodes[node_index]; + node.im = 0.0; + } + + generate_bending_constraints(2); + reoptimize_link_order(); + + update_constants(); + update_normals(); + update_bounds(); + + return true; +} + +void SoftBody3DSW::generate_bending_constraints(int p_distance) { + uint32_t i, j; + + if (p_distance > 1) { + // Build graph. + const uint32_t n = nodes.size(); + const unsigned inf = (~(unsigned)0) >> 1; + const uint32_t adj_size = n * n; + unsigned *adj = memnew_arr(unsigned, adj_size); + +#define IDX(_x_, _y_) ((_y_)*n + (_x_)) + for (j = 0; j < n; ++j) { + for (i = 0; i < n; ++i) { + int idx_ij = j * n + i; + int idx_ji = i * n + j; + if (i != j) { + adj[idx_ij] = adj[idx_ji] = inf; + } else { + adj[idx_ij] = adj[idx_ji] = 0; + } + } + } + for (i = 0; i < links.size(); ++i) { + const int ia = (int)(links[i].n[0] - &nodes[0]); + const int ib = (int)(links[i].n[1] - &nodes[0]); + int idx = ib * n + ia; + int idx_inv = ia * n + ib; + adj[idx] = 1; + adj[idx_inv] = 1; + } + + // Special optimized case for distance == 2. + if (p_distance == 2) { + LocalVector<LocalVector<int>> node_links; + + // Build node links. + node_links.resize(nodes.size()); + + for (i = 0; i < links.size(); ++i) { + const int ia = (int)(links[i].n[0] - &nodes[0]); + const int ib = (int)(links[i].n[1] - &nodes[0]); + if (node_links[ia].find(ib) == -1) { + node_links[ia].push_back(ib); + } + + if (node_links[ib].find(ia) == -1) { + node_links[ib].push_back(ia); + } + } + for (uint32_t ii = 0; ii < node_links.size(); ii++) { + for (uint32_t jj = 0; jj < node_links[ii].size(); jj++) { + int k = node_links[ii][jj]; + for (uint32_t kk = 0; kk < node_links[k].size(); kk++) { + int l = node_links[k][kk]; + if ((int)ii != l) { + int idx_ik = k * n + ii; + int idx_kj = l * n + k; + const unsigned sum = adj[idx_ik] + adj[idx_kj]; + ERR_FAIL_COND(sum != 2); + int idx_ij = l * n + ii; + if (adj[idx_ij] > sum) { + int idx_ji = l * n + ii; + adj[idx_ij] = adj[idx_ji] = sum; + } + } + } + } + } + } else { + // Generic Floyd's algorithm. + for (uint32_t k = 0; k < n; ++k) { + for (j = 0; j < n; ++j) { + for (i = j + 1; i < n; ++i) { + int idx_ik = k * n + i; + int idx_kj = j * n + k; + const unsigned sum = adj[idx_ik] + adj[idx_kj]; + int idx_ij = j * n + i; + if (adj[idx_ij] > sum) { + int idx_ji = j * n + i; + adj[idx_ij] = adj[idx_ji] = sum; + } + } + } + } + } + + // Build links. + for (j = 0; j < n; ++j) { + for (i = j + 1; i < n; ++i) { + int idx_ij = j * n + i; + if (adj[idx_ij] == (unsigned)p_distance) { + append_link(i, j); + } + } + } + memdelete_arr(adj); + } +} + +//=================================================================== +// +// +// This function takes in a list of interdependent Links and tries +// to maximize the distance between calculation +// of dependent links. This increases the amount of parallelism that can +// be exploited by out-of-order instruction processors with large but +// (inevitably) finite instruction windows. +// +//=================================================================== + +// A small structure to track lists of dependent link calculations. +class LinkDeps { +public: + int value; // A link calculation that is dependent on this one + // Positive values = "input A" while negative values = "input B" + LinkDeps *next; // Next dependence in the list +}; +typedef LinkDeps *LinkDepsPtr; + +void SoftBody3DSW::reoptimize_link_order() { + const int reop_not_dependent = -1; + const int reop_node_complete = -2; + + uint32_t i, link_count = links.size(), node_count = nodes.size(); + Link *lr; + int ar, br; + Node *node0 = &(nodes[0]); + Node *node1 = &(nodes[1]); + LinkDepsPtr link_dep; + int ready_list_head, ready_list_tail, link_num, link_dep_frees, dep_link; + + // Allocate temporary buffers. + int *node_written_at = memnew_arr(int, node_count + 1); // What link calculation produced this node's current values? + int *link_dep_A = memnew_arr(int, link_count); // Link calculation input is dependent upon prior calculation #N + int *link_dep_B = memnew_arr(int, link_count); + int *ready_list = memnew_arr(int, link_count); // List of ready-to-process link calculations (# of links, maximum) + LinkDeps *link_dep_free_list = memnew_arr(LinkDeps, 2 * link_count); // Dependent-on-me list elements (2x# of links, maximum) + LinkDepsPtr *link_dep_list_starts = memnew_arr(LinkDepsPtr, link_count); // Start nodes of dependent-on-me lists, one for each link + + // Copy the original, unsorted links to a side buffer. + Link *link_buffer = memnew_arr(Link, link_count); + memcpy(link_buffer, &(links[0]), sizeof(Link) * link_count); + + // Clear out the node setup and ready list. + for (i = 0; i < node_count + 1; i++) { + node_written_at[i] = reop_not_dependent; + } + for (i = 0; i < link_count; i++) { + link_dep_list_starts[i] = nullptr; + } + ready_list_head = ready_list_tail = link_dep_frees = 0; + + // Initial link analysis to set up data structures. + for (i = 0; i < link_count; i++) { + // Note which prior link calculations we are dependent upon & build up dependence lists. + lr = &(links[i]); + ar = (lr->n[0] - node0) / (node1 - node0); + br = (lr->n[1] - node0) / (node1 - node0); + if (node_written_at[ar] > reop_not_dependent) { + link_dep_A[i] = node_written_at[ar]; + link_dep = &link_dep_free_list[link_dep_frees++]; + link_dep->value = i; + link_dep->next = link_dep_list_starts[node_written_at[ar]]; + link_dep_list_starts[node_written_at[ar]] = link_dep; + } else { + link_dep_A[i] = reop_not_dependent; + } + if (node_written_at[br] > reop_not_dependent) { + link_dep_B[i] = node_written_at[br]; + link_dep = &link_dep_free_list[link_dep_frees++]; + link_dep->value = -(int)(i + 1); + link_dep->next = link_dep_list_starts[node_written_at[br]]; + link_dep_list_starts[node_written_at[br]] = link_dep; + } else { + link_dep_B[i] = reop_not_dependent; + } + + // Add this link to the initial ready list, if it is not dependent on any other links. + if ((link_dep_A[i] == reop_not_dependent) && (link_dep_B[i] == reop_not_dependent)) { + ready_list[ready_list_tail++] = i; + link_dep_A[i] = link_dep_B[i] = reop_node_complete; // Probably not needed now. + } + + // Update the nodes to mark which ones are calculated by this link. + node_written_at[ar] = node_written_at[br] = i; + } + + // Process the ready list and create the sorted list of links: + // -- By treating the ready list as a queue, we maximize the distance between any + // inter-dependent node calculations. + // -- All other (non-related) nodes in the ready list will automatically be inserted + // in between each set of inter-dependent link calculations by this loop. + i = 0; + while (ready_list_head != ready_list_tail) { + // Use ready list to select the next link to process. + link_num = ready_list[ready_list_head++]; + // Copy the next-to-calculate link back into the original link array. + links[i++] = link_buffer[link_num]; + + // Free up any link inputs that are dependent on this one. + link_dep = link_dep_list_starts[link_num]; + while (link_dep) { + dep_link = link_dep->value; + if (dep_link >= 0) { + link_dep_A[dep_link] = reop_not_dependent; + } else { + dep_link = -dep_link - 1; + link_dep_B[dep_link] = reop_not_dependent; + } + // Add this dependent link calculation to the ready list if *both* inputs are clear. + if ((link_dep_A[dep_link] == reop_not_dependent) && (link_dep_B[dep_link] == reop_not_dependent)) { + ready_list[ready_list_tail++] = dep_link; + link_dep_A[dep_link] = link_dep_B[dep_link] = reop_node_complete; // Probably not needed now. + } + link_dep = link_dep->next; + } + } + + // Delete the temporary buffers. + memdelete_arr(node_written_at); + memdelete_arr(link_dep_A); + memdelete_arr(link_dep_B); + memdelete_arr(ready_list); + memdelete_arr(link_dep_free_list); + memdelete_arr(link_dep_list_starts); + memdelete_arr(link_buffer); +} + +void SoftBody3DSW::append_link(uint32_t p_node1, uint32_t p_node2) { + if (p_node1 == p_node2) { + return; + } + + Node *node1 = &nodes[p_node1]; + Node *node2 = &nodes[p_node2]; + + Link link; + link.n[0] = node1; + link.n[1] = node2; + link.rl = (node1->x - node2->x).length(); + + links.push_back(link); +} + +void SoftBody3DSW::append_face(uint32_t p_node1, uint32_t p_node2, uint32_t p_node3) { + if (p_node1 == p_node2) { + return; + } + if (p_node1 == p_node3) { + return; + } + if (p_node2 == p_node3) { + return; + } + + Node *node1 = &nodes[p_node1]; + Node *node2 = &nodes[p_node2]; + Node *node3 = &nodes[p_node3]; + + Face face; + face.n[0] = node1; + face.n[1] = node2; + face.n[2] = node3; + + face.index = faces.size(); + + faces.push_back(face); +} + +void SoftBody3DSW::set_iteration_count(int p_val) { + iteration_count = p_val; +} + +void SoftBody3DSW::set_total_mass(real_t p_val) { + ERR_FAIL_COND(p_val < 0.0); + + inv_total_mass = 1.0 / p_val; + real_t mass_factor = total_mass * inv_total_mass; + total_mass = p_val; + + uint32_t node_count = nodes.size(); + for (uint32_t node_index = 0; node_index < node_count; ++node_index) { + Node &node = nodes[node_index]; + node.im *= mass_factor; + } + + update_constants(); +} + +void SoftBody3DSW::set_collision_margin(real_t p_val) { + collision_margin = p_val; +} + +void SoftBody3DSW::set_linear_stiffness(real_t p_val) { + linear_stiffness = p_val; +} + +void SoftBody3DSW::set_pressure_coefficient(real_t p_val) { + pressure_coefficient = p_val; +} + +void SoftBody3DSW::set_damping_coefficient(real_t p_val) { + damping_coefficient = p_val; +} + +void SoftBody3DSW::set_drag_coefficient(real_t p_val) { + drag_coefficient = p_val; +} + +void SoftBody3DSW::add_velocity(const Vector3 &p_velocity) { + for (uint32_t i = 0, ni = nodes.size(); i < ni; ++i) { + Node &node = nodes[i]; + if (node.im > 0) { + node.v += p_velocity; + } + } +} + +void SoftBody3DSW::apply_forces() { + if (pressure_coefficient < CMP_EPSILON) { + return; + } + + if (nodes.is_empty()) { + return; + } + + uint32_t i, ni; + + // Calculate volume. + real_t volume = 0.0; + const Vector3 &org = nodes[0].x; + for (i = 0, ni = faces.size(); i < ni; ++i) { + const Face &face = faces[i]; + volume += vec3_dot(face.n[0]->x - org, vec3_cross(face.n[1]->x - org, face.n[2]->x - org)); + } + volume /= 6.0; + + // Apply per node forces. + real_t ivolumetp = 1.0 / Math::abs(volume) * pressure_coefficient; + for (i = 0, ni = nodes.size(); i < ni; ++i) { + Node &node = nodes[i]; + if (node.im > 0) { + node.f += node.n * (node.area * ivolumetp); + } + } +} + +void SoftBody3DSW::predict_motion(real_t p_delta) { + const real_t inv_delta = 1.0 / p_delta; + + ERR_FAIL_COND(!get_space()); + + Area3DSW *def_area = get_space()->get_default_area(); + ERR_FAIL_COND(!def_area); + + // Apply forces. + Vector3 gravity = def_area->get_gravity_vector() * def_area->get_gravity(); + add_velocity(gravity * p_delta); + apply_forces(); + + // Avoid soft body from 'exploding' so use some upper threshold of maximum motion + // that a node can travel per frame. + const real_t max_displacement = 1000.0; + real_t clamp_delta_v = max_displacement * inv_delta; + + // Integrate. + uint32_t i, ni; + for (i = 0, ni = nodes.size(); i < ni; ++i) { + Node &node = nodes[i]; + node.q = node.x; + Vector3 delta_v = node.f * node.im * p_delta; + for (int c = 0; c < 3; c++) { + delta_v[c] = CLAMP(delta_v[c], -clamp_delta_v, clamp_delta_v); + } + node.v += delta_v; + node.x += node.v * p_delta; + node.f = Vector3(); + } + + // Bounds and tree update. + update_bounds(); + + // Node tree update. + for (i = 0, ni = nodes.size(); i < ni; ++i) { + const Node &node = nodes[i]; + + AABB node_aabb(node.x, Vector3()); + node_aabb.expand_to(node.x + node.v * p_delta); + node_aabb.grow_by(collision_margin); + + node_tree.update(node.leaf, node_aabb); + } + + // Face tree update. + if (!face_tree.is_empty()) { + update_face_tree(p_delta); + } + + // Optimize node tree. + node_tree.optimize_incremental(1); + face_tree.optimize_incremental(1); +} + +void SoftBody3DSW::solve_constraints(real_t p_delta) { + const real_t inv_delta = 1.0 / p_delta; + + uint32_t i, ni; + + for (i = 0, ni = links.size(); i < ni; ++i) { + Link &link = links[i]; + link.c3 = link.n[1]->q - link.n[0]->q; + link.c2 = 1 / (link.c3.length_squared() * link.c0); + } + + // Solve velocities. + for (i = 0, ni = nodes.size(); i < ni; ++i) { + Node &node = nodes[i]; + node.x = node.q + node.v * p_delta; + } + + // Solve positions. + for (int isolve = 0; isolve < iteration_count; ++isolve) { + const real_t ti = isolve / (real_t)iteration_count; + solve_links(1.0, ti); + } + const real_t vc = (1.0 - damping_coefficient) * inv_delta; + for (i = 0, ni = nodes.size(); i < ni; ++i) { + Node &node = nodes[i]; + + node.x += node.bv * p_delta; + node.bv = Vector3(); + + node.v = (node.x - node.q) * vc; + + node.q = node.x; + } + + update_normals(); +} + +void SoftBody3DSW::solve_links(real_t kst, real_t ti) { + for (uint32_t i = 0, ni = links.size(); i < ni; ++i) { + Link &link = links[i]; + if (link.c0 > 0) { + Node &node_a = *link.n[0]; + Node &node_b = *link.n[1]; + const Vector3 del = node_b.x - node_a.x; + const real_t len = del.length_squared(); + if (link.c1 + len > CMP_EPSILON) { + const real_t k = ((link.c1 - len) / (link.c0 * (link.c1 + len))) * kst; + node_a.x -= del * (k * node_a.im); + node_b.x += del * (k * node_b.im); + } + } + } +} + +struct AABBQueryResult { + const SoftBody3DSW *soft_body = nullptr; + void *userdata = nullptr; + SoftBody3DSW::QueryResultCallback result_callback = nullptr; + + _FORCE_INLINE_ bool operator()(void *p_data) { + return result_callback(soft_body->get_node_index(p_data), userdata); + }; +}; + +void SoftBody3DSW::query_aabb(const AABB &p_aabb, SoftBody3DSW::QueryResultCallback p_result_callback, void *p_userdata) { + AABBQueryResult query_result; + query_result.soft_body = this; + query_result.result_callback = p_result_callback; + query_result.userdata = p_userdata; + + node_tree.aabb_query(p_aabb, query_result); +} + +struct RayQueryResult { + const SoftBody3DSW *soft_body = nullptr; + void *userdata = nullptr; + SoftBody3DSW::QueryResultCallback result_callback = nullptr; + + _FORCE_INLINE_ bool operator()(void *p_data) { + return result_callback(soft_body->get_face_index(p_data), userdata); + }; +}; + +void SoftBody3DSW::query_ray(const Vector3 &p_from, const Vector3 &p_to, SoftBody3DSW::QueryResultCallback p_result_callback, void *p_userdata) { + if (face_tree.is_empty()) { + initialize_face_tree(); + } + + RayQueryResult query_result; + query_result.soft_body = this; + query_result.result_callback = p_result_callback; + query_result.userdata = p_userdata; + + face_tree.ray_query(p_from, p_to, query_result); +} + +void SoftBody3DSW::initialize_face_tree() { + face_tree.clear(); + for (uint32_t i = 0; i < faces.size(); ++i) { + Face &face = faces[i]; + + AABB face_aabb; + + face_aabb.position = face.n[0]->x; + face_aabb.expand_to(face.n[1]->x); + face_aabb.expand_to(face.n[2]->x); + + face_aabb.grow_by(collision_margin); + + face.leaf = face_tree.insert(face_aabb, &face); + } +} + +void SoftBody3DSW::update_face_tree(real_t p_delta) { + for (uint32_t i = 0; i < faces.size(); ++i) { + const Face &face = faces[i]; + + AABB face_aabb; + + const Node *node0 = face.n[0]; + face_aabb.position = node0->x; + face_aabb.expand_to(node0->x + node0->v * p_delta); + + const Node *node1 = face.n[1]; + face_aabb.expand_to(node1->x); + face_aabb.expand_to(node1->x + node1->v * p_delta); + + const Node *node2 = face.n[2]; + face_aabb.expand_to(node2->x); + face_aabb.expand_to(node2->x + node2->v * p_delta); + + face_aabb.grow_by(collision_margin); + + face_tree.update(face.leaf, face_aabb); + } +} + +void SoftBody3DSW::initialize_shape(bool p_force_move) { + if (get_shape_count() == 0) { + SoftBodyShape3DSW *soft_body_shape = memnew(SoftBodyShape3DSW(this)); + add_shape(soft_body_shape); + } else if (p_force_move) { + SoftBodyShape3DSW *soft_body_shape = static_cast<SoftBodyShape3DSW *>(get_shape(0)); + soft_body_shape->update_bounds(); + } +} + +void SoftBody3DSW::deinitialize_shape() { + if (get_shape_count() > 0) { + Shape3DSW *shape = get_shape(0); + remove_shape(shape); + memdelete(shape); + } +} + +void SoftBody3DSW::destroy() { + map_visual_to_physics.clear(); + + node_tree.clear(); + face_tree.clear(); + + nodes.clear(); + links.clear(); + faces.clear(); + + bounds = AABB(); + deinitialize_shape(); +} + +void SoftBodyShape3DSW::update_bounds() { + ERR_FAIL_COND(!soft_body); + + AABB collision_aabb = soft_body->get_bounds(); + collision_aabb.grow_by(soft_body->get_collision_margin()); + configure(collision_aabb); +} + +SoftBodyShape3DSW::SoftBodyShape3DSW(SoftBody3DSW *p_soft_body) { + soft_body = p_soft_body; + update_bounds(); +} + +struct _SoftBodyIntersectSegmentInfo { + const SoftBody3DSW *soft_body = nullptr; + Vector3 from; + Vector3 dir; + Vector3 hit_position; + uint32_t hit_face_index = -1; + real_t hit_dist_sq = Math_INF; + + static bool process_hit(uint32_t p_face_index, void *p_userdata) { + _SoftBodyIntersectSegmentInfo &query_info = *(_SoftBodyIntersectSegmentInfo *)(p_userdata); + + Vector3 points[3]; + query_info.soft_body->get_face_points(p_face_index, points[0], points[1], points[2]); + + Vector3 result; + if (Geometry3D::ray_intersects_triangle(query_info.from, query_info.dir, points[0], points[1], points[2], &result)) { + real_t dist_sq = query_info.from.distance_squared_to(result); + if (dist_sq < query_info.hit_dist_sq) { + query_info.hit_dist_sq = dist_sq; + query_info.hit_position = result; + query_info.hit_face_index = p_face_index; + } + } + + // Continue with the query. + return false; + } +}; + +bool SoftBodyShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { + _SoftBodyIntersectSegmentInfo query_info; + query_info.soft_body = soft_body; + query_info.from = p_begin; + query_info.dir = (p_end - p_begin).normalized(); + + soft_body->query_ray(p_begin, p_end, _SoftBodyIntersectSegmentInfo::process_hit, &query_info); + + if (query_info.hit_dist_sq != Math_INF) { + r_result = query_info.hit_position; + r_normal = soft_body->get_face_normal(query_info.hit_face_index); + return true; + } + + return false; +} + +bool SoftBodyShape3DSW::intersect_point(const Vector3 &p_point) const { + return false; +} + +Vector3 SoftBodyShape3DSW::get_closest_point_to(const Vector3 &p_point) const { + ERR_FAIL_V_MSG(Vector3(), "Get closest point is not supported for soft bodies."); +} diff --git a/servers/physics_3d/soft_body_3d_sw.h b/servers/physics_3d/soft_body_3d_sw.h new file mode 100644 index 0000000000..6c0451ff45 --- /dev/null +++ b/servers/physics_3d/soft_body_3d_sw.h @@ -0,0 +1,247 @@ +/*************************************************************************/ +/* soft_body_3d_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 SOFT_BODY_3D_SW_H +#define SOFT_BODY_3D_SW_H + +#include "collision_object_3d_sw.h" + +#include "core/math/aabb.h" +#include "core/math/dynamic_bvh.h" +#include "core/math/vector3.h" +#include "core/templates/local_vector.h" +#include "core/templates/set.h" +#include "core/templates/vset.h" +#include "scene/resources/mesh.h" + +class Constraint3DSW; + +class SoftBody3DSW : public CollisionObject3DSW { + Ref<Mesh> soft_mesh; + + struct Node { + Vector3 s; // Source position + Vector3 x; // Position + Vector3 q; // Previous step position/Test position + Vector3 f; // Force accumulator + Vector3 v; // Velocity + Vector3 bv; // Biased Velocity + Vector3 n; // Normal + real_t area = 0.0; // Area + real_t im = 0.0; // 1/mass + DynamicBVH::ID leaf; // Leaf data + uint32_t index = 0; + }; + + struct Link { + Vector3 c3; // gradient + Node *n[2] = { nullptr, nullptr }; // Node pointers + real_t rl = 0.0; // Rest length + real_t c0 = 0.0; // (ima+imb)*kLST + real_t c1 = 0.0; // rl^2 + real_t c2 = 0.0; // |gradient|^2/c0 + }; + + struct Face { + Node *n[3] = { nullptr, nullptr, nullptr }; // Node pointers + Vector3 normal; // Normal + real_t ra = 0.0; // Rest area + DynamicBVH::ID leaf; // Leaf data + uint32_t index = 0; + }; + + LocalVector<Node> nodes; + LocalVector<Link> links; + LocalVector<Face> faces; + + DynamicBVH node_tree; + DynamicBVH face_tree; + + LocalVector<uint32_t> map_visual_to_physics; + + AABB bounds; + + real_t collision_margin = 0.05; + + real_t total_mass = 1.0; + real_t inv_total_mass = 1.0; + + int iteration_count = 5; + real_t linear_stiffness = 0.5; // [0,1] + real_t pressure_coefficient = 0.0; // [-inf,+inf] + real_t damping_coefficient = 0.01; // [0,1] + real_t drag_coefficient = 0.0; // [0,1] + LocalVector<int> pinned_vertices; + + SelfList<SoftBody3DSW> active_list; + + Set<Constraint3DSW *> constraints; + + VSet<RID> exceptions; + +public: + SoftBody3DSW(); + + const AABB &get_bounds() const { return bounds; } + + void set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant); + Variant get_state(PhysicsServer3D::BodyState p_state) const; + + _FORCE_INLINE_ void add_constraint(Constraint3DSW *p_constraint) { constraints.insert(p_constraint); } + _FORCE_INLINE_ void remove_constraint(Constraint3DSW *p_constraint) { constraints.erase(p_constraint); } + _FORCE_INLINE_ const Set<Constraint3DSW *> &get_constraints() const { return constraints; } + _FORCE_INLINE_ void clear_constraints() { constraints.clear(); } + + _FORCE_INLINE_ void add_exception(const RID &p_exception) { exceptions.insert(p_exception); } + _FORCE_INLINE_ void remove_exception(const RID &p_exception) { exceptions.erase(p_exception); } + _FORCE_INLINE_ bool has_exception(const RID &p_exception) const { return exceptions.has(p_exception); } + _FORCE_INLINE_ const VSet<RID> &get_exceptions() const { return exceptions; } + + virtual void set_space(Space3DSW *p_space); + + void set_mesh(const Ref<Mesh> &p_mesh); + + void update_rendering_server(RenderingServerHandler *p_rendering_server_handler); + + Vector3 get_vertex_position(int p_index) const; + void set_vertex_position(int p_index, const Vector3 &p_position); + + void pin_vertex(int p_index); + void unpin_vertex(int p_index); + void unpin_all_vertices(); + bool is_vertex_pinned(int p_index) const; + + uint32_t get_node_count() const; + real_t get_node_inv_mass(uint32_t p_node_index) const; + Vector3 get_node_position(uint32_t p_node_index) const; + Vector3 get_node_velocity(uint32_t p_node_index) const; + Vector3 get_node_biased_velocity(uint32_t p_node_index) const; + void apply_node_impulse(uint32_t p_node_index, const Vector3 &p_impulse); + void apply_node_bias_impulse(uint32_t p_node_index, const Vector3 &p_impulse); + + uint32_t get_face_count() const; + void get_face_points(uint32_t p_face_index, Vector3 &r_point_1, Vector3 &r_point_2, Vector3 &r_point_3) const; + Vector3 get_face_normal(uint32_t p_face_index) const; + + void set_iteration_count(int p_val); + _FORCE_INLINE_ real_t get_iteration_count() const { return iteration_count; } + + void set_total_mass(real_t p_val); + _FORCE_INLINE_ real_t get_total_mass() const { return total_mass; } + _FORCE_INLINE_ real_t get_total_inv_mass() const { return inv_total_mass; } + + void set_collision_margin(real_t p_val); + _FORCE_INLINE_ real_t get_collision_margin() const { return collision_margin; } + + void set_linear_stiffness(real_t p_val); + _FORCE_INLINE_ real_t get_linear_stiffness() const { return linear_stiffness; } + + void set_pressure_coefficient(real_t p_val); + _FORCE_INLINE_ real_t get_pressure_coefficient() const { return pressure_coefficient; } + + void set_damping_coefficient(real_t p_val); + _FORCE_INLINE_ real_t get_damping_coefficient() const { return damping_coefficient; } + + void set_drag_coefficient(real_t p_val); + _FORCE_INLINE_ real_t get_drag_coefficient() const { return drag_coefficient; } + + void predict_motion(real_t p_delta); + void solve_constraints(real_t p_delta); + + _FORCE_INLINE_ uint32_t get_node_index(void *p_node) const { return ((Node *)p_node)->index; } + _FORCE_INLINE_ uint32_t get_face_index(void *p_face) const { return ((Face *)p_face)->index; } + + // Return true to stop the query. + // p_index is the node index for AABB query, face index for Ray query. + typedef bool (*QueryResultCallback)(uint32_t p_index, void *p_userdata); + + void query_aabb(const AABB &p_aabb, QueryResultCallback p_result_callback, void *p_userdata); + void query_ray(const Vector3 &p_from, const Vector3 &p_to, QueryResultCallback p_result_callback, void *p_userdata); + +protected: + virtual void _shapes_changed(); + +private: + void update_normals(); + void update_bounds(); + void update_constants(); + void update_area(); + void reset_link_rest_lengths(); + void update_link_constants(); + + void apply_nodes_transform(const Transform &p_transform); + + void add_velocity(const Vector3 &p_velocity); + + void apply_forces(); + + bool create_from_trimesh(const Vector<int> &p_indices, const Vector<Vector3> &p_vertices); + void generate_bending_constraints(int p_distance); + void reoptimize_link_order(); + void append_link(uint32_t p_node1, uint32_t p_node2); + void append_face(uint32_t p_node1, uint32_t p_node2, uint32_t p_node3); + + void solve_links(real_t kst, real_t ti); + + void initialize_face_tree(); + void update_face_tree(real_t p_delta); + + void initialize_shape(bool p_force_move = true); + void deinitialize_shape(); + + void destroy(); +}; + +class SoftBodyShape3DSW : public Shape3DSW { + SoftBody3DSW *soft_body = nullptr; + +public: + SoftBody3DSW *get_soft_body() const { return soft_body; } + + virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_SOFT_BODY; } + virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { r_min = r_max = 0.0; } + virtual Vector3 get_support(const Vector3 &p_normal) const { return Vector3(); } + virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { r_amount = 0; } + + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; + virtual bool intersect_point(const Vector3 &p_point) const; + virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; + virtual Vector3 get_moment_of_inertia(real_t p_mass) const { return Vector3(); } + + virtual void set_data(const Variant &p_data) {} + virtual Variant get_data() const { return Variant(); } + + void update_bounds(); + + SoftBodyShape3DSW(SoftBody3DSW *p_soft_body); + ~SoftBodyShape3DSW() {} +}; + +#endif // SOFT_BODY_3D_SW_H diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/space_3d_sw.cpp index c8741dc930..2df824b320 100644 --- a/servers/physics_3d/space_3d_sw.cpp +++ b/servers/physics_3d/space_3d_sw.cpp @@ -47,6 +47,10 @@ _FORCE_INLINE_ static bool _can_collide_with(CollisionObject3DSW *p_object, uint return false; } + if (p_object->get_type() == CollisionObject3DSW::TYPE_SOFT_BODY && !p_collide_with_bodies) { + return false; + } + return true; } @@ -332,7 +336,8 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor best_first = false; if (col_obj->get_type() == CollisionObject3DSW::TYPE_BODY) { const Body3DSW *body = static_cast<const Body3DSW *>(col_obj); - r_info->linear_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(body->get_transform().origin - closest_B); + Vector3 rel_vec = closest_B - (body->get_transform().origin + body->get_center_of_mass()); + r_info->linear_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec); } } } @@ -407,7 +412,7 @@ struct _RestCallbackData { real_t min_allowed_depth; }; -static void _rest_cbk_result(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) { +static void _rest_cbk_result(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { _RestCallbackData *rd = (_RestCallbackData *)p_userdata; Vector3 contact_rel = p_point_B - p_point_A; @@ -478,8 +483,8 @@ bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform &p_shap r_info->rid = rcd.best_object->get_self(); if (rcd.best_object->get_type() == CollisionObject3DSW::TYPE_BODY) { const Body3DSW *body = static_cast<const Body3DSW *>(rcd.best_object); - r_info->linear_velocity = body->get_linear_velocity() + - (body->get_angular_velocity()).cross(body->get_transform().origin - rcd.best_contact); // * mPos); + Vector3 rel_vec = rcd.best_contact - (body->get_transform().origin + body->get_center_of_mass()); + r_info->linear_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec); } else { r_info->linear_velocity = Vector3(); @@ -544,6 +549,8 @@ int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) { keep = false; } else if (intersection_query_results[i]->get_type() == CollisionObject3DSW::TYPE_AREA) { keep = false; + } else if (intersection_query_results[i]->get_type() == CollisionObject3DSW::TYPE_SOFT_BODY) { + keep = false; } else if ((static_cast<Body3DSW *>(intersection_query_results[i])->test_collision_mask(p_body)) == 0) { keep = false; } else if (static_cast<Body3DSW *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) { @@ -684,10 +691,8 @@ int Space3DSW::test_body_ray_separation(Body3DSW *p_body, const Transform &p_tra //result.collider_metadata = col_obj->get_shape_metadata(shape_idx); if (col_obj->get_type() == CollisionObject3DSW::TYPE_BODY) { Body3DSW *body = (Body3DSW *)col_obj; - - Vector3 rel_vec = b - body->get_transform().get_origin(); - //result.collider_velocity = Vector3(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity(); - result.collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(body->get_transform().origin - rel_vec); // * mPos); + Vector3 rel_vec = b - (body->get_transform().origin + body->get_center_of_mass()); + result.collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec); } } } @@ -1009,9 +1014,9 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons //r_result->collider_metadata = rcd.best_object->get_shape_metadata(rcd.best_shape); const Body3DSW *body = static_cast<const Body3DSW *>(rcd.best_object); - //Vector3 rel_vec = r_result->collision_point - body->get_transform().get_origin(); - // r_result->collider_velocity = Vector3(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity(); - r_result->collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(body->get_transform().origin - rcd.best_contact); // * mPos); + + Vector3 rel_vec = rcd.best_contact - (body->get_transform().origin + body->get_center_of_mass()); + r_result->collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec); r_result->motion = safe * p_motion; r_result->remainder = p_motion - safe * p_motion; @@ -1054,14 +1059,23 @@ void *Space3DSW::_broadphase_pair(CollisionObject3DSW *A, int p_subindex_A, Coll Area3DSW *area_b = static_cast<Area3DSW *>(B); Area2Pair3DSW *area2_pair = memnew(Area2Pair3DSW(area_b, p_subindex_B, area, p_subindex_A)); return area2_pair; + } else if (type_B == CollisionObject3DSW::TYPE_SOFT_BODY) { + // Area/Soft Body, not supported. } else { Body3DSW *body = static_cast<Body3DSW *>(B); AreaPair3DSW *area_pair = memnew(AreaPair3DSW(body, p_subindex_B, area, p_subindex_A)); return area_pair; } + } else if (type_A == CollisionObject3DSW::TYPE_BODY) { + if (type_B == CollisionObject3DSW::TYPE_SOFT_BODY) { + BodySoftBodyPair3DSW *soft_pair = memnew(BodySoftBodyPair3DSW((Body3DSW *)A, p_subindex_A, (SoftBody3DSW *)B)); + return soft_pair; + } else { + BodyPair3DSW *b = memnew(BodyPair3DSW((Body3DSW *)A, p_subindex_A, (Body3DSW *)B, p_subindex_B)); + return b; + } } else { - BodyPair3DSW *b = memnew(BodyPair3DSW((Body3DSW *)A, p_subindex_A, (Body3DSW *)B, p_subindex_B)); - return b; + // Soft Body/Soft Body, not supported. } return nullptr; @@ -1144,6 +1158,18 @@ const SelfList<Area3DSW>::List &Space3DSW::get_moved_area_list() const { return area_moved_list; } +const SelfList<SoftBody3DSW>::List &Space3DSW::get_active_soft_body_list() const { + return active_soft_body_list; +} + +void Space3DSW::soft_body_add_to_active_list(SelfList<SoftBody3DSW> *p_soft_body) { + active_soft_body_list.add(p_soft_body); +} + +void Space3DSW::soft_body_remove_from_active_list(SelfList<SoftBody3DSW> *p_soft_body) { + active_soft_body_list.remove(p_soft_body); +} + void Space3DSW::call_queries() { while (state_query_list.first()) { Body3DSW *b = state_query_list.first()->self(); diff --git a/servers/physics_3d/space_3d_sw.h b/servers/physics_3d/space_3d_sw.h index eed3d86a72..3a8f452e54 100644 --- a/servers/physics_3d/space_3d_sw.h +++ b/servers/physics_3d/space_3d_sw.h @@ -40,6 +40,7 @@ #include "core/config/project_settings.h" #include "core/templates/hash_map.h" #include "core/typedefs.h" +#include "soft_body_3d_sw.h" class PhysicsDirectSpaceState3DSW : public PhysicsDirectSpaceState3D { GDCLASS(PhysicsDirectSpaceState3DSW, PhysicsDirectSpaceState3D); @@ -82,6 +83,7 @@ private: SelfList<Body3DSW>::List state_query_list; SelfList<Area3DSW>::List monitor_query_list; SelfList<Area3DSW>::List area_moved_list; + SelfList<SoftBody3DSW>::List active_soft_body_list; static void *_broadphase_pair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_self); static void _broadphase_unpair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_data, void *p_self); @@ -145,6 +147,10 @@ public: void area_remove_from_moved_list(SelfList<Area3DSW> *p_area); const SelfList<Area3DSW>::List &get_moved_area_list() const; + const SelfList<SoftBody3DSW>::List &get_active_soft_body_list() const; + void soft_body_add_to_active_list(SelfList<SoftBody3DSW> *p_soft_body); + void soft_body_remove_from_active_list(SelfList<SoftBody3DSW> *p_soft_body); + BroadPhase3DSW *get_broadphase(); void add_object(CollisionObject3DSW *p_object); diff --git a/servers/physics_3d/step_3d_sw.cpp b/servers/physics_3d/step_3d_sw.cpp index d9370de6a3..2133a38670 100644 --- a/servers/physics_3d/step_3d_sw.cpp +++ b/servers/physics_3d/step_3d_sw.cpp @@ -146,6 +146,8 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { const SelfList<Body3DSW>::List *body_list = &p_space->get_active_body_list(); + const SelfList<SoftBody3DSW>::List *soft_body_list = &p_space->get_active_soft_body_list(); + /* INTEGRATE FORCES */ uint64_t profile_begtime = OS::get_singleton()->get_ticks_usec(); @@ -160,6 +162,15 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { active_count++; } + /* UPDATE SOFT BODY MOTION */ + + const SelfList<SoftBody3DSW> *sb = soft_body_list->first(); + while (sb) { + sb->self()->predict_motion(p_delta); + sb = sb->next(); + active_count++; + } + p_space->set_active_objects(active_count); { //profile @@ -214,6 +225,21 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { p_space->area_remove_from_moved_list((SelfList<Area3DSW> *)aml.first()); //faster to remove here } + sb = soft_body_list->first(); + while (sb) { + for (const Set<Constraint3DSW *>::Element *E = sb->self()->get_constraints().front(); E; E = E->next()) { + Constraint3DSW *c = E->get(); + if (c->get_island_step() == _step) { + continue; + } + c->set_island_step(_step); + c->set_island_next(nullptr); + c->set_island_list_next(constraint_island_list); + constraint_island_list = c; + } + sb = sb->next(); + } + { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_GENERATE_ISLANDS, profile_endtime - profile_begtime); @@ -272,6 +298,14 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { } } + /* UPDATE SOFT BODY CONSTRAINTS */ + + sb = soft_body_list->first(); + while (sb) { + sb->self()->solve_constraints(p_delta); + sb = sb->next(); + } + { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_INTEGRATE_VELOCITIES, profile_endtime - profile_begtime); diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index af25029f04..586845de99 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -556,6 +556,10 @@ void PhysicsServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer3D::body_get_direct_state); + /* SOFT BODY API */ + + ClassDB::bind_method(D_METHOD("soft_body_get_bounds", "body"), &PhysicsServer3D::soft_body_get_bounds); + /* JOINT API */ ClassDB::bind_method(D_METHOD("joint_create"), &PhysicsServer3D::joint_create); @@ -693,6 +697,7 @@ void PhysicsServer3D::_bind_methods() { BIND_ENUM_CONSTANT(SHAPE_CONVEX_POLYGON); BIND_ENUM_CONSTANT(SHAPE_CONCAVE_POLYGON); BIND_ENUM_CONSTANT(SHAPE_HEIGHTMAP); + BIND_ENUM_CONSTANT(SHAPE_SOFT_BODY); BIND_ENUM_CONSTANT(SHAPE_CUSTOM); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY); diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index e16857192c..69f5c1c0ad 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -216,6 +216,15 @@ public: PhysicsShapeQueryResult3D(); }; +class RenderingServerHandler { +public: + virtual void set_vertex(int p_vertex_id, const void *p_vector3) = 0; + virtual void set_normal(int p_vertex_id, const void *p_vector3) = 0; + virtual void set_aabb(const AABB &p_aabb) = 0; + + virtual ~RenderingServerHandler() {} +}; + class PhysicsServer3D : public Object { GDCLASS(PhysicsServer3D, Object); @@ -237,6 +246,7 @@ public: SHAPE_CONVEX_POLYGON, ///< array of planes:"planes" SHAPE_CONCAVE_POLYGON, ///< vector3 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector3 array) SHAPE_HEIGHTMAP, ///< dict( int:"width", int:"depth",float:"cell_size", float_array:"heights" + SHAPE_SOFT_BODY, ///< Used internally, can't be created from the physics server. SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_create() with this value will result in an error }; @@ -522,13 +532,15 @@ public: virtual RID soft_body_create() = 0; - virtual void soft_body_update_rendering_server(RID p_body, class SoftBodyRenderingServerHandler *p_rendering_server_handler) = 0; + virtual void soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) = 0; virtual void soft_body_set_space(RID p_body, RID p_space) = 0; virtual RID soft_body_get_space(RID p_body) const = 0; virtual void soft_body_set_mesh(RID p_body, const REF &p_mesh) = 0; + virtual AABB soft_body_get_bounds(RID p_body) const = 0; + virtual void soft_body_set_collision_layer(RID p_body, uint32_t p_layer) = 0; virtual uint32_t soft_body_get_collision_layer(RID p_body) const = 0; @@ -543,7 +555,6 @@ public: virtual Variant soft_body_get_state(RID p_body, BodyState p_state) const = 0; virtual void soft_body_set_transform(RID p_body, const Transform &p_transform) = 0; - virtual Vector3 soft_body_get_vertex_position(RID p_body, int vertex_index) const = 0; virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) = 0; @@ -556,18 +567,9 @@ public: virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) = 0; virtual real_t soft_body_get_linear_stiffness(RID p_body) const = 0; - virtual void soft_body_set_angular_stiffness(RID p_body, real_t p_stiffness) = 0; - virtual real_t soft_body_get_angular_stiffness(RID p_body) const = 0; - - virtual void soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) = 0; - virtual real_t soft_body_get_volume_stiffness(RID p_body) const = 0; - virtual void soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) = 0; virtual real_t soft_body_get_pressure_coefficient(RID p_body) const = 0; - virtual void soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) = 0; - virtual real_t soft_body_get_pose_matching_coefficient(RID p_body) const = 0; - virtual void soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) = 0; virtual real_t soft_body_get_damping_coefficient(RID p_body) const = 0; @@ -577,8 +579,6 @@ public: virtual void soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) = 0; virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) const = 0; - virtual Vector3 soft_body_get_point_offset(RID p_body, int p_point_index) const = 0; - virtual void soft_body_remove_all_pinned_points(RID p_body) = 0; virtual void soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) = 0; virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) const = 0; diff --git a/servers/rendering/renderer_rd/SCsub b/servers/rendering/renderer_rd/SCsub index 6a2e682c67..9c95f538ac 100644 --- a/servers/rendering/renderer_rd/SCsub +++ b/servers/rendering/renderer_rd/SCsub @@ -4,4 +4,5 @@ Import("env") env.add_source_files(env.servers_sources, "*.cpp") +SConscript("forward_clustered/SCsub") SConscript("shaders/SCsub") diff --git a/servers/rendering/renderer_rd/forward_clustered/SCsub b/servers/rendering/renderer_rd/forward_clustered/SCsub new file mode 100644 index 0000000000..86681f9c74 --- /dev/null +++ b/servers/rendering/renderer_rd/forward_clustered/SCsub @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +Import("env") + +env.add_source_files(env.servers_sources, "*.cpp") diff --git a/servers/rendering/renderer_rd/renderer_scene_render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 7a19495f48..cdff3139eb 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* renderer_scene_render_forward_clustered.cpp */ +/* render_forward_clustered.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,508 +28,18 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "renderer_scene_render_forward_clustered.h" +#include "render_forward_clustered.h" #include "core/config/project_settings.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/rendering_server_default.h" -/* SCENE SHADER */ -void RendererSceneRenderForwardClustered::ShaderData::set_code(const String &p_code) { - //compile +using namespace RendererSceneRenderImplementation; - code = p_code; - valid = false; - ubo_size = 0; - uniforms.clear(); - uses_screen_texture = false; - - if (code == String()) { - return; //just invalid, but no error - } - - ShaderCompilerRD::GeneratedCode gen_code; - - int blend_mode = BLEND_MODE_MIX; - int depth_testi = DEPTH_TEST_ENABLED; - int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF; - int cull = CULL_BACK; - - uses_point_size = false; - uses_alpha = false; - uses_blend_alpha = false; - uses_depth_pre_pass = false; - uses_discard = false; - uses_roughness = false; - uses_normal = false; - bool wireframe = false; - - unshaded = false; - uses_vertex = false; - uses_sss = false; - uses_transmittance = false; - uses_screen_texture = false; - uses_depth_texture = false; - uses_normal_texture = false; - uses_time = false; - writes_modelview_or_projection = false; - uses_world_coordinates = false; - - int depth_drawi = DEPTH_DRAW_OPAQUE; - - ShaderCompilerRD::IdentifierActions actions; - - actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_mode, BLEND_MODE_ADD); - actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX); - actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_mode, BLEND_MODE_SUB); - actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MUL); - - actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE); - actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE); - - actions.render_mode_values["depth_draw_never"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_DISABLED); - actions.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_OPAQUE); - actions.render_mode_values["depth_draw_always"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_ALWAYS); - - actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED); - - actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull, CULL_DISABLED); - actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull, CULL_FRONT); - actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull, CULL_BACK); - - actions.render_mode_flags["unshaded"] = &unshaded; - actions.render_mode_flags["wireframe"] = &wireframe; - - actions.usage_flag_pointers["ALPHA"] = &uses_alpha; - actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass; - - actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; - actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance; - - actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; - actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture; - actions.usage_flag_pointers["NORMAL_TEXTURE"] = &uses_normal_texture; - actions.usage_flag_pointers["DISCARD"] = &uses_discard; - actions.usage_flag_pointers["TIME"] = &uses_time; - actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness; - actions.usage_flag_pointers["NORMAL"] = &uses_normal; - actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal; - - actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size; - actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size; - - actions.write_flag_pointers["MODELVIEW_MATRIX"] = &writes_modelview_or_projection; - actions.write_flag_pointers["PROJECTION_MATRIX"] = &writes_modelview_or_projection; - actions.write_flag_pointers["VERTEX"] = &uses_vertex; - - actions.uniforms = &uniforms; - - RendererSceneRenderForwardClustered *scene_singleton = (RendererSceneRenderForwardClustered *)RendererSceneRenderForwardClustered::singleton; - - Error err = scene_singleton->shader.compiler.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code); - - ERR_FAIL_COND(err != OK); - - if (version.is_null()) { - version = scene_singleton->shader.scene_shader.version_create(); - } - - depth_draw = DepthDraw(depth_drawi); - depth_test = DepthTest(depth_testi); - -#if 0 - print_line("**compiling shader:"); - print_line("**defines:\n"); - for (int i = 0; i < gen_code.defines.size(); i++) { - print_line(gen_code.defines[i]); - } - print_line("\n**uniforms:\n" + gen_code.uniforms); - print_line("\n**vertex_globals:\n" + gen_code.vertex_global); - print_line("\n**vertex_code:\n" + gen_code.vertex); - print_line("\n**fragment_globals:\n" + gen_code.fragment_global); - print_line("\n**fragment_code:\n" + gen_code.fragment); - print_line("\n**light_code:\n" + gen_code.light); -#endif - scene_singleton->shader.scene_shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines); - ERR_FAIL_COND(!scene_singleton->shader.scene_shader.version_is_valid(version)); - - ubo_size = gen_code.uniform_total_size; - ubo_offsets = gen_code.uniform_offsets; - texture_uniforms = gen_code.texture_uniforms; - - //blend modes - - // if any form of Alpha Antialiasing is enabled, set the blend mode to alpha to coverage - if (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF) { - blend_mode = BLEND_MODE_ALPHA_TO_COVERAGE; - } - - RD::PipelineColorBlendState::Attachment blend_attachment; - - switch (blend_mode) { - case BLEND_MODE_MIX: { - blend_attachment.enable_blend = true; - blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD; - blend_attachment.color_blend_op = RD::BLEND_OP_ADD; - blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; - blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; - blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - - } break; - case BLEND_MODE_ADD: { - blend_attachment.enable_blend = true; - blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD; - blend_attachment.color_blend_op = RD::BLEND_OP_ADD; - blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; - blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE; - blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; - blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; - uses_blend_alpha = true; //force alpha used because of blend - - } break; - case BLEND_MODE_SUB: { - blend_attachment.enable_blend = true; - blend_attachment.alpha_blend_op = RD::BLEND_OP_SUBTRACT; - blend_attachment.color_blend_op = RD::BLEND_OP_SUBTRACT; - blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; - blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE; - blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; - blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; - uses_blend_alpha = true; //force alpha used because of blend - - } break; - case BLEND_MODE_MUL: { - blend_attachment.enable_blend = true; - blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD; - blend_attachment.color_blend_op = RD::BLEND_OP_ADD; - blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_DST_COLOR; - blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ZERO; - blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_DST_ALPHA; - blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO; - uses_blend_alpha = true; //force alpha used because of blend - } break; - case BLEND_MODE_ALPHA_TO_COVERAGE: { - blend_attachment.enable_blend = true; - blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD; - blend_attachment.color_blend_op = RD::BLEND_OP_ADD; - blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; - blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; - blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO; - } - } - - RD::PipelineColorBlendState blend_state_blend; - blend_state_blend.attachments.push_back(blend_attachment); - RD::PipelineColorBlendState blend_state_opaque = RD::PipelineColorBlendState::create_disabled(1); - RD::PipelineColorBlendState blend_state_opaque_specular = RD::PipelineColorBlendState::create_disabled(2); - RD::PipelineColorBlendState blend_state_depth_normal_roughness = RD::PipelineColorBlendState::create_disabled(1); - RD::PipelineColorBlendState blend_state_depth_normal_roughness_giprobe = RD::PipelineColorBlendState::create_disabled(2); - - //update pipelines - - RD::PipelineDepthStencilState depth_stencil_state; - - if (depth_test != DEPTH_TEST_DISABLED) { - depth_stencil_state.enable_depth_test = true; - depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; - depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false; - } - - for (int i = 0; i < CULL_VARIANT_MAX; i++) { - RD::PolygonCullMode cull_mode_rd_table[CULL_VARIANT_MAX][3] = { - { RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_FRONT, RD::POLYGON_CULL_BACK }, - { RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_BACK, RD::POLYGON_CULL_FRONT }, - { RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED } - }; - - RD::PolygonCullMode cull_mode_rd = cull_mode_rd_table[i][cull]; - - for (int j = 0; j < RS::PRIMITIVE_MAX; j++) { - RD::RenderPrimitive primitive_rd_table[RS::PRIMITIVE_MAX] = { - RD::RENDER_PRIMITIVE_POINTS, - RD::RENDER_PRIMITIVE_LINES, - RD::RENDER_PRIMITIVE_LINESTRIPS, - RD::RENDER_PRIMITIVE_TRIANGLES, - RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, - }; - - RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[j]; - - for (int k = 0; k < SHADER_VERSION_MAX; k++) { - if (!static_cast<RendererSceneRenderForwardClustered *>(singleton)->shader.scene_shader.is_variant_enabled(k)) { - continue; - } - RD::PipelineRasterizationState raster_state; - raster_state.cull_mode = cull_mode_rd; - raster_state.wireframe = wireframe; - - RD::PipelineColorBlendState blend_state; - RD::PipelineDepthStencilState depth_stencil = depth_stencil_state; - RD::PipelineMultisampleState multisample_state; - - if (uses_alpha || uses_blend_alpha) { - // only allow these flags to go through if we have some form of msaa - if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) { - multisample_state.enable_alpha_to_coverage = true; - } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) { - multisample_state.enable_alpha_to_coverage = true; - multisample_state.enable_alpha_to_one = true; - } - - if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) { - blend_state = blend_state_blend; - if (depth_draw == DEPTH_DRAW_OPAQUE) { - depth_stencil.enable_depth_write = false; //alpha does not draw depth - } - } else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS || k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL)) { - if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) { - //none, blend state contains nothing - } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) { - blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way - } else { - blend_state = blend_state_opaque; //writes to normal and roughness in opaque way - } - } else { - pipelines[i][j][k].clear(); - continue; // do not use this version (will error if using it is attempted) - } - } else { - if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) { - blend_state = blend_state_opaque; - } else if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) { - //none, leave empty - } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) { - blend_state = blend_state_depth_normal_roughness; - } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE) { - blend_state = blend_state_depth_normal_roughness_giprobe; - } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) { - blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way - } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_SDF) { - blend_state = RD::PipelineColorBlendState(); //no color targets for SDF - } else { - //specular write - blend_state = blend_state_opaque_specular; - depth_stencil.enable_depth_test = false; - depth_stencil.enable_depth_write = false; - } - } - - RID shader_variant = scene_singleton->shader.scene_shader.version_get_shader(version, k); - pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0); - } - } - } - - valid = true; -} - -void RendererSceneRenderForwardClustered::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { - if (!p_texture.is_valid()) { - default_texture_params.erase(p_name); - } else { - default_texture_params[p_name] = p_texture; - } -} - -void RendererSceneRenderForwardClustered::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; - - for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { - if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { - continue; - } - - if (E->get().texture_order >= 0) { - order[E->get().texture_order + 100000] = E->key(); - } else { - order[E->get().order] = E->key(); - } - } - - for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) { - PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]); - pi.name = E->get(); - p_param_list->push_back(pi); - } -} - -void RendererSceneRenderForwardClustered::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { - for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { - if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - RendererStorage::InstanceShaderParam p; - p.info = ShaderLanguage::uniform_to_property_info(E->get()); - p.info.name = E->key(); //supply name - p.index = E->get().instance_index; - p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().hint); - p_param_list->push_back(p); - } -} - -bool RendererSceneRenderForwardClustered::ShaderData::is_param_texture(const StringName &p_param) const { - if (!uniforms.has(p_param)) { - return false; - } - - return uniforms[p_param].texture_order >= 0; -} - -bool RendererSceneRenderForwardClustered::ShaderData::is_animated() const { - return false; -} - -bool RendererSceneRenderForwardClustered::ShaderData::casts_shadows() const { - return false; -} - -Variant RendererSceneRenderForwardClustered::ShaderData::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.hint); - } - return Variant(); -} - -RS::ShaderNativeSourceCode RendererSceneRenderForwardClustered::ShaderData::get_native_source_code() const { - RendererSceneRenderForwardClustered *scene_singleton = (RendererSceneRenderForwardClustered *)RendererSceneRenderForwardClustered::singleton; - - return scene_singleton->shader.scene_shader.version_get_native_source_code(version); -} - -RendererSceneRenderForwardClustered::ShaderData::ShaderData() { - valid = false; - uses_screen_texture = false; -} - -RendererSceneRenderForwardClustered::ShaderData::~ShaderData() { - RendererSceneRenderForwardClustered *scene_singleton = (RendererSceneRenderForwardClustered *)RendererSceneRenderForwardClustered::singleton; - ERR_FAIL_COND(!scene_singleton); - //pipeline variants will clear themselves if shader is gone - if (version.is_valid()) { - scene_singleton->shader.scene_shader.version_free(version); - } -} - -RendererStorageRD::ShaderData *RendererSceneRenderForwardClustered::_create_shader_func() { - ShaderData *shader_data = memnew(ShaderData); - return shader_data; -} - -void RendererSceneRenderForwardClustered::MaterialData::set_render_priority(int p_priority) { - priority = p_priority - RS::MATERIAL_RENDER_PRIORITY_MIN; //8 bits -} - -void RendererSceneRenderForwardClustered::MaterialData::set_next_pass(RID p_pass) { - next_pass = p_pass; -} - -void RendererSceneRenderForwardClustered::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - RendererSceneRenderForwardClustered *scene_singleton = (RendererSceneRenderForwardClustered *)RendererSceneRenderForwardClustered::singleton; - - if ((uint32_t)ubo_data.size() != shader_data->ubo_size) { - p_uniform_dirty = true; - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - uniform_buffer = RID(); - } - - ubo_data.resize(shader_data->ubo_size); - if (ubo_data.size()) { - uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); - memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear - } - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - //check whether buffer changed - if (p_uniform_dirty && ubo_data.size()) { - update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false); - RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), RD::BARRIER_MASK_RASTER); - } - - uint32_t tex_uniform_count = shader_data->texture_uniforms.size(); - - if ((uint32_t)texture_cache.size() != tex_uniform_count) { - texture_cache.resize(tex_uniform_count); - p_textures_dirty = true; - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - if (p_textures_dirty && tex_uniform_count) { - update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true); - } - - if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) { - // This material does not require an uniform set, so don't create it. - return; - } - - if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - //no reason to update uniform set, only UBO (or nothing) was needed to update - return; - } - - Vector<RD::Uniform> uniforms; - - { - if (shader_data->ubo_size) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 0; - u.ids.push_back(uniform_buffer); - uniforms.push_back(u); - } - - const RID *textures = texture_cache.ptrw(); - for (uint32_t i = 0; i < tex_uniform_count; i++) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1 + i; - u.ids.push_back(textures[i]); - uniforms.push_back(u); - } - } - - uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->shader.scene_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET); -} - -RendererSceneRenderForwardClustered::MaterialData::~MaterialData() { - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - } - - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - } -} - -RendererStorageRD::MaterialData *RendererSceneRenderForwardClustered::_create_material_func(ShaderData *p_shader) { - MaterialData *material_data = memnew(MaterialData); - material_data->shader_data = p_shader; - material_data->last_frame = false; - //update will happen later anyway so do nothing. - return material_data; -} - -RendererSceneRenderForwardClustered::RenderBufferDataForward::~RenderBufferDataForward() { +RenderForwardClustered::RenderBufferDataForwardClustered::~RenderBufferDataForwardClustered() { clear(); } -void RendererSceneRenderForwardClustered::RenderBufferDataForward::ensure_specular() { +void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular() { if (!specular.is_valid()) { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; @@ -583,7 +93,7 @@ void RendererSceneRenderForwardClustered::RenderBufferDataForward::ensure_specul } } -void RendererSceneRenderForwardClustered::RenderBufferDataForward::ensure_giprobe() { +void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_giprobe() { if (!giprobe_buffer.is_valid()) { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R8G8_UINT; @@ -619,7 +129,7 @@ void RendererSceneRenderForwardClustered::RenderBufferDataForward::ensure_giprob } } -void RendererSceneRenderForwardClustered::RenderBufferDataForward::clear() { +void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { if (giprobe_buffer != RID()) { RD::get_singleton()->free(giprobe_buffer); giprobe_buffer = RID(); @@ -673,7 +183,7 @@ void RendererSceneRenderForwardClustered::RenderBufferDataForward::clear() { } } -void RendererSceneRenderForwardClustered::RenderBufferDataForward::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) { +void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) { clear(); msaa = p_msaa; @@ -740,7 +250,7 @@ void RendererSceneRenderForwardClustered::RenderBufferDataForward::configure(RID } } -void RendererSceneRenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferDataForward *rb) { +void RenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb) { if (rb->normal_roughness_buffer.is_valid()) { return; } @@ -778,11 +288,11 @@ void RendererSceneRenderForwardClustered::_allocate_normal_roughness_texture(Ren _render_buffers_clear_uniform_set(rb); } -RendererSceneRenderRD::RenderBufferData *RendererSceneRenderForwardClustered::_create_render_buffer_data() { - return memnew(RenderBufferDataForward); +RendererSceneRenderRD::RenderBufferData *RenderForwardClustered::_create_render_buffer_data() { + return memnew(RenderBufferDataForwardClustered); } -bool RendererSceneRenderForwardClustered::free(RID p_rid) { +bool RenderForwardClustered::free(RID p_rid) { if (RendererSceneRenderRD::free(p_rid)) { return true; } @@ -791,15 +301,15 @@ bool RendererSceneRenderForwardClustered::free(RID p_rid) { /// RENDERING /// -template <RendererSceneRenderForwardClustered::PassMode p_pass_mode> -void RendererSceneRenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) { +template <RenderForwardClustered::PassMode p_pass_mode> +void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) { RD::DrawListID draw_list = p_draw_list; RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format; //global scope bindings RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_base_uniform_set, SCENE_UNIFORM_SET); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_params->render_pass_uniform_set, RENDER_PASS_UNIFORM_SET); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_vec4_xform_uniform_set, TRANSFORMS_UNIFORM_SET); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, scene_shader.default_vec4_xform_uniform_set, TRANSFORMS_UNIFORM_SET); RID prev_material_uniform_set; @@ -826,7 +336,7 @@ void RendererSceneRenderForwardClustered::_render_list_template(RenderingDevice: push_constant.base_index = i + p_params->element_offset; RID material_uniform_set; - ShaderData *shader; + SceneShaderForwardClustered::ShaderData *shader; void *mesh_surface; if (shadow_pass || p_params->pass_mode == PASS_MODE_DEPTH) { //regular depth pass can use these too @@ -845,59 +355,59 @@ void RendererSceneRenderForwardClustered::_render_list_template(RenderingDevice: } //find cull variant - ShaderData::CullVariant cull_variant; + SceneShaderForwardClustered::ShaderData::CullVariant cull_variant; if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL || p_params->pass_mode == PASS_MODE_SDF || ((p_params->pass_mode == PASS_MODE_SHADOW || p_params->pass_mode == PASS_MODE_SHADOW_DP) && surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS)) { - cull_variant = ShaderData::CULL_VARIANT_DOUBLE_SIDED; + cull_variant = SceneShaderForwardClustered::ShaderData::CULL_VARIANT_DOUBLE_SIDED; } else { bool mirror = surf->owner->mirror; if (p_params->reverse_cull) { mirror = !mirror; } - cull_variant = mirror ? ShaderData::CULL_VARIANT_REVERSED : ShaderData::CULL_VARIANT_NORMAL; + cull_variant = mirror ? SceneShaderForwardClustered::ShaderData::CULL_VARIANT_REVERSED : SceneShaderForwardClustered::ShaderData::CULL_VARIANT_NORMAL; } RS::PrimitiveType primitive = surf->primitive; RID xforms_uniform_set = surf->owner->transforms_uniform_set; - ShaderVersion shader_version = SHADER_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized. + SceneShaderForwardClustered::ShaderVersion shader_version = SceneShaderForwardClustered::SHADER_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized. switch (p_params->pass_mode) { case PASS_MODE_COLOR: case PASS_MODE_COLOR_TRANSPARENT: { if (element_info.uses_lightmap) { - shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS; + shader_version = SceneShaderForwardClustered::SHADER_VERSION_LIGHTMAP_COLOR_PASS; } else if (element_info.uses_forward_gi) { - shader_version = SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI; + shader_version = SceneShaderForwardClustered::SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI; } else { - shader_version = SHADER_VERSION_COLOR_PASS; + shader_version = SceneShaderForwardClustered::SHADER_VERSION_COLOR_PASS; } } break; case PASS_MODE_COLOR_SPECULAR: { if (element_info.uses_lightmap) { - shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR; + shader_version = SceneShaderForwardClustered::SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR; } else { - shader_version = SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR; + shader_version = SceneShaderForwardClustered::SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR; } } break; case PASS_MODE_SHADOW: case PASS_MODE_DEPTH: { - shader_version = SHADER_VERSION_DEPTH_PASS; + shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS; } break; case PASS_MODE_SHADOW_DP: { - shader_version = SHADER_VERSION_DEPTH_PASS_DP; + shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_DP; } break; case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { - shader_version = SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS; + shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS; } break; case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE: { - shader_version = SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE; + shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE; } break; case PASS_MODE_DEPTH_MATERIAL: { - shader_version = SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL; + shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL; } break; case PASS_MODE_SDF: { - shader_version = SHADER_VERSION_DEPTH_PASS_WITH_SDF; + shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_SDF; } break; } @@ -961,7 +471,7 @@ void RendererSceneRenderForwardClustered::_render_list_template(RenderingDevice: } } -void RendererSceneRenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) { +void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) { //use template for faster performance (pass mode comparisons are inlined) switch (p_params->pass_mode) { @@ -998,7 +508,7 @@ void RendererSceneRenderForwardClustered::_render_list(RenderingDevice::DrawList } } -void RendererSceneRenderForwardClustered::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) { +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 render_from = p_thread * render_total / total_threads; @@ -1006,7 +516,7 @@ void RendererSceneRenderForwardClustered::_render_list_thread_function(uint32_t _render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to); } -void RendererSceneRenderForwardClustered::_render_list_with_threads(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) { +void RenderForwardClustered::_render_list_with_threads(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) { RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_framebuffer); p_params->framebuffer_format = fb_format; @@ -1014,7 +524,7 @@ void RendererSceneRenderForwardClustered::_render_list_with_threads(RenderListPa //multi threaded thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.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, &RendererSceneRenderForwardClustered::_render_list_thread_function, p_params); + RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardClustered::_render_list_thread_function, p_params); RD::get_singleton()->draw_list_end(p_params->barrier); } else { //single threaded @@ -1024,7 +534,7 @@ void RendererSceneRenderForwardClustered::_render_list_with_threads(RenderListPa } } -void RendererSceneRenderForwardClustered::_setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2i &p_screen_size, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) { +void RenderForwardClustered::_setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2i &p_screen_size, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) { //CameraMatrix projection = p_cam_projection; //projection.flip_y(); // Vulkan and modern APIs use Y-Down CameraMatrix correction; @@ -1083,7 +593,7 @@ void RendererSceneRenderForwardClustered::_setup_environment(RID p_environment, scene_state.ubo.fog_enabled = false; if (p_render_buffers.is_valid()) { - RenderBufferDataForward *render_buffers = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); + RenderBufferDataForwardClustered *render_buffers = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffers); if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) { scene_state.ubo.gi_upscale_for_msaa = true; } @@ -1274,7 +784,7 @@ void RendererSceneRenderForwardClustered::_setup_environment(RID p_environment, RD::get_singleton()->buffer_update(scene_state.uniform_buffers[p_index], 0, sizeof(SceneState::UBO), &scene_state.ubo, RD::BARRIER_MASK_RASTER); } -void RendererSceneRenderForwardClustered::_update_instance_data_buffer(RenderListType p_render_list) { +void RenderForwardClustered::_update_instance_data_buffer(RenderListType p_render_list) { if (scene_state.instance_data[p_render_list].size() > 0) { if (scene_state.instance_buffer[p_render_list] == RID() || scene_state.instance_buffer_size[p_render_list] < scene_state.instance_data[p_render_list].size()) { if (scene_state.instance_buffer[p_render_list] != RID()) { @@ -1287,7 +797,7 @@ void RendererSceneRenderForwardClustered::_update_instance_data_buffer(RenderLis RD::get_singleton()->buffer_update(scene_state.instance_buffer[p_render_list], 0, sizeof(SceneState::InstanceData) * scene_state.instance_data[p_render_list].size(), scene_state.instance_data[p_render_list].ptr(), RD::BARRIER_MASK_RASTER); } } -void RendererSceneRenderForwardClustered::_fill_instance_data(RenderListType p_render_list, uint32_t p_offset, int32_t p_max_elements, bool p_update_buffer) { +void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, uint32_t p_offset, int32_t p_max_elements, bool p_update_buffer) { RenderList *rl = &render_list[p_render_list]; uint32_t element_total = p_max_elements >= 0 ? uint32_t(p_max_elements) : rl->elements.size(); @@ -1355,7 +865,7 @@ void RendererSceneRenderForwardClustered::_fill_instance_data(RenderListType p_r } } -void RendererSceneRenderForwardClustered::_fill_render_list(RenderListType p_render_list, const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi, bool p_using_opaque_gi, const Plane &p_lod_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, bool p_append) { +void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi, bool p_using_opaque_gi, const Plane &p_lod_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, bool p_append) { if (p_render_list == RENDER_LIST_OPAQUE) { scene_state.used_sss = false; scene_state.used_screen_texture = false; @@ -1549,14 +1059,14 @@ void RendererSceneRenderForwardClustered::_fill_render_list(RenderListType p_ren } } -void RendererSceneRenderForwardClustered::_setup_giprobes(const PagedArray<RID> &p_giprobes) { +void RenderForwardClustered::_setup_giprobes(const PagedArray<RID> &p_giprobes) { scene_state.giprobes_used = MIN(p_giprobes.size(), uint32_t(MAX_GI_PROBES)); for (uint32_t i = 0; i < scene_state.giprobes_used; i++) { scene_state.giprobe_ids[i] = p_giprobes[i]; } } -void RendererSceneRenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform) { +void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform) { scene_state.lightmaps_used = 0; for (int i = 0; i < (int)p_lightmaps.size(); i++) { if (i >= (int)scene_state.max_lightmaps) { @@ -1578,10 +1088,10 @@ void RendererSceneRenderForwardClustered::_setup_lightmaps(const PagedArray<RID> } } -void RendererSceneRenderForwardClustered::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) { - RenderBufferDataForward *render_buffer = nullptr; +void RenderForwardClustered::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) { + RenderBufferDataForwardClustered *render_buffer = nullptr; if (p_render_buffer.is_valid()) { - render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffer); + render_buffer = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffer); } RendererSceneEnvironmentRD *env = get_environment(p_environment); @@ -1981,7 +1491,7 @@ void RendererSceneRenderForwardClustered::_render_scene(RID p_render_buffer, con RD::get_singleton()->draw_command_end_label(); } -void RendererSceneRenderForwardClustered::_render_shadow_begin() { +void RenderForwardClustered::_render_shadow_begin() { scene_state.shadow_passes.clear(); RD::get_singleton()->draw_command_begin_label("Shadow Setup"); _update_render_base_uniform_set(); @@ -1989,7 +1499,7 @@ void RendererSceneRenderForwardClustered::_render_shadow_begin() { render_list[RENDER_LIST_SECONDARY].clear(); scene_state.instance_data[RENDER_LIST_SECONDARY].clear(); } -void RendererSceneRenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &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_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end) { +void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &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_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end) { uint32_t shadow_pass_index = scene_state.shadow_passes.size(); SceneState::ShadowPass shadow_pass; @@ -2036,7 +1546,7 @@ void RendererSceneRenderForwardClustered::_render_shadow_append(RID p_framebuffe } } -void RendererSceneRenderForwardClustered::_render_shadow_process() { +void RenderForwardClustered::_render_shadow_process() { _update_instance_data_buffer(RENDER_LIST_SECONDARY); //render shadows one after the other, so this can be done un-barriered and the driver can optimize (as well as allow us to run compute at the same time) @@ -2048,7 +1558,7 @@ void RendererSceneRenderForwardClustered::_render_shadow_process() { RD::get_singleton()->draw_command_end_label(); } -void RendererSceneRenderForwardClustered::_render_shadow_end(uint32_t p_barrier) { +void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) { RD::get_singleton()->draw_command_begin_label("Shadow Render"); for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) { @@ -2063,7 +1573,7 @@ void RendererSceneRenderForwardClustered::_render_shadow_end(uint32_t p_barrier) RD::get_singleton()->draw_command_end_label(); } -void RendererSceneRenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) { +void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) { RENDER_TIMESTAMP("Setup Render Collider Heightfield"); RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield"); @@ -2091,7 +1601,7 @@ void RendererSceneRenderForwardClustered::_render_particle_collider_heightfield( RD::get_singleton()->draw_command_end_label(); } -void RendererSceneRenderForwardClustered::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RenderForwardClustered::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { RENDER_TIMESTAMP("Setup Rendering Material"); RD::get_singleton()->draw_command_begin_label("Render Material"); @@ -2129,7 +1639,7 @@ void RendererSceneRenderForwardClustered::_render_material(const Transform &p_ca RD::get_singleton()->draw_command_end_label(); } -void RendererSceneRenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { RENDER_TIMESTAMP("Setup Rendering UV2"); RD::get_singleton()->draw_command_begin_label("Render UV2"); @@ -2191,14 +1701,14 @@ void RendererSceneRenderForwardClustered::_render_uv2(const PagedArray<GeometryI RD::get_singleton()->draw_command_end_label(); } -void RendererSceneRenderForwardClustered::_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<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) { RENDER_TIMESTAMP("Render SDFGI"); RD::get_singleton()->draw_command_begin_label("Render SDFGI Voxel"); _update_render_base_uniform_set(); - RenderBufferDataForward *render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); + RenderBufferDataForwardClustered *render_buffer = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffers); ERR_FAIL_COND(!render_buffer); PassMode pass_mode = PASS_MODE_SDF; @@ -2272,14 +1782,14 @@ void RendererSceneRenderForwardClustered::_render_sdfgi(RID p_render_buffers, co RD::get_singleton()->draw_command_end_label(); } -void RendererSceneRenderForwardClustered::_base_uniforms_changed() { +void RenderForwardClustered::_base_uniforms_changed() { if (!render_base_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { RD::get_singleton()->free(render_base_uniform_set); } render_base_uniform_set = RID(); } -void RendererSceneRenderForwardClustered::_update_render_base_uniform_set() { +void RenderForwardClustered::_update_render_base_uniform_set() { if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version())) { if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { RD::get_singleton()->free(render_base_uniform_set); @@ -2314,7 +1824,7 @@ void RendererSceneRenderForwardClustered::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.ids.push_back(shadow_sampler); + u.ids.push_back(scene_shader.shadow_sampler); uniforms.push_back(u); } @@ -2401,17 +1911,17 @@ void RendererSceneRenderForwardClustered::_update_render_base_uniform_set() { uniforms.push_back(u); } - render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, SCENE_UNIFORM_SET); + render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_rd, SCENE_UNIFORM_SET); } } -RID RendererSceneRenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_render_list, RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, RID p_cluster_buffer, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, bool p_use_directional_shadow_atlas, int p_index) { +RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_render_list, RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, RID p_cluster_buffer, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, bool p_use_directional_shadow_atlas, int p_index) { //there should always be enough uniform buffers for render passes, otherwise bugs ERR_FAIL_INDEX_V(p_index, (int)scene_state.uniform_buffers.size(), RID()); - RenderBufferDataForward *rb = nullptr; + RenderBufferDataForwardClustered *rb = nullptr; if (p_render_buffers.is_valid()) { - rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); + rb = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffers); } //default render buffer and scene state uniform set @@ -2431,7 +1941,7 @@ RID RendererSceneRenderForwardClustered::_setup_render_pass_uniform_set(RenderLi u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; RID instance_buffer = scene_state.instance_buffer[p_render_list]; if (instance_buffer == RID()) { - instance_buffer = default_vec4_xform_buffer; // any buffer will do since its not used + instance_buffer = scene_shader.default_vec4_xform_buffer; // any buffer will do since its not used } u.ids.push_back(instance_buffer); uniforms.push_back(u); @@ -2532,7 +2042,7 @@ RID RendererSceneRenderForwardClustered::_setup_render_pass_uniform_set(RenderLi RD::Uniform u; u.binding = 8; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - RID cb = p_cluster_buffer.is_valid() ? p_cluster_buffer : default_vec4_xform_buffer; + RID cb = p_cluster_buffer.is_valid() ? p_cluster_buffer : scene_shader.default_vec4_xform_buffer; u.ids.push_back(cb); uniforms.push_back(u); } @@ -2651,11 +2161,11 @@ RID RendererSceneRenderForwardClustered::_setup_render_pass_uniform_set(RenderLi RD::get_singleton()->free(render_pass_uniform_sets[p_index]); } - render_pass_uniform_sets[p_index] = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_PASS_UNIFORM_SET); + render_pass_uniform_sets[p_index] = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_rd, RENDER_PASS_UNIFORM_SET); return render_pass_uniform_sets[p_index]; } -RID RendererSceneRenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture) { +RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture) { if (sdfgi_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_pass_uniform_set)) { RD::get_singleton()->free(sdfgi_pass_uniform_set); } @@ -2748,7 +2258,7 @@ RID RendererSceneRenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RI RD::Uniform u; u.binding = 8; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - RID cb = default_vec4_xform_buffer; + RID cb = scene_shader.default_vec4_xform_buffer; u.ids.push_back(cb); uniforms.push_back(u); } @@ -2784,28 +2294,28 @@ RID RendererSceneRenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RI uniforms.push_back(u); } - sdfgi_pass_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_sdfgi_rd, RENDER_PASS_UNIFORM_SET); + sdfgi_pass_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_sdfgi_rd, RENDER_PASS_UNIFORM_SET); return sdfgi_pass_uniform_set; } -void RendererSceneRenderForwardClustered::_render_buffers_clear_uniform_set(RenderBufferDataForward *rb) { +void RenderForwardClustered::_render_buffers_clear_uniform_set(RenderBufferDataForwardClustered *rb) { } -void RendererSceneRenderForwardClustered::_render_buffers_uniform_set_changed(RID p_render_buffers) { - RenderBufferDataForward *rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); +void RenderForwardClustered::_render_buffers_uniform_set_changed(RID p_render_buffers) { + RenderBufferDataForwardClustered *rb = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffers); _render_buffers_clear_uniform_set(rb); } -RID RendererSceneRenderForwardClustered::_render_buffers_get_normal_texture(RID p_render_buffers) { - RenderBufferDataForward *rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); +RID RenderForwardClustered::_render_buffers_get_normal_texture(RID p_render_buffers) { + RenderBufferDataForwardClustered *rb = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffers); return rb->normal_roughness_buffer; } -RendererSceneRenderForwardClustered *RendererSceneRenderForwardClustered::singleton = nullptr; +RenderForwardClustered *RenderForwardClustered::singleton = nullptr; -void RendererSceneRenderForwardClustered::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) { +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()) { return; @@ -2825,7 +2335,7 @@ void RendererSceneRenderForwardClustered::_geometry_instance_mark_dirty(Geometry geometry_instance_dirty_list.add(&ginstance->dirty_list_element); } -void RendererSceneRenderForwardClustered::_geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) { +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) { bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture; bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha); bool has_blend_alpha = p_material->shader_data->uses_blend_alpha; @@ -2853,10 +2363,10 @@ void RendererSceneRenderForwardClustered::_geometry_instance_add_surface_with_ma flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS; } - if (has_alpha || has_read_screen_alpha || p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED) { + if (has_alpha || has_read_screen_alpha || p_material->shader_data->depth_draw == SceneShaderForwardClustered::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardClustered::ShaderData::DEPTH_TEST_DISABLED) { //material is only meant for alpha pass flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA; - if (p_material->shader_data->uses_depth_pre_pass && !(p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED)) { + if (p_material->shader_data->uses_depth_pre_pass && !(p_material->shader_data->depth_draw == SceneShaderForwardClustered::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardClustered::ShaderData::DEPTH_TEST_DISABLED)) { flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH; flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW; } @@ -2866,11 +2376,11 @@ void RendererSceneRenderForwardClustered::_geometry_instance_add_surface_with_ma flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW; } - MaterialData *material_shadow = nullptr; + SceneShaderForwardClustered::MaterialData *material_shadow = nullptr; void *surface_shadow = nullptr; if (!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) { flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL; - material_shadow = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D); + material_shadow = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D); RID shadow_mesh = storage->mesh_get_shadow_mesh(p_mesh); @@ -2921,15 +2431,15 @@ void RendererSceneRenderForwardClustered::_geometry_instance_add_surface_with_ma sdcache->sort.priority = p_material->priority; } -void RendererSceneRenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) { +void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) { RID m_src; m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material; - MaterialData *material = nullptr; + SceneShaderForwardClustered::MaterialData *material = nullptr; if (m_src.is_valid()) { - material = (MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D); + material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -2940,8 +2450,8 @@ void RendererSceneRenderForwardClustered::_geometry_instance_add_surface(Geometr storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); } } else { - material = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D); - m_src = default_material; + material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D); + m_src = scene_shader.default_material; } ERR_FAIL_COND(!material); @@ -2950,7 +2460,7 @@ void RendererSceneRenderForwardClustered::_geometry_instance_add_surface(Geometr while (material->next_pass.is_valid()) { RID next_pass = material->next_pass; - material = (MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D); + material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D); if (!material || !material->shader_data->valid) { break; } @@ -2961,7 +2471,7 @@ void RendererSceneRenderForwardClustered::_geometry_instance_add_surface(Geometr } } -void RendererSceneRenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geometry_instance) { +void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geometry_instance) { GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); if (ginstance->data->dirty_dependencies) { @@ -3022,8 +2532,9 @@ void RendererSceneRenderForwardClustered::_geometry_instance_update(GeometryInst for (int j = 0; j < draw_passes; j++) { RID mesh = storage->particles_get_draw_pass_mesh(ginstance->data->base, j); - if (!mesh.is_valid()) + if (!mesh.is_valid()) { continue; + } const RID *materials = nullptr; uint32_t surface_count; @@ -3067,7 +2578,7 @@ void RendererSceneRenderForwardClustered::_geometry_instance_update(GeometryInst } ginstance->base_flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT); - ginstance->transforms_uniform_set = storage->multimesh_get_3d_uniform_set(ginstance->data->base, default_shader_rd, TRANSFORMS_UNIFORM_SET); + ginstance->transforms_uniform_set = storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); } else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) { ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH; @@ -3090,12 +2601,12 @@ void RendererSceneRenderForwardClustered::_geometry_instance_update(GeometryInst if (!storage->particles_is_using_local_coords(ginstance->data->base)) { store_transform = false; } - ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, default_shader_rd, TRANSFORMS_UNIFORM_SET); + ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); } else if (ginstance->data->base_type == RS::INSTANCE_MESH) { if (storage->skeleton_is_valid(ginstance->data->skeleton)) { ginstance->base_flags |= INSTANCE_DATA_FLAG_SKELETON; - ginstance->transforms_uniform_set = storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, default_shader_rd, TRANSFORMS_UNIFORM_SET); + ginstance->transforms_uniform_set = storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); if (ginstance->data->dirty_dependencies) { storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker); } @@ -3119,24 +2630,24 @@ void RendererSceneRenderForwardClustered::_geometry_instance_update(GeometryInst ginstance->dirty_list_element.remove_from_list(); } -void RendererSceneRenderForwardClustered::_update_dirty_geometry_instances() { +void RenderForwardClustered::_update_dirty_geometry_instances() { while (geometry_instance_dirty_list.first()) { _geometry_instance_update(geometry_instance_dirty_list.first()->self()); } } -void RendererSceneRenderForwardClustered::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) { +void RenderForwardClustered::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) { switch (p_notification) { case RendererStorage::DEPENDENCY_CHANGED_MATERIAL: case RendererStorage::DEPENDENCY_CHANGED_MESH: case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH: case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: { - static_cast<RendererSceneRenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); + static_cast<RenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); } break; case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata); if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { - ginstance->instance_count = static_cast<RendererSceneRenderForwardClustered *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base); + ginstance->instance_count = static_cast<RenderForwardClustered *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base); } } break; default: { @@ -3144,11 +2655,11 @@ void RendererSceneRenderForwardClustered::_geometry_instance_dependency_changed( } break; } } -void RendererSceneRenderForwardClustered::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) { - static_cast<RendererSceneRenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); +void RenderForwardClustered::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) { + static_cast<RenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); } -RendererSceneRender::GeometryInstance *RendererSceneRenderForwardClustered::geometry_instance_create(RID p_base) { +RendererSceneRender::GeometryInstance *RenderForwardClustered::geometry_instance_create(RID p_base) { RS::InstanceType type = storage->get_base_type(p_base); ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr); @@ -3165,34 +2676,34 @@ RendererSceneRender::GeometryInstance *RendererSceneRenderForwardClustered::geom return ginstance; } -void RendererSceneRenderForwardClustered::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) { +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 RendererSceneRenderForwardClustered::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) { +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 RendererSceneRenderForwardClustered::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) { +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 RendererSceneRenderForwardClustered::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) { +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 RendererSceneRenderForwardClustered::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) { +void RenderForwardClustered::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) { GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); ginstance->transform = p_transform; @@ -3209,24 +2720,24 @@ void RendererSceneRenderForwardClustered::geometry_instance_set_transform(Geomet ginstance->lod_model_scale = max_scale; } -void RendererSceneRenderForwardClustered::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) { +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 RendererSceneRenderForwardClustered::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) { +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 RendererSceneRenderForwardClustered::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) { +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 RendererSceneRenderForwardClustered::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) { +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; @@ -3234,7 +2745,7 @@ void RendererSceneRenderForwardClustered::geometry_instance_set_use_lightmap(Geo ginstance->lightmap_slice_index = p_lightmap_slice_index; _geometry_instance_mark_dirty(ginstance); } -void RendererSceneRenderForwardClustered::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) { +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); if (p_sh9) { @@ -3251,13 +2762,13 @@ void RendererSceneRenderForwardClustered::geometry_instance_set_lightmap_capture } _geometry_instance_mark_dirty(ginstance); } -void RendererSceneRenderForwardClustered::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) { +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 RendererSceneRenderForwardClustered::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) { +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); @@ -3265,13 +2776,13 @@ void RendererSceneRenderForwardClustered::geometry_instance_set_cast_double_side _geometry_instance_mark_dirty(ginstance); } -void RendererSceneRenderForwardClustered::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) { +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 RendererSceneRenderForwardClustered::geometry_instance_free(GeometryInstance *p_geometry_instance) { +void RenderForwardClustered::geometry_instance_free(GeometryInstance *p_geometry_instance) { GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); if (ginstance->lightmap_sh != nullptr) { @@ -3287,28 +2798,28 @@ void RendererSceneRenderForwardClustered::geometry_instance_free(GeometryInstanc geometry_instance_alloc.free(ginstance); } -uint32_t RendererSceneRenderForwardClustered::geometry_instance_get_pair_mask() { +uint32_t RenderForwardClustered::geometry_instance_get_pair_mask() { return (1 << RS::INSTANCE_GI_PROBE); } -void RendererSceneRenderForwardClustered::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_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) { } -void RendererSceneRenderForwardClustered::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_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) { } -void RendererSceneRenderForwardClustered::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) { +void RenderForwardClustered::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) { } -Transform RendererSceneRenderForwardClustered::geometry_instance_get_transform(GeometryInstance *p_instance) { +Transform RenderForwardClustered::geometry_instance_get_transform(GeometryInstance *p_instance) { GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_instance); ERR_FAIL_COND_V(!ginstance, Transform()); return ginstance->transform; } -AABB RendererSceneRenderForwardClustered::geometry_instance_get_aabb(GeometryInstance *p_instance) { +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 RendererSceneRenderForwardClustered::geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) { +void RenderForwardClustered::geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) { GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); if (p_gi_probe_instance_count > 0) { @@ -3324,10 +2835,9 @@ void RendererSceneRenderForwardClustered::geometry_instance_pair_gi_probe_instan } } -RendererSceneRenderForwardClustered::RendererSceneRenderForwardClustered(RendererStorageRD *p_storage) : +RenderForwardClustered::RenderForwardClustered(RendererStorageRD *p_storage) : RendererSceneRenderRD(p_storage) { singleton = this; - low_end = is_low_end(); /* SCENE SHADER */ @@ -3362,267 +2872,13 @@ RendererSceneRenderForwardClustered::RendererSceneRenderForwardClustered(Rendere defines += "\n#define MATERIAL_UNIFORM_SET " + itos(MATERIAL_UNIFORM_SET) + "\n"; } - Vector<String> shader_versions; - shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); - shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); - shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n"); - shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_GIPROBE\n"); - shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); - shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n"); - shader_versions.push_back(""); - shader_versions.push_back("\n#define USE_FORWARD_GI\n"); - shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n"); - shader_versions.push_back("\n#define USE_LIGHTMAP\n"); - shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n"); - shader.scene_shader.initialize(shader_versions, defines); - - if (is_low_end()) { - //disable the high end versions - shader.scene_shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS, false); - shader.scene_shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE, false); - shader.scene_shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_SDF, false); - shader.scene_shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI, false); - shader.scene_shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR, false); - shader.scene_shader.set_variant_enabled(SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, false); - } - } - - storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs); - storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_material_funcs); - - { - //shader compiler - ShaderCompilerRD::DefaultIdentifierActions actions; - - actions.renames["WORLD_MATRIX"] = "world_matrix"; - actions.renames["WORLD_NORMAL_MATRIX"] = "world_normal_matrix"; - actions.renames["INV_CAMERA_MATRIX"] = "scene_data.inv_camera_matrix"; - actions.renames["CAMERA_MATRIX"] = "scene_data.camera_matrix"; - actions.renames["PROJECTION_MATRIX"] = "projection_matrix"; - actions.renames["INV_PROJECTION_MATRIX"] = "scene_data.inv_projection_matrix"; - actions.renames["MODELVIEW_MATRIX"] = "modelview"; - actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal"; - - actions.renames["VERTEX"] = "vertex"; - actions.renames["NORMAL"] = "normal"; - actions.renames["TANGENT"] = "tangent"; - actions.renames["BINORMAL"] = "binormal"; - actions.renames["POSITION"] = "position"; - actions.renames["UV"] = "uv_interp"; - actions.renames["UV2"] = "uv2_interp"; - actions.renames["COLOR"] = "color_interp"; - actions.renames["POINT_SIZE"] = "gl_PointSize"; - actions.renames["INSTANCE_ID"] = "gl_InstanceIndex"; - - actions.renames["ALPHA_SCISSOR_THRESHOLD"] = "alpha_scissor_threshold"; - actions.renames["ALPHA_HASH_SCALE"] = "alpha_hash_scale"; - actions.renames["ALPHA_ANTIALIASING_EDGE"] = "alpha_antialiasing_edge"; - actions.renames["ALPHA_TEXTURE_COORDINATE"] = "alpha_texture_coordinate"; - - //builtins - - actions.renames["TIME"] = "scene_data.time"; - actions.renames["VIEWPORT_SIZE"] = "scene_data.viewport_size"; - - actions.renames["FRAGCOORD"] = "gl_FragCoord"; - actions.renames["FRONT_FACING"] = "gl_FrontFacing"; - actions.renames["NORMAL_MAP"] = "normal_map"; - actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth"; - actions.renames["ALBEDO"] = "albedo"; - actions.renames["ALPHA"] = "alpha"; - actions.renames["METALLIC"] = "metallic"; - actions.renames["SPECULAR"] = "specular"; - actions.renames["ROUGHNESS"] = "roughness"; - actions.renames["RIM"] = "rim"; - actions.renames["RIM_TINT"] = "rim_tint"; - actions.renames["CLEARCOAT"] = "clearcoat"; - actions.renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss"; - actions.renames["ANISOTROPY"] = "anisotropy"; - actions.renames["ANISOTROPY_FLOW"] = "anisotropy_flow"; - actions.renames["SSS_STRENGTH"] = "sss_strength"; - actions.renames["SSS_TRANSMITTANCE_COLOR"] = "transmittance_color"; - actions.renames["SSS_TRANSMITTANCE_DEPTH"] = "transmittance_depth"; - actions.renames["SSS_TRANSMITTANCE_CURVE"] = "transmittance_curve"; - actions.renames["SSS_TRANSMITTANCE_BOOST"] = "transmittance_boost"; - actions.renames["BACKLIGHT"] = "backlight"; - actions.renames["AO"] = "ao"; - actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect"; - actions.renames["EMISSION"] = "emission"; - actions.renames["POINT_COORD"] = "gl_PointCoord"; - actions.renames["INSTANCE_CUSTOM"] = "instance_custom"; - actions.renames["SCREEN_UV"] = "screen_uv"; - actions.renames["SCREEN_TEXTURE"] = "color_buffer"; - actions.renames["DEPTH_TEXTURE"] = "depth_buffer"; - 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["RADIANCE"] = "custom_radiance"; - actions.renames["IRRADIANCE"] = "custom_irradiance"; - actions.renames["BONE_INDICES"] = "bone_attrib"; - actions.renames["BONE_WEIGHTS"] = "weight_attrib"; - actions.renames["CUSTOM0"] = "custom0_attrib"; - actions.renames["CUSTOM1"] = "custom1_attrib"; - actions.renames["CUSTOM2"] = "custom2_attrib"; - actions.renames["CUSTOM3"] = "custom3_attrib"; - - //for light - actions.renames["VIEW"] = "view"; - actions.renames["LIGHT_COLOR"] = "light_color"; - actions.renames["LIGHT"] = "light"; - actions.renames["ATTENUATION"] = "attenuation"; - actions.renames["SHADOW_ATTENUATION"] = "shadow_attenuation"; - actions.renames["DIFFUSE_LIGHT"] = "diffuse_light"; - actions.renames["SPECULAR_LIGHT"] = "specular_light"; - - actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n"; - actions.usage_defines["TANGENT"] = "#define TANGENT_USED\n"; - actions.usage_defines["BINORMAL"] = "@TANGENT"; - actions.usage_defines["RIM"] = "#define LIGHT_RIM_USED\n"; - actions.usage_defines["RIM_TINT"] = "@RIM"; - actions.usage_defines["CLEARCOAT"] = "#define LIGHT_CLEARCOAT_USED\n"; - actions.usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT"; - actions.usage_defines["ANISOTROPY"] = "#define LIGHT_ANISOTROPY_USED\n"; - actions.usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY"; - actions.usage_defines["AO"] = "#define AO_USED\n"; - actions.usage_defines["AO_LIGHT_AFFECT"] = "#define AO_USED\n"; - actions.usage_defines["UV"] = "#define UV_USED\n"; - actions.usage_defines["UV2"] = "#define UV2_USED\n"; - actions.usage_defines["BONE_INDICES"] = "#define BONES_USED\n"; - actions.usage_defines["BONE_WEIGHTS"] = "#define WEIGHTS_USED\n"; - actions.usage_defines["CUSTOM0"] = "#define CUSTOM0\n"; - actions.usage_defines["CUSTOM1"] = "#define CUSTOM1\n"; - actions.usage_defines["CUSTOM2"] = "#define CUSTOM2\n"; - actions.usage_defines["CUSTOM3"] = "#define CUSTOM3\n"; - actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n"; - actions.usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP"; - actions.usage_defines["COLOR"] = "#define COLOR_USED\n"; - actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; - actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n"; - - actions.usage_defines["ALPHA_SCISSOR_THRESHOLD"] = "#define ALPHA_SCISSOR_USED\n"; - actions.usage_defines["ALPHA_HASH_SCALE"] = "#define ALPHA_HASH_USED\n"; - actions.usage_defines["ALPHA_ANTIALIASING_EDGE"] = "#define ALPHA_ANTIALIASING_EDGE_USED\n"; - actions.usage_defines["ALPHA_TEXTURE_COORDINATE"] = "@ALPHA_ANTIALIASING_EDGE"; - - actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; - actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n"; - actions.usage_defines["BACKLIGHT"] = "#define LIGHT_BACKLIGHT_USED\n"; - actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; - actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; - - actions.usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - actions.usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - - actions.usage_defines["FOG"] = "#define CUSTOM_FOG_USED\n"; - actions.usage_defines["RADIANCE"] = "#define CUSTOM_RADIANCE_USED\n"; - actions.usage_defines["IRRADIANCE"] = "#define CUSTOM_IRRADIANCE_USED\n"; - - actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; - actions.render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; - actions.render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n"; - actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n"; - actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n"; - - bool force_lambert = GLOBAL_GET("rendering/shading/overrides/force_lambert_over_burley"); - - if (!force_lambert) { - actions.render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n"; - } - - actions.render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n"; - actions.render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n"; - actions.render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n"; - - actions.render_mode_defines["sss_mode_skin"] = "#define SSS_MODE_SKIN\n"; - - bool force_blinn = GLOBAL_GET("rendering/shading/overrides/force_blinn_over_ggx"); - - if (!force_blinn) { - actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; - } else { - actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n"; - } - - actions.render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n"; - actions.render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n"; - actions.render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; - actions.render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; - actions.render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; - actions.render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n"; - actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; - actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; - - actions.sampler_array_name = "material_samplers"; - actions.base_texture_binding_index = 1; - actions.texture_layout_set = MATERIAL_UNIFORM_SET; - actions.base_uniform_string = "material."; - actions.base_varying_index = 10; - - actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; - actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; - actions.global_buffer_array_variable = "global_variables.data"; - actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs"; - - shader.compiler.initialize(actions); - } - - { - //default material and shader - default_shader = storage->shader_allocate(); - storage->shader_initialize(default_shader); - storage->shader_set_code(default_shader, "shader_type spatial; void vertex() { ROUGHNESS = 0.8; } void fragment() { ALBEDO=vec3(0.6); ROUGHNESS=0.8; METALLIC=0.2; } \n"); - default_material = storage->material_allocate(); - storage->material_initialize(default_material); - storage->material_set_shader(default_material, default_shader); - - MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D); - default_shader_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); - if (!low_end) { - default_shader_sdfgi_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF); - } - } - - { - overdraw_material_shader = storage->shader_allocate(); - storage->shader_initialize(overdraw_material_shader); - storage->shader_set_code(overdraw_material_shader, "shader_type spatial;\nrender_mode blend_add,unshaded;\n void fragment() { ALBEDO=vec3(0.4,0.8,0.8); ALPHA=0.2; }"); - overdraw_material = storage->material_allocate(); - storage->material_initialize(overdraw_material); - storage->material_set_shader(overdraw_material, overdraw_material_shader); - - wireframe_material_shader = storage->shader_allocate(); - storage->shader_initialize(wireframe_material_shader); - storage->shader_set_code(wireframe_material_shader, "shader_type spatial;\nrender_mode wireframe,unshaded;\n void fragment() { ALBEDO=vec3(0.0,0.0,0.0); }"); - wireframe_material = storage->material_allocate(); - storage->material_initialize(wireframe_material); - storage->material_set_shader(wireframe_material, wireframe_material_shader); - } - - { - default_vec4_xform_buffer = RD::get_singleton()->storage_buffer_create(256); - Vector<RD::Uniform> uniforms; - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(default_vec4_xform_buffer); - u.binding = 0; - uniforms.push_back(u); - - default_vec4_xform_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, TRANSFORMS_UNIFORM_SET); - } - { - RD::SamplerState sampler; - sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR; - sampler.min_filter = RD::SAMPLER_FILTER_LINEAR; - sampler.enable_compare = true; - sampler.compare_op = RD::COMPARE_OP_LESS; - shadow_sampler = RD::get_singleton()->sampler_create(sampler); + scene_shader.init(p_storage, defines, low_end); } render_list_thread_threshold = GLOBAL_GET("rendering/limits/forward_renderer/threaded_render_minimum_instances"); } -RendererSceneRenderForwardClustered::~RendererSceneRenderForwardClustered() { +RenderForwardClustered::~RenderForwardClustered() { directional_shadow_atlas_set_size(0); //clear base uniform set if still valid @@ -3636,17 +2892,6 @@ RendererSceneRenderForwardClustered::~RendererSceneRenderForwardClustered() { RD::get_singleton()->free(sdfgi_pass_uniform_set); } - RD::get_singleton()->free(default_vec4_xform_buffer); - RD::get_singleton()->free(shadow_sampler); - - storage->free(wireframe_material_shader); - storage->free(overdraw_material_shader); - storage->free(default_shader); - - storage->free(wireframe_material); - storage->free(overdraw_material); - storage->free(default_material); - { for (uint32_t i = 0; i < scene_state.uniform_buffers.size(); i++) { RD::get_singleton()->free(scene_state.uniform_buffers[i]); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 98e2a7efcc..72e84a6f24 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* renderer_scene_render_forward_clustered.h */ +/* render_forward_clustered.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -32,12 +32,17 @@ #define RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H #include "core/templates/paged_allocator.h" +#include "servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h" -class RendererSceneRenderForwardClustered : public RendererSceneRenderRD { +namespace RendererSceneRenderImplementation { + +class RenderForwardClustered : public RendererSceneRenderRD { + friend SceneShaderForwardClustered; + enum { SCENE_UNIFORM_SET = 0, RENDER_PASS_UNIFORM_SET = 1, @@ -63,155 +68,11 @@ class RendererSceneRenderForwardClustered : public RendererSceneRenderRD { /* Scene Shader */ - enum ShaderVersion { - SHADER_VERSION_DEPTH_PASS, - SHADER_VERSION_DEPTH_PASS_DP, - SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS, - SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE, - SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL, - SHADER_VERSION_DEPTH_PASS_WITH_SDF, - SHADER_VERSION_COLOR_PASS, - SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI, - SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR, - SHADER_VERSION_LIGHTMAP_COLOR_PASS, - SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, - SHADER_VERSION_MAX - }; - - struct { - SceneForwardClusteredShaderRD scene_shader; - ShaderCompilerRD compiler; - } shader; - - /* Material */ - - struct ShaderData : public RendererStorageRD::ShaderData { - enum BlendMode { //used internally - BLEND_MODE_MIX, - BLEND_MODE_ADD, - BLEND_MODE_SUB, - BLEND_MODE_MUL, - BLEND_MODE_ALPHA_TO_COVERAGE - }; - - enum DepthDraw { - DEPTH_DRAW_DISABLED, - DEPTH_DRAW_OPAQUE, - DEPTH_DRAW_ALWAYS - }; - - enum DepthTest { - DEPTH_TEST_DISABLED, - DEPTH_TEST_ENABLED - }; - - enum Cull { - CULL_DISABLED, - CULL_FRONT, - CULL_BACK - }; - - enum CullVariant { - CULL_VARIANT_NORMAL, - CULL_VARIANT_REVERSED, - CULL_VARIANT_DOUBLE_SIDED, - CULL_VARIANT_MAX - - }; - - enum AlphaAntiAliasing { - ALPHA_ANTIALIASING_OFF, - ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE, - ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE - }; - - bool valid; - RID version; - uint32_t vertex_input_mask; - PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX]; - - String path; - - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; - Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms; - - Vector<uint32_t> ubo_offsets; - uint32_t ubo_size; - - String code; - Map<StringName, RID> default_texture_params; - - DepthDraw depth_draw; - DepthTest depth_test; - - bool uses_point_size; - bool uses_alpha; - bool uses_blend_alpha; - bool uses_alpha_clip; - bool uses_depth_pre_pass; - bool uses_discard; - bool uses_roughness; - bool uses_normal; - - bool unshaded; - bool uses_vertex; - bool uses_sss; - bool uses_transmittance; - bool uses_screen_texture; - bool uses_depth_texture; - bool uses_normal_texture; - bool uses_time; - bool writes_modelview_or_projection; - bool uses_world_coordinates; - - uint64_t last_pass = 0; - uint32_t index = 0; - - virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture); - virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - void get_instance_param_list(List<RendererStorage::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; - - ShaderData(); - virtual ~ShaderData(); - }; - - RendererStorageRD::ShaderData *_create_shader_func(); - static RendererStorageRD::ShaderData *_create_shader_funcs() { - return static_cast<RendererSceneRenderForwardClustered *>(singleton)->_create_shader_func(); - } - - struct MaterialData : public RendererStorageRD::MaterialData { - uint64_t last_frame; - ShaderData *shader_data; - RID uniform_buffer; - RID uniform_set; - Vector<RID> texture_cache; - Vector<uint8_t> ubo_data; - uint64_t last_pass = 0; - uint32_t index = 0; - RID next_pass; - uint8_t priority; - virtual void set_render_priority(int p_priority); - virtual void set_next_pass(RID p_pass); - virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); - virtual ~MaterialData(); - }; - - RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); - static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) { - return static_cast<RendererSceneRenderForwardClustered *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); - } + SceneShaderForwardClustered scene_shader; /* Framebuffer */ - struct RenderBufferDataForward : public RenderBufferData { + struct RenderBufferDataForwardClustered : public RenderBufferData { //for rendering, may be MSAAd RID color; @@ -244,13 +105,12 @@ class RendererSceneRenderForwardClustered : public RendererSceneRenderRD { void clear(); virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa); - ~RenderBufferDataForward(); + ~RenderBufferDataForwardClustered(); }; virtual RenderBufferData *_create_render_buffer_data(); - void _allocate_normal_roughness_texture(RenderBufferDataForward *rb); + void _allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb); - RID shadow_sampler; RID render_base_uniform_set; LocalVector<RID> render_pass_uniform_sets; RID sdfgi_pass_uniform_set; @@ -258,7 +118,7 @@ class RendererSceneRenderForwardClustered : public RendererSceneRenderRD { uint64_t lightmap_texture_array_version = 0xFFFFFFFF; virtual void _base_uniforms_changed(); - void _render_buffers_clear_uniform_set(RenderBufferDataForward *rb); + void _render_buffers_clear_uniform_set(RenderBufferDataForwardClustered *rb); virtual void _render_buffers_uniform_set_changed(RID p_render_buffers); virtual RID _render_buffers_get_normal_texture(RID p_render_buffers); @@ -488,19 +348,7 @@ class RendererSceneRenderForwardClustered : public RendererSceneRenderRD { } scene_state; - static RendererSceneRenderForwardClustered *singleton; - - RID default_shader; - RID default_material; - RID overdraw_material_shader; - RID overdraw_material; - RID wireframe_material_shader; - RID wireframe_material; - RID default_shader_rd; - RID default_shader_sdfgi_rd; - - RID default_vec4_xform_buffer; - RID default_vec4_xform_uniform_set; + static RenderForwardClustered *singleton; void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2i &p_screen_size, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0); void _setup_giprobes(const PagedArray<RID> &p_giprobes); @@ -578,11 +426,11 @@ class RendererSceneRenderForwardClustered : public RendererSceneRenderRD { void *surface = nullptr; RID material_uniform_set; - ShaderData *shader = nullptr; + SceneShaderForwardClustered::ShaderData *shader = nullptr; void *surface_shadow = nullptr; RID material_uniform_set_shadow; - ShaderData *shader_shadow = nullptr; + SceneShaderForwardClustered::ShaderData *shader_shadow = nullptr; GeometryInstanceSurfaceDataCache *next = nullptr; GeometryInstanceForwardClustered *owner = nullptr; @@ -650,14 +498,12 @@ class RendererSceneRenderForwardClustered : public RendererSceneRenderRD { PagedAllocator<GeometryInstanceSurfaceDataCache> geometry_instance_surface_alloc; PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh; - void _geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh); + 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(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 _update_dirty_geometry_instances(); - bool low_end = false; - /* Render List */ struct RenderList { @@ -760,7 +606,8 @@ public: virtual bool free(RID p_rid); - RendererSceneRenderForwardClustered(RendererStorageRD *p_storage); - ~RendererSceneRenderForwardClustered(); + RenderForwardClustered(RendererStorageRD *p_storage); + ~RenderForwardClustered(); }; +} // namespace RendererSceneRenderImplementation #endif // !RENDERING_SERVER_SCENE_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 new file mode 100644 index 0000000000..cb8c6e0cf3 --- /dev/null +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -0,0 +1,807 @@ +/*************************************************************************/ +/* scene_shader_forward_clustered.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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_shader_forward_clustered.h" +#include "core/config/project_settings.h" +#include "render_forward_clustered.h" + +using namespace RendererSceneRenderImplementation; + +void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { + //compile + + code = p_code; + valid = false; + ubo_size = 0; + uniforms.clear(); + uses_screen_texture = false; + + if (code == String()) { + return; //just invalid, but no error + } + + ShaderCompilerRD::GeneratedCode gen_code; + + int blend_mode = BLEND_MODE_MIX; + int depth_testi = DEPTH_TEST_ENABLED; + int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF; + int cull = CULL_BACK; + + uses_point_size = false; + uses_alpha = false; + uses_blend_alpha = false; + uses_depth_pre_pass = false; + uses_discard = false; + uses_roughness = false; + uses_normal = false; + bool wireframe = false; + + unshaded = false; + uses_vertex = false; + uses_sss = false; + uses_transmittance = false; + uses_screen_texture = false; + uses_depth_texture = false; + uses_normal_texture = false; + uses_time = false; + writes_modelview_or_projection = false; + uses_world_coordinates = false; + + int depth_drawi = DEPTH_DRAW_OPAQUE; + + ShaderCompilerRD::IdentifierActions actions; + + actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_mode, BLEND_MODE_ADD); + actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX); + actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_mode, BLEND_MODE_SUB); + actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MUL); + + actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE); + actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE); + + actions.render_mode_values["depth_draw_never"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_DISABLED); + actions.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_OPAQUE); + actions.render_mode_values["depth_draw_always"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_ALWAYS); + + actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED); + + actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull, CULL_DISABLED); + actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull, CULL_FRONT); + actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull, CULL_BACK); + + actions.render_mode_flags["unshaded"] = &unshaded; + actions.render_mode_flags["wireframe"] = &wireframe; + + actions.usage_flag_pointers["ALPHA"] = &uses_alpha; + actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass; + + actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; + actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance; + + actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; + actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture; + actions.usage_flag_pointers["NORMAL_TEXTURE"] = &uses_normal_texture; + actions.usage_flag_pointers["DISCARD"] = &uses_discard; + actions.usage_flag_pointers["TIME"] = &uses_time; + actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness; + actions.usage_flag_pointers["NORMAL"] = &uses_normal; + actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal; + + actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size; + actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size; + + actions.write_flag_pointers["MODELVIEW_MATRIX"] = &writes_modelview_or_projection; + actions.write_flag_pointers["PROJECTION_MATRIX"] = &writes_modelview_or_projection; + actions.write_flag_pointers["VERTEX"] = &uses_vertex; + + actions.uniforms = &uniforms; + + SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton; + Error err = shader_singleton->compiler.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code); + + ERR_FAIL_COND(err != OK); + + if (version.is_null()) { + version = shader_singleton->shader.version_create(); + } + + depth_draw = DepthDraw(depth_drawi); + depth_test = DepthTest(depth_testi); + +#if 0 + print_line("**compiling shader:"); + print_line("**defines:\n"); + for (int i = 0; i < gen_code.defines.size(); i++) { + print_line(gen_code.defines[i]); + } + print_line("\n**uniforms:\n" + gen_code.uniforms); + print_line("\n**vertex_globals:\n" + gen_code.vertex_global); + print_line("\n**vertex_code:\n" + gen_code.vertex); + print_line("\n**fragment_globals:\n" + gen_code.fragment_global); + print_line("\n**fragment_code:\n" + gen_code.fragment); + print_line("\n**light_code:\n" + gen_code.light); +#endif + shader_singleton->shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines); + ERR_FAIL_COND(!shader_singleton->shader.version_is_valid(version)); + + ubo_size = gen_code.uniform_total_size; + ubo_offsets = gen_code.uniform_offsets; + texture_uniforms = gen_code.texture_uniforms; + + //blend modes + + // if any form of Alpha Antialiasing is enabled, set the blend mode to alpha to coverage + if (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF) { + blend_mode = BLEND_MODE_ALPHA_TO_COVERAGE; + } + + RD::PipelineColorBlendState::Attachment blend_attachment; + + switch (blend_mode) { + case BLEND_MODE_MIX: { + blend_attachment.enable_blend = true; + blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD; + blend_attachment.color_blend_op = RD::BLEND_OP_ADD; + blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + + } break; + case BLEND_MODE_ADD: { + blend_attachment.enable_blend = true; + blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD; + blend_attachment.color_blend_op = RD::BLEND_OP_ADD; + blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE; + blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + uses_blend_alpha = true; //force alpha used because of blend + + } break; + case BLEND_MODE_SUB: { + blend_attachment.enable_blend = true; + blend_attachment.alpha_blend_op = RD::BLEND_OP_SUBTRACT; + blend_attachment.color_blend_op = RD::BLEND_OP_SUBTRACT; + blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE; + blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + uses_blend_alpha = true; //force alpha used because of blend + + } break; + case BLEND_MODE_MUL: { + blend_attachment.enable_blend = true; + blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD; + blend_attachment.color_blend_op = RD::BLEND_OP_ADD; + blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_DST_COLOR; + blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ZERO; + blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_DST_ALPHA; + blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO; + uses_blend_alpha = true; //force alpha used because of blend + } break; + case BLEND_MODE_ALPHA_TO_COVERAGE: { + blend_attachment.enable_blend = true; + blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD; + blend_attachment.color_blend_op = RD::BLEND_OP_ADD; + blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO; + } + } + + RD::PipelineColorBlendState blend_state_blend; + blend_state_blend.attachments.push_back(blend_attachment); + RD::PipelineColorBlendState blend_state_opaque = RD::PipelineColorBlendState::create_disabled(1); + RD::PipelineColorBlendState blend_state_opaque_specular = RD::PipelineColorBlendState::create_disabled(2); + RD::PipelineColorBlendState blend_state_depth_normal_roughness = RD::PipelineColorBlendState::create_disabled(1); + RD::PipelineColorBlendState blend_state_depth_normal_roughness_giprobe = RD::PipelineColorBlendState::create_disabled(2); + + //update pipelines + + RD::PipelineDepthStencilState depth_stencil_state; + + if (depth_test != DEPTH_TEST_DISABLED) { + depth_stencil_state.enable_depth_test = true; + depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; + depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false; + } + + for (int i = 0; i < CULL_VARIANT_MAX; i++) { + RD::PolygonCullMode cull_mode_rd_table[CULL_VARIANT_MAX][3] = { + { RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_FRONT, RD::POLYGON_CULL_BACK }, + { RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_BACK, RD::POLYGON_CULL_FRONT }, + { RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED } + }; + + RD::PolygonCullMode cull_mode_rd = cull_mode_rd_table[i][cull]; + + for (int j = 0; j < RS::PRIMITIVE_MAX; j++) { + RD::RenderPrimitive primitive_rd_table[RS::PRIMITIVE_MAX] = { + RD::RENDER_PRIMITIVE_POINTS, + RD::RENDER_PRIMITIVE_LINES, + RD::RENDER_PRIMITIVE_LINESTRIPS, + RD::RENDER_PRIMITIVE_TRIANGLES, + RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, + }; + + RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[j]; + + for (int k = 0; k < SHADER_VERSION_MAX; k++) { + if (!static_cast<SceneShaderForwardClustered *>(singleton)->shader.is_variant_enabled(k)) { + continue; + } + RD::PipelineRasterizationState raster_state; + raster_state.cull_mode = cull_mode_rd; + raster_state.wireframe = wireframe; + + RD::PipelineColorBlendState blend_state; + RD::PipelineDepthStencilState depth_stencil = depth_stencil_state; + RD::PipelineMultisampleState multisample_state; + + if (uses_alpha || uses_blend_alpha) { + // only allow these flags to go through if we have some form of msaa + if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) { + multisample_state.enable_alpha_to_coverage = true; + } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) { + multisample_state.enable_alpha_to_coverage = true; + multisample_state.enable_alpha_to_one = true; + } + + if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) { + blend_state = blend_state_blend; + if (depth_draw == DEPTH_DRAW_OPAQUE) { + depth_stencil.enable_depth_write = false; //alpha does not draw depth + } + } else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS || k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL)) { + if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) { + //none, blend state contains nothing + } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) { + blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way + } else { + blend_state = blend_state_opaque; //writes to normal and roughness in opaque way + } + } else { + pipelines[i][j][k].clear(); + continue; // do not use this version (will error if using it is attempted) + } + } else { + if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) { + blend_state = blend_state_opaque; + } else if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) { + //none, leave empty + } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) { + blend_state = blend_state_depth_normal_roughness; + } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE) { + blend_state = blend_state_depth_normal_roughness_giprobe; + } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) { + blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way + } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_SDF) { + blend_state = RD::PipelineColorBlendState(); //no color targets for SDF + } else { + //specular write + blend_state = blend_state_opaque_specular; + depth_stencil.enable_depth_test = false; + depth_stencil.enable_depth_write = false; + } + } + + RID shader_variant = shader_singleton->shader.version_get_shader(version, k); + pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0); + } + } + } + + valid = true; +} + +void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { + if (!p_texture.is_valid()) { + default_texture_params.erase(p_name); + } else { + default_texture_params[p_name] = p_texture; + } +} + +void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { + Map<int, StringName> order; + + for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { + if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { + continue; + } + + if (E->get().texture_order >= 0) { + order[E->get().texture_order + 100000] = E->key(); + } else { + order[E->get().order] = E->key(); + } + } + + for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) { + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]); + pi.name = E->get(); + p_param_list->push_back(pi); + } +} + +void SceneShaderForwardClustered::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { + for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { + if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { + continue; + } + + RendererStorage::InstanceShaderParam p; + p.info = ShaderLanguage::uniform_to_property_info(E->get()); + p.info.name = E->key(); //supply name + p.index = E->get().instance_index; + p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().hint); + p_param_list->push_back(p); + } +} + +bool SceneShaderForwardClustered::ShaderData::is_param_texture(const StringName &p_param) const { + if (!uniforms.has(p_param)) { + return false; + } + + return uniforms[p_param].texture_order >= 0; +} + +bool SceneShaderForwardClustered::ShaderData::is_animated() const { + return false; +} + +bool SceneShaderForwardClustered::ShaderData::casts_shadows() const { + return false; +} + +Variant SceneShaderForwardClustered::ShaderData::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.hint); + } + return Variant(); +} + +RS::ShaderNativeSourceCode SceneShaderForwardClustered::ShaderData::get_native_source_code() const { + SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton; + + return shader_singleton->shader.version_get_native_source_code(version); +} + +SceneShaderForwardClustered::ShaderData::ShaderData() { + valid = false; + uses_screen_texture = false; +} + +SceneShaderForwardClustered::ShaderData::~ShaderData() { + SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton; + ERR_FAIL_COND(!shader_singleton); + //pipeline variants will clear themselves if shader is gone + if (version.is_valid()) { + shader_singleton->shader.version_free(version); + } +} + +RendererStorageRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() { + ShaderData *shader_data = memnew(ShaderData); + return shader_data; +} + +void SceneShaderForwardClustered::MaterialData::set_render_priority(int p_priority) { + priority = p_priority - RS::MATERIAL_RENDER_PRIORITY_MIN; //8 bits +} + +void SceneShaderForwardClustered::MaterialData::set_next_pass(RID p_pass) { + next_pass = p_pass; +} + +void SceneShaderForwardClustered::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { + SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton; + + if ((uint32_t)ubo_data.size() != shader_data->ubo_size) { + p_uniform_dirty = true; + if (uniform_buffer.is_valid()) { + RD::get_singleton()->free(uniform_buffer); + uniform_buffer = RID(); + } + + ubo_data.resize(shader_data->ubo_size); + if (ubo_data.size()) { + uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); + memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear + } + + //clear previous uniform set + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->free(uniform_set); + uniform_set = RID(); + } + } + + //check whether buffer changed + if (p_uniform_dirty && ubo_data.size()) { + update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false); + RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), RD::BARRIER_MASK_RASTER); + } + + uint32_t tex_uniform_count = shader_data->texture_uniforms.size(); + + if ((uint32_t)texture_cache.size() != tex_uniform_count) { + texture_cache.resize(tex_uniform_count); + p_textures_dirty = true; + + //clear previous uniform set + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->free(uniform_set); + uniform_set = RID(); + } + } + + if (p_textures_dirty && tex_uniform_count) { + update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true); + } + + if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) { + // This material does not require an uniform set, so don't create it. + return; + } + + if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + //no reason to update uniform set, only UBO (or nothing) was needed to update + return; + } + + Vector<RD::Uniform> uniforms; + + { + if (shader_data->ubo_size) { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 0; + u.ids.push_back(uniform_buffer); + uniforms.push_back(u); + } + + const RID *textures = texture_cache.ptrw(); + for (uint32_t i = 0; i < tex_uniform_count; i++) { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1 + i; + u.ids.push_back(textures[i]); + uniforms.push_back(u); + } + } + + uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET); +} + +SceneShaderForwardClustered::MaterialData::~MaterialData() { + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->free(uniform_set); + } + + if (uniform_buffer.is_valid()) { + RD::get_singleton()->free(uniform_buffer); + } +} + +RendererStorageRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) { + MaterialData *material_data = memnew(MaterialData); + material_data->shader_data = p_shader; + material_data->last_frame = false; + //update will happen later anyway so do nothing. + return material_data; +} + +SceneShaderForwardClustered *SceneShaderForwardClustered::singleton = nullptr; + +SceneShaderForwardClustered::SceneShaderForwardClustered() { + // there should be only one of these, contained within our RenderFM singleton. + singleton = this; +} + +SceneShaderForwardClustered::~SceneShaderForwardClustered() { + RD::get_singleton()->free(default_vec4_xform_buffer); + RD::get_singleton()->free(shadow_sampler); + + storage->free(wireframe_material_shader); + storage->free(overdraw_material_shader); + storage->free(default_shader); + + storage->free(wireframe_material); + storage->free(overdraw_material); + storage->free(default_material); +} + +void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const String p_defines, bool p_is_low_end) { + storage = p_storage; + + { + Vector<String> shader_versions; + shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); + shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); + shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n"); + shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_GIPROBE\n"); + shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); + shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n"); + shader_versions.push_back(""); + shader_versions.push_back("\n#define USE_FORWARD_GI\n"); + shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n"); + shader_versions.push_back("\n#define USE_LIGHTMAP\n"); + shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n"); + shader.initialize(shader_versions, p_defines); + + if (p_is_low_end) { + //disable the high end versions + shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS, false); + shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE, false); + shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_SDF, false); + shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI, false); + shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR, false); + shader.set_variant_enabled(SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, false); + } + } + + storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs); + storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_material_funcs); + + { + //shader compiler + ShaderCompilerRD::DefaultIdentifierActions actions; + + actions.renames["WORLD_MATRIX"] = "world_matrix"; + actions.renames["WORLD_NORMAL_MATRIX"] = "world_normal_matrix"; + actions.renames["INV_CAMERA_MATRIX"] = "scene_data.inv_camera_matrix"; + actions.renames["CAMERA_MATRIX"] = "scene_data.camera_matrix"; + actions.renames["PROJECTION_MATRIX"] = "projection_matrix"; + actions.renames["INV_PROJECTION_MATRIX"] = "scene_data.inv_projection_matrix"; + actions.renames["MODELVIEW_MATRIX"] = "modelview"; + actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal"; + + actions.renames["VERTEX"] = "vertex"; + actions.renames["NORMAL"] = "normal"; + actions.renames["TANGENT"] = "tangent"; + actions.renames["BINORMAL"] = "binormal"; + actions.renames["POSITION"] = "position"; + actions.renames["UV"] = "uv_interp"; + actions.renames["UV2"] = "uv2_interp"; + actions.renames["COLOR"] = "color_interp"; + actions.renames["POINT_SIZE"] = "gl_PointSize"; + actions.renames["INSTANCE_ID"] = "gl_InstanceIndex"; + + actions.renames["ALPHA_SCISSOR_THRESHOLD"] = "alpha_scissor_threshold"; + actions.renames["ALPHA_HASH_SCALE"] = "alpha_hash_scale"; + actions.renames["ALPHA_ANTIALIASING_EDGE"] = "alpha_antialiasing_edge"; + actions.renames["ALPHA_TEXTURE_COORDINATE"] = "alpha_texture_coordinate"; + + //builtins + + actions.renames["TIME"] = "scene_data.time"; + actions.renames["VIEWPORT_SIZE"] = "scene_data.viewport_size"; + + actions.renames["FRAGCOORD"] = "gl_FragCoord"; + actions.renames["FRONT_FACING"] = "gl_FrontFacing"; + actions.renames["NORMAL_MAP"] = "normal_map"; + actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth"; + actions.renames["ALBEDO"] = "albedo"; + actions.renames["ALPHA"] = "alpha"; + actions.renames["METALLIC"] = "metallic"; + actions.renames["SPECULAR"] = "specular"; + actions.renames["ROUGHNESS"] = "roughness"; + actions.renames["RIM"] = "rim"; + actions.renames["RIM_TINT"] = "rim_tint"; + actions.renames["CLEARCOAT"] = "clearcoat"; + actions.renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss"; + actions.renames["ANISOTROPY"] = "anisotropy"; + actions.renames["ANISOTROPY_FLOW"] = "anisotropy_flow"; + actions.renames["SSS_STRENGTH"] = "sss_strength"; + actions.renames["SSS_TRANSMITTANCE_COLOR"] = "transmittance_color"; + actions.renames["SSS_TRANSMITTANCE_DEPTH"] = "transmittance_depth"; + actions.renames["SSS_TRANSMITTANCE_CURVE"] = "transmittance_curve"; + actions.renames["SSS_TRANSMITTANCE_BOOST"] = "transmittance_boost"; + actions.renames["BACKLIGHT"] = "backlight"; + actions.renames["AO"] = "ao"; + actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect"; + actions.renames["EMISSION"] = "emission"; + actions.renames["POINT_COORD"] = "gl_PointCoord"; + actions.renames["INSTANCE_CUSTOM"] = "instance_custom"; + actions.renames["SCREEN_UV"] = "screen_uv"; + actions.renames["SCREEN_TEXTURE"] = "color_buffer"; + actions.renames["DEPTH_TEXTURE"] = "depth_buffer"; + 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["RADIANCE"] = "custom_radiance"; + actions.renames["IRRADIANCE"] = "custom_irradiance"; + actions.renames["BONE_INDICES"] = "bone_attrib"; + actions.renames["BONE_WEIGHTS"] = "weight_attrib"; + actions.renames["CUSTOM0"] = "custom0_attrib"; + actions.renames["CUSTOM1"] = "custom1_attrib"; + actions.renames["CUSTOM2"] = "custom2_attrib"; + actions.renames["CUSTOM3"] = "custom3_attrib"; + + //for light + actions.renames["VIEW"] = "view"; + actions.renames["LIGHT_COLOR"] = "light_color"; + actions.renames["LIGHT"] = "light"; + actions.renames["ATTENUATION"] = "attenuation"; + actions.renames["SHADOW_ATTENUATION"] = "shadow_attenuation"; + actions.renames["DIFFUSE_LIGHT"] = "diffuse_light"; + actions.renames["SPECULAR_LIGHT"] = "specular_light"; + + actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n"; + actions.usage_defines["TANGENT"] = "#define TANGENT_USED\n"; + actions.usage_defines["BINORMAL"] = "@TANGENT"; + actions.usage_defines["RIM"] = "#define LIGHT_RIM_USED\n"; + actions.usage_defines["RIM_TINT"] = "@RIM"; + actions.usage_defines["CLEARCOAT"] = "#define LIGHT_CLEARCOAT_USED\n"; + actions.usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT"; + actions.usage_defines["ANISOTROPY"] = "#define LIGHT_ANISOTROPY_USED\n"; + actions.usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY"; + actions.usage_defines["AO"] = "#define AO_USED\n"; + actions.usage_defines["AO_LIGHT_AFFECT"] = "#define AO_USED\n"; + actions.usage_defines["UV"] = "#define UV_USED\n"; + actions.usage_defines["UV2"] = "#define UV2_USED\n"; + actions.usage_defines["BONE_INDICES"] = "#define BONES_USED\n"; + actions.usage_defines["BONE_WEIGHTS"] = "#define WEIGHTS_USED\n"; + actions.usage_defines["CUSTOM0"] = "#define CUSTOM0\n"; + actions.usage_defines["CUSTOM1"] = "#define CUSTOM1\n"; + actions.usage_defines["CUSTOM2"] = "#define CUSTOM2\n"; + actions.usage_defines["CUSTOM3"] = "#define CUSTOM3\n"; + actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n"; + actions.usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP"; + actions.usage_defines["COLOR"] = "#define COLOR_USED\n"; + actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; + actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n"; + + actions.usage_defines["ALPHA_SCISSOR_THRESHOLD"] = "#define ALPHA_SCISSOR_USED\n"; + actions.usage_defines["ALPHA_HASH_SCALE"] = "#define ALPHA_HASH_USED\n"; + actions.usage_defines["ALPHA_ANTIALIASING_EDGE"] = "#define ALPHA_ANTIALIASING_EDGE_USED\n"; + actions.usage_defines["ALPHA_TEXTURE_COORDINATE"] = "@ALPHA_ANTIALIASING_EDGE"; + + actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; + actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n"; + actions.usage_defines["BACKLIGHT"] = "#define LIGHT_BACKLIGHT_USED\n"; + actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; + actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; + + actions.usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; + actions.usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; + + actions.usage_defines["FOG"] = "#define CUSTOM_FOG_USED\n"; + actions.usage_defines["RADIANCE"] = "#define CUSTOM_RADIANCE_USED\n"; + actions.usage_defines["IRRADIANCE"] = "#define CUSTOM_IRRADIANCE_USED\n"; + + actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; + actions.render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; + actions.render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n"; + actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n"; + actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n"; + + bool force_lambert = GLOBAL_GET("rendering/shading/overrides/force_lambert_over_burley"); + + if (!force_lambert) { + actions.render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n"; + } + + actions.render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n"; + actions.render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n"; + actions.render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n"; + + actions.render_mode_defines["sss_mode_skin"] = "#define SSS_MODE_SKIN\n"; + + bool force_blinn = GLOBAL_GET("rendering/shading/overrides/force_blinn_over_ggx"); + + if (!force_blinn) { + actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; + } else { + actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n"; + } + + actions.render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n"; + actions.render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n"; + actions.render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; + actions.render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; + actions.render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; + actions.render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n"; + actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; + actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; + + actions.sampler_array_name = "material_samplers"; + actions.base_texture_binding_index = 1; + actions.texture_layout_set = RenderForwardClustered::MATERIAL_UNIFORM_SET; + actions.base_uniform_string = "material."; + actions.base_varying_index = 10; + + actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; + actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; + actions.global_buffer_array_variable = "global_variables.data"; + actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs"; + + compiler.initialize(actions); + } + + { + //default material and shader + default_shader = storage->shader_allocate(); + storage->shader_initialize(default_shader); + storage->shader_set_code(default_shader, "shader_type spatial; void vertex() { ROUGHNESS = 0.8; } void fragment() { ALBEDO=vec3(0.6); ROUGHNESS=0.8; METALLIC=0.2; } \n"); + default_material = storage->material_allocate(); + storage->material_initialize(default_material); + storage->material_set_shader(default_material, default_shader); + + MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D); + default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); + if (!p_is_low_end) { + default_shader_sdfgi_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF); + } + } + + { + overdraw_material_shader = storage->shader_allocate(); + storage->shader_initialize(overdraw_material_shader); + storage->shader_set_code(overdraw_material_shader, "shader_type spatial;\nrender_mode blend_add,unshaded;\n void fragment() { ALBEDO=vec3(0.4,0.8,0.8); ALPHA=0.2; }"); + overdraw_material = storage->material_allocate(); + storage->material_initialize(overdraw_material); + storage->material_set_shader(overdraw_material, overdraw_material_shader); + + wireframe_material_shader = storage->shader_allocate(); + storage->shader_initialize(wireframe_material_shader); + storage->shader_set_code(wireframe_material_shader, "shader_type spatial;\nrender_mode wireframe,unshaded;\n void fragment() { ALBEDO=vec3(0.0,0.0,0.0); }"); + wireframe_material = storage->material_allocate(); + storage->material_initialize(wireframe_material); + storage->material_set_shader(wireframe_material, wireframe_material_shader); + } + + { + default_vec4_xform_buffer = RD::get_singleton()->storage_buffer_create(256); + Vector<RD::Uniform> uniforms; + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.ids.push_back(default_vec4_xform_buffer); + u.binding = 0; + uniforms.push_back(u); + + default_vec4_xform_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RenderForwardClustered::TRANSFORMS_UNIFORM_SET); + } + { + RD::SamplerState sampler; + sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR; + sampler.min_filter = RD::SAMPLER_FILTER_LINEAR; + sampler.enable_compare = true; + sampler.compare_op = RD::COMPARE_OP_LESS; + shadow_sampler = RD::get_singleton()->sampler_create(sampler); + } +} 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 new file mode 100644 index 0000000000..368340e258 --- /dev/null +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -0,0 +1,210 @@ +/*************************************************************************/ +/* scene_shader_forward_clustered.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 RSSR_SCENE_SHADER_FC_H +#define RSSR_SCENE_SHADER_FC_H + +#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" +#include "servers/rendering/renderer_rd/renderer_storage_rd.h" +#include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h" + +namespace RendererSceneRenderImplementation { + +class SceneShaderForwardClustered { +private: + static SceneShaderForwardClustered *singleton; + +public: + RendererStorageRD *storage; + + enum ShaderVersion { + SHADER_VERSION_DEPTH_PASS, + SHADER_VERSION_DEPTH_PASS_DP, + SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS, + SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE, + SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL, + SHADER_VERSION_DEPTH_PASS_WITH_SDF, + SHADER_VERSION_COLOR_PASS, + SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI, + SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR, + SHADER_VERSION_LIGHTMAP_COLOR_PASS, + SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, + SHADER_VERSION_MAX + }; + + struct ShaderData : public RendererStorageRD::ShaderData { + enum BlendMode { //used internally + BLEND_MODE_MIX, + BLEND_MODE_ADD, + BLEND_MODE_SUB, + BLEND_MODE_MUL, + BLEND_MODE_ALPHA_TO_COVERAGE + }; + + enum DepthDraw { + DEPTH_DRAW_DISABLED, + DEPTH_DRAW_OPAQUE, + DEPTH_DRAW_ALWAYS + }; + + enum DepthTest { + DEPTH_TEST_DISABLED, + DEPTH_TEST_ENABLED + }; + + enum Cull { + CULL_DISABLED, + CULL_FRONT, + CULL_BACK + }; + + enum CullVariant { + CULL_VARIANT_NORMAL, + CULL_VARIANT_REVERSED, + CULL_VARIANT_DOUBLE_SIDED, + CULL_VARIANT_MAX + + }; + + enum AlphaAntiAliasing { + ALPHA_ANTIALIASING_OFF, + ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE, + ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE + }; + + bool valid; + RID version; + uint32_t vertex_input_mask; + PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX]; + + String path; + + Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms; + + Vector<uint32_t> ubo_offsets; + uint32_t ubo_size; + + String code; + Map<StringName, RID> default_texture_params; + + DepthDraw depth_draw; + DepthTest depth_test; + + bool uses_point_size; + bool uses_alpha; + bool uses_blend_alpha; + bool uses_alpha_clip; + bool uses_depth_pre_pass; + bool uses_discard; + bool uses_roughness; + bool uses_normal; + + bool unshaded; + bool uses_vertex; + bool uses_sss; + bool uses_transmittance; + bool uses_screen_texture; + bool uses_depth_texture; + bool uses_normal_texture; + bool uses_time; + bool writes_modelview_or_projection; + bool uses_world_coordinates; + + uint64_t last_pass = 0; + uint32_t index = 0; + + virtual void set_code(const String &p_Code); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture); + virtual void get_param_list(List<PropertyInfo> *p_param_list) const; + void get_instance_param_list(List<RendererStorage::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; + + ShaderData(); + virtual ~ShaderData(); + }; + + RendererStorageRD::ShaderData *_create_shader_func(); + static RendererStorageRD::ShaderData *_create_shader_funcs() { + return static_cast<SceneShaderForwardClustered *>(singleton)->_create_shader_func(); + } + + struct MaterialData : public RendererStorageRD::MaterialData { + uint64_t last_frame; + ShaderData *shader_data; + RID uniform_buffer; + RID uniform_set; + Vector<RID> texture_cache; + Vector<uint8_t> ubo_data; + uint64_t last_pass = 0; + uint32_t index = 0; + RID next_pass; + uint8_t priority; + virtual void set_render_priority(int p_priority); + virtual void set_next_pass(RID p_pass); + virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual ~MaterialData(); + }; + + RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); + static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) { + return static_cast<SceneShaderForwardClustered *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); + } + + SceneForwardClusteredShaderRD shader; + ShaderCompilerRD compiler; + + RID default_shader; + RID default_material; + RID overdraw_material_shader; + RID overdraw_material; + RID wireframe_material_shader; + RID wireframe_material; + RID default_shader_rd; + RID default_shader_sdfgi_rd; + + RID default_vec4_xform_buffer; + RID default_vec4_xform_uniform_set; + + RID shadow_sampler; + + SceneShaderForwardClustered(); + ~SceneShaderForwardClustered(); + + void init(RendererStorageRD *p_storage, const String p_defines, bool p_is_low_end); +}; + +} // namespace RendererSceneRenderImplementation +#endif // !RSSR_SCENE_SHADER_FM_H diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index d5ac05d1d1..2247b841c9 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -175,5 +175,5 @@ RendererCompositorRD::RendererCompositorRD() { storage = memnew(RendererStorageRD); canvas = memnew(RendererCanvasRenderRD(storage)); - scene = memnew(RendererSceneRenderForwardClustered(storage)); + scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered(storage)); } diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index 67a843452b..5b5f3ad0cb 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -34,8 +34,8 @@ #include "core/os/os.h" #include "core/templates/thread_work_pool.h" #include "servers/rendering/renderer_compositor.h" +#include "servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h" #include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h" -#include "servers/rendering/renderer_rd/renderer_scene_render_forward_clustered.h" #include "servers/rendering/renderer_rd/renderer_storage_rd.h" class RendererCompositorRD : public RendererCompositor { diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp index 4e4e553605..3856f38457 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp @@ -2992,6 +2992,7 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p } } default_giprobe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GIProbeData) * MAX_GIPROBES); + half_resolution = GLOBAL_GET("rendering/global_illumination/gi/use_half_resolution"); } void RendererSceneGIRD::free() { @@ -3097,10 +3098,10 @@ void RendererSceneGIRD::setup_giprobes(RID p_render_buffers, const Transform &p_ } if (giprobes_changed) { - if (RD::get_singleton()->uniform_set_is_valid(rb->gi_uniform_set)) { - RD::get_singleton()->free(rb->gi_uniform_set); + if (RD::get_singleton()->uniform_set_is_valid(rb->gi.uniform_set)) { + RD::get_singleton()->free(rb->gi.uniform_set); } - rb->gi_uniform_set = RID(); + rb->gi.uniform_set = RID(); if (rb->volumetric_fog) { if (RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set)) { RD::get_singleton()->free(rb->volumetric_fog->uniform_set); @@ -3125,7 +3126,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ ERR_FAIL_COND(rb == nullptr); RendererSceneEnvironmentRD *env = p_scene_render->environment_owner.getornull(p_environment); - if (rb->ambient_buffer.is_null() || rb->using_half_size_gi != half_resolution) { + if (rb->ambient_buffer.is_null() || rb->gi.using_half_size_gi != half_resolution) { if (rb->ambient_buffer.is_valid()) { RD::get_singleton()->free(rb->ambient_buffer); RD::get_singleton()->free(rb->reflection_buffer); @@ -3142,7 +3143,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; rb->reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); rb->ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); - rb->using_half_size_gi = half_resolution; + rb->gi.using_half_size_gi = half_resolution; p_scene_render->_render_buffers_uniform_set_changed(p_render_buffers); } @@ -3187,7 +3188,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ push_constant.cam_rotation[10] = p_transform.basis[2][2]; push_constant.cam_rotation[11] = 0; - if (rb->gi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->gi_uniform_set)) { + if (rb->gi.uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->gi.uniform_set)) { Vector<RD::Uniform> uniforms; { RD::Uniform u; @@ -3340,22 +3341,22 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ uniforms.push_back(u); } - rb->gi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0); + rb->gi.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0); } Mode mode; - if (rb->using_half_size_gi) { + if (rb->gi.using_half_size_gi) { mode = (use_sdfgi && use_giprobes) ? MODE_HALF_RES_COMBINED : (use_sdfgi ? MODE_HALF_RES_SDFGI : MODE_HALF_RES_GIPROBE); } else { mode = (use_sdfgi && use_giprobes) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_GIPROBE); } RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[mode]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->gi_uniform_set, 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->gi.uniform_set, 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); - if (rb->using_half_size_gi) { + if (rb->gi.using_half_size_gi) { RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width >> 1, rb->height >> 1, 1); } else { RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width, rb->height, 1); diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h index c0f3318538..df20011b23 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h @@ -561,6 +561,9 @@ public: RID full_buffer; RID full_dispatch; RID full_mask; + + RID uniform_set; + bool using_half_size_gi = false; }; struct SDFGIData { diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 4cf296f0db..4c5bded2ff 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -522,9 +522,13 @@ RID RendererSceneRenderRD::reflection_atlas_create() { ra.count = GLOBAL_GET("rendering/reflections/reflection_atlas/reflection_count"); ra.size = GLOBAL_GET("rendering/reflections/reflection_atlas/reflection_size"); - ra.cluster_builder = memnew(ClusterBuilderRD); - ra.cluster_builder->set_shared(&cluster_builder_shared); - ra.cluster_builder->setup(Size2i(ra.size, ra.size), max_cluster_elements, RID(), RID(), RID()); + if (is_clustered_enabled()) { + ra.cluster_builder = memnew(ClusterBuilderRD); + ra.cluster_builder->set_shared(&cluster_builder_shared); + ra.cluster_builder->setup(Size2i(ra.size, ra.size), max_cluster_elements, RID(), RID(), RID()); + } else { + ra.cluster_builder = nullptr; + } return reflection_atlas_owner.make_rid(ra); } @@ -537,7 +541,10 @@ void RendererSceneRenderRD::reflection_atlas_set_size(RID p_ref_atlas, int p_ref return; //no changes } - ra->cluster_builder->setup(Size2i(ra->size, ra->size), max_cluster_elements, RID(), RID(), RID()); + if (ra->cluster_builder) { + // only if we're using our cluster + ra->cluster_builder->setup(Size2i(ra->size, ra->size), max_cluster_elements, RID(), RID(), RID()); + } ra->size = p_reflection_size; ra->count = p_reflection_count; @@ -2124,10 +2131,13 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p rb->msaa = p_msaa; rb->screen_space_aa = p_screen_space_aa; rb->use_debanding = p_use_debanding; - if (rb->cluster_builder == nullptr) { - rb->cluster_builder = memnew(ClusterBuilderRD); + + if (is_clustered_enabled()) { + if (rb->cluster_builder == nullptr) { + rb->cluster_builder = memnew(ClusterBuilderRD); + } + rb->cluster_builder->set_shared(&cluster_builder_shared); } - rb->cluster_builder->set_shared(&cluster_builder_shared); _free_render_buffer_data(rb); @@ -2170,7 +2180,9 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p rb->data->configure(rb->texture, rb->depth_texture, p_width, p_height, p_msaa); _render_buffers_uniform_set_changed(p_render_buffers); - rb->cluster_builder->setup(Size2i(p_width, p_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture); + if (is_clustered_enabled()) { + rb->cluster_builder->setup(Size2i(p_width, p_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture); + } } void RendererSceneRenderRD::gi_set_use_half_resolution(bool p_enable) { @@ -2943,6 +2955,7 @@ void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) { } void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_gi_probe_count) { + ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(!rb); RendererSceneEnvironmentRD *env = environment_owner.getornull(p_environment); @@ -3505,7 +3518,9 @@ void RendererSceneRenderRD::_pre_opaque_render(bool p_use_ssao, bool p_use_gi, R break; } } - _update_volumetric_fog(render_state.render_buffers, render_state.environment, render_state.cam_projection, render_state.cam_transform, render_state.shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.gi_probe_count); + if (is_volumetric_supported()) { + _update_volumetric_fog(render_state.render_buffers, render_state.environment, render_state.cam_projection, render_state.cam_transform, render_state.shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.gi_probe_count); + } } } @@ -3578,8 +3593,8 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform & } if (render_buffers_owner.owns(render_state.render_buffers)) { - RenderBuffers *rs_rb = render_buffers_owner.getornull(render_state.render_buffers); - current_cluster_builder = rs_rb->cluster_builder; + // render_state.render_buffers == p_render_buffers so we can use our already retrieved rb + current_cluster_builder = rb->cluster_builder; } else if (reflection_probe_instance_owner.owns(render_state.reflection_probe)) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(render_state.reflection_probe); ReflectionAtlas *ra = reflection_atlas_owner.getornull(rpi->atlas); @@ -3590,7 +3605,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform & current_cluster_builder = ra->cluster_builder; } } else { - ERR_PRINT("No cluster builder, bug"); //should never happen, will crash + ERR_PRINT("No render buffer nor reflection atlas, bug"); //should never happen, will crash current_cluster_builder = nullptr; } @@ -4077,7 +4092,23 @@ int RendererSceneRenderRD::get_max_directional_lights() const { } bool RendererSceneRenderRD::is_low_end() const { - return low_end; + // by default we switch this on this (may be ignored in some implementations) + return GLOBAL_GET("rendering/driver/rd_renderer/use_low_end_renderer"); +} + +bool RendererSceneRenderRD::is_dynamic_gi_supported() const { + // usable by default (unless low end = true) + return true; +} + +bool RendererSceneRenderRD::is_clustered_enabled() const { + // used by default. + return true; +} + +bool RendererSceneRenderRD::is_volumetric_supported() const { + // usable by default (unless low end = true) + return true; } RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) { @@ -4091,7 +4122,7 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) { uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); - low_end = GLOBAL_GET("rendering/driver/rd_renderer/use_low_end_renderer"); + low_end = is_low_end(); if (textures_per_stage < 48) { low_end = true; @@ -4103,7 +4134,7 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) { /* GI */ - if (!low_end) { + if (!low_end && is_dynamic_gi_supported()) { gi.init(storage, &sky); } @@ -4141,7 +4172,7 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) { cluster.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size); } - if (!low_end) { + if (!low_end && is_volumetric_supported()) { String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(cluster.max_directional_lights) + "\n"; Vector<String> volumetric_fog_modes; volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n"); @@ -4188,8 +4219,6 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) { environment_set_volumetric_fog_filter_active(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter")); cull_argument.set_page_pool(&cull_argument_pool); - - gi.half_resolution = GLOBAL_GET("rendering/global_illumination/gi/use_half_resolution"); } RendererSceneRenderRD::~RendererSceneRenderRD() { diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 001cfeb74d..264c0e4276 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -51,6 +51,7 @@ protected: RendererStorageRD *storage; double time; double time_step = 0; + bool low_end = false; // If true GI and Volumetric fog are disabled struct RenderBufferData { virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) = 0; @@ -383,9 +384,9 @@ private: RID texture; //main texture for rendering to, must be filled after done rendering RID depth_texture; //main depth texture - RID gi_uniform_set; RendererSceneGIRD::SDFGI *sdfgi = nullptr; VolumetricFog *volumetric_fog = nullptr; + RendererSceneGIRD::RenderBuffersGI gi; ClusterBuilderRD *cluster_builder = nullptr; @@ -428,9 +429,6 @@ private: RID ambient_buffer; RID reflection_buffer; - bool using_half_size_gi = false; - - RendererSceneGIRD::RenderBuffersGI gi; }; /* GI */ @@ -719,7 +717,6 @@ private: */ uint32_t max_cluster_elements = 512; - bool low_end = false; 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_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true); @@ -1193,7 +1190,11 @@ public: void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir); - bool is_low_end() const; + virtual bool is_low_end() const; + + virtual bool is_dynamic_gi_supported() const; + virtual bool is_clustered_enabled() const; + virtual bool is_volumetric_supported() const; RendererSceneRenderRD(RendererStorageRD *p_storage); ~RendererSceneRenderRD(); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index ba5ace8f31..b984f850a0 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -4692,10 +4692,11 @@ void RendererStorageRD::update_particles() { if (particles->clear && particles->pre_process_time > 0.0) { float frame_time; - if (particles->fixed_fps > 0) + if (particles->fixed_fps > 0) { frame_time = 1.0 / particles->fixed_fps; - else + } else { frame_time = 1.0 / 30.0; + } float todo = particles->pre_process_time; @@ -4731,10 +4732,11 @@ void RendererStorageRD::update_particles() { particles->frame_remainder = todo; } else { - if (zero_time_scale) + if (zero_time_scale) { _particles_process(particles, 0.0); - else + } else { _particles_process(particles, RendererCompositorRD::singleton->get_frame_delta_time()); + } } //copy particles to instance buffer diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index cd3d4604eb..6405bb75b0 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -691,21 +691,21 @@ private: }; struct Particles { - bool inactive; - float inactive_time; - bool emitting; - bool one_shot; - int amount; - float lifetime; - float pre_process_time; - float explosiveness; - float randomness; - bool restart_request; - AABB custom_aabb; - bool use_local_coords; + bool inactive = true; + float inactive_time = 0.0; + bool emitting = false; + bool one_shot = false; + int amount = 0; + float lifetime = 1.0; + float pre_process_time = 0.0; + float explosiveness = 0.0; + float randomness = 0.0; + bool restart_request = false; + AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8)); + bool use_local_coords = true; RID process_material; - RS::ParticlesDrawOrder draw_order; + RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX; Vector<RID> draw_passes; @@ -730,21 +730,21 @@ private: RID sub_emitter; - float phase; - float prev_phase; - uint64_t prev_ticks; - uint32_t random_seed; + float phase = 0.0; + float prev_phase = 0.0; + uint64_t prev_ticks = 0; + uint32_t random_seed = 0; - uint32_t cycle_number; + uint32_t cycle_number = 0; - float speed_scale; + float speed_scale = 1.0; - int fixed_fps; - bool fractional_delta; - float frame_remainder; - float collision_base_size; + int fixed_fps = 0; + bool fractional_delta = false; + float frame_remainder = 0; + float collision_base_size = 0.01; - bool clear; + bool clear = true; bool force_sub_emit = false; @@ -757,31 +757,6 @@ private: Set<RID> collisions; - Particles() : - inactive(true), - inactive_time(0.0), - emitting(false), - one_shot(false), - amount(0), - lifetime(1.0), - pre_process_time(0.0), - explosiveness(0.0), - randomness(0.0), - restart_request(false), - custom_aabb(AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8))), - use_local_coords(true), - draw_order(RS::PARTICLES_DRAW_ORDER_INDEX), - prev_ticks(0), - random_seed(0), - cycle_number(0), - speed_scale(1.0), - fixed_fps(0), - fractional_delta(false), - frame_remainder(0), - collision_base_size(0.01), - clear(true) { - } - Dependency dependency; ParticlesFrameParams frame_params; diff --git a/servers/rendering/renderer_rd/shaders/cluster_render.glsl b/servers/rendering/renderer_rd/shaders/cluster_render.glsl index 8723ea78e4..ca92d2104e 100644 --- a/servers/rendering/renderer_rd/shaders/cluster_render.glsl +++ b/servers/rendering/renderer_rd/shaders/cluster_render.glsl @@ -65,7 +65,7 @@ void main() { VERSION_DEFINES -#if defined(GL_KHR_shader_subgroup_ballot) && defined(GL_KHR_shader_subgroup_arithmetic) && defined(GL_KHR_shader_subgroup_vote) +#if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic) && defined(has_GL_KHR_shader_subgroup_vote) #extension GL_KHR_shader_subgroup_ballot : enable #extension GL_KHR_shader_subgroup_arithmetic : enable 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 d78890fa9e..4ea05c9ccc 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl @@ -3,7 +3,7 @@ #define MAX_GI_PROBES 8 -#if defined(GL_KHR_shader_subgroup_ballot) && defined(GL_KHR_shader_subgroup_arithmetic) +#if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic) #extension GL_KHR_shader_subgroup_ballot : enable #extension GL_KHR_shader_subgroup_arithmetic : enable diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl index e7ba8feb80..ce8a459b24 100644 --- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl +++ b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl @@ -5,10 +5,10 @@ VERSION_DEFINES /* Do not use subgroups here, seems there is not much advantage and causes glitches +#if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic) #extension GL_KHR_shader_subgroup_ballot: enable #extension GL_KHR_shader_subgroup_arithmetic: enable -#if defined(GL_KHR_shader_subgroup_ballot) && defined(GL_KHR_shader_subgroup_arithmetic) #define USE_SUBGROUPS #endif */ diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 27a9353e4e..e6ad001807 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -59,7 +59,7 @@ Vector<uint8_t> RenderingDevice::shader_compile_from_source(ShaderStage p_stage, ERR_FAIL_COND_V(!compile_function, Vector<uint8_t>()); - return compile_function(p_stage, p_source_code, p_language, r_error); + return compile_function(p_stage, p_source_code, p_language, r_error, &device_capabilities); } RID RenderingDevice::_texture_create(const Ref<RDTextureFormat> &p_format, const Ref<RDTextureView> &p_view, const TypedArray<PackedByteArray> &p_data) { diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 9fbf58d131..2de0549e8d 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -51,6 +51,13 @@ class RDPipelineColorBlendState; class RenderingDevice : public Object { GDCLASS(RenderingDevice, Object) public: + enum DeviceFamily { + DEVICE_UNKNOWN, + DEVICE_OPENGL, + DEVICE_VULKAN, + DEVICE_DIRECTX + }; + enum ShaderStage { SHADER_STAGE_VERTEX, SHADER_STAGE_FRAGMENT, @@ -70,7 +77,29 @@ public: SHADER_LANGUAGE_HLSL }; - typedef Vector<uint8_t> (*ShaderCompileFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error); + enum SubgroupOperations { + SUBGROUP_BASIC_BIT = 1, + SUBGROUP_VOTE_BIT = 2, + SUBGROUP_ARITHMETIC_BIT = 4, + SUBGROUP_BALLOT_BIT = 8, + SUBGROUP_SHUFFLE_BIT = 16, + SUBGROUP_SHUFFLE_RELATIVE_BIT = 32, + SUBGROUP_CLUSTERED_BIT = 64, + SUBGROUP_QUAD_BIT = 128, + }; + + struct Capabilities { + // main device info + 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 + }; + + typedef Vector<uint8_t> (*ShaderCompileFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const Capabilities *p_capabilities); typedef Vector<uint8_t> (*ShaderCacheFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language); private: @@ -82,6 +111,8 @@ private: protected: static void _bind_methods(); + Capabilities device_capabilities; + public: //base numeric ID for all types enum { @@ -597,6 +628,8 @@ public: /**** SHADER ****/ /****************/ + const Capabilities *get_device_capabilities() const { return &device_capabilities; }; + virtual Vector<uint8_t> shader_compile_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); static void shader_set_compile_function(ShaderCompileFunction p_function); diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index df1a7d58d0..4ae0eda232 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -6825,7 +6825,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else { _set_tkpos(pos2); - Node *n = _parse_and_reduce_expression(NULL, FunctionInfo()); + Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo()); if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) { _set_error("Expected single integer constant > 0"); return ERR_PARSE_ERROR; @@ -6906,7 +6906,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization while (true) { - Node *n = _parse_and_reduce_expression(NULL, FunctionInfo()); + Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo()); if (!n) { return ERR_PARSE_ERROR; } @@ -6932,10 +6932,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct decl.initializer.push_back(n); break; } else { - if (curly) + if (curly) { _set_error("Expected '}' or ','"); - else + } else { _set_error("Expected ')' or ','"); + } return ERR_PARSE_ERROR; } } @@ -6961,9 +6962,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct constant.initializer = static_cast<ConstantNode *>(expr); } else { //variable created with assignment! must parse an expression - Node *expr = _parse_and_reduce_expression(NULL, FunctionInfo()); - if (!expr) + Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo()); + if (!expr) { return ERR_PARSE_ERROR; + } if (expr->type == Node::TYPE_OPERATOR && ((OperatorNode *)expr)->op == OP_CALL) { _set_error("Expected constant expression after '='"); return ERR_PARSE_ERROR; diff --git a/servers/text_server.cpp b/servers/text_server.cpp index d6d3c11cfb..8b03565291 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -291,6 +291,8 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_hex_code_box_size", "size", "index"), &TextServer::get_hex_code_box_size); ClassDB::bind_method(D_METHOD("draw_hex_code_box", "canvas", "size", "pos", "index", "color"), &TextServer::draw_hex_code_box); + ClassDB::bind_method(D_METHOD("font_get_glyph_contours", "font", "size", "index"), &TextServer::_font_get_glyph_contours); + /* Shaped text buffer interface */ ClassDB::bind_method(D_METHOD("create_shaped_text", "direction", "orientation"), &TextServer::create_shaped_text, DEFVAL(DIRECTION_AUTO), DEFVAL(ORIENTATION_HORIZONTAL)); @@ -403,6 +405,11 @@ void TextServer::_bind_methods() { BIND_ENUM_CONSTANT(FEATURE_FONT_SYSTEM); BIND_ENUM_CONSTANT(FEATURE_FONT_VARIABLE); BIND_ENUM_CONSTANT(FEATURE_USE_SUPPORT_DATA); + + /* FT Contour Point Types */ + BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_ON); + BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_OFF_CONIC); + BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_OFF_CUBIC); } Vector3 TextServer::hex_code_box_font_size[2] = { Vector3(5, 5, 1), Vector3(10, 10, 2) }; @@ -1212,6 +1219,21 @@ RID TextServer::_create_font_memory(const PackedByteArray &p_data, const String return create_font_memory(p_data.ptr(), p_data.size(), p_type, p_base_size); } +Dictionary TextServer::_font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index) const { + Vector<Vector3> points; + Vector<int32_t> contours; + bool orientation; + bool ok = font_get_glyph_contours(p_font, p_size, p_index, points, contours, orientation); + Dictionary out; + + if (ok) { + out["points"] = points; + out["contours"] = contours; + out["orientation"] = orientation; + } + return out; +} + void TextServer::_shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) { Vector<Vector2i> overrides; for (int i = 0; i < p_override.size(); i++) { diff --git a/servers/text_server.h b/servers/text_server.h index e1429da1d1..7fcfb91151 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -99,6 +99,12 @@ public: FEATURE_USE_SUPPORT_DATA = 1 << 7 }; + enum ContourPointTag { + CONTOUR_CURVE_TAG_ON = 0x01, + CONTOUR_CURVE_TAG_OFF_CONIC = 0x00, + CONTOUR_CURVE_TAG_OFF_CUBIC = 0x02 + }; + struct Glyph { int start = -1; // Start offset in the source string. int end = -1; // End offset in the source string. @@ -286,6 +292,8 @@ public: virtual Vector2 font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0; virtual Vector2 font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0; + virtual bool font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const = 0; + virtual float font_get_oversampling() const = 0; virtual void font_set_oversampling(float p_oversampling) = 0; @@ -372,6 +380,8 @@ public: /* GDScript wrappers */ RID _create_font_memory(const PackedByteArray &p_data, const String &p_type, int p_base_size = 16); + Dictionary _font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index) const; + Array _shaped_text_get_glyphs(RID p_shaped) const; Dictionary _shaped_text_get_carets(RID p_shaped, int p_position) const; @@ -454,5 +464,6 @@ VARIANT_ENUM_CAST(TextServer::LineBreakFlag); VARIANT_ENUM_CAST(TextServer::GraphemeFlag); VARIANT_ENUM_CAST(TextServer::Hinting); VARIANT_ENUM_CAST(TextServer::Feature); +VARIANT_ENUM_CAST(TextServer::ContourPointTag); #endif // TEXT_SERVER_H diff --git a/servers/xr/xr_positional_tracker.h b/servers/xr/xr_positional_tracker.h index 420d818342..a5c6459471 100644 --- a/servers/xr/xr_positional_tracker.h +++ b/servers/xr/xr_positional_tracker.h @@ -43,8 +43,8 @@ This is where potentially additional AR/VR interfaces may be active as there are AR/VR SDKs that solely deal with positional tracking. */ -class XRPositionalTracker : public Object { - GDCLASS(XRPositionalTracker, Object); +class XRPositionalTracker : public Reference { + GDCLASS(XRPositionalTracker, Reference); _THREAD_SAFE_CLASS_ public: diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp index 2acc2e398c..5678071857 100644 --- a/servers/xr_server.cpp +++ b/servers/xr_server.cpp @@ -48,12 +48,17 @@ void XRServer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "world_scale"), "set_world_scale", "get_world_scale"); + ClassDB::bind_method(D_METHOD("add_interface", "interface"), &XRServer::add_interface); + ClassDB::bind_method(D_METHOD("clear_primary_interface_if", "interface"), &XRServer::clear_primary_interface_if); ClassDB::bind_method(D_METHOD("get_interface_count"), &XRServer::get_interface_count); + ClassDB::bind_method(D_METHOD("remove_interface", "interface"), &XRServer::remove_interface); ClassDB::bind_method(D_METHOD("get_interface", "idx"), &XRServer::get_interface); ClassDB::bind_method(D_METHOD("get_interfaces"), &XRServer::get_interfaces); ClassDB::bind_method(D_METHOD("find_interface", "name"), &XRServer::find_interface); ClassDB::bind_method(D_METHOD("get_tracker_count"), &XRServer::get_tracker_count); ClassDB::bind_method(D_METHOD("get_tracker", "idx"), &XRServer::get_tracker); + ClassDB::bind_method(D_METHOD("add_tracker", "tracker"), &XRServer::add_tracker); + ClassDB::bind_method(D_METHOD("remove_tracker", "tracker"), &XRServer::remove_tracker); ClassDB::bind_method(D_METHOD("get_primary_interface"), &XRServer::get_primary_interface); ClassDB::bind_method(D_METHOD("set_primary_interface", "interface"), &XRServer::set_primary_interface); @@ -260,15 +265,15 @@ int XRServer::get_free_tracker_id_for_type(TrackerType p_tracker_type) { return tracker_id; }; -void XRServer::add_tracker(XRPositionalTracker *p_tracker) { - ERR_FAIL_NULL(p_tracker); +void XRServer::add_tracker(Ref<XRPositionalTracker> p_tracker) { + ERR_FAIL_COND(p_tracker.is_null()); trackers.push_back(p_tracker); emit_signal("tracker_added", p_tracker->get_tracker_name(), p_tracker->get_tracker_type(), p_tracker->get_tracker_id()); }; -void XRServer::remove_tracker(XRPositionalTracker *p_tracker) { - ERR_FAIL_NULL(p_tracker); +void XRServer::remove_tracker(Ref<XRPositionalTracker> p_tracker) { + ERR_FAIL_COND(p_tracker.is_null()); int idx = -1; for (int i = 0; i < trackers.size(); i++) { @@ -288,14 +293,14 @@ int XRServer::get_tracker_count() const { return trackers.size(); }; -XRPositionalTracker *XRServer::get_tracker(int p_index) const { - ERR_FAIL_INDEX_V(p_index, trackers.size(), nullptr); +Ref<XRPositionalTracker> XRServer::get_tracker(int p_index) const { + ERR_FAIL_INDEX_V(p_index, trackers.size(), Ref<XRPositionalTracker>()); return trackers[p_index]; }; -XRPositionalTracker *XRServer::find_by_type_and_id(TrackerType p_tracker_type, int p_tracker_id) const { - ERR_FAIL_COND_V(p_tracker_id == 0, nullptr); +Ref<XRPositionalTracker> XRServer::find_by_type_and_id(TrackerType p_tracker_type, int p_tracker_id) const { + ERR_FAIL_COND_V(p_tracker_id == 0, Ref<XRPositionalTracker>()); for (int i = 0; i < trackers.size(); i++) { if (trackers[i]->get_tracker_type() == p_tracker_type && trackers[i]->get_tracker_id() == p_tracker_id) { @@ -303,7 +308,7 @@ XRPositionalTracker *XRServer::find_by_type_and_id(TrackerType p_tracker_type, i }; }; - return nullptr; + return Ref<XRPositionalTracker>(); }; Ref<XRInterface> XRServer::get_primary_interface() const { @@ -311,6 +316,7 @@ Ref<XRInterface> XRServer::get_primary_interface() const { }; void XRServer::set_primary_interface(const Ref<XRInterface> &p_primary_interface) { + ERR_FAIL_COND(p_primary_interface.is_null()); primary_interface = p_primary_interface; print_verbose("XR: Primary interface set to: " + primary_interface->get_name()); diff --git a/servers/xr_server.h b/servers/xr_server.h index d3972be838..46243d7fd0 100644 --- a/servers/xr_server.h +++ b/servers/xr_server.h @@ -77,7 +77,7 @@ public: private: Vector<Ref<XRInterface>> interfaces; - Vector<XRPositionalTracker *> trackers; + Vector<Ref<XRPositionalTracker>> trackers; Ref<XRInterface> primary_interface; /* we'll identify one interface as primary, this will be used by our viewports */ @@ -167,11 +167,11 @@ public: */ bool is_tracker_id_in_use_for_type(TrackerType p_tracker_type, int p_tracker_id) const; int get_free_tracker_id_for_type(TrackerType p_tracker_type); - void add_tracker(XRPositionalTracker *p_tracker); - void remove_tracker(XRPositionalTracker *p_tracker); + void add_tracker(Ref<XRPositionalTracker> p_tracker); + void remove_tracker(Ref<XRPositionalTracker> p_tracker); int get_tracker_count() const; - XRPositionalTracker *get_tracker(int p_index) const; - XRPositionalTracker *find_by_type_and_id(TrackerType p_tracker_type, int p_tracker_id) const; + Ref<XRPositionalTracker> get_tracker(int p_index) const; + Ref<XRPositionalTracker> find_by_type_and_id(TrackerType p_tracker_type, int p_tracker_id) const; uint64_t get_last_process_usec(); uint64_t get_last_commit_usec(); diff --git a/tests/test_dictionary.h b/tests/test_dictionary.h new file mode 100644 index 0000000000..b94cf36109 --- /dev/null +++ b/tests/test_dictionary.h @@ -0,0 +1,159 @@ +/*************************************************************************/ +/* test_dictionary.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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_DICTIONARY_H +#define TEST_DICTIONARY_H + +#include "core/templates/ordered_hash_map.h" +#include "core/templates/safe_refcount.h" +#include "core/variant/dictionary.h" +#include "core/variant/variant.h" +#include "tests/test_macros.h" + +namespace TestDictionary { + +TEST_CASE("[Dictionary] Assignment using bracket notation ([])") { + Dictionary map; + map["Hello"] = 0; + CHECK(int(map["Hello"]) == 0); + map["Hello"] = 3; + CHECK(int(map["Hello"]) == 3); + map["World!"] = 4; + CHECK(int(map["World!"]) == 4); + + // Test non-string keys, since keys can be of any Variant type. + map[12345] = -5; + CHECK(int(map[12345]) == -5); + map[false] = 128; + CHECK(int(map[false]) == 128); + map[Vector2(10, 20)] = 30; + CHECK(int(map[Vector2(10, 20)]) == 30); + map[0] = 400; + CHECK(int(map[0]) == 400); + // Check that assigning 0 doesn't overwrite the value for `false`. + CHECK(int(map[false]) == 128); +} + +TEST_CASE("[Dictionary] == and != operators") { + Dictionary map1; + Dictionary map2; + CHECK(map1 != map2); + map1[1] = 3; + map2 = map1; + CHECK(map1 == map2); +} + +TEST_CASE("[Dictionary] get_key_lists()") { + Dictionary map; + List<Variant> keys; + List<Variant> *ptr = &keys; + map.get_key_list(ptr); + CHECK(keys.is_empty()); + map[1] = 3; + map.get_key_list(ptr); + CHECK(keys.size() == 1); + CHECK(int(keys[0]) == 1); + map[2] = 4; + map.get_key_list(ptr); + CHECK(keys.size() == 3); +} + +TEST_CASE("[Dictionary] get_key_at_index()") { + Dictionary map; + map[4] = 3; + Variant val = map.get_key_at_index(0); + CHECK(int(val) == 4); + map[3] = 1; + val = map.get_key_at_index(0); + CHECK(int(val) == 4); + val = map.get_key_at_index(1); + CHECK(int(val) == 3); +} + +TEST_CASE("[Dictionary] getptr()") { + Dictionary map; + map[1] = 3; + Variant *key = map.getptr(1); + CHECK(int(*key) == 3); + key = map.getptr(2); + CHECK(key == nullptr); +} + +TEST_CASE("[Dictionary] get_valid()") { + Dictionary map; + map[1] = 3; + Variant val = map.get_valid(1); + CHECK(int(val) == 3); +} +TEST_CASE("[Dictionary] get()") { + Dictionary map; + map[1] = 3; + Variant val = map.get(1, -1); + CHECK(int(val) == 3); +} + +TEST_CASE("[Dictionary] size(), empty() and clear()") { + Dictionary map; + CHECK(map.size() == 0); + CHECK(map.is_empty()); + map[1] = 3; + CHECK(map.size() == 1); + CHECK(!map.is_empty()); + map.clear(); + CHECK(map.size() == 0); + CHECK(map.is_empty()); +} + +TEST_CASE("[Dictionary] has() and has_all()") { + Dictionary map; + CHECK(map.has(1) == false); + map[1] = 3; + CHECK(map.has(1)); + Array keys; + keys.push_back(1); + CHECK(map.has_all(keys)); + keys.push_back(2); + CHECK(map.has_all(keys) == false); +} + +TEST_CASE("[Dictionary] keys() and values()") { + Dictionary map; + Array keys = map.keys(); + Array values = map.values(); + CHECK(keys.is_empty()); + CHECK(values.is_empty()); + map[1] = 3; + keys = map.keys(); + values = map.values(); + CHECK(int(keys[0]) == 1); + CHECK(int(values[0]) == 3); +} +} // namespace TestDictionary +#endif // TEST_DICTIONARY_H diff --git a/tests/test_geometry_2d.h b/tests/test_geometry_2d.h index ea02d1114f..c9313f3625 100644 --- a/tests/test_geometry_2d.h +++ b/tests/test_geometry_2d.h @@ -113,7 +113,7 @@ TEST_CASE("[Geometry2D] Polygon clockwise") { p.push_back(Vector2(1, 5)); CHECK(Geometry2D::is_polygon_clockwise(p)); - p.invert(); + p.reverse(); CHECK_FALSE(Geometry2D::is_polygon_clockwise(p)); } diff --git a/tests/test_list.h b/tests/test_list.h index 1c70b6e961..52d5edff70 100644 --- a/tests/test_list.h +++ b/tests/test_list.h @@ -260,7 +260,7 @@ TEST_CASE("[List] Invert") { List<int>::Element *n[4]; populate_integers(list, n, 4); - list.invert(); + list.reverse(); CHECK(list.front()->get() == 3); CHECK(list.front()->next()->get() == 2); diff --git a/tests/test_main.cpp b/tests/test_main.cpp index f2a546de9b..d06d604532 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -42,6 +42,7 @@ #include "test_config_file.h" #include "test_crypto.h" #include "test_curve.h" +#include "test_dictionary.h" #include "test_expression.h" #include "test_file_access.h" #include "test_geometry_2d.h" @@ -62,6 +63,7 @@ #include "test_object.h" #include "test_ordered_hash_map.h" #include "test_paged_array.h" +#include "test_path_3d.h" #include "test_pck_packer.h" #include "test_physics_2d.h" #include "test_physics_3d.h" diff --git a/editor/import/resource_importer_csv.cpp b/tests/test_path_3d.h index f621ce7855..9961ae6e97 100644 --- a/editor/import/resource_importer_csv.cpp +++ b/tests/test_path_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* resource_importer_csv.cpp */ +/* test_path_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,49 +28,58 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "resource_importer_csv.h" +#ifndef TEST_PATH_3D_H +#define TEST_PATH_3D_H -#include "core/io/resource_saver.h" -#include "core/os/file_access.h" +#include "scene/3d/path_3d.h" +#include "scene/resources/curve.h" -String ResourceImporterCSV::get_importer_name() const { - return "csv"; -} +#include "tests/test_macros.h" -String ResourceImporterCSV::get_visible_name() const { - return "CSV"; -} +namespace TestPath3D { -void ResourceImporterCSV::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("csv"); +TEST_CASE("[Path3D] Initialization") { + SUBCASE("Path should be empty right after initialization") { + Path3D *test_path = memnew(Path3D); + CHECK(test_path->get_curve() == nullptr); + memdelete(test_path); + } } -String ResourceImporterCSV::get_save_extension() const { - return ""; //does not save a single resource -} +TEST_CASE("[Path3D] Curve setter and getter") { + SUBCASE("Curve passed to the class should remain the same") { + Path3D *test_path = memnew(Path3D); + const Ref<Curve3D> &curve = memnew(Curve3D); -String ResourceImporterCSV::get_resource_type() const { - return "TextFile"; -} + test_path->set_curve(curve); + CHECK(test_path->get_curve() == curve); + memdelete(test_path); + } + SUBCASE("Curve passed many times to the class should remain the same") { + Path3D *test_path = memnew(Path3D); + const Ref<Curve3D> &curve = memnew(Curve3D); -bool ResourceImporterCSV::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { - return true; -} + test_path->set_curve(curve); + test_path->set_curve(curve); + test_path->set_curve(curve); + CHECK(test_path->get_curve() == curve); + memdelete(test_path); + } + SUBCASE("Curve rewrite testing") { + Path3D *test_path = memnew(Path3D); + const Ref<Curve3D> &curve1 = memnew(Curve3D); + const Ref<Curve3D> &curve2 = memnew(Curve3D); -int ResourceImporterCSV::get_preset_count() const { - return 0; + test_path->set_curve(curve1); + test_path->set_curve(curve2); + CHECK_MESSAGE(test_path->get_curve() != curve1, + "After rewrite, second curve should be in class"); + CHECK_MESSAGE(test_path->get_curve() == curve2, + "After rewrite, second curve should be in class"); + memdelete(test_path); + } } -String ResourceImporterCSV::get_preset_name(int p_idx) const { - return ""; -} +} // namespace TestPath3D -void ResourceImporterCSV::get_import_options(List<ImportOption> *r_options, int p_preset) const { -} - -Error ResourceImporterCSV::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { - return OK; -} - -ResourceImporterCSV::ResourceImporterCSV() { -} +#endif // TEST_PATH_3D diff --git a/tests/test_physics_2d.cpp b/tests/test_physics_2d.cpp index 570e1897d6..047697e314 100644 --- a/tests/test_physics_2d.cpp +++ b/tests/test_physics_2d.cpp @@ -216,10 +216,10 @@ protected: if (mm.is_valid()) { Point2 p = mm->get_position(); - if (mm->get_button_mask() & BUTTON_MASK_LEFT) { + if (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { ray_to = p; _do_ray_query(); - } else if (mm->get_button_mask() & BUTTON_MASK_RIGHT) { + } else if (mm->get_button_mask() & MOUSE_BUTTON_MASK_RIGHT) { ray_from = p; _do_ray_query(); } diff --git a/tests/test_physics_3d.cpp b/tests/test_physics_3d.cpp index 74afbad9d1..bb324d8ffe 100644 --- a/tests/test_physics_3d.cpp +++ b/tests/test_physics_3d.cpp @@ -187,8 +187,10 @@ protected: RenderingServer *vs = RenderingServer::get_singleton(); PhysicsServer3D *ps = PhysicsServer3D::get_singleton(); RID trimesh_shape = ps->shape_create(PhysicsServer3D::SHAPE_CONCAVE_POLYGON); - ps->shape_set_data(trimesh_shape, p_faces); - p_faces = ps->shape_get_data(trimesh_shape); // optimized one + Dictionary trimesh_params; + trimesh_params["faces"] = p_faces; + trimesh_params["backface_collision"] = false; + ps->shape_set_data(trimesh_shape, trimesh_params); Vector<Vector3> normals; // for drawing for (int i = 0; i < p_faces.size() / 3; i++) { Plane p(p_faces[i * 3 + 0], p_faces[i * 3 + 1], p_faces[i * 3 + 2]); diff --git a/tests/test_text_server.h b/tests/test_text_server.h index b0b40447fe..3d700f8ec4 100644 --- a/tests/test_text_server.h +++ b/tests/test_text_server.h @@ -28,6 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifdef TOOLS_ENABLED + #ifndef TEST_TEXT_SERVER_H #define TEST_TEXT_SERVER_H @@ -247,3 +249,4 @@ TEST_SUITE("[[TextServer]") { }; // namespace TestTextServer #endif // TEST_TEXT_SERVER_H +#endif // TOOLS_ENABLED diff --git a/thirdparty/README.md b/thirdparty/README.md index b05f074bd6..6dca29e856 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -370,6 +370,9 @@ The only modified file is `miniupnpcstrings.h`, which was created for Godot (it is usually autogenerated by cmake). Bump the version number for miniupnpc in that file when upgrading. +Note: The following upstream patch has been applied, remove this notice on next update. +https://github.com/miniupnp/miniupnp/commit/3a08dd4b89af2e9effa22a136bac86f2f306fd79 + ## minizip diff --git a/thirdparty/miniupnpc/miniupnpc/minissdpc.c b/thirdparty/miniupnpc/miniupnpc/minissdpc.c index 0ef7e12cfb..5d3a0fd049 100644 --- a/thirdparty/miniupnpc/miniupnpc/minissdpc.c +++ b/thirdparty/miniupnpc/miniupnpc/minissdpc.c @@ -576,7 +576,17 @@ ssdpDiscoverDevices(const char * const deviceTypes[], * in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */ if(!ipv6) { DWORD ifbestidx; +#if _WIN32_WINNT >= 0x0600 // _WIN32_WINNT_VISTA + // While we don't need IPv6 support, the IPv4 only funciton is not available in UWP apps. + SOCKADDR_IN destAddr; + memset(&destAddr, 0, sizeof(destAddr)); + destAddr.sin_family = AF_INET; + destAddr.sin_addr.s_addr = inet_addr("223.255.255.255"); + destAddr.sin_port = 0; + if (GetBestInterfaceEx((struct sockaddr *)&destAddr, &ifbestidx) == NO_ERROR) { +#else if (GetBestInterface(inet_addr("223.255.255.255"), &ifbestidx) == NO_ERROR) { +#endif DWORD dwRetVal = NO_ERROR; PIP_ADAPTER_ADDRESSES pAddresses = NULL; ULONG outBufLen = 15360; |