diff options
61 files changed, 853 insertions, 242 deletions
diff --git a/.github/workflows/android_builds.yml b/.github/workflows/android_builds.yml index 74f8fa8eae..dd3622f1f0 100644 --- a/.github/workflows/android_builds.yml +++ b/.github/workflows/android_builds.yml @@ -25,10 +25,10 @@ jobs: sudo cp -f misc/ci/sources.list /etc/apt/sources.list sudo apt-get update - - name: Set up Java 8 + - name: Set up Java 11 uses: actions/setup-java@v1 with: - java-version: 8 + java-version: 11 - name: Setup Godot build cache uses: ./.github/actions/godot-cache @@ -58,6 +58,7 @@ J08nY <johny@neuromancer.sk> <jancar.jj@gmail.com> J08nY <johny@neuromancer.sk> <J08nY@users.noreply.github.com> Jakub Grzesik <kubecz3k@gmail.com> janglee <merupatel123@gmail.com> +Jean-Michel Bernard <jmb462@gmail.com> Jérôme Gully <jerome.gully0@gmail.com> JFonS <joan.fonssanchez@gmail.com> Juan Linietsky <reduzio@gmail.com> @@ -67,6 +68,9 @@ Juan Linietsky <reduzio@gmail.com> <reduz@Juans-MBP.fibertel.com.ar> Juan Linietsky <reduzio@gmail.com> <red@kyoko> Julian Murgia <the.straton@gmail.com> Kanabenki <lucien.menassol@gmail.com> <18357657+Kanabenki@users.noreply.github.com> +karroffel <therzog@mail.de> +karroffel <therzog@mail.de> <thomas.herzog@mail.com> +karroffel <therzog@mail.de> <thomas.herzog@simedis.com> Kelly Thomas <kelly.thomas@hotmail.com.au> Kongfa Waroros <gongpha@hotmail.com> K. S. Ernest (iFire) Lee <ernest.lee@chibifire.com> @@ -123,11 +127,10 @@ romulox_x <romulox_x@yahoo.com> Ruslan Mustakov <r.mustakov@gmail.com> <ruslan.mustakov@xored.com> Saracen <SaracenOne@gmail.com> sheepandshepherd <sheepandshepherd@hotmail.com> <sheepandshepherd@users.noreply.github.com> +Silc 'Tokage' Renew <tokage.it.lab@gmail.com> +Silc 'Tokage' Renew <tokage.it.lab@gmail.com> <61938263+TokageItLab@users.noreply.github.com> Swarnim Arun <swarnimarun11@gmail.com> Theo Hallenius <redsymbzone@hotmail.com> -Thomas Herzog <therzog@mail.de> -Thomas Herzog <therzog@mail.de> <thomas.herzog@mail.com> -Thomas Herzog <therzog@mail.de> <thomas.herzog@simedis.com> Tomasz Chabora <kobewi4e@gmail.com> Twarit <wtwarit@gmail.com> V.VamsiKrishna <vk@bsb.in> <vamsikrishna.v@gmail.com> diff --git a/AUTHORS.md b/AUTHORS.md index 0a0e3a9c21..a86bc3ffe4 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -122,6 +122,7 @@ name is available. Julien Nguyen (Blackiris) Jummit Justo Delgado (mrcdk) + karroffel Kelly Thomas (KellyThomas) kleonc Kongfa Waroros (gongpha) @@ -179,6 +180,7 @@ name is available. Ralf Hölzemer (rollenrolm) Ramesh Ravone (RameshRavone) raphael10241024 + Raul Santos (raulsntos) Ray Koopa (RayKoopa) Rémi Verschelde (akien-mga) Rhody Lugo (rraallvv) @@ -194,13 +196,13 @@ name is available. Sergey Minakov (naithar) sersoong Shiqing (kawa-yoiko) + Silc 'Tokage' Renew (TokageItLab) Simon Wenner (swenner) Stijn Hinlopen (hinlopen) Swarnim Arun (minraws) Thakee Nathees (ThakeeNathees) thebestnom Theo Hallenius (TheoXD) - Thomas Herzog (karroffel) Timo Schwarzer (timoschwarzer) Timo (toger5) Tomasz Chabora (KoBeWi) @@ -28,6 +28,7 @@ generous deed immortalized in the next stable release of Godot Engine. Ben Nolan Brandon Lamb + Bri Garry Newman Gordon MacPherson Hunter Dickson @@ -41,7 +42,6 @@ generous deed immortalized in the next stable release of Godot Engine. AD Ford alex brown Andrew Bowen - Andrew Dunai Angry Skull anti666 blurp @@ -81,9 +81,7 @@ generous deed immortalized in the next stable release of Godot Engine. Slobodan Milnovic Stephan Lanfermann Steve - Stonesoft io Thomas Krampl - Tristan Pemble Violin Iliev Xwdit @@ -103,7 +101,6 @@ generous deed immortalized in the next stable release of Godot Engine. David Graham David Snopek Ed Morley - Ellen Poe Florian Rämisch Gamejunkey Jacobus Dens @@ -120,12 +117,14 @@ generous deed immortalized in the next stable release of Godot Engine. Maciej Pendolski Manuele Finocchiaro Markus Wiesner + Mathieu Matthew Hillier Michael Mick Monster Vial Officine Pixel S.n.c. Patrick Brock + Paul E Hansen Pedro Silva Petrus Prinsloo Retro Village @@ -147,7 +146,6 @@ generous deed immortalized in the next stable release of Godot Engine. Vagabond Arcade Vitaliy Sapronenko Xeno Coliseum - Zaven Muradyan Adam Nakonieczny Adam Nelson @@ -155,6 +153,7 @@ generous deed immortalized in the next stable release of Godot Engine. Alexander J Maynard Alex Khayrullin alice gambrell + Amar Šahinović Andrew Cunningham Andrew Farr Andriy @@ -211,15 +210,14 @@ generous deed immortalized in the next stable release of Godot Engine. Hunter Barabas Jake Burga James Couzens - James Zahn Jan Sælid Jared Jared White Jennifer Wilcox + Jeremi Biernacki Jesús Chicharro Joel Fivat Johnathan Kupferer - Jonathan Turner Josef Stumpfegger Jose Malheiro Jose Manuel Muñoz Perez @@ -238,6 +236,7 @@ generous deed immortalized in the next stable release of Godot Engine. kinfox Kis Levente Lorand Kos + Lakshaya Goel Laszlo Kiss leetNightshade Leo Fidel R Liban @@ -347,11 +346,11 @@ generous deed immortalized in the next stable release of Godot Engine. Adam Long Adam McCurdy Adam N Webber - Adam R Pope Adam Smeltzer Adam Szymański Adisibio Adrien de Pierres + Agustinus Arya Ahmet Kalyoncu Aidan O'Flannagain Aki Mimoto @@ -377,6 +376,7 @@ generous deed immortalized in the next stable release of Godot Engine. Andrew Groot andrew james morris Andrew Thomas + angrykoala Ano Nim Anthony Avina Anton Bouwer @@ -394,6 +394,7 @@ generous deed immortalized in the next stable release of Godot Engine. Balázs Batári Baptiste Le Bourhis Bartosz Bielecki + bcat Benedikt Benoit Jauvin-Girard Ben Ridley @@ -409,6 +410,7 @@ generous deed immortalized in the next stable release of Godot Engine. Blunderjack Bobby CC Wong Borkzilla + Brad Harms Bram brian Brian Klein @@ -417,6 +419,7 @@ generous deed immortalized in the next stable release of Godot Engine. Bruno Hurth Burney Waring bwhirt + c64cosmin Caleb Gartner Caleb Makela Cameron Meyer @@ -480,11 +483,13 @@ generous deed immortalized in the next stable release of Godot Engine. Eric Stokes Eric Walkingshaw Eric Williams + Erika Sanders Erkki Seppälä Faisal Alkubaisi Fancy Ants Studios fby Fekinox + Felix Adam Felix Bohmann Filip Lundby Forty Doubleu @@ -494,6 +499,7 @@ generous deed immortalized in the next stable release of Godot Engine. FrostMarble Game Endeavor Gary Thomas + gebba George Marques Georgi Petkov Graham Overby @@ -502,6 +508,7 @@ generous deed immortalized in the next stable release of Godot Engine. Greg Olson Greyson Richey Grid + Grok Games Grominet Guillaume Pham Ngoc Guldoman @@ -532,15 +539,16 @@ generous deed immortalized in the next stable release of Godot Engine. Jan Vetulani JARKKO PARVIAINEN Jason Bolton + Jason Evans Jason Malcolm-Herzmark Jason Uechi Jeff Hungerford Jeff Messer Jeffrey Berube Jennifer Graves - JernauGurgeh Jesse Dubay Jim Engstrand + Joe Hurdle Joe Klemmer Joel Höglund John Bruce @@ -577,13 +585,14 @@ generous deed immortalized in the next stable release of Godot Engine. Justin Oaksford Justin Spedding KaDokta - Karol Porzycki Keedong Park + keeganstoybox Keinan Powers Keith Bradner Kenji Kawabata Ken Minardo Kent Jofur + Kerotasma Ketafuki Kevin van Rooijen Kiri Jolly @@ -602,6 +611,7 @@ generous deed immortalized in the next stable release of Godot Engine. Kyle Burnett Kyle Jacobs Kyuppin + La diagonale du poulpe Lasse le Dous Laurent CHEA Laxman Pradhan @@ -627,7 +637,6 @@ generous deed immortalized in the next stable release of Godot Engine. Martin Liška Martin Trbola Martin Zabinski - Mathieu Matt Edwards Matthew Booe Matt Sylvia @@ -657,11 +666,11 @@ generous deed immortalized in the next stable release of Godot Engine. Molinghu Molly Jameson MoltenGears + Moowool MrAZIE Mrjemandem Nathan Fish Nathaniel - nee neighty Neil Blakey-Milner Neil Wang @@ -704,6 +713,7 @@ generous deed immortalized in the next stable release of Godot Engine. Rad Cat Rafa Laguna Raffaele Aramo + Ragnar Pettersson Rainer Amler Rami Hanano Rammeow @@ -728,8 +738,10 @@ generous deed immortalized in the next stable release of Godot Engine. Ryan Groom Sam Caulfield Sam Edson + Samuel Egger Scott Longley Sean Lynch + Sean Wall Sebastian Michailidis SeongWan Kim SeungJong k @@ -744,6 +756,7 @@ generous deed immortalized in the next stable release of Godot Engine. Simon Wenner sirn Skalli + slavfox smbe19 smo1704 Solene Waked @@ -793,6 +806,7 @@ generous deed immortalized in the next stable release of Godot Engine. UltyX Uther v01tech + Vaida Narušė Vaughan Ling Victor Vincent Foulon @@ -800,7 +814,7 @@ generous deed immortalized in the next stable release of Godot Engine. Vladimir Savin Vladislav Smirnov VoxelVisions.com - Vytenis Narušis + Wapiti . werner mendizabal Wiley Thompson William Edwards diff --git a/core/variant/variant.h b/core/variant/variant.h index 9ec131a1b8..d3f694e7ca 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -641,6 +641,7 @@ public: static UtilityFunctionType get_utility_function_type(const StringName &p_name); + static MethodInfo get_utility_function_info(const StringName &p_name); static int get_utility_function_argument_count(const StringName &p_name); static Variant::Type get_utility_function_argument_type(const StringName &p_name, int p_arg); static String get_utility_function_argument_name(const StringName &p_name, int p_arg); diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 06e201d50a..e89bdd4faa 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -1338,6 +1338,28 @@ Variant::UtilityFunctionType Variant::get_utility_function_type(const StringName return bfi->type; } +MethodInfo Variant::get_utility_function_info(const StringName &p_name) { + MethodInfo info; + const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name); + if (bfi) { + info.name = p_name; + if (bfi->returns_value && bfi->return_type == Variant::NIL) { + info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; + } + info.return_val.type = bfi->return_type; + if (bfi->is_vararg) { + info.flags |= METHOD_FLAG_VARARG; + } + for (int i = 0; i < bfi->argnames.size(); ++i) { + PropertyInfo arg; + arg.type = bfi->get_arg_type(i); + arg.name = bfi->argnames[i]; + info.arguments.push_back(arg); + } + } + return info; +} + int Variant::get_utility_function_argument_count(const StringName &p_name) { const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name); if (!bfi) { diff --git a/doc/classes/EditorSyntaxHighlighter.xml b/doc/classes/EditorSyntaxHighlighter.xml index 8880ce4d44..462323a067 100644 --- a/doc/classes/EditorSyntaxHighlighter.xml +++ b/doc/classes/EditorSyntaxHighlighter.xml @@ -5,7 +5,7 @@ </brief_description> <description> Base syntax highlighter resource all editor syntax highlighters extend from, it is used in the [ScriptEditor]. - Add a syntax highlighter to an individual script by calling ScriptEditorBase._add_syntax_highlighter (currently not working). To apply to all scripts on open, call [method ScriptEditor.register_syntax_highlighter] + Add a syntax highlighter to an individual script by calling [method ScriptEditorBase.add_syntax_highlighter]. To apply to all scripts on open, call [method ScriptEditor.register_syntax_highlighter] </description> <tutorials> </tutorials> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index cae74ca553..843db8c174 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -551,6 +551,7 @@ <argument index="0" name="node" type="Node" /> <description> Removes a child node. The node is NOT deleted and must be deleted manually. + [b]Note:[/b] This function may set the [member owner] of the removed Node (or its descendants) to be [code]null[/code], if that [member owner] is no longer a parent or ancestor. </description> </method> <method name="remove_from_group"> diff --git a/doc/classes/ScriptEditorBase.xml b/doc/classes/ScriptEditorBase.xml index 1e72fe9090..88adeaf12f 100644 --- a/doc/classes/ScriptEditorBase.xml +++ b/doc/classes/ScriptEditorBase.xml @@ -9,6 +9,13 @@ <tutorials> </tutorials> <methods> + <method name="add_syntax_highlighter"> + <return type="void" /> + <argument index="0" name="highlighter" type="EditorSyntaxHighlighter" /> + <description> + Adds a [EditorSyntaxHighlighter] to the open script. + </description> + </method> <method name="get_base_editor" qualifiers="const"> <return type="Control" /> <description> diff --git a/doc/classes/Timer.xml b/doc/classes/Timer.xml index fde887dd87..f360099f2b 100644 --- a/doc/classes/Timer.xml +++ b/doc/classes/Timer.xml @@ -52,7 +52,7 @@ </member> <member name="wait_time" type="float" setter="set_wait_time" getter="get_wait_time" default="1.0"> The wait time in seconds. - [b]Note:[/b] Timers can only emit once per rendered frame at most (or once per physics frame if [member process_callback] is [constant TIMER_PROCESS_PHYSICS). This means very low wait times (lower than 0.05 seconds) will behave in significantly different ways depending on the rendered framerate. For very low wait times, it is recommended to use a process loop in a script instead of using a Timer node. + [b]Note:[/b] Timers can only emit once per rendered frame at most (or once per physics frame if [member process_callback] is [constant TIMER_PROCESS_PHYSICS]). This means very low wait times (lower than 0.05 seconds) will behave in significantly different ways depending on the rendered framerate. For very low wait times, it is recommended to use a process loop in a script instead of using a Timer node. </member> </members> <signals> diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp index 38db48a4d4..363d542fd5 100644 --- a/editor/action_map_editor.cpp +++ b/editor/action_map_editor.cpp @@ -126,28 +126,30 @@ void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event) { while (category) { TreeItem *input_item = category->get_first_child(); - // has_type this should be always true, unless the tree structure has been misconfigured. - bool has_type = input_item->get_parent()->has_meta("__type"); - int input_type = input_item->get_parent()->get_meta("__type"); - if (!has_type) { - return; - } + if (input_item != nullptr) { + // has_type this should be always true, unless the tree structure has been misconfigured. + bool has_type = input_item->get_parent()->has_meta("__type"); + int input_type = input_item->get_parent()->get_meta("__type"); + if (!has_type) { + return; + } - // If event type matches input types of this category. - if ((k.is_valid() && input_type == INPUT_KEY) || (joyb.is_valid() && input_type == INPUT_JOY_BUTTON) || (joym.is_valid() && input_type == INPUT_JOY_MOTION) || (mb.is_valid() && input_type == INPUT_MOUSE_BUTTON)) { - // Loop through all items of this category until one matches. - while (input_item) { - bool key_match = k.is_valid() && (Variant(k->get_keycode()) == input_item->get_meta("__keycode") || Variant(k->get_physical_keycode()) == input_item->get_meta("__keycode")); - bool joyb_match = joyb.is_valid() && Variant(joyb->get_button_index()) == input_item->get_meta("__index"); - bool joym_match = joym.is_valid() && Variant(joym->get_axis()) == input_item->get_meta("__axis") && joym->get_axis_value() == (float)input_item->get_meta("__value"); - bool mb_match = mb.is_valid() && Variant(mb->get_button_index()) == input_item->get_meta("__index"); - if (key_match || joyb_match || joym_match || mb_match) { - category->set_collapsed(false); - input_item->select(0); - input_list_tree->ensure_cursor_is_visible(); - return; + // If event type matches input types of this category. + if ((k.is_valid() && input_type == INPUT_KEY) || (joyb.is_valid() && input_type == INPUT_JOY_BUTTON) || (joym.is_valid() && input_type == INPUT_JOY_MOTION) || (mb.is_valid() && input_type == INPUT_MOUSE_BUTTON)) { + // Loop through all items of this category until one matches. + while (input_item) { + bool key_match = k.is_valid() && (Variant(k->get_keycode()) == input_item->get_meta("__keycode") || Variant(k->get_physical_keycode()) == input_item->get_meta("__keycode")); + bool joyb_match = joyb.is_valid() && Variant(joyb->get_button_index()) == input_item->get_meta("__index"); + bool joym_match = joym.is_valid() && Variant(joym->get_axis()) == input_item->get_meta("__axis") && joym->get_axis_value() == (float)input_item->get_meta("__value"); + bool mb_match = mb.is_valid() && Variant(mb->get_button_index()) == input_item->get_meta("__index"); + if (key_match || joyb_match || joym_match || mb_match) { + category->set_collapsed(false); + input_item->select(0); + input_list_tree->ensure_cursor_is_visible(); + return; + } + input_item = input_item->get_next(); } - input_item = input_item->get_next(); } } diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index 5b52554335..a6e1e1d094 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -130,6 +130,7 @@ void ImportDock::set_edit_path(const String &p_path) { _add_keep_import_option(importer_name); import->set_disabled(false); + _set_dirty(false); import_as->set_disabled(false); preset->set_disabled(false); @@ -280,6 +281,7 @@ void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) { params->paths = p_paths; import->set_disabled(false); + _set_dirty(false); import_as->set_disabled(false); preset->set_disabled(false); @@ -533,6 +535,8 @@ void ImportDock::_reimport() { EditorFileSystem::get_singleton()->reimport_files(params->paths); EditorFileSystem::get_singleton()->emit_signal(SNAME("filesystem_changed")); //it changed, so force emitting the signal + + _set_dirty(false); } void ImportDock::_notification(int p_what) { @@ -548,6 +552,24 @@ void ImportDock::_notification(int p_what) { } } +void ImportDock::_property_edited(const StringName &p_prop) { + _set_dirty(true); +} + +void ImportDock::_set_dirty(bool p_dirty) { + if (p_dirty) { + // Add a dirty marker to notify the user that they should reimport the selected resource to see changes. + import->set_text(TTR("Reimport") + " (*)"); + import->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor"))); + import->set_tooltip(TTR("You have pending changes that haven't been applied yet. Click Reimport to apply changes made to the import options.\nSelecting another resource in the FileSystem dock without clicking Reimport first will discard changes made in the Import dock.")); + } else { + // Remove the dirty marker on the Reimport button. + import->set_text(TTR("Reimport")); + import->remove_theme_color_override("font_color"); + import->set_tooltip(""); + } +} + void ImportDock::_property_toggled(const StringName &p_prop, bool p_checked) { if (p_checked) { params->checked.insert(p_prop); @@ -588,6 +610,7 @@ ImportDock::ImportDock() { import_opts = memnew(EditorInspector); add_child(import_opts); import_opts->set_v_size_flags(SIZE_EXPAND_FILL); + import_opts->connect("property_edited", callable_mp(this, &ImportDock::_property_edited)); import_opts->connect("property_toggled", callable_mp(this, &ImportDock::_property_toggled)); hb = memnew(HBoxContainer); diff --git a/editor/import_dock.h b/editor/import_dock.h index 3c28bbcd89..150c44576d 100644 --- a/editor/import_dock.h +++ b/editor/import_dock.h @@ -68,7 +68,9 @@ class ImportDock : public VBoxContainer { void _update_preset_menu(); void _add_keep_import_option(const String &p_importer_name); + void _property_edited(const StringName &p_prop); void _property_toggled(const StringName &p_prop, bool p_checked); + void _set_dirty(bool p_dirty); void _reimport_attempt(); void _reimport_and_restart(); void _reimport(); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 5df6743f4c..ca6ecfbd3a 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -214,6 +214,7 @@ Ref<EditorSyntaxHighlighter> EditorPlainTextSyntaxHighlighter::_create() const { void ScriptEditorBase::_bind_methods() { ClassDB::bind_method(D_METHOD("get_base_editor"), &ScriptEditorBase::get_base_editor); + ClassDB::bind_method(D_METHOD("add_syntax_highlighter", "highlighter"), &ScriptEditorBase::add_syntax_highlighter); ADD_SIGNAL(MethodInfo("name_changed")); ADD_SIGNAL(MethodInfo("edited_script_changed")); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 1c251075de..2c02389db2 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -1341,8 +1341,6 @@ void ScriptTextEditor::_bind_methods() { ClassDB::bind_method("_get_drag_data_fw", &ScriptTextEditor::get_drag_data_fw); ClassDB::bind_method("_can_drop_data_fw", &ScriptTextEditor::can_drop_data_fw); ClassDB::bind_method("_drop_data_fw", &ScriptTextEditor::drop_data_fw); - - ClassDB::bind_method(D_METHOD("add_syntax_highlighter", "highlighter"), &ScriptTextEditor::add_syntax_highlighter); } Control *ScriptTextEditor::get_edit_menu() { diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 06ba8a6168..1fc7eb98e0 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -407,10 +407,6 @@ void TextEditor::_convert_case(CodeTextEditor::CaseStyle p_case) { code_editor->convert_case(p_case); } -void TextEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_syntax_highlighter", "highlighter"), &TextEditor::add_syntax_highlighter); -} - static ScriptEditorBase *create_editor(const RES &p_resource) { if (Object::cast_to<TextFile>(*p_resource)) { return memnew(TextEditor); diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h index 9308fec210..7404557f46 100644 --- a/editor/plugins/text_editor.h +++ b/editor/plugins/text_editor.h @@ -87,8 +87,6 @@ private: }; protected: - static void _bind_methods(); - void _edit_option(int p_op); void _make_context_menu(bool p_selection, bool p_can_fold, bool p_is_folded, Vector2 p_position); void _text_edit_gui_input(const Ref<InputEvent> &ev); diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index cc5ff90541..c2e86f8b43 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -465,6 +465,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p } tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } + _fix_invalid_tiles_in_tile_map_selection(); } break; case DRAG_TYPE_BUCKET: { Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->world_to_map(drag_last_mouse_pos), tile_map->world_to_map(mpos)); @@ -483,6 +484,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p } } } + _fix_invalid_tiles_in_tile_map_selection(); } break; default: break; @@ -508,6 +510,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p drag_start_mouse_pos = mpos; if (tile_map_selection.has(tile_map->world_to_map(drag_start_mouse_pos)) && !mb->is_shift_pressed()) { // Move the selection + _update_selection_pattern_from_tilemap_selection(); // Make sure the pattern is up to date before moving. drag_type = DRAG_TYPE_MOVE; drag_modified.clear(); for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { @@ -541,6 +544,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p } tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } + _fix_invalid_tiles_in_tile_map_selection(); } else if (tool_buttons_group->get_pressed_button() == line_tool_button) { drag_type = DRAG_TYPE_LINE; drag_start_mouse_pos = mpos; @@ -569,6 +573,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p } } } + _fix_invalid_tiles_in_tile_map_selection(); } } } @@ -1323,6 +1328,25 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() { } } +void TileMapEditorTilesPlugin::_fix_invalid_tiles_in_tile_map_selection() { + TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); + if (!tile_map) { + return; + } + + Set<Vector2i> to_remove; + for (Vector2i selected : tile_map_selection) { + TileMapCell cell = tile_map->get_cell(tile_map_layer, selected); + if (cell.source_id == TileSet::INVALID_SOURCE && cell.get_atlas_coords() == TileSetSource::INVALID_ATLAS_COORDS && cell.alternative_tile == TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) { + to_remove.insert(selected); + } + } + + for (Vector2i cell : to_remove) { + tile_map_selection.erase(cell); + } +} + void TileMapEditorTilesPlugin::_update_selection_pattern_from_tilemap_selection() { TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (!tile_map) { @@ -1423,6 +1447,8 @@ void TileMapEditorTilesPlugin::_update_tileset_selection_from_selection_pattern( } } _update_bottom_panel(); + tile_atlas_control->update(); + alternative_tiles_control->update(); } void TileMapEditorTilesPlugin::_tile_atlas_control_draw() { diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_editor.h index 6126db59e9..a1ab3db318 100644 --- a/editor/plugins/tiles/tile_map_editor.h +++ b/editor/plugins/tiles/tile_map_editor.h @@ -124,6 +124,7 @@ private: void _update_selection_pattern_from_tileset_selection(); void _update_tileset_selection_from_selection_pattern(); void _update_fix_selected_and_hovered(); + void _fix_invalid_tiles_in_tile_map_selection(); ///// Bottom panel. ////. Label *missing_source_label; diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 2dafc85f45..fd7664049a 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -875,18 +875,32 @@ void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class) { GDScriptParser::ClassNode *previous_class = parser->current_class; parser->current_class = p_class; - // Do functions now. + // Do functions and properties now. for (int i = 0; i < p_class->members.size(); i++) { GDScriptParser::ClassNode::Member member = p_class->members[i]; - if (member.type != GDScriptParser::ClassNode::Member::FUNCTION) { - continue; - } + if (member.type == GDScriptParser::ClassNode::Member::FUNCTION) { + resolve_function_body(member.function); - resolve_function_body(member.function); + // Apply annotations. + for (GDScriptParser::AnnotationNode *&E : member.function->annotations) { + E->apply(parser, member.function); + } + } else if (member.type == GDScriptParser::ClassNode::Member::VARIABLE && member.variable->property != GDScriptParser::VariableNode::PROP_NONE) { + if (member.variable->property == GDScriptParser::VariableNode::PROP_INLINE) { + if (member.variable->getter != nullptr) { + member.variable->getter->set_datatype(member.variable->datatype); - // Apply annotations. - for (GDScriptParser::AnnotationNode *&E : member.function->annotations) { - E->apply(parser, member.function); + resolve_function_body(member.variable->getter); + } + if (member.variable->setter != nullptr) { + if (member.variable->setter->parameters.size() > 0) { + member.variable->setter->parameters[0]->datatype_specifier = member.variable->datatype_specifier; + } + + resolve_function_signature(member.variable->setter); + resolve_function_body(member.variable->setter); + } + } } } @@ -902,17 +916,80 @@ void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class) { resolve_class_body(member.m_class); } - // Check unused variables. + // Check unused variables and datatypes of property getters and setters. for (int i = 0; i < p_class->members.size(); i++) { GDScriptParser::ClassNode::Member member = p_class->members[i]; - if (member.type != GDScriptParser::ClassNode::Member::VARIABLE) { - continue; - } + if (member.type == GDScriptParser::ClassNode::Member::VARIABLE) { #ifdef DEBUG_ENABLED - if (member.variable->usages == 0 && String(member.variable->identifier->name).begins_with("_")) { - parser->push_warning(member.variable->identifier, GDScriptWarning::UNUSED_PRIVATE_CLASS_VARIABLE, member.variable->identifier->name); - } + if (member.variable->usages == 0 && String(member.variable->identifier->name).begins_with("_")) { + parser->push_warning(member.variable->identifier, GDScriptWarning::UNUSED_PRIVATE_CLASS_VARIABLE, member.variable->identifier->name); + } +#endif + + if (member.variable->property == GDScriptParser::VariableNode::PROP_SETGET) { + GDScriptParser::FunctionNode *getter_function = nullptr; + GDScriptParser::FunctionNode *setter_function = nullptr; + + bool has_valid_getter = false; + bool has_valid_setter = false; + + if (member.variable->getter_pointer != nullptr) { + if (p_class->has_function(member.variable->getter_pointer->name)) { + getter_function = p_class->get_member(member.variable->getter_pointer->name).function; + } + + if (getter_function == nullptr) { + push_error(vformat(R"(Getter "%s" not found.)", member.variable->getter_pointer->name), member.variable); + + } else if (getter_function->parameters.size() != 0 || getter_function->datatype.has_no_type()) { + push_error(vformat(R"(Function "%s" cannot be used as getter because of its signature.)", getter_function->identifier->name), member.variable); + + } else if (!is_type_compatible(member.variable->datatype, getter_function->datatype, true)) { + push_error(vformat(R"(Function with return type "%s" cannot be used as getter for a property of type "%s".)", getter_function->datatype.to_string(), member.variable->datatype.to_string()), member.variable); + + } else { + has_valid_getter = true; + +#ifdef DEBUG_ENABLED + if (member.variable->datatype.builtin_type == Variant::INT && getter_function->datatype.builtin_type == Variant::FLOAT) { + parser->push_warning(member.variable, GDScriptWarning::NARROWING_CONVERSION); + } +#endif + } + } + + if (member.variable->setter_pointer != nullptr) { + if (p_class->has_function(member.variable->setter_pointer->name)) { + setter_function = p_class->get_member(member.variable->setter_pointer->name).function; + } + + if (setter_function == nullptr) { + push_error(vformat(R"(Setter "%s" not found.)", member.variable->setter_pointer->name), member.variable); + + } else if (setter_function->parameters.size() != 1) { + push_error(vformat(R"(Function "%s" cannot be used as setter because of its signature.)", setter_function->identifier->name), member.variable); + + } else if (!is_type_compatible(member.variable->datatype, setter_function->parameters[0]->datatype, true)) { + push_error(vformat(R"(Function with argument type "%s" cannot be used as setter for a property of type "%s".)", setter_function->parameters[0]->datatype.to_string(), member.variable->datatype.to_string()), member.variable); + + } else { + has_valid_setter = true; + +#ifdef DEBUG_ENABLED + if (member.variable->datatype.builtin_type == Variant::INT && setter_function->return_type->datatype.builtin_type == Variant::FLOAT) { + parser->push_warning(member.variable, GDScriptWarning::NARROWING_CONVERSION); + } #endif + } + } + + if (member.variable->datatype.is_variant() && has_valid_getter && has_valid_setter) { + if (!is_type_compatible(getter_function->datatype, setter_function->parameters[0]->datatype, true)) { + push_error(vformat(R"(Getter with type "%s" cannot be used along with setter of type "%s".)", getter_function->datatype.to_string(), setter_function->parameters[0]->datatype.to_string()), member.variable); + } + } + } + } } } @@ -1529,12 +1606,20 @@ void GDScriptAnalyzer::resolve_parameter(GDScriptParser::ParameterNode *p_parame void GDScriptAnalyzer::resolve_return(GDScriptParser::ReturnNode *p_return) { GDScriptParser::DataType result; + GDScriptParser::DataType expected_type; + bool has_expected_type = false; + + if (parser->current_function != nullptr) { + expected_type = parser->current_function->get_datatype(); + has_expected_type = true; + } + 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)); + if (has_expected_type && expected_type.has_container_element_type() && p_return->return_value->type == GDScriptParser::Node::ARRAY) { + update_array_literal_element_type(expected_type, static_cast<GDScriptParser::ArrayNode *>(p_return->return_value)); } } result = p_return->return_value->get_datatype(); @@ -1546,23 +1631,24 @@ void GDScriptAnalyzer::resolve_return(GDScriptParser::ReturnNode *p_return) { result.is_constant = true; } - GDScriptParser::DataType function_type = parser->current_function->get_datatype(); - function_type.is_meta_type = false; - if (function_type.is_hard_type()) { - if (!is_type_compatible(function_type, result)) { - // Try other way. Okay but not safe. - if (!is_type_compatible(result, function_type)) { - push_error(vformat(R"(Cannot return value of type "%s" because the function return type is "%s".)", result.to_string(), function_type.to_string()), p_return); - } else { - // TODO: Add warning. - mark_node_unsafe(p_return); - } + if (has_expected_type) { + expected_type.is_meta_type = false; + if (expected_type.is_hard_type()) { + if (!is_type_compatible(expected_type, result)) { + // Try other way. Okay but not safe. + if (!is_type_compatible(result, expected_type)) { + push_error(vformat(R"(Cannot return value of type "%s" because the function return type is "%s".)", result.to_string(), expected_type.to_string()), p_return); + } else { + // TODO: Add warning. + mark_node_unsafe(p_return); + } #ifdef DEBUG_ENABLED - } else if (function_type.builtin_type == Variant::INT && result.builtin_type == Variant::FLOAT) { - parser->push_warning(p_return, GDScriptWarning::NARROWING_CONVERSION); - } else if (result.is_variant()) { - mark_node_unsafe(p_return); + } else if (expected_type.builtin_type == Variant::INT && result.builtin_type == Variant::FLOAT) { + parser->push_warning(p_return, GDScriptWarning::NARROWING_CONVERSION); + } else if (result.is_variant()) { + mark_node_unsafe(p_return); #endif + } } } diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index b8300cd872..6a7e4278d2 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -692,7 +692,8 @@ void GDScriptByteCodeGenerator::write_end_ternary() { void GDScriptByteCodeGenerator::write_set(const Address &p_target, const Address &p_index, const Address &p_source) { if (HAS_BUILTIN_TYPE(p_target)) { - if (IS_BUILTIN_TYPE(p_index, Variant::INT) && Variant::get_member_validated_indexed_setter(p_target.type.builtin_type)) { + if (IS_BUILTIN_TYPE(p_index, Variant::INT) && Variant::get_member_validated_indexed_setter(p_target.type.builtin_type) && + IS_BUILTIN_TYPE(p_source, Variant::get_indexed_element_type(p_target.type.builtin_type))) { // Use indexed setter instead. Variant::ValidatedIndexedSetter setter = Variant::get_member_validated_indexed_setter(p_target.type.builtin_type); append(GDScriptFunction::OPCODE_SET_INDEXED_VALIDATED, 3); @@ -746,7 +747,8 @@ void GDScriptByteCodeGenerator::write_get(const Address &p_target, const Address } void GDScriptByteCodeGenerator::write_set_named(const Address &p_target, const StringName &p_name, const Address &p_source) { - if (HAS_BUILTIN_TYPE(p_target) && Variant::get_member_validated_setter(p_target.type.builtin_type, p_name)) { + if (HAS_BUILTIN_TYPE(p_target) && Variant::get_member_validated_setter(p_target.type.builtin_type, p_name) && + IS_BUILTIN_TYPE(p_source, Variant::get_member_type(p_target.type.builtin_type, p_name))) { Variant::ValidatedSetter setter = Variant::get_member_validated_setter(p_target.type.builtin_type, p_name); append(GDScriptFunction::OPCODE_SET_NAMED_VALIDATED, 2); append(p_target); diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 34b1e45cdf..1f9aad40af 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -2089,77 +2089,18 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_ Error GDScriptCompiler::_parse_setter_getter(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::VariableNode *p_variable, bool p_is_setter) { Error error = OK; - CodeGen codegen; - codegen.generator = memnew(GDScriptByteCodeGenerator); - - codegen.class_node = p_class; - codegen.script = p_script; - StringName func_name; + GDScriptParser::FunctionNode *function; if (p_is_setter) { - func_name = "@" + p_variable->identifier->name + "_setter"; + function = p_variable->setter; } else { - func_name = "@" + p_variable->identifier->name + "_getter"; + function = p_variable->getter; } - codegen.function_name = func_name; - - GDScriptDataType return_type; - if (p_is_setter) { - return_type.has_type = true; - return_type.kind = GDScriptDataType::BUILTIN; - return_type.builtin_type = Variant::NIL; - } else { - return_type = _gdtype_from_datatype(p_variable->get_datatype(), p_script); - } + _parse_function(error, p_script, p_class, function); - codegen.generator->write_start(p_script, func_name, false, Multiplayer::RPCConfig(), return_type); - - if (p_is_setter) { - uint32_t par_addr = codegen.generator->add_parameter(p_variable->setter_parameter->name, false, _gdtype_from_datatype(p_variable->get_datatype())); - codegen.parameters[p_variable->setter_parameter->name] = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::FUNCTION_PARAMETER, par_addr, _gdtype_from_datatype(p_variable->get_datatype())); - } - - error = _parse_block(codegen, p_is_setter ? p_variable->setter : p_variable->getter); - if (error) { - memdelete(codegen.generator); - return error; - } - - GDScriptFunction *gd_function = codegen.generator->write_end(); - - p_script->member_functions[func_name] = gd_function; - -#ifdef DEBUG_ENABLED - if (EngineDebugger::is_active()) { - String signature; - //path - if (p_script->get_path() != String()) { - signature += p_script->get_path(); - } - //loc - signature += "::" + itos(p_is_setter ? p_variable->setter->start_line : p_variable->getter->start_line); - - //function and class - - if (p_class->identifier) { - signature += "::" + String(p_class->identifier->name) + "." + String(func_name); - } else { - signature += "::" + String(func_name); - } - - codegen.generator->set_signature(signature); - } -#endif - codegen.generator->set_initial_line(p_is_setter ? p_variable->setter->start_line : p_variable->getter->start_line); - -#ifdef TOOLS_ENABLED - p_script->member_lines[func_name] = p_is_setter ? p_variable->setter->start_line : p_variable->getter->start_line; -#endif - memdelete(codegen.generator); - - return OK; + return error; } Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) { diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index e49bf518a2..71d2699c2e 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -1089,6 +1089,15 @@ static void _find_identifiers(GDScriptParser::CompletionContext &p_context, bool kwa++; } + List<StringName> utility_func_names; + Variant::get_utility_function_list(&utility_func_names); + + for (List<StringName>::Element *E = utility_func_names.front(); E; E = E->next()) { + ScriptCodeCompletionOption option(E->get(), ScriptCodeCompletionOption::KIND_FUNCTION); + option.insert_text += "("; + r_result.insert(option.display, option); + } + OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) { if (!E.value().is_singleton) { @@ -2325,7 +2334,11 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c GDScriptCompletionIdentifier connect_base; - if (GDScriptUtilityFunctions::function_exists(call->function_name)) { + if (Variant::has_utility_function(call->function_name)) { + MethodInfo info = Variant::get_utility_function_info(call->function_name); + r_arghint = _make_arguments_hint(info, p_argidx); + return; + } else if (GDScriptUtilityFunctions::function_exists(call->function_name)) { MethodInfo info = GDScriptUtilityFunctions::get_function_info(call->function_name); r_arghint = _make_arguments_hint(info, p_argidx); return; diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index d3b57fbe18..40be5cb324 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -947,7 +947,7 @@ GDScriptParser::VariableNode *GDScriptParser::parse_property(VariableNode *p_var void GDScriptParser::parse_property_setter(VariableNode *p_variable) { switch (p_variable->property) { - case VariableNode::PROP_INLINE: + case VariableNode::PROP_INLINE: { consume(GDScriptTokenizer::Token::PARENTHESIS_OPEN, R"(Expected "(" after "set".)"); if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected parameter name after "(".)")) { p_variable->setter_parameter = parse_identifier(); @@ -955,9 +955,30 @@ void GDScriptParser::parse_property_setter(VariableNode *p_variable) { consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected ")" after parameter name.)*"); consume(GDScriptTokenizer::Token::COLON, R"*(Expected ":" after ")".)*"); - p_variable->setter = parse_suite("setter definition"); - break; + IdentifierNode *identifier = alloc_node<IdentifierNode>(); + identifier->name = "@" + p_variable->identifier->name + "_setter"; + + FunctionNode *function = alloc_node<FunctionNode>(); + function->identifier = identifier; + + FunctionNode *previous_function = current_function; + current_function = function; + + ParameterNode *parameter = alloc_node<ParameterNode>(); + parameter->identifier = p_variable->setter_parameter; + + function->parameters_indices[parameter->identifier->name] = 0; + function->parameters.push_back(parameter); + + SuiteNode *body = alloc_node<SuiteNode>(); + body->add_local(parameter, function); + + function->body = parse_suite("setter declaration", body); + p_variable->setter = function; + current_function = previous_function; + break; + } case VariableNode::PROP_SETGET: consume(GDScriptTokenizer::Token::EQUAL, R"(Expected "=" after "set")"); make_completion_context(COMPLETION_PROPERTY_METHOD, p_variable); @@ -972,11 +993,25 @@ void GDScriptParser::parse_property_setter(VariableNode *p_variable) { void GDScriptParser::parse_property_getter(VariableNode *p_variable) { switch (p_variable->property) { - case VariableNode::PROP_INLINE: + case VariableNode::PROP_INLINE: { consume(GDScriptTokenizer::Token::COLON, R"(Expected ":" after "get".)"); - p_variable->getter = parse_suite("getter definition"); + IdentifierNode *identifier = alloc_node<IdentifierNode>(); + identifier->name = "@" + p_variable->identifier->name + "_getter"; + + FunctionNode *function = alloc_node<FunctionNode>(); + function->identifier = identifier; + + FunctionNode *previous_function = current_function; + current_function = function; + + SuiteNode *body = alloc_node<SuiteNode>(); + function->body = parse_suite("getter declaration", body); + + p_variable->getter = function; + current_function = previous_function; break; + } case VariableNode::PROP_SETGET: consume(GDScriptTokenizer::Token::EQUAL, R"(Expected "=" after "get")"); make_completion_context(COMPLETION_PROPERTY_METHOD, p_variable); @@ -3423,7 +3458,7 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node 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 += E->key().operator String().capitalize().xml_escape(); enum_hint_string += ":"; enum_hint_string += String::num_int64(E->get()).xml_escape(); @@ -4437,7 +4472,7 @@ void GDScriptParser::TreePrinter::print_variable(VariableNode *p_variable) { if (p_variable->property == VariableNode::PROP_INLINE) { push_line(":"); increase_indent(); - print_suite(p_variable->getter); + print_suite(p_variable->getter->body); decrease_indent(); } else { push_line(" ="); @@ -4457,7 +4492,7 @@ void GDScriptParser::TreePrinter::print_variable(VariableNode *p_variable) { } push_line("):"); increase_indent(); - print_suite(p_variable->setter); + print_suite(p_variable->setter->body); decrease_indent(); } else { push_line(" ="); diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 593fb0cc5e..af9b973ada 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -1109,12 +1109,12 @@ public: PropertyStyle property = PROP_NONE; union { - SuiteNode *setter = nullptr; + FunctionNode *setter = nullptr; IdentifierNode *setter_pointer; }; IdentifierNode *setter_parameter = nullptr; union { - SuiteNode *getter = nullptr; + FunctionNode *getter = nullptr; IdentifierNode *getter_pointer; }; diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp index 730e554476..f4c0c4d9bb 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.cpp +++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp @@ -165,7 +165,7 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p case ClassNode::Member::VARIABLE: { lsp::DocumentSymbol symbol; symbol.name = m.variable->identifier->name; - symbol.kind = m.variable->property == VariableNode::PropertyStyle::PROP_NONE ? lsp::SymbolKind::Variable : lsp::SymbolKind::Property; + symbol.kind = m.variable->property == VariableNode::PROP_NONE ? lsp::SymbolKind::Variable : lsp::SymbolKind::Property; symbol.deprecated = false; symbol.range.start.line = LINE_NUMBER_TO_INDEX(m.variable->start_line); symbol.range.start.character = LINE_NUMBER_TO_INDEX(m.variable->start_column); diff --git a/modules/gdscript/tests/scripts/analyzer/errors/property_function_get_type_error.gd b/modules/gdscript/tests/scripts/analyzer/errors/property_function_get_type_error.gd new file mode 100644 index 0000000000..f1be6aaa0c --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/property_function_get_type_error.gd @@ -0,0 +1,11 @@ +var _prop : int + +# Getter function has wrong return type. +var prop : String: + get = get_prop + +func get_prop(): + return _prop + +func test(): + pass diff --git a/modules/gdscript/tests/scripts/analyzer/errors/property_function_get_type_error.out b/modules/gdscript/tests/scripts/analyzer/errors/property_function_get_type_error.out new file mode 100644 index 0000000000..29eec51ef2 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/property_function_get_type_error.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Function with return type "int" cannot be used as getter for a property of type "String". diff --git a/modules/gdscript/tests/scripts/analyzer/errors/property_function_set_type_error.gd b/modules/gdscript/tests/scripts/analyzer/errors/property_function_set_type_error.gd new file mode 100644 index 0000000000..dd190157a1 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/property_function_set_type_error.gd @@ -0,0 +1,11 @@ +var _prop : int + +# Setter function has wrong argument type. +var prop : String: + set = set_prop + +func set_prop(value : int): + _prop = value + +func test(): + pass diff --git a/modules/gdscript/tests/scripts/analyzer/errors/property_function_set_type_error.out b/modules/gdscript/tests/scripts/analyzer/errors/property_function_set_type_error.out new file mode 100644 index 0000000000..7a25280d55 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/property_function_set_type_error.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Function with argument type "int" cannot be used as setter for a property of type "String". diff --git a/modules/gdscript/tests/scripts/analyzer/errors/property_inline_get_type_error.gd b/modules/gdscript/tests/scripts/analyzer/errors/property_inline_get_type_error.gd new file mode 100644 index 0000000000..7f2b29222a --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/property_inline_get_type_error.gd @@ -0,0 +1,9 @@ +var _prop : int + +# Inline getter returns int instead of String. +var prop : String: + get: + return _prop + +func test(): + pass diff --git a/modules/gdscript/tests/scripts/analyzer/errors/property_inline_get_type_error.out b/modules/gdscript/tests/scripts/analyzer/errors/property_inline_get_type_error.out new file mode 100644 index 0000000000..e0adef1bf8 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/property_inline_get_type_error.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Cannot return value of type "int" because the function return type is "String". diff --git a/modules/gdscript/tests/scripts/analyzer/errors/property_inline_set_type_error.gd b/modules/gdscript/tests/scripts/analyzer/errors/property_inline_set_type_error.gd new file mode 100644 index 0000000000..0ce239dbbd --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/property_inline_set_type_error.gd @@ -0,0 +1,9 @@ +var _prop : int + +# Inline setter assigns String to int. +var prop : String: + set(value): + _prop = value + +func test(): + pass diff --git a/modules/gdscript/tests/scripts/analyzer/errors/property_inline_set_type_error.out b/modules/gdscript/tests/scripts/analyzer/errors/property_inline_set_type_error.out new file mode 100644 index 0000000000..bbadf1ce27 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/property_inline_set_type_error.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Cannot assign a value of type "String" to a target of type "int". diff --git a/modules/gdscript/tests/scripts/analyzer/features/property_functions.gd b/modules/gdscript/tests/scripts/analyzer/features/property_functions.gd new file mode 100644 index 0000000000..1706087f82 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/property_functions.gd @@ -0,0 +1,16 @@ +var _prop = 1 +var prop: + get = get_prop, set = set_prop + +func get_prop(): + return _prop + +func set_prop(value): + _prop = value + +func test(): + print(prop) + + prop = 2 + + print(prop) diff --git a/modules/gdscript/tests/scripts/analyzer/features/property_functions.out b/modules/gdscript/tests/scripts/analyzer/features/property_functions.out new file mode 100644 index 0000000000..f1253ca57e --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/property_functions.out @@ -0,0 +1,3 @@ +GDTEST_OK +1 +2 diff --git a/modules/gdscript/tests/scripts/analyzer/features/property_inline.gd b/modules/gdscript/tests/scripts/analyzer/features/property_inline.gd new file mode 100644 index 0000000000..23eb011b23 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/property_inline.gd @@ -0,0 +1,46 @@ +# Untyped inline property +var prop1: + get: + return prop1 + set(value): + prop1 = value + +# Typed inline property +var prop2 : int: + get: + return prop2 + set(value): + prop2 = value + +# Typed inline property with default value +var prop3 : int = 1: + get: + return prop3 + set(value): + prop3 = value + +# Typed inline property with backing variable +var _prop4 : int = 2 +var prop4: int: + get: + return _prop4 + set(value): + _prop4 = value + +func test(): + print(prop1) + print(prop2) + print(prop3) + print(prop4) + + print() + + prop1 = 1 + prop2 = 2 + prop3 = 3 + prop4 = 4 + + print(prop1) + print(prop2) + print(prop3) + print(prop4) diff --git a/modules/gdscript/tests/scripts/analyzer/features/property_inline.out b/modules/gdscript/tests/scripts/analyzer/features/property_inline.out new file mode 100644 index 0000000000..5482592e90 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/property_inline.out @@ -0,0 +1,10 @@ +GDTEST_OK +null +0 +1 +2 + +1 +2 +3 +4 diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 8cb701ea20..d73b8d3ca0 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -4262,8 +4262,6 @@ void VisualScriptEditor::_bind_methods() { ClassDB::bind_method("_update_members", &VisualScriptEditor::_update_members); ClassDB::bind_method("_generic_search", &VisualScriptEditor::_generic_search); - - ClassDB::bind_method(D_METHOD("add_syntax_highlighter", "highlighter"), &VisualScriptEditor::add_syntax_highlighter); } VisualScriptEditor::VisualScriptEditor() { diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 60ba1c558a..727ce0ae46 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -429,9 +429,8 @@ String EditorExportPlatformAndroid::get_package_name(const String &p_package) co return pname; } -String EditorExportPlatformAndroid::get_assets_directory(const Ref<EditorExportPreset> &p_preset) const { - int export_format = int(p_preset->get("custom_template/export_format")); - return export_format == EXPORT_FORMAT_AAB ? AAB_ASSETS_DIRECTORY : APK_ASSETS_DIRECTORY; +String EditorExportPlatformAndroid::get_assets_directory(const Ref<EditorExportPreset> &p_preset, int p_export_format) const { + return p_export_format == EXPORT_FORMAT_AAB ? AAB_ASSETS_DIRECTORY : APK_ASSETS_DIRECTORY; } bool EditorExportPlatformAndroid::is_package_name_valid(const String &p_package, String *r_error) const { @@ -2477,7 +2476,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP return ERR_UNCONFIGURED; } } - const String assets_directory = get_assets_directory(p_preset); + const String assets_directory = get_assets_directory(p_preset, export_format); String sdk_path = EDITOR_GET("export/android/android_sdk_path"); ERR_FAIL_COND_V_MSG(sdk_path.is_empty(), ERR_UNCONFIGURED, "Android SDK path must be configured in Editor Settings at 'export/android/android_sdk_path'."); print_verbose("Android sdk path: " + sdk_path); diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h index d33f616f11..e0ffaa718b 100644 --- a/platform/android/export/export_plugin.h +++ b/platform/android/export/export_plugin.h @@ -104,7 +104,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { String get_package_name(const String &p_package) const; - String get_assets_directory(const Ref<EditorExportPreset> &p_preset) const; + String get_assets_directory(const Ref<EditorExportPreset> &p_preset, int p_export_format) const; bool is_package_name_valid(const String &p_package, String *r_error = nullptr) const; diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 21fb31d991..034885aa32 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -230,10 +230,13 @@ String OS_Android::get_user_data_dir() const { } String OS_Android::get_cache_path() const { + if (cache_dir_cache != String()) + return cache_dir_cache; + String cache_dir = godot_io_java->get_cache_dir(); if (cache_dir != "") { - cache_dir = _remove_symlink(cache_dir); - return cache_dir; + cache_dir_cache = _remove_symlink(cache_dir); + return cache_dir_cache; } return "."; } diff --git a/platform/android/os_android.h b/platform/android/os_android.h index c938297821..ce8083388f 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -57,6 +57,7 @@ private: #endif mutable String data_dir_cache; + mutable String cache_dir_cache; AudioDriverOpenSL audio_driver_android; diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm index d10ea5c68c..c6f91665c5 100644 --- a/platform/iphone/app_delegate.mm +++ b/platform/iphone/app_delegate.mm @@ -44,7 +44,7 @@ extern int gargc; extern char **gargv; -extern int iphone_main(int, char **, String); +extern int iphone_main(int, char **, String, String); extern void iphone_finish(); @implementation AppDelegate @@ -67,8 +67,10 @@ static ViewController *mainViewController = nil; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; + paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); + NSString *cacheDirectory = [paths objectAtIndex:0]; - int err = iphone_main(gargc, gargv, String::utf8([documentsDirectory UTF8String])); + int err = iphone_main(gargc, gargv, String::utf8([documentsDirectory UTF8String]), String::utf8([cacheDirectory UTF8String])); if (err != 0) { // bail, things did not go very well for us, should probably output a message on screen with our error code... diff --git a/platform/iphone/godot_iphone.mm b/platform/iphone/godot_iphone.mm index 6c3e1eabde..6f6f9d0708 100644 --- a/platform/iphone/godot_iphone.mm +++ b/platform/iphone/godot_iphone.mm @@ -74,7 +74,7 @@ int add_cmdline(int p_argc, char **p_args) { return p_argc; }; -int iphone_main(int argc, char **argv, String data_dir) { +int iphone_main(int argc, char **argv, String data_dir, String cache_dir) { size_t len = strlen(argv[0]); while (len--) { @@ -95,7 +95,7 @@ int iphone_main(int argc, char **argv, String data_dir) { char cwd[512]; getcwd(cwd, sizeof(cwd)); printf("cwd %s\n", cwd); - os = new OSIPhone(data_dir); + os = new OSIPhone(data_dir, cache_dir); // We must override main when testing is enabled TEST_MAIN_OVERRIDE diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index 248369369d..7a81d8f593 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -72,6 +72,7 @@ private: virtual void finalize() override; String user_data_dir; + String cache_dir; bool is_focused = false; @@ -80,7 +81,7 @@ private: public: static OSIPhone *get_singleton(); - OSIPhone(String p_data_dir); + OSIPhone(String p_data_dir, String p_cache_dir); ~OSIPhone(); void initialize_modules(); @@ -103,6 +104,8 @@ public: void set_user_data_dir(String p_dir); virtual String get_user_data_dir() const override; + virtual String get_cache_path() const override; + virtual String get_locale() const override; virtual String get_unique_id() const override; diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm index c88d253691..fc07d321b7 100644 --- a/platform/iphone/os_iphone.mm +++ b/platform/iphone/os_iphone.mm @@ -87,7 +87,7 @@ OSIPhone *OSIPhone::get_singleton() { return (OSIPhone *)OS::get_singleton(); } -OSIPhone::OSIPhone(String p_data_dir) { +OSIPhone::OSIPhone(String p_data_dir, String p_cache_dir) { for (int i = 0; i < ios_init_callbacks_count; ++i) { ios_init_callbacks[i](); } @@ -101,6 +101,7 @@ OSIPhone::OSIPhone(String p_data_dir) { // can't call set_data_dir from here, since it requires DirAccess // which is initialized in initialize_core user_data_dir = p_data_dir; + cache_dir = p_cache_dir; Vector<Logger *> loggers; loggers.push_back(memnew(SyslogLogger)); @@ -266,6 +267,10 @@ String OSIPhone::get_user_data_dir() const { return user_data_dir; } +String OSIPhone::get_cache_path() const { + return cache_dir; +} + String OSIPhone::get_locale() const { NSString *preferedLanguage = [NSLocale preferredLanguages].firstObject; diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index c03b600f2e..6c02bf1e16 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -677,18 +677,27 @@ String OS_Windows::get_data_path() const { } String OS_Windows::get_cache_path() const { - // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well. - if (has_environment("XDG_CACHE_HOME")) { - if (get_environment("XDG_CACHE_HOME").is_absolute_path()) { - return get_environment("XDG_CACHE_HOME").replace("\\", "/"); - } else { - WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `%TEMP%` or `get_config_path()` per the XDG Base Directory specification."); + static String cache_path_cache; + if (cache_path_cache.is_empty()) { + // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well. + if (has_environment("XDG_CACHE_HOME")) { + if (get_environment("XDG_CACHE_HOME").is_absolute_path()) { + cache_path_cache = get_environment("XDG_CACHE_HOME").replace("\\", "/"); + } else { + WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `%LOCALAPPDATA%\\cache`, `%TEMP%` or `get_config_path()` per the XDG Base Directory specification."); + } + } + if (cache_path_cache.is_empty() && has_environment("LOCALAPPDATA")) { + cache_path_cache = get_environment("LOCALAPPDATA").replace("\\", "/"); + } + if (cache_path_cache.is_empty() && has_environment("TEMP")) { + cache_path_cache = get_environment("TEMP").replace("\\", "/"); + } + if (cache_path_cache.is_empty()) { + cache_path_cache = get_config_path(); } } - if (has_environment("TEMP")) { - return get_environment("TEMP").replace("\\", "/"); - } - return get_config_path(); + return cache_path_cache; } // Get properly capitalized engine name for system paths diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index bddc342c1a..18a50ae098 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -68,7 +68,7 @@ void AudioStreamPlayer2D::_notification(int p_what) { active.set(); Ref<AudioStreamPlayback> new_playback = stream->instance_playback(); ERR_FAIL_COND_MSG(new_playback.is_null(), "Failed to instantiate playback."); - AudioServer::get_singleton()->start_playback_stream(new_playback, _get_actual_bus(), volume_vector, setplay.get()); + AudioServer::get_singleton()->start_playback_stream(new_playback, _get_actual_bus(), volume_vector, setplay.get(), pitch_scale); stream_playbacks.push_back(new_playback); setplay.set(-1); } diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index a54b10ba70..c422070480 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -282,7 +282,7 @@ void AudioStreamPlayer3D::_notification(int p_what) { ERR_FAIL_COND_MSG(new_playback.is_null(), "Failed to instantiate playback."); Map<StringName, Vector<AudioFrame>> bus_map; bus_map[_get_actual_bus()] = volume_vector; - AudioServer::get_singleton()->start_playback_stream(new_playback, bus_map, setplay.get(), linear_attenuation, attenuation_filter_cutoff_hz, actual_pitch_scale); + AudioServer::get_singleton()->start_playback_stream(new_playback, bus_map, setplay.get(), actual_pitch_scale, linear_attenuation, attenuation_filter_cutoff_hz); stream_playbacks.push_back(new_playback); setplay.set(-1); } diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp index 0334ba667b..d2fd65d3d9 100644 --- a/scene/audio/audio_stream_player.cpp +++ b/scene/audio/audio_stream_player.cpp @@ -135,7 +135,7 @@ void AudioStreamPlayer::play(float p_from_pos) { Ref<AudioStreamPlayback> stream_playback = stream->instance_playback(); ERR_FAIL_COND_MSG(stream_playback.is_null(), "Failed to instantiate playback."); - AudioServer::get_singleton()->start_playback_stream(stream_playback, bus, _get_volume_vector(), p_from_pos); + AudioServer::get_singleton()->start_playback_stream(stream_playback, bus, _get_volume_vector(), p_from_pos, pitch_scale); stream_playbacks.push_back(stream_playback); active.set(); set_process_internal(true); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 653885aa08..54e7d8f960 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -241,7 +241,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { _reset_caret_blink_timer(); if (b->is_pressed()) { - accept_event(); //don't pass event further when clicked on text field + accept_event(); // don't pass event further when clicked on text field if (!text.is_empty() && is_editable() && _is_over_clear_button(b->get_position())) { clear_button_status.press_attempt = true; clear_button_status.pressing_inside = true; @@ -1931,7 +1931,7 @@ void LineEdit::_shape() { TS->shaped_text_clear(text_rid); String t; - if (text.length() == 0) { + if (text.length() == 0 && ime_text.length() == 0) { t = placeholder_translated; } else if (pass) { t = secret_character.repeat(text.length() + ime_text.length()); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 3ab6e12e01..0e62e6e30a 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1079,8 +1079,11 @@ Transform2D Viewport::_get_input_pre_xform() const { } Ref<InputEvent> Viewport::_make_input_local(const Ref<InputEvent> &ev) { - Transform2D ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); + if (ev.is_null()) { + return ev; // No transformation defined for null event + } + Transform2D ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); return ev->xformed_by(ai); } @@ -2878,9 +2881,8 @@ bool Viewport::gui_is_dragging() const { void Viewport::set_input_as_handled() { _drop_physics_mouseover(); - if (handle_input_locally) { - local_input_handled = true; - } else { + + if (!handle_input_locally) { ERR_FAIL_COND(!is_inside_tree()); Viewport *vp = this; while (true) { @@ -2892,16 +2894,19 @@ void Viewport::set_input_as_handled() { } vp = vp->get_parent()->get_viewport(); } - vp->set_input_as_handled(); + if (vp != this) { + vp->set_input_as_handled(); + return; + } } + + local_input_handled = true; } bool Viewport::is_input_handled() const { - if (handle_input_locally) { - return local_input_handled; - } else { - const Viewport *vp = this; + if (!handle_input_locally) { ERR_FAIL_COND_V(!is_inside_tree(), false); + const Viewport *vp = this; while (true) { if (Object::cast_to<Window>(vp)) { break; @@ -2911,8 +2916,11 @@ bool Viewport::is_input_handled() const { } vp = vp->get_parent()->get_viewport(); } - return vp->is_input_handled(); + if (vp != this) { + return vp->is_input_handled(); + } } + return local_input_handled; } void Viewport::set_handle_input_locally(bool p_enable) { diff --git a/scene/resources/importer_mesh.cpp b/scene/resources/importer_mesh.cpp index af69b799cc..2572c5de33 100644 --- a/scene/resources/importer_mesh.cpp +++ b/scene/resources/importer_mesh.cpp @@ -37,26 +37,34 @@ #include <cstdint> void ImporterMesh::Surface::split_normals(const LocalVector<int> &p_indices, const LocalVector<Vector3> &p_normals) { - ERR_FAIL_COND(arrays.size() != RS::ARRAY_MAX); + _split_normals(arrays, p_indices, p_normals); - const PackedVector3Array &vertices = arrays[RS::ARRAY_VERTEX]; + for (BlendShape &blend_shape : blend_shape_data) { + _split_normals(blend_shape.arrays, p_indices, p_normals); + } +} + +void ImporterMesh::Surface::_split_normals(Array &r_arrays, const LocalVector<int> &p_indices, const LocalVector<Vector3> &p_normals) { + ERR_FAIL_COND(r_arrays.size() != RS::ARRAY_MAX); + + const PackedVector3Array &vertices = r_arrays[RS::ARRAY_VERTEX]; int current_vertex_count = vertices.size(); int new_vertex_count = p_indices.size(); int final_vertex_count = current_vertex_count + new_vertex_count; const int *indices_ptr = p_indices.ptr(); - for (int i = 0; i < arrays.size(); i++) { + for (int i = 0; i < r_arrays.size(); i++) { if (i == RS::ARRAY_INDEX) { continue; } - if (arrays[i].get_type() == Variant::NIL) { + if (r_arrays[i].get_type() == Variant::NIL) { continue; } - switch (arrays[i].get_type()) { + switch (r_arrays[i].get_type()) { case Variant::PACKED_VECTOR3_ARRAY: { - PackedVector3Array data = arrays[i]; + PackedVector3Array data = r_arrays[i]; data.resize(final_vertex_count); Vector3 *data_ptr = data.ptrw(); if (i == RS::ARRAY_NORMAL) { @@ -67,55 +75,55 @@ void ImporterMesh::Surface::split_normals(const LocalVector<int> &p_indices, con data_ptr[current_vertex_count + j] = data_ptr[indices_ptr[j]]; } } - arrays[i] = data; + r_arrays[i] = data; } break; case Variant::PACKED_VECTOR2_ARRAY: { - PackedVector2Array data = arrays[i]; + PackedVector2Array data = r_arrays[i]; data.resize(final_vertex_count); Vector2 *data_ptr = data.ptrw(); for (int j = 0; j < new_vertex_count; j++) { data_ptr[current_vertex_count + j] = data_ptr[indices_ptr[j]]; } - arrays[i] = data; + r_arrays[i] = data; } break; case Variant::PACKED_FLOAT32_ARRAY: { - PackedFloat32Array data = arrays[i]; + PackedFloat32Array data = r_arrays[i]; int elements = data.size() / current_vertex_count; data.resize(final_vertex_count * elements); float *data_ptr = data.ptrw(); for (int j = 0; j < new_vertex_count; j++) { memcpy(&data_ptr[(current_vertex_count + j) * elements], &data_ptr[indices_ptr[j] * elements], sizeof(float) * elements); } - arrays[i] = data; + r_arrays[i] = data; } break; case Variant::PACKED_INT32_ARRAY: { - PackedInt32Array data = arrays[i]; + PackedInt32Array data = r_arrays[i]; int elements = data.size() / current_vertex_count; data.resize(final_vertex_count * elements); int32_t *data_ptr = data.ptrw(); for (int j = 0; j < new_vertex_count; j++) { memcpy(&data_ptr[(current_vertex_count + j) * elements], &data_ptr[indices_ptr[j] * elements], sizeof(int32_t) * elements); } - arrays[i] = data; + r_arrays[i] = data; } break; case Variant::PACKED_BYTE_ARRAY: { - PackedByteArray data = arrays[i]; + PackedByteArray data = r_arrays[i]; int elements = data.size() / current_vertex_count; data.resize(final_vertex_count * elements); uint8_t *data_ptr = data.ptrw(); for (int j = 0; j < new_vertex_count; j++) { memcpy(&data_ptr[(current_vertex_count + j) * elements], &data_ptr[indices_ptr[j] * elements], sizeof(uint8_t) * elements); } - arrays[i] = data; + r_arrays[i] = data; } break; case Variant::PACKED_COLOR_ARRAY: { - PackedColorArray data = arrays[i]; + PackedColorArray data = r_arrays[i]; data.resize(final_vertex_count); Color *data_ptr = data.ptrw(); for (int j = 0; j < new_vertex_count; j++) { data_ptr[current_vertex_count + j] = data_ptr[indices_ptr[j]]; } - arrays[i] = data; + r_arrays[i] = data; } break; default: { ERR_FAIL_MSG("Unhandled array type."); @@ -261,9 +269,6 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli if (surfaces[i].primitive != Mesh::PRIMITIVE_TRIANGLES) { continue; } - if (get_blend_shape_count()) { - continue; - } surfaces.write[i].lods.clear(); Vector<Vector3> vertices = surfaces[i].arrays[RS::ARRAY_VERTEX]; diff --git a/scene/resources/importer_mesh.h b/scene/resources/importer_mesh.h index 89909f17f0..8576312a8a 100644 --- a/scene/resources/importer_mesh.h +++ b/scene/resources/importer_mesh.h @@ -70,6 +70,7 @@ class ImporterMesh : public Resource { }; void split_normals(const LocalVector<int> &p_indices, const LocalVector<Vector3> &p_normals); + static void _split_normals(Array &r_arrays, const LocalVector<int> &p_indices, const LocalVector<Vector3> &p_normals); }; Vector<Surface> surfaces; Vector<String> blend_shapes; diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index e19ca38b82..f5e52b70e6 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -171,6 +171,8 @@ void TileSet::set_source_id(int p_source_id, int p_new_source_id) { source_ids.append(p_new_source_id); source_ids.sort(); + _compute_next_source_id(); + emit_changed(); } diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index ac1569c15d..a420134626 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -1112,16 +1112,16 @@ float AudioServer::get_playback_speed_scale() const { return playback_speed_scale; } -void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time) { +void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time, float p_pitch_scale) { ERR_FAIL_COND(p_playback.is_null()); Map<StringName, Vector<AudioFrame>> map; map[p_bus] = p_volume_db_vector; - start_playback_stream(p_playback, map, p_start_time); + start_playback_stream(p_playback, map, p_start_time, p_pitch_scale); } -void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time, float p_highshelf_gain, float p_attenuation_cutoff_hz, float p_pitch_scale) { +void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time, float p_pitch_scale, float p_highshelf_gain, float p_attenuation_cutoff_hz) { ERR_FAIL_COND(p_playback.is_null()); AudioStreamPlaybackListNode *playback_node = new AudioStreamPlaybackListNode(); diff --git a/servers/audio_server.h b/servers/audio_server.h index a60d4ae4c4..46873845dc 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -368,9 +368,9 @@ public: float get_playback_speed_scale() const; // Convenience method. - void start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time = 0); + void start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time = 0, float p_pitch_scale = 1); // Expose all parameters. - void start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time = 0, float p_highshelf_gain = 0, float p_attenuation_cutoff_hz = 0, float p_pitch_scale = 1); + void start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time = 0, float p_pitch_scale = 1, float p_highshelf_gain = 0, float p_attenuation_cutoff_hz = 0); void stop_playback_stream(Ref<AudioStreamPlayback> p_playback); void set_playback_bus_exclusive(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volumes); diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index f3db4abe3b..4d466342f8 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -97,6 +97,11 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #endif inout vec3 diffuse_light, inout vec3 specular_light) { + vec4 orms_unpacked = unpackUnorm4x8(orms); + + float roughness = orms_unpacked.y; + float metallic = orms_unpacked.z; + #if defined(LIGHT_CODE_USED) // light is written by the light shader @@ -125,9 +130,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte float cLdotH = clamp(A + dot(L, H), 0.0, 1.0); #endif - float metallic = unpackUnorm4x8(orms).z; if (metallic < 1.0) { - float roughness = unpackUnorm4x8(orms).y; float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance #if defined(DIFFUSE_LAMBERT_WRAP) @@ -199,7 +202,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #endif //LIGHT_TRANSMITTANCE_USED } - float roughness = unpackUnorm4x8(orms).y; if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely // D @@ -211,7 +213,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte float blinn = pow(cNdotH, shininess); blinn *= (shininess + 2.0) * (1.0 / (8.0 * M_PI)); - specular_light += light_color * attenuation * specular_amount * blinn * f0 * unpackUnorm4x8(orms).w; + specular_light += light_color * attenuation * specular_amount * blinn * f0 * orms_unpacked.w; #elif defined(SPECULAR_PHONG) @@ -221,7 +223,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte float phong = pow(cRdotV, shininess); phong *= (shininess + 1.0) * (1.0 / (8.0 * M_PI)); - specular_light += light_color * attenuation * specular_amount * phong * f0 * unpackUnorm4x8(orms).w; + specular_light += light_color * attenuation * specular_amount * phong * f0 * orms_unpacked.w; #elif defined(SPECULAR_TOON) diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index ebebb849d0..81a9e00d7c 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -1599,7 +1599,8 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type } const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { - //constructors + // Constructors. + { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, @@ -1672,7 +1673,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "mat3", TYPE_MAT3, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, { "mat4", TYPE_MAT4, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, - //conversion scalars + // Conversion scalars. { "int", TYPE_INT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, { "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, @@ -1694,7 +1695,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "bool", TYPE_BOOL, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true }, { "bool", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, - //conversion vectors + // Conversion vectors. { "ivec2", TYPE_IVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, { "ivec2", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, @@ -1756,7 +1757,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true }, { "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, - //conversion between matrixes + // Conversion between matrixes. { "mat2", TYPE_MAT2, { TYPE_MAT3, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, { "mat2", TYPE_MAT2, { TYPE_MAT4, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, @@ -1765,43 +1766,58 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "mat4", TYPE_MAT4, { TYPE_MAT2, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, { "mat4", TYPE_MAT4, { TYPE_MAT3, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, - //builtins - trigonometry + // Built-ins - trigonometric functions. + // radians { "radians", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false }, { "radians", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false }, { "radians", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false }, { "radians", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false }, + // degrees + { "degrees", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false }, { "degrees", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false }, { "degrees", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false }, { "degrees", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false }, + // sin + { "sin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "sin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "sin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "sin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, + // cos + { "cos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "cos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "cos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "cos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, + // tan + { "tan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "tan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "tan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "tan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, + // asin + { "asin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "asin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "asin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "asin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // acos + { "acos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "acos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "acos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "acos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // atan + { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "y_over_x" }, TAG_GLOBAL, false }, { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "y_over_x" }, TAG_GLOBAL, false }, { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "y_over_x" }, TAG_GLOBAL, false }, @@ -1811,66 +1827,101 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "y", "x" }, TAG_GLOBAL, false }, { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "y", "x" }, TAG_GLOBAL, false }, + // sinh + { "sinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // cosh + { "cosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "cosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "cosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "cosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // tanh + { "tanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "tanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "tanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "tanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // asinh + { "asinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "asinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "asinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "asinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // acosh + { "acosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "acosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "acosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "acosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // atanh + { "atanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "atanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "atanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "atanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, - //builtins - exponential + // Builtins - exponential functions. + // pow + { "pow", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, { "pow", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, { "pow", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, { "pow", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, + + // exp + { "exp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "exp", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "exp", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "exp", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // log + { "log", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "log", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "log", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "log", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // exp2 + { "exp2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "exp2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "exp2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "exp2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // log2 + { "log2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "log2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "log2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "log2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // sqrt + { "sqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // inversesqrt + { "inversesqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "inversesqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "inversesqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "inversesqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, - //builtins - common + + // Built-ins - common functions. + // abs + { "abs", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "abs", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "abs", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, @@ -1881,6 +1932,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "abs", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "abs", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // sign + { "sign", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sign", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sign", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, @@ -1891,31 +1944,50 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "sign", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sign", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // floor + { "floor", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "floor", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "floor", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "floor", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // trunc + { "trunc", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "trunc", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "trunc", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "trunc", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // round + { "round", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "round", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "round", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "round", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // roundEven + { "roundEven", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "roundEven", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "roundEven", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "roundEven", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // ceil + { "ceil", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "ceil", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "ceil", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "ceil", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // fract + { "fract", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "fract", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "fract", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "fract", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // mod + { "mod", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, @@ -1924,11 +1996,15 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, + // modf + { "modf", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true }, { "modf", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true }, { "modf", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true }, { "modf", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true }, + // min + { "min", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, @@ -1953,6 +2029,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, + // max + { "max", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, @@ -1977,6 +2055,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, + // clamp + { "clamp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false }, { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false }, { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false }, @@ -2001,6 +2081,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true }, { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true }, + // mix + { "mix", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false }, { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false }, { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_BVEC2, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false }, @@ -2012,6 +2094,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BVEC4, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false }, { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false }, + // step + { "step", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false }, { "step", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false }, { "step", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false }, @@ -2019,6 +2103,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "step", TYPE_VEC2, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false }, { "step", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false }, { "step", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false }, + + // smoothstep + { "smoothstep", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false }, { "smoothstep", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false }, { "smoothstep", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false }, @@ -2027,77 +2114,127 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "smoothstep", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false }, { "smoothstep", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false }, + // isnan + { "isnan", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "isnan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "isnan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "isnan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // isinf + { "isinf", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "isinf", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "isinf", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "isinf", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // floatBitsToInt + { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, + // floatBitsToUint + { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, + // intBitsToFloat + { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "intBitsToFloat", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "intBitsToFloat", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, + // uintBitsToFloat + { "uintBitsToFloat", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "uintBitsToFloat", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "uintBitsToFloat", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "uintBitsToFloat", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, - //builtins - geometric + // Built-ins - geometric functions. + // length + + { "length", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "length", TYPE_FLOAT, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "length", TYPE_FLOAT, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "length", TYPE_FLOAT, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // distance + + { "distance", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "distance", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "distance", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "distance", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, + + // dot + + { "dot", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "dot", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "dot", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "dot", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, + + // cross + { "cross", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, + + // normalize + + { "normalize", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false }, { "normalize", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, false }, { "normalize", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "v" }, TAG_GLOBAL, false }, { "normalize", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, false }, + + // reflect + { "reflect", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false }, + + // refract + { "refract", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false }, + // faceforward + { "faceforward", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "N", "I", "Nref" }, TAG_GLOBAL, false }, { "faceforward", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "N", "I", "Nref" }, TAG_GLOBAL, false }, { "faceforward", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "N", "I", "Nref" }, TAG_GLOBAL, false }, + // matrixCompMult + { "matrixCompMult", TYPE_MAT2, { TYPE_MAT2, TYPE_MAT2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "matrixCompMult", TYPE_MAT3, { TYPE_MAT3, TYPE_MAT3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "matrixCompMult", TYPE_MAT4, { TYPE_MAT4, TYPE_MAT4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, + // outerProduct + { "outerProduct", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "c", "r" }, TAG_GLOBAL, false }, { "outerProduct", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "c", "r" }, TAG_GLOBAL, false }, { "outerProduct", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "c", "r" }, TAG_GLOBAL, false }, + // transpose + { "transpose", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, { "transpose", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, { "transpose", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, + // determinant + { "determinant", TYPE_FLOAT, { TYPE_MAT2, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, { "determinant", TYPE_FLOAT, { TYPE_MAT3, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, { "determinant", TYPE_FLOAT, { TYPE_MAT4, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, + // inverse + { "inverse", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, { "inverse", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, { "inverse", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, + // lessThan + { "lessThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "lessThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "lessThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, @@ -2110,6 +2247,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "lessThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, { "lessThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, + // greaterThan + { "greaterThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "greaterThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "greaterThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, @@ -2122,6 +2261,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "greaterThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, { "greaterThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, + // lessThanEqual + { "lessThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "lessThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "lessThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, @@ -2134,6 +2275,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "lessThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, { "lessThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, + // greaterThanEqual + { "greaterThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "greaterThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "greaterThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, @@ -2146,6 +2289,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "greaterThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, { "greaterThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, + // equal + { "equal", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "equal", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "equal", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, @@ -2162,6 +2307,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "equal", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "equal", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, + // notEqual + { "notEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "notEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "notEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, @@ -2178,19 +2325,27 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "notEqual", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "notEqual", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, + // any + { "any", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "any", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "any", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // all + { "all", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "all", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "all", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // not + { "not", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "not", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "not", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, - //builtins - texture + // Built-ins: texture functions. + // textureSize + { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true }, { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true }, { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true }, @@ -2203,6 +2358,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true }, { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBEARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true }, + // texture + { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false }, { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false }, { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true }, @@ -2226,6 +2383,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false }, { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false }, + // textureProj + { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true }, { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true }, { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true }, @@ -2245,6 +2404,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true }, { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true }, + // textureLod + { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false }, { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, @@ -2257,6 +2418,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false }, { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false }, + // texelFetch + { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, @@ -2267,6 +2430,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, + // textureProjLod + { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, @@ -2277,6 +2442,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, + // textureGrad + { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true }, { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true }, { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true }, @@ -2289,39 +2456,148 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true }, { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true }, + // dFdx + { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + // dFdy + { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "dFdy", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + // fwidth + { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "fwidth", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, - //sub-functions + // Sub-functions. + // array - //array { "length", TYPE_INT, { TYPE_VOID }, { "" }, TAG_ARRAY, true }, - // modern functions + // Modern functions. + // fma { "fma", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false }, { "fma", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false }, { "fma", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false }, { "fma", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false }, + // Packing/Unpacking functions. + + { "packHalf2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + { "packUnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + { "packSnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + { "packUnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + { "packSnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + + { "unpackHalf2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + { "unpackUnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + { "unpackSnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + { "unpackUnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + { "unpackSnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + + // bitfieldExtract + + { "bitfieldExtract", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldExtract", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldExtract", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldExtract", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true }, + + { "bitfieldExtract", TYPE_UINT, { TYPE_UINT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldExtract", TYPE_UVEC2, { TYPE_UVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldExtract", TYPE_UVEC3, { TYPE_UVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldExtract", TYPE_UVEC4, { TYPE_UVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true }, + + // bitfieldInsert + + { "bitfieldInsert", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldInsert", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldInsert", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldInsert", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true }, + + { "bitfieldInsert", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldInsert", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldInsert", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldInsert", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true }, + + // bitfieldReverse + + { "bitfieldReverse", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitfieldReverse", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitfieldReverse", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitfieldReverse", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + + { "bitfieldReverse", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitfieldReverse", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitfieldReverse", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitfieldReverse", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + + // bitCount + + { "bitCount", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitCount", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitCount", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitCount", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + + { "bitCount", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitCount", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitCount", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitCount", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + + // findLSB + + { "findLSB", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findLSB", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findLSB", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findLSB", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + + { "findLSB", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findLSB", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findLSB", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findLSB", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + + // findMSB + + { "findMSB", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findMSB", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findMSB", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findMSB", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + + { "findMSB", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findMSB", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findMSB", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findMSB", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + + // uaddCarry + + { "uaddCarry", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "y", "carry" }, TAG_GLOBAL, true }, + { "uaddCarry", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "y", "carry" }, TAG_GLOBAL, true }, + { "uaddCarry", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "y", "carry" }, TAG_GLOBAL, true }, + { "uaddCarry", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "y", "carry" }, TAG_GLOBAL, true }, + + // usubBorrow + + { "usubBorrow", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true }, + { "usubBorrow", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true }, + { "usubBorrow", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true }, + { "usubBorrow", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true }, + { nullptr, TYPE_VOID, { TYPE_VOID }, { "" }, TAG_GLOBAL, false } }; const ShaderLanguage::BuiltinFuncOutArgs ShaderLanguage::builtin_func_out_args[] = { //constructors { "modf", 1 }, + { "uaddCarry", 2 }, + { "usubBorrow", 2 }, { nullptr, 0 } }; diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 7e66ddbb0f..b3efe840b6 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -934,7 +934,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa } } - ERR_FAIL_COND_V_MSG((bsformat) != (format & (ARRAY_FORMAT_VERTEX | ARRAY_FORMAT_NORMAL | ARRAY_FORMAT_TANGENT)), ERR_INVALID_PARAMETER, "Blend shape format must match the main array format for Vertex, Normal and Tangent arrays."); + ERR_FAIL_COND_V_MSG((bsformat & RS::ARRAY_FORMAT_BLEND_SHAPE_MASK) != (format & RS::ARRAY_FORMAT_BLEND_SHAPE_MASK), ERR_INVALID_PARAMETER, "Blend shape format must match the main array format for Vertex, Normal and Tangent arrays."); } } |