diff options
545 files changed, 11706 insertions, 5622 deletions
diff --git a/AUTHORS.md b/AUTHORS.md index 4d6d8919f7..430596e611 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -55,6 +55,7 @@ name is available. bruvzg Cameron Reikes (creikey) Camille Mohr-Daurat (pouleyKetchoupp) + Caner Demirer (cdemirer) Carl Olsson (not-surt) Carter Anderson (cart) Chris Bradfield (cbscribe) @@ -147,6 +148,7 @@ name is available. Marcus Elg (MCrafterzz) Mariano Javier Suligoy (MarianoGnu) Mario Schlack (hurikhan) + Marios Staikopoulos (marstaik) Martin Capitanio (capnm) Martin Liška (marxin) Martin Sjursen (binbitten) @@ -160,6 +162,7 @@ name is available. Meru Patel (Janglee123) Michael Alexsander (YeldhamDev) MichiRecRoom (LikeLakers2) + Morris "Tabor" Arroad (mortarroad) mrezai muiroc Nathan Franke (nathanfranke) @@ -169,6 +172,7 @@ name is available. Nils André-Chang (NilsIrl) Noah Beard (TwistedTwigleg) Nuno Donato (nunodonato) + Omar El Sheikh (The-O-King) Ovnuniarchos Pascal Richter (ShyRed) Patrick (firefly2442) diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index f3611fe83d..368e321a2d 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -171,17 +171,16 @@ Comment: DroidSans font Copyright: 2008, The Android Open Source Project License: Apache-2.0 +Files: ./thirdparty/fonts/JetBrainsMono_Regular.ttf +Comment: JetBrains Mono font +Copyright: 2020, JetBrains s.r.o. +License: OFL-1.1 + Files: ./thirdparty/fonts/NotoSans*.ttf Comment: Noto Sans font Copyright: 2012, Google Inc. License: OFL-1.1 -Files: ./thirdparty/fonts/Hack_Regular.ttf -Comment: Hack font -Copyright: 2018, Source Foundry Authors - 2003, Bitstream Inc. -License: Expat and Bitstream Vera Fonts Copyright - Files: ./thirdparty/freetype/ Comment: The FreeType Project Copyright: 1996-2021, David Turner, Robert Wilhelm, and Werner Lemberg. @@ -42,9 +42,9 @@ generous deed immortalized in the next stable release of Godot Engine. ## Mini sponsors AD Ford + Andres Hernandez Andrew Bowen Andrew Dunai - Angry Skull anti666 blurp Christian Baune @@ -86,15 +86,12 @@ generous deed immortalized in the next stable release of Godot Engine. Steve Thomas Krampl Violin Iliev - Xwdit - Zetaphor ## Gold donors Acheron Adam Brown albinaask - Andres Hernandez Arisaka Mayuki Asher Glick Barugon @@ -107,6 +104,7 @@ generous deed immortalized in the next stable release of Godot Engine. First Last Florian Rämisch Gamejunkey + Hunter Jones Jacobus Dens Jakub Grzesik Javier Roman @@ -118,12 +116,11 @@ generous deed immortalized in the next stable release of Godot Engine. Maciej Pendolski Manuele Finocchiaro Markus Wiesner + Mateo Navarrete Mathieu Matthew Hillier - Mick Officine Pixel S.n.c. Patrick Brock - Paul E Hansen Pedro Silva Retro Village Rob Messick @@ -161,11 +158,9 @@ generous deed immortalized in the next stable release of Godot Engine. Arch Henderson III Arthur S. Muszynski Brandon Hawkinson - Caleb Sizemore Cameron Connolly Charlie Whitfield Chase Taranto - Chelsea Hash Chris Petrich Chris Serino Cow @@ -182,10 +177,10 @@ generous deed immortalized in the next stable release of Godot Engine. Darrian Little Dennis Belfrage Dev To be curious + Dima Fedotov Dimitri Nüscheler Donn Eddy Douglas Hammond - Edgar Sun Eric Brand Eugenio Hugo Salgüero Jáñez EXUREI @@ -193,6 +188,7 @@ generous deed immortalized in the next stable release of Godot Engine. flesk foxydevloper Fransiska + Freeman Gabrielius Vaiškūnas Gary Hulst gavlig @@ -211,6 +207,7 @@ generous deed immortalized in the next stable release of Godot Engine. Hunter Barabas HurrieCrane Jake Burga + Jamal Bencharki James Couzens Jan Sælid Jared @@ -256,8 +253,8 @@ generous deed immortalized in the next stable release of Godot Engine. medecau Michael Dürwald Michael Policastro + Michael Seawell MikadoSC - Mike B Mike Barbee nate etan Nick Abousselam @@ -273,6 +270,7 @@ generous deed immortalized in the next stable release of Godot Engine. Petr Malac PhaineOfCatz Piotr Wyszyński + Rafał Michno Raymond Harris Reilt Rene Tailleur @@ -283,7 +281,7 @@ generous deed immortalized in the next stable release of Godot Engine. Robert Willes Rob McInroy Rocknight Studios - Rod Zilla + RodZilla Romeo Disca Ronnie Ashlock Ronny Mühle @@ -301,7 +299,6 @@ generous deed immortalized in the next stable release of Godot Engine. SKison Song Junwoo spacechase0 - SpiderGlitch_2002 Stephan Hennion Stephen Brown Steven Landow @@ -332,11 +329,11 @@ generous deed immortalized in the next stable release of Godot Engine. Yifan Lai Yuancheng Zhang Zie Weaver + Артём Равбецкий ## Silver donors 1D_Inc - Aaron Mayfield Aaron Oldenburg A. B. Adam Brunnmeier @@ -349,13 +346,11 @@ generous deed immortalized in the next stable release of Godot Engine. Adisibio Adrien de Pierres Agustinus Arya - Ahmet Kalyoncu Aidan O'Flannagain Aki Mimoto Alan Beauchamp Alberto Salazar Muñoz Alberto Vilches - Albin Jonasson Svärdsby Alder Stefano Alejandro Saucedo AleMax @@ -386,15 +381,15 @@ generous deed immortalized in the next stable release of Godot Engine. Arturo Rosales Ashley Claymore Aubrey Falconer + Auré Franky aurelien condomines Avner AzulCrescent b110110 Balázs Batári - Balázs Kondákor Bálint Horváth - Baptiste Le Bourhis bcat + Beau Seymour Benedikt Benoit Jauvin-Girard Ben Ridley @@ -405,7 +400,6 @@ generous deed immortalized in the next stable release of Godot Engine. bitbrain Bjarne Voigtländer Black Block - blackjacksike Blair Allen Blunderjack Bobby CC Wong @@ -425,7 +419,6 @@ generous deed immortalized in the next stable release of Godot Engine. Carl van der Geest Casey Cassidy James - Cédric Givord Chad Steadman Checkpoint Charlie Chris Chapin @@ -438,12 +431,12 @@ generous deed immortalized in the next stable release of Godot Engine. Christopher Chin Christoph Woinke Cody Parker + CoffeeFingers Conall O Conner Lane Corchari Craig Maloney Craig Post - C. R. Messen damucz Daniel Cheney Daren Scot Wilson @@ -456,7 +449,7 @@ generous deed immortalized in the next stable release of Godot Engine. Devin Carraway Diego Pereira Dimitri Roche - Dmitry Fisher + Dmitry Fisher (Raccoon path) Dmytro Korchynskyi Dominik Wetzel Don B @@ -465,7 +458,6 @@ generous deed immortalized in the next stable release of Godot Engine. Dr Ewan Murray Duobix Duodecimal - DurrDiss Eduardo Teixeira Edward Herbert Edward Swartz @@ -480,25 +472,22 @@ generous deed immortalized in the next stable release of Godot Engine. Erika Sanders Erkki Seppälä Faisal Alkubaisi - Fancy Ants Studios + Fault Boy fby Fekinox Felix Adam Felix Bohmann Fer DC Filip Lundby - Forty Doubleu Francisco Garcia Florez - Francois Holland Frank freakazoid FrostMarble Game Endeavor + Garett Bass Gary Thomas gebba George Marques - Georgi Petkov - Graham Overby Green Fox Greg Lincoln Greg Olson @@ -512,12 +501,14 @@ generous deed immortalized in the next stable release of Godot Engine. Haplo Hayden Foley Heribert Hirth + Hillel Taub-Tabib + Hinken Houdini Blueprints - Hunter Jones Ian ORourke Ian Williams IndustrialRobot iveks + izzy neuhaus Jackson Harmer Jacob D Jaguar @@ -533,6 +524,7 @@ generous deed immortalized in the next stable release of Godot Engine. Jamie Massey Janis Skuja Jan Vetulani + Japortie JARKKO PARVIAINEN Jason Bolton Jason Evans @@ -573,6 +565,7 @@ generous deed immortalized in the next stable release of Godot Engine. Juan Maggi Juan Uys Jueast + Julian le Roux Julian Murgia June Little Justin Hamilton @@ -580,6 +573,7 @@ generous deed immortalized in the next stable release of Godot Engine. Justin Oaksford Justin Spedding KaDokta + Katsuomi Kobayashi Keedong Park keeganstoybox Keinan Powers @@ -591,7 +585,6 @@ generous deed immortalized in the next stable release of Godot Engine. Ketafuki Kevin van Rooijen Kiri Jolly - Kjetil Haugland Kodera Software Kolandrious Konstantin Goncharov @@ -607,16 +600,16 @@ generous deed immortalized in the next stable release of Godot Engine. La diagonale du poulpe Lasse le Dous Laurent CHEA + Laurent Dethoor Laxman Pradhan LEMMiNO Leonardo Dimano - Lin Chear Linus Lind Lundgren Logan Apple Ludovic DELVAL Luigi Renna Luis Gaemperle - Luis M + Luke Kasz LunaticInAHat Major Haul Malcolm @@ -638,9 +631,11 @@ generous deed immortalized in the next stable release of Godot Engine. Maverick Max Fiedler Maxime Blade + Maxime Santerre Maxwell Melissa Mears Merlyn Morgan-Graham + Metal Demon 2000 mewin mhilbrunner Michael @@ -649,8 +644,6 @@ generous deed immortalized in the next stable release of Godot Engine. Michael Morrison Michael Toporkov Michał Skwarek - Michel Candries - MidoriBunn 'tis BS Mikael Nordenberg Mikayla Mike @@ -694,6 +687,7 @@ generous deed immortalized in the next stable release of Godot Engine. Pascal Patrick Indermühle Patrick Nafarrete + Paul E Hansen Paul Gieske Paweł Kowal Paweł Łyczkowski @@ -705,6 +699,7 @@ generous deed immortalized in the next stable release of Godot Engine. pj Point08 Preethi Vaidyanathan + PsycHead pwab RabidTunes RackBar Dingum @@ -730,19 +725,18 @@ generous deed immortalized in the next stable release of Godot Engine. Roger Smith Roglozor Roland Rząsa - Roman Tinkov Ronald Ho Hip (CrimsonZA) Ronan Roy Scayged Ryan Groom Sam Caulfield Sam Edson - Samuel Egger + Sammy Fischer Sangeeth Pavithran + schroedinger's possum Scott Longley Sean Wall Sebastian Michailidis - Sébastien SeongWan Kim Sessamekesh SeungJong k @@ -784,11 +778,12 @@ generous deed immortalized in the next stable release of Godot Engine. Thomas Bechtold Thomas Detoy Thomas Pickett - Tianren Qin + thommy Till1805 Tim Drumheller Tim Erskine Tim Gleason + Tim Klein Timothy B. MacDonald Title Plinsut TMoney @@ -798,7 +793,7 @@ generous deed immortalized in the next stable release of Godot Engine. Tom Webster Torgeir Lilleskog Torsten Crass - toupeira + TQQQ Travis O'Brien Trent Skinner tril zerobyte diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 9a3234d4a2..8d03f35617 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -623,7 +623,6 @@ void OS::_bind_methods() { // Those default values need to be specified for the docs generator, // to avoid using values from the documentation writer's own OS instance. - ADD_PROPERTY_DEFAULT("exit_code", 0); ADD_PROPERTY_DEFAULT("low_processor_usage_mode", false); ADD_PROPERTY_DEFAULT("low_processor_usage_mode_sleep_usec", 6900); diff --git a/core/core_constants.cpp b/core/core_constants.cpp index 6f26288eb7..2f5fd05e6a 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -584,6 +584,7 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_INT_IS_OBJECTID); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_INT_IS_POINTER); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ARRAY_TYPE); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALE_ID); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NONE); diff --git a/core/input/input.cpp b/core/input/input.cpp index fa2f00bf8d..7106bd0745 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -90,6 +90,7 @@ Input::MouseMode Input::get_mouse_mode() const { } void Input::_bind_methods() { + ClassDB::bind_method(D_METHOD("is_anything_pressed"), &Input::is_anything_pressed); ClassDB::bind_method(D_METHOD("is_key_pressed", "keycode"), &Input::is_key_pressed); ClassDB::bind_method(D_METHOD("is_physical_key_pressed", "keycode"), &Input::is_physical_key_pressed); ClassDB::bind_method(D_METHOD("is_mouse_button_pressed", "button"), &Input::is_mouse_button_pressed); @@ -218,6 +219,19 @@ Input::VelocityTrack::VelocityTrack() { reset(); } +bool Input::is_anything_pressed() const { + _THREAD_SAFE_METHOD_ + + for (Map<StringName, Input::Action>::Element *E = action_state.front(); E; E = E->next()) { + if (E->get().pressed) { + return true; + } + } + return !keys_pressed.is_empty() || + !joy_buttons_pressed.is_empty() || + mouse_button_mask > MouseButton::NONE; +} + bool Input::is_key_pressed(Key p_keycode) const { _THREAD_SAFE_METHOD_ return keys_pressed.has(p_keycode); @@ -504,18 +518,20 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em Ref<InputEventMouseMotion> mm = p_event; if (mm.is_valid()) { - Point2 pos = mm->get_global_position(); - if (mouse_pos != pos) { - set_mouse_position(pos); + Point2 position = mm->get_global_position(); + if (mouse_pos != position) { + set_mouse_position(position); } + Vector2 relative = mm->get_relative(); + mouse_velocity_track.update(relative); if (event_dispatch_function && emulate_touch_from_mouse && !p_is_emulated && (mm->get_button_mask() & MouseButton::LEFT) != MouseButton::NONE) { Ref<InputEventScreenDrag> drag_event; drag_event.instantiate(); - drag_event->set_position(mm->get_position()); - drag_event->set_relative(mm->get_relative()); - drag_event->set_velocity(mm->get_velocity()); + drag_event->set_position(position); + drag_event->set_relative(relative); + drag_event->set_velocity(get_last_mouse_velocity()); event_dispatch_function(drag_event); } @@ -696,7 +712,6 @@ void Input::set_gyroscope(const Vector3 &p_gyroscope) { } void Input::set_mouse_position(const Point2 &p_posf) { - mouse_velocity_track.update(p_posf - mouse_pos); mouse_pos = p_posf; } diff --git a/core/input/input.h b/core/input/input.h index e5ef31ab4f..80f260f30e 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -242,6 +242,7 @@ public: static Input *get_singleton(); + bool is_anything_pressed() const; bool is_key_pressed(Key p_keycode) const; bool is_physical_key_pressed(Key p_keycode) const; bool is_mouse_button_pressed(MouseButton p_button) const; diff --git a/core/io/http_client.h b/core/io/http_client.h index 8be6e6524c..90c859d685 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -180,7 +180,7 @@ public: virtual bool is_response_chunked() const = 0; virtual int get_response_code() const = 0; virtual Error get_response_headers(List<String> *r_response) = 0; - virtual int get_response_body_length() const = 0; + virtual int64_t get_response_body_length() const = 0; virtual PackedByteArray read_response_body_chunk() = 0; // Can't get body as partial text because of most encodings UTF8, gzip, etc. diff --git a/core/io/http_client_tcp.cpp b/core/io/http_client_tcp.cpp index 4c27cd1b10..6e4417e1ff 100644 --- a/core/io/http_client_tcp.cpp +++ b/core/io/http_client_tcp.cpp @@ -534,7 +534,7 @@ Error HTTPClientTCP::poll() { return OK; } -int HTTPClientTCP::get_response_body_length() const { +int64_t HTTPClientTCP::get_response_body_length() const { return body_size; } diff --git a/core/io/http_client_tcp.h b/core/io/http_client_tcp.h index 886ad0ef48..3fe8e2c0df 100644 --- a/core/io/http_client_tcp.h +++ b/core/io/http_client_tcp.h @@ -87,7 +87,7 @@ public: bool is_response_chunked() const override; int get_response_code() const override; Error get_response_headers(List<String> *r_response) override; - int get_response_body_length() const override; + int64_t get_response_body_length() const override; PackedByteArray read_response_body_chunk() override; void set_blocking_mode(bool p_enable) override; bool is_blocking_mode_enabled() const override; diff --git a/core/io/image.cpp b/core/io/image.cpp index 7956d0bad7..9df2b6835c 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -1434,12 +1434,11 @@ int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int & } // Set mipmap size. - // It might be necessary to put this after the minimum mipmap size check because of the possible occurrence of "1 >> 1". if (r_mm_width) { - *r_mm_width = bw >> 1; + *r_mm_width = w; } if (r_mm_height) { - *r_mm_height = bh >> 1; + *r_mm_height = h; } // Reach target mipmap. diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index 6a0668f027..555d4f6df4 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -52,9 +52,8 @@ ObjectID EncodedObjectAsID::get_object_id() const { return id; } -#define _S(a) ((int32_t)a) -#define ERR_FAIL_ADD_OF(a, b, err) ERR_FAIL_COND_V(_S(b) < 0 || _S(a) < 0 || _S(a) > INT_MAX - _S(b), err) -#define ERR_FAIL_MUL_OF(a, b, err) ERR_FAIL_COND_V(_S(a) < 0 || _S(b) <= 0 || _S(a) > INT_MAX / _S(b), err) +#define ERR_FAIL_ADD_OF(a, b, err) ERR_FAIL_COND_V(((int32_t)(b)) < 0 || ((int32_t)(a)) < 0 || ((int32_t)(a)) > INT_MAX - ((int32_t)(b)), err) +#define ERR_FAIL_MUL_OF(a, b, err) ERR_FAIL_COND_V(((int32_t)(a)) < 0 || ((int32_t)(b)) <= 0 || ((int32_t)(a)) > INT_MAX / ((int32_t)(b)), err) #define ENCODE_MASK 0xFF #define ENCODE_FLAG_64 1 << 16 diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 8fe1ac29b3..21bf566b1b 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -806,38 +806,26 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem // To find the path of the remapped resource, we extract the locale name after // the last ':' to match the project locale. - // We also fall back in case of regional locales as done in TranslationServer::translate - // (e.g. 'ru_RU' -> 'ru' if the former has no specific mapping). String locale = TranslationServer::get_singleton()->get_locale(); ERR_FAIL_COND_V_MSG(locale.length() < 2, p_path, "Could not remap path '" + p_path + "' for translation as configured locale '" + locale + "' is invalid."); - String lang = TranslationServer::get_language_code(locale); Vector<String> &res_remaps = *translation_remaps.getptr(new_path); - bool near_match = false; + int best_score = 0; for (int i = 0; i < res_remaps.size(); i++) { int split = res_remaps[i].rfind(":"); if (split == -1) { continue; } - String l = res_remaps[i].substr(split + 1).strip_edges(); - if (l == locale) { // Exact match. - new_path = res_remaps[i].left(split); - break; - } else if (near_match) { - continue; // Already found near match, keep going for potential exact match. - } - - // No exact match (e.g. locale 'ru_RU' but remap is 'ru'), let's look further - // for a near match (same language code, i.e. first 2 or 3 letters before - // regional code, if included). - if (TranslationServer::get_language_code(l) == lang) { - // Language code matches, that's a near match. Keep looking for exact match. - near_match = true; + int score = TranslationServer::get_singleton()->compare_locales(locale, l); + if (score > 0 && score >= best_score) { new_path = res_remaps[i].left(split); - continue; + best_score = score; + if (score == 10) { + break; // Exact match, skip the rest. + } } } diff --git a/core/math/aabb.h b/core/math/aabb.h index 2eaaafa27d..3d19410ddf 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -41,7 +41,7 @@ */ class Variant; -class AABB { +class _NO_DISCARD_ AABB { public: Vector3 position; Vector3 size; diff --git a/core/math/basis.h b/core/math/basis.h index 709f2cb3cf..802da82089 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -34,7 +34,7 @@ #include "core/math/quaternion.h" #include "core/math/vector3.h" -class Basis { +class _NO_DISCARD_ Basis { private: void _set_diagonal(const Vector3 &p_diag); diff --git a/core/math/color.h b/core/math/color.h index 6c09f7941c..72a4a5f8be 100644 --- a/core/math/color.h +++ b/core/math/color.h @@ -34,7 +34,7 @@ #include "core/math/math_funcs.h" #include "core/string/ustring.h" -struct Color { +struct _NO_DISCARD_ Color { union { struct { float r; diff --git a/core/math/face3.cpp b/core/math/face3.cpp index ba10b50465..d588f34e5d 100644 --- a/core/math/face3.cpp +++ b/core/math/face3.cpp @@ -260,8 +260,8 @@ void Face3::project_range(const Vector3 &p_normal, const Transform3D &p_transfor } void Face3::get_support(const Vector3 &p_normal, const Transform3D &p_transform, Vector3 *p_vertices, int *p_count, int p_max) const { -#define _FACE_IS_VALID_SUPPORT_THRESHOLD 0.98 -#define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.05 + constexpr double face_support_threshold = 0.98; + constexpr double edge_support_threshold = 0.05; if (p_max <= 0) { return; @@ -270,7 +270,7 @@ void Face3::get_support(const Vector3 &p_normal, const Transform3D &p_transform, Vector3 n = p_transform.basis.xform_inv(p_normal); /** TEST FACE AS SUPPORT **/ - if (get_plane().normal.dot(n) > _FACE_IS_VALID_SUPPORT_THRESHOLD) { + if (get_plane().normal.dot(n) > face_support_threshold) { *p_count = MIN(3, p_max); for (int i = 0; i < *p_count; i++) { @@ -304,7 +304,7 @@ void Face3::get_support(const Vector3 &p_normal, const Transform3D &p_transform, // check if edge is valid as a support real_t dot = (vertex[i] - vertex[(i + 1) % 3]).normalized().dot(n); dot = ABS(dot); - if (dot < _EDGE_IS_VALID_SUPPORT_THRESHOLD) { + if (dot < edge_support_threshold) { *p_count = MIN(2, p_max); for (int j = 0; j < *p_count; j++) { diff --git a/core/math/face3.h b/core/math/face3.h index 5a34858ccb..3dbbca09e0 100644 --- a/core/math/face3.h +++ b/core/math/face3.h @@ -36,7 +36,7 @@ #include "core/math/transform_3d.h" #include "core/math/vector3.h" -class Face3 { +class _NO_DISCARD_ Face3 { public: enum Side { SIDE_OVER, diff --git a/core/math/geometry_3d.cpp b/core/math/geometry_3d.cpp index 98a2c27d93..a9ff46410e 100644 --- a/core/math/geometry_3d.cpp +++ b/core/math/geometry_3d.cpp @@ -281,16 +281,16 @@ static inline void _plot_face(uint8_t ***p_cell_status, int x, int y, int z, int int div_y = len_y > 1 ? 2 : 1; int div_z = len_z > 1 ? 2 : 1; -#define _SPLIT(m_i, m_div, m_v, m_len_v, m_new_v, m_new_len_v) \ - if (m_div == 1) { \ - m_new_v = m_v; \ - m_new_len_v = 1; \ - } else if (m_i == 0) { \ - m_new_v = m_v; \ - m_new_len_v = m_len_v / 2; \ - } else { \ - m_new_v = m_v + m_len_v / 2; \ - m_new_len_v = m_len_v - m_len_v / 2; \ +#define SPLIT_DIV(m_i, m_div, m_v, m_len_v, m_new_v, m_new_len_v) \ + if (m_div == 1) { \ + m_new_v = m_v; \ + m_new_len_v = 1; \ + } else if (m_i == 0) { \ + m_new_v = m_v; \ + m_new_len_v = m_len_v / 2; \ + } else { \ + m_new_v = m_v + m_len_v / 2; \ + m_new_len_v = m_len_v - m_len_v / 2; \ } int new_x; @@ -301,18 +301,20 @@ static inline void _plot_face(uint8_t ***p_cell_status, int x, int y, int z, int int new_len_z; for (int i = 0; i < div_x; i++) { - _SPLIT(i, div_x, x, len_x, new_x, new_len_x); + SPLIT_DIV(i, div_x, x, len_x, new_x, new_len_x); for (int j = 0; j < div_y; j++) { - _SPLIT(j, div_y, y, len_y, new_y, new_len_y); + SPLIT_DIV(j, div_y, y, len_y, new_y, new_len_y); for (int k = 0; k < div_z; k++) { - _SPLIT(k, div_z, z, len_z, new_z, new_len_z); + SPLIT_DIV(k, div_z, z, len_z, new_z, new_len_z); _plot_face(p_cell_status, new_x, new_y, new_z, new_len_x, new_len_y, new_len_z, voxelsize, p_face); } } } + +#undef SPLIT_DIV } static inline void _mark_outside(uint8_t ***p_cell_status, int x, int y, int z, int len_x, int len_y, int len_z) { @@ -491,11 +493,10 @@ static inline void _build_faces(uint8_t ***p_cell_status, int x, int y, int z, i } Vector<Face3> Geometry3D::wrap_geometry(Vector<Face3> p_array, real_t *p_error) { -#define _MIN_SIZE 1.0 -#define _MAX_LENGTH 20 - int face_count = p_array.size(); const Face3 *faces = p_array.ptr(); + constexpr double min_size = 1.0; + constexpr int max_length = 20; AABB global_aabb; @@ -512,22 +513,22 @@ Vector<Face3> Geometry3D::wrap_geometry(Vector<Face3> p_array, real_t *p_error) // Determine amount of cells in grid axis. int div_x, div_y, div_z; - if (global_aabb.size.x / _MIN_SIZE < _MAX_LENGTH) { - div_x = (int)(global_aabb.size.x / _MIN_SIZE) + 1; + if (global_aabb.size.x / min_size < max_length) { + div_x = (int)(global_aabb.size.x / min_size) + 1; } else { - div_x = _MAX_LENGTH; + div_x = max_length; } - if (global_aabb.size.y / _MIN_SIZE < _MAX_LENGTH) { - div_y = (int)(global_aabb.size.y / _MIN_SIZE) + 1; + if (global_aabb.size.y / min_size < max_length) { + div_y = (int)(global_aabb.size.y / min_size) + 1; } else { - div_y = _MAX_LENGTH; + div_y = max_length; } - if (global_aabb.size.z / _MIN_SIZE < _MAX_LENGTH) { - div_z = (int)(global_aabb.size.z / _MIN_SIZE) + 1; + if (global_aabb.size.z / min_size < max_length) { + div_z = (int)(global_aabb.size.z / min_size) + 1; } else { - div_z = _MAX_LENGTH; + div_z = max_length; } Vector3 voxelsize = global_aabb.size; diff --git a/core/math/plane.h b/core/math/plane.h index bac946502b..8cb6f62b3b 100644 --- a/core/math/plane.h +++ b/core/math/plane.h @@ -35,7 +35,7 @@ class Variant; -class Plane { +class _NO_DISCARD_ Plane { public: Vector3 normal; real_t d = 0; diff --git a/core/math/quaternion.h b/core/math/quaternion.h index cf3762e090..2575d7d229 100644 --- a/core/math/quaternion.h +++ b/core/math/quaternion.h @@ -36,7 +36,7 @@ #include "core/math/vector3.h" #include "core/string/ustring.h" -class Quaternion { +class _NO_DISCARD_ Quaternion { public: union { struct { diff --git a/core/math/rect2.h b/core/math/rect2.h index f34550bef1..4ea24e8f88 100644 --- a/core/math/rect2.h +++ b/core/math/rect2.h @@ -35,7 +35,7 @@ struct Transform2D; -struct Rect2 { +struct _NO_DISCARD_ Rect2 { Point2 position; Size2 size; @@ -363,7 +363,7 @@ struct Rect2 { } }; -struct Rect2i { +struct _NO_DISCARD_ Rect2i { Point2i position; Size2i size; diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h index 752a885eba..6c2d51bd9b 100644 --- a/core/math/transform_2d.h +++ b/core/math/transform_2d.h @@ -33,7 +33,7 @@ #include "core/math/rect2.h" // also includes vector2, math_funcs, and ustring -struct Transform2D { +struct _NO_DISCARD_ Transform2D { // Warning #1: basis of Transform2D is stored differently from Basis. In terms of elements array, the basis matrix looks like "on paper": // M = (elements[0][0] elements[1][0]) // (elements[0][1] elements[1][1]) diff --git a/core/math/transform_3d.h b/core/math/transform_3d.h index c0ef2ecfc1..c16c278e74 100644 --- a/core/math/transform_3d.h +++ b/core/math/transform_3d.h @@ -35,7 +35,7 @@ #include "core/math/basis.h" #include "core/math/plane.h" -class Transform3D { +class _NO_DISCARD_ Transform3D { public: Basis basis; Vector3 origin; diff --git a/core/math/vector2.h b/core/math/vector2.h index a340036ac7..af40b9e68d 100644 --- a/core/math/vector2.h +++ b/core/math/vector2.h @@ -36,7 +36,7 @@ struct Vector2i; -struct Vector2 { +struct _NO_DISCARD_ Vector2 { static const int AXIS_COUNT = 2; enum Axis { @@ -284,7 +284,7 @@ typedef Vector2 Point2; /* INTEGER STUFF */ -struct Vector2i { +struct _NO_DISCARD_ Vector2i { enum Axis { AXIS_X, AXIS_Y, diff --git a/core/math/vector3.h b/core/math/vector3.h index d7a72b05a8..b62edef40f 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -37,7 +37,7 @@ #include "core/string/ustring.h" class Basis; -struct Vector3 { +struct _NO_DISCARD_ Vector3 { static const int AXIS_COUNT = 3; enum Axis { diff --git a/core/math/vector3i.h b/core/math/vector3i.h index 1416c98057..1564ee9173 100644 --- a/core/math/vector3i.h +++ b/core/math/vector3i.h @@ -35,7 +35,7 @@ #include "core/string/ustring.h" #include "core/typedefs.h" -struct Vector3i { +struct _NO_DISCARD_ Vector3i { enum Axis { AXIS_X, AXIS_Y, diff --git a/core/object/object.h b/core/object/object.h index 602bd3cda1..63130a1aef 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -94,6 +94,7 @@ enum PropertyHint { PROPERTY_HINT_INT_IS_OBJECTID, PROPERTY_HINT_ARRAY_TYPE, PROPERTY_HINT_INT_IS_POINTER, + PROPERTY_HINT_LOCALE_ID, PROPERTY_HINT_MAX, // When updating PropertyHint, also sync the hardcoded list in VisualScriptEditorVariableEdit }; diff --git a/core/os/os.h b/core/os/os.h index 6b4e2798bd..36d85da70b 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -295,6 +295,9 @@ public: virtual void debug_break(); virtual int get_exit_code() const; + // `set_exit_code` should only be used from `SceneTree` (or from a similar + // level, e.g. from the `Main::start` if leaving without creating a `SceneTree`). + // For other components, `SceneTree.quit()` should be used instead. virtual void set_exit_code(int p_code); virtual int get_processor_count() const; diff --git a/core/string/locales.h b/core/string/locales.h new file mode 100644 index 0000000000..32d6608ec2 --- /dev/null +++ b/core/string/locales.h @@ -0,0 +1,1197 @@ +/*************************************************************************/ +/* locales.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef LOCALES_H +#define LOCALES_H + +// Windows has some weird locale identifiers which do not honor the ISO 639-1 +// standardized nomenclature. Whenever those don't conflict with existing ISO +// identifiers, we override them. +// +// Reference: +// - https://msdn.microsoft.com/en-us/library/windows/desktop/ms693062(v=vs.85).aspx + +static const char *locale_renames[][2] = { + { "in", "id" }, // Indonesian + { "iw", "he" }, // Hebrew + { "no", "nb" }, // Norwegian Bokmål + { "C", "en" }, // Locale is not set, fallback to English. + { nullptr, nullptr } +}; + +// Additional script information to preferred scripts. +// Language code, script code, default country, supported countries. +// Reference: +// - https://lh.2xlibre.net/locales/ +// - https://www.localeplanet.com/icu/index.html +// - https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/70feba9f-294e-491e-b6eb-56532684c37f + +static const char *locale_scripts[][4] = { + { "az", "Latn", "", "AZ" }, + { "az", "Arab", "", "IR" }, + { "bs", "Latn", "", "BA" }, + { "ff", "Latn", "", "BF,CM,GH,GM,GN,GW,LR,MR,NE,NG,SL,SN" }, + { "pa", "Arab", "PK", "PK" }, + { "pa", "Guru", "IN", "IN" }, + { "sd", "Arab", "PK", "PK" }, + { "sd", "Deva", "IN", "IN" }, + { "shi", "Tfng", "", "MA" }, + { "sr", "Cyrl", "", "BA,RS,XK" }, + { "sr", "Latn", "", "ME" }, + { "uz", "Latn", "", "UZ" }, + { "uz", "Arab", "AF", "AF" }, + { "vai", "Vaii", "", "LR" }, + { "yue", "Hans", "CN", "CN" }, + { "yue", "Hant", "HK", "HK" }, + { "zh", "Hans", "CN", "CN,SG" }, + { "zh", "Hant", "TW", "HK,MO,TW" }, + { nullptr, nullptr, nullptr, nullptr } +}; + +// Additional mapping for outdated, temporary or exceptionally reserved country codes. +// Reference: +// - https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 +// - https://www.iso.org/obp/ui/#search/code/ + +static const char *country_renames[][2] = { + { "BU", "MM" }, // Burma, name changed to Myanmar. + { "KV", "XK" }, // Kosovo (temporary FIPS code to European Commission code), no official ISO code assigned. + { "TP", "TL" }, // East Timor, name changed to Timor-Leste. + { "UK", "GB" }, // United Kingdom, exceptionally reserved code. + { nullptr, nullptr } +}; + +// Country code, country name. +// Reference: +// - https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 +// - https://www.iso.org/obp/ui/#search/code/ + +static const char *country_names[][2] = { + { "AC", "Ascension Island" }, // Exceptionally reserved. + { "AD", "Andorra" }, + { "AE", "United Arab Emirates" }, + { "AF", "Afghanistan" }, + { "AG", "Antigua and Barbuda" }, + { "AI", "Anguilla" }, + { "AL", "Albania" }, + { "AM", "Armenia" }, + { "AN", "Netherlands Antilles" }, // Transitionally reserved, divided into BQ, CW and SX. + { "AO", "Angola" }, + { "AQ", "Antarctica" }, + { "AR", "Argentina" }, + { "AS", "American Samoa" }, + { "AT", "Austria" }, + { "AU", "Australia" }, + { "AW", "Aruba" }, + { "AX", "Åland Islands" }, + { "AZ", "Azerbaijan" }, + { "BA", "Bosnia and Herzegovina" }, + { "BB", "Barbados" }, + { "BD", "Bangladesh" }, + { "BE", "Belgium" }, + { "BF", "Burkina Faso" }, + { "BG", "Bulgaria" }, + { "BH", "Bahrain" }, + { "BI", "Burundi" }, + { "BJ", "Benin" }, + { "BL", "St. Barthélemy" }, + { "BM", "Bermuda" }, + { "BN", "Brunei" }, + { "BO", "Bolivia" }, + { "BQ", "Caribbean Netherlands" }, + { "BR", "Brazil" }, + { "BS", "Bahamas" }, + { "BT", "Bhutan" }, + { "BV", "Bouvet Island" }, + { "BW", "Botswana" }, + { "BY", "Belarus" }, + { "BZ", "Belize" }, + { "CA", "Canada" }, + { "CC", "Cocos (Keeling) Islands" }, + { "CD", "Congo - Kinshasa" }, + { "CF", "Central African Republic" }, + { "CG", "Congo - Brazzaville" }, + { "CH", "Switzerland" }, + { "CI", "Côte d'Ivoire" }, + { "CK", "Cook Islands" }, + { "CL", "Chile" }, + { "CM", "Cameroon" }, + { "CN", "China" }, + { "CO", "Colombia" }, + { "CP", "Clipperton Island" }, // Exceptionally reserved. + { "CR", "Costa Rica" }, + { "CQ", "Island of Sark" }, // Exceptionally reserved. + { "CU", "Cuba" }, + { "CV", "Cabo Verde" }, + { "CW", "Curaçao" }, + { "CX", "Christmas Island" }, + { "CY", "Cyprus" }, + { "CZ", "Czechia" }, + { "DE", "Germany" }, + { "DG", "Diego Garcia" }, // Exceptionally reserved. + { "DJ", "Djibouti" }, + { "DK", "Denmark" }, + { "DM", "Dominica" }, + { "DO", "Dominican Republic" }, + { "DZ", "Algeria" }, + { "EA", "Ceuta and Melilla" }, // Exceptionally reserved. + { "EC", "Ecuador" }, + { "EE", "Estonia" }, + { "EG", "Egypt" }, + { "EH", "Western Sahara" }, + { "ER", "Eritrea" }, + { "ES", "Spain" }, + { "ET", "Ethiopia" }, + { "EU", "European Union" }, // Exceptionally reserved. + { "EZ", "Eurozone" }, // Exceptionally reserved. + { "FI", "Finland" }, + { "FJ", "Fiji" }, + { "FK", "Falkland Islands" }, + { "FM", "Micronesia" }, + { "FO", "Faroe Islands" }, + { "FR", "France" }, + { "FX", "France, Metropolitan" }, // Exceptionally reserved. + { "GA", "Gabon" }, + { "GB", "United Kingdom" }, + { "GD", "Grenada" }, + { "GE", "Georgia" }, + { "GF", "French Guiana" }, + { "GG", "Guernsey" }, + { "GH", "Ghana" }, + { "GI", "Gibraltar" }, + { "GL", "Greenland" }, + { "GM", "Gambia" }, + { "GN", "Guinea" }, + { "GP", "Guadeloupe" }, + { "GQ", "Equatorial Guinea" }, + { "GR", "Greece" }, + { "GS", "South Georgia and South Sandwich Islands" }, + { "GT", "Guatemala" }, + { "GU", "Guam" }, + { "GW", "Guinea-Bissau" }, + { "GY", "Guyana" }, + { "HK", "Hong Kong" }, + { "HM", "Heard Island and McDonald Islands" }, + { "HN", "Honduras" }, + { "HR", "Croatia" }, + { "HT", "Haiti" }, + { "HU", "Hungary" }, + { "IC", "Canary Islands" }, // Exceptionally reserved. + { "ID", "Indonesia" }, + { "IE", "Ireland" }, + { "IL", "Israel" }, + { "IM", "Isle of Man" }, + { "IN", "India" }, + { "IO", "British Indian Ocean Territory" }, + { "IQ", "Iraq" }, + { "IR", "Iran" }, + { "IS", "Iceland" }, + { "IT", "Italy" }, + { "JE", "Jersey" }, + { "JM", "Jamaica" }, + { "JO", "Jordan" }, + { "JP", "Japan" }, + { "KE", "Kenya" }, + { "KG", "Kyrgyzstan" }, + { "KH", "Cambodia" }, + { "KI", "Kiribati" }, + { "KM", "Comoros" }, + { "KN", "St. Kitts and Nevis" }, + { "KP", "North Korea" }, + { "KR", "South Korea" }, + { "KW", "Kuwait" }, + { "KY", "Cayman Islands" }, + { "KZ", "Kazakhstan" }, + { "LA", "Laos" }, + { "LB", "Lebanon" }, + { "LC", "St. Lucia" }, + { "LI", "Liechtenstein" }, + { "LK", "Sri Lanka" }, + { "LR", "Liberia" }, + { "LS", "Lesotho" }, + { "LT", "Lithuania" }, + { "LU", "Luxembourg" }, + { "LV", "Latvia" }, + { "LY", "Libya" }, + { "MA", "Morocco" }, + { "MC", "Monaco" }, + { "MD", "Moldova" }, + { "ME", "Montenegro" }, + { "MF", "St. Martin" }, + { "MG", "Madagascar" }, + { "MH", "Marshall Islands" }, + { "MK", "North Macedonia" }, + { "ML", "Mali" }, + { "MM", "Myanmar" }, + { "MN", "Mongolia" }, + { "MO", "Macao" }, + { "MP", "Northern Mariana Islands" }, + { "MQ", "Martinique" }, + { "MR", "Mauritania" }, + { "MS", "Montserrat" }, + { "MT", "Malta" }, + { "MU", "Mauritius" }, + { "MV", "Maldives" }, + { "MW", "Malawi" }, + { "MX", "Mexico" }, + { "MY", "Malaysia" }, + { "MZ", "Mozambique" }, + { "NA", "Namibia" }, + { "NC", "New Caledonia" }, + { "NE", "Niger" }, + { "NF", "Norfolk Island" }, + { "NG", "Nigeria" }, + { "NI", "Nicaragua" }, + { "NL", "Netherlands" }, + { "NO", "Norway" }, + { "NP", "Nepal" }, + { "NR", "Nauru" }, + { "NU", "Niue" }, + { "NZ", "New Zealand" }, + { "OM", "Oman" }, + { "PA", "Panama" }, + { "PE", "Peru" }, + { "PF", "French Polynesia" }, + { "PG", "Papua New Guinea" }, + { "PH", "Philippines" }, + { "PK", "Pakistan" }, + { "PL", "Poland" }, + { "PM", "St. Pierre and Miquelon" }, + { "PN", "Pitcairn Islands" }, + { "PR", "Puerto Rico" }, + { "PS", "Palestine" }, + { "PT", "Portugal" }, + { "PW", "Palau" }, + { "PY", "Paraguay" }, + { "QA", "Qatar" }, + { "RE", "Réunion" }, + { "RO", "Romania" }, + { "RS", "Serbia" }, + { "RU", "Russia" }, + { "RW", "Rwanda" }, + { "SA", "Saudi Arabia" }, + { "SB", "Solomon Islands" }, + { "SC", "Seychelles" }, + { "SD", "Sudan" }, + { "SE", "Sweden" }, + { "SG", "Singapore" }, + { "SH", "St. Helena, Ascension and Tristan da Cunha" }, + { "SI", "Slovenia" }, + { "SJ", "Svalbard and Jan Mayen" }, + { "SK", "Slovakia" }, + { "SL", "Sierra Leone" }, + { "SM", "San Marino" }, + { "SN", "Senegal" }, + { "SO", "Somalia" }, + { "SR", "Suriname" }, + { "SS", "South Sudan" }, + { "ST", "Sao Tome and Principe" }, + { "SV", "El Salvador" }, + { "SX", "Sint Maarten" }, + { "SY", "Syria" }, + { "SZ", "Eswatini" }, + { "TA", "Tristan da Cunha" }, // Exceptionally reserved. + { "TC", "Turks and Caicos Islands" }, + { "TD", "Chad" }, + { "TF", "French Southern Territories" }, + { "TG", "Togo" }, + { "TH", "Thailand" }, + { "TJ", "Tajikistan" }, + { "TK", "Tokelau" }, + { "TL", "Timor-Leste" }, + { "TM", "Turkmenistan" }, + { "TN", "Tunisia" }, + { "TO", "Tonga" }, + { "TR", "Turkey" }, + { "TT", "Trinidad and Tobago" }, + { "TV", "Tuvalu" }, + { "TW", "Taiwan" }, + { "TZ", "Tanzania" }, + { "UA", "Ukraine" }, + { "UG", "Uganda" }, + { "UM", "U.S. Outlying Islands" }, + { "US", "United States of America" }, + { "UY", "Uruguay" }, + { "UZ", "Uzbekistan" }, + { "VA", "Holy See" }, + { "VC", "St. Vincent and the Grenadines" }, + { "VE", "Venezuela" }, + { "VG", "British Virgin Islands" }, + { "VI", "U.S. Virgin Islands" }, + { "VN", "Viet Nam" }, + { "VU", "Vanuatu" }, + { "WF", "Wallis and Futuna" }, + { "WS", "Samoa" }, + { "XK", "Kosovo" }, // Temporary code, no official ISO code assigned. + { "YE", "Yemen" }, + { "YT", "Mayotte" }, + { "ZA", "South Africa" }, + { "ZM", "Zambia" }, + { "ZW", "Zimbabwe" }, + { nullptr, nullptr } +}; + +// Languages code, language name. +// Reference: +// - https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes +// - https://www.localeplanet.com/icu/index.html +// - https://lh.2xlibre.net/locales/ + +static const char *language_list[][2] = { + { "aa", "Afar" }, + { "ab", "Abkhazian" }, + { "ace", "Achinese" }, + { "ach", "Acoli" }, + { "ada", "Adangme" }, + { "ady", "Adyghe" }, + { "ae", "Avestan" }, + { "aeb", "Tunisian Arabic" }, + { "af", "Afrikaans" }, + { "afh", "Afrihili" }, + { "agq", "Aghem" }, + { "ain", "Ainu" }, + { "agr", "Aguaruna" }, + { "ak", "Akan" }, + { "akk", "Akkadian" }, + { "akz", "Alabama" }, + { "ale", "Aleut" }, + { "aln", "Gheg Albanian" }, + { "alt", "Southern Altai" }, + { "am", "Amharic" }, + { "an", "Aragonese" }, + { "ang", "Old English" }, + { "anp", "Angika" }, + { "ar", "Arabic" }, + { "arc", "Aramaic" }, + { "arn", "Mapudungun" }, + { "aro", "Araona" }, + { "arp", "Arapaho" }, + { "arq", "Algerian Arabic" }, + { "ars", "Najdi Arabic" }, + { "arw", "Arawak" }, + { "ary", "Moroccan Arabic" }, + { "arz", "Egyptian Arabic" }, + { "as", "Assamese" }, + { "asa", "Asu" }, + { "ase", "American Sign Language" }, + { "ast", "Asturian" }, + { "av", "Avaric" }, + { "avk", "Kotava" }, + { "awa", "Awadhi" }, + { "ayc", "Southern Aymara" }, + { "ay", "Aymara" }, + { "az", "Azerbaijani" }, + { "ba", "Bashkir" }, + { "bal", "Baluchi" }, + { "ban", "Balinese" }, + { "bar", "Bavarian" }, + { "bas", "Bassa" }, + { "bax", "Bamun" }, + { "bbc", "Batak Toba" }, + { "bbj", "Ghomala" }, + { "be", "Belarusian" }, + { "bej", "Beja" }, + { "bem", "Bemba" }, + { "ber", "Berber" }, + { "bew", "Betawi" }, + { "bez", "Bena" }, + { "bfd", "Bafut" }, + { "bfq", "Badaga" }, + { "bg", "Bulgarian" }, + { "bhb", "Bhili" }, + { "bgn", "Western Balochi" }, + { "bho", "Bhojpuri" }, + { "bi", "Bislama" }, + { "bik", "Bikol" }, + { "bin", "Bini" }, + { "bjn", "Banjar" }, + { "bkm", "Kom" }, + { "bla", "Siksika" }, + { "bm", "Bambara" }, + { "bn", "Bengali" }, + { "bo", "Tibetan" }, + { "bpy", "Bishnupriya" }, + { "bqi", "Bakhtiari" }, + { "br", "Breton" }, + { "brh", "Brahui" }, + { "brx", "Bodo" }, + { "bs", "Bosnian" }, + { "bss", "Akoose" }, + { "bua", "Buriat" }, + { "bug", "Buginese" }, + { "bum", "Bulu" }, + { "byn", "Bilin" }, + { "byv", "Medumba" }, + { "ca", "Catalan" }, + { "cad", "Caddo" }, + { "car", "Carib" }, + { "cay", "Cayuga" }, + { "cch", "Atsam" }, + { "ccp", "Chakma" }, + { "ce", "Chechen" }, + { "ceb", "Cebuano" }, + { "cgg", "Chiga" }, + { "ch", "Chamorro" }, + { "chb", "Chibcha" }, + { "chg", "Chagatai" }, + { "chk", "Chuukese" }, + { "chm", "Mari" }, + { "chn", "Chinook Jargon" }, + { "cho", "Choctaw" }, + { "chp", "Chipewyan" }, + { "chr", "Cherokee" }, + { "chy", "Cheyenne" }, + { "cic", "Chickasaw" }, + { "ckb", "Central Kurdish" }, + { "csb", "Kashubian" }, + { "cmn", "Mandarin Chinese" }, + { "co", "Corsican" }, + { "cop", "Coptic" }, + { "cps", "Capiznon" }, + { "cr", "Cree" }, + { "crh", "Crimean Tatar" }, + { "crs", "Seselwa Creole French" }, + { "cs", "Czech" }, + { "csb", "Kashubian" }, + { "cu", "Church Slavic" }, + { "cv", "Chuvash" }, + { "cy", "Welsh" }, + { "da", "Danish" }, + { "dak", "Dakota" }, + { "dar", "Dargwa" }, + { "dav", "Taita" }, + { "de", "German" }, + { "del", "Delaware" }, + { "den", "Slave" }, + { "dgr", "Dogrib" }, + { "din", "Dinka" }, + { "dje", "Zarma" }, + { "doi", "Dogri" }, + { "dsb", "Lower Sorbian" }, + { "dtp", "Central Dusun" }, + { "dua", "Duala" }, + { "dum", "Middle Dutch" }, + { "dv", "Dhivehi" }, + { "dyo", "Jola-Fonyi" }, + { "dyu", "Dyula" }, + { "dz", "Dzongkha" }, + { "dzg", "Dazaga" }, + { "ebu", "Embu" }, + { "ee", "Ewe" }, + { "efi", "Efik" }, + { "egl", "Emilian" }, + { "egy", "Ancient Egyptian" }, + { "eka", "Ekajuk" }, + { "el", "Greek" }, + { "elx", "Elamite" }, + { "en", "English" }, + { "enm", "Middle English" }, + { "eo", "Esperanto" }, + { "es", "Spanish" }, + { "esu", "Central Yupik" }, + { "et", "Estonian" }, + { "eu", "Basque" }, + { "ewo", "Ewondo" }, + { "ext", "Extremaduran" }, + { "fa", "Persian" }, + { "fan", "Fang" }, + { "fat", "Fanti" }, + { "ff", "Fulah" }, + { "fi", "Finnish" }, + { "fil", "Filipino" }, + { "fit", "Tornedalen Finnish" }, + { "fj", "Fijian" }, + { "fo", "Faroese" }, + { "fon", "Fon" }, + { "fr", "French" }, + { "frc", "Cajun French" }, + { "frm", "Middle French" }, + { "fro", "Old French" }, + { "frp", "Arpitan" }, + { "frr", "Northern Frisian" }, + { "frs", "Eastern Frisian" }, + { "fur", "Friulian" }, + { "fy", "Western Frisian" }, + { "ga", "Irish" }, + { "gaa", "Ga" }, + { "gag", "Gagauz" }, + { "gan", "Gan Chinese" }, + { "gay", "Gayo" }, + { "gba", "Gbaya" }, + { "gbz", "Zoroastrian Dari" }, + { "gd", "Scottish Gaelic" }, + { "gez", "Geez" }, + { "gil", "Gilbertese" }, + { "gl", "Galician" }, + { "glk", "Gilaki" }, + { "gmh", "Middle High German" }, + { "gn", "Guarani" }, + { "goh", "Old High German" }, + { "gom", "Goan Konkani" }, + { "gon", "Gondi" }, + { "gor", "Gorontalo" }, + { "got", "Gothic" }, + { "grb", "Grebo" }, + { "grc", "Ancient Greek" }, + { "gsw", "Swiss German" }, + { "gu", "Gujarati" }, + { "guc", "Wayuu" }, + { "gur", "Frafra" }, + { "guz", "Gusii" }, + { "gv", "Manx" }, + { "gwi", "Gwichʼin" }, + { "ha", "Hausa" }, + { "hai", "Haida" }, + { "hak", "Hakka Chinese" }, + { "haw", "Hawaiian" }, + { "he", "Hebrew" }, + { "hi", "Hindi" }, + { "hif", "Fiji Hindi" }, + { "hil", "Hiligaynon" }, + { "hit", "Hittite" }, + { "hmn", "Hmong" }, + { "ho", "Hiri Motu" }, + { "hne", "Chhattisgarhi" }, + { "hr", "Croatian" }, + { "hsb", "Upper Sorbian" }, + { "hsn", "Xiang Chinese" }, + { "ht", "Haitian" }, + { "hu", "Hungarian" }, + { "hup", "Hupa" }, + { "hus", "Huastec" }, + { "hy", "Armenian" }, + { "hz", "Herero" }, + { "ia", "Interlingua" }, + { "iba", "Iban" }, + { "ibb", "Ibibio" }, + { "id", "Indonesian" }, + { "ie", "Interlingue" }, + { "ig", "Igbo" }, + { "ii", "Sichuan Yi" }, + { "ik", "Inupiaq" }, + { "ilo", "Iloko" }, + { "inh", "Ingush" }, + { "io", "Ido" }, + { "is", "Icelandic" }, + { "it", "Italian" }, + { "iu", "Inuktitut" }, + { "izh", "Ingrian" }, + { "ja", "Japanese" }, + { "jam", "Jamaican Creole English" }, + { "jbo", "Lojban" }, + { "jgo", "Ngomba" }, + { "jmc", "Machame" }, + { "jpr", "Judeo-Persian" }, + { "jrb", "Judeo-Arabic" }, + { "jut", "Jutish" }, + { "jv", "Javanese" }, + { "ka", "Georgian" }, + { "kaa", "Kara-Kalpak" }, + { "kab", "Kabyle" }, + { "kac", "Kachin" }, + { "kaj", "Jju" }, + { "kam", "Kamba" }, + { "kaw", "Kawi" }, + { "kbd", "Kabardian" }, + { "kbl", "Kanembu" }, + { "kcg", "Tyap" }, + { "kde", "Makonde" }, + { "kea", "Kabuverdianu" }, + { "ken", "Kenyang" }, + { "kfo", "Koro" }, + { "kg", "Kongo" }, + { "kgp", "Kaingang" }, + { "kha", "Khasi" }, + { "kho", "Khotanese" }, + { "khq", "Koyra Chiini" }, + { "khw", "Khowar" }, + { "ki", "Kikuyu" }, + { "kiu", "Kirmanjki" }, + { "kj", "Kuanyama" }, + { "kk", "Kazakh" }, + { "kkj", "Kako" }, + { "kl", "Kalaallisut" }, + { "kln", "Kalenjin" }, + { "km", "Central Khmer" }, + { "kmb", "Kimbundu" }, + { "kn", "Kannada" }, + { "ko", "Korean" }, + { "koi", "Komi-Permyak" }, + { "kok", "Konkani" }, + { "kos", "Kosraean" }, + { "kpe", "Kpelle" }, + { "kr", "Kanuri" }, + { "krc", "Karachay-Balkar" }, + { "kri", "Krio" }, + { "krj", "Kinaray-a" }, + { "krl", "Karelian" }, + { "kru", "Kurukh" }, + { "ks", "Kashmiri" }, + { "ksb", "Shambala" }, + { "ksf", "Bafia" }, + { "ksh", "Colognian" }, + { "ku", "Kurdish" }, + { "kum", "Kumyk" }, + { "kut", "Kutenai" }, + { "kv", "Komi" }, + { "kw", "Cornish" }, + { "ky", "Kirghiz" }, + { "lag", "Langi" }, + { "la", "Latin" }, + { "lad", "Ladino" }, + { "lag", "Langi" }, + { "lah", "Lahnda" }, + { "lam", "Lamba" }, + { "lb", "Luxembourgish" }, + { "lez", "Lezghian" }, + { "lfn", "Lingua Franca Nova" }, + { "lg", "Ganda" }, + { "li", "Limburgan" }, + { "lij", "Ligurian" }, + { "liv", "Livonian" }, + { "lkt", "Lakota" }, + { "lmo", "Lombard" }, + { "ln", "Lingala" }, + { "lo", "Lao" }, + { "lol", "Mongo" }, + { "lou", "Louisiana Creole" }, + { "loz", "Lozi" }, + { "lrc", "Northern Luri" }, + { "lt", "Lithuanian" }, + { "ltg", "Latgalian" }, + { "lu", "Luba-Katanga" }, + { "lua", "Luba-Lulua" }, + { "lui", "Luiseno" }, + { "lun", "Lunda" }, + { "luo", "Luo" }, + { "lus", "Mizo" }, + { "luy", "Luyia" }, + { "lv", "Latvian" }, + { "lzh", "Literary Chinese" }, + { "lzz", "Laz" }, + { "mad", "Madurese" }, + { "maf", "Mafa" }, + { "mag", "Magahi" }, + { "mai", "Maithili" }, + { "mak", "Makasar" }, + { "man", "Mandingo" }, + { "mas", "Masai" }, + { "mde", "Maba" }, + { "mdf", "Moksha" }, + { "mdr", "Mandar" }, + { "men", "Mende" }, + { "mer", "Meru" }, + { "mfe", "Morisyen" }, + { "mg", "Malagasy" }, + { "mga", "Middle Irish" }, + { "mgh", "Makhuwa-Meetto" }, + { "mgo", "Metaʼ" }, + { "mh", "Marshallese" }, + { "mhr", "Eastern Mari" }, + { "mi", "Māori" }, + { "mic", "Mi'kmaq" }, + { "min", "Minangkabau" }, + { "miq", "Mískito" }, + { "mjw", "Karbi" }, + { "mk", "Macedonian" }, + { "ml", "Malayalam" }, + { "mn", "Mongolian" }, + { "mnc", "Manchu" }, + { "mni", "Manipuri" }, + { "mnw", "Mon" }, + { "mos", "Mossi" }, + { "moh", "Mohawk" }, + { "mr", "Marathi" }, + { "mrj", "Western Mari" }, + { "ms", "Malay" }, + { "mt", "Maltese" }, + { "mua", "Mundang" }, + { "mus", "Muscogee" }, + { "mwl", "Mirandese" }, + { "mwr", "Marwari" }, + { "mwv", "Mentawai" }, + { "my", "Burmese" }, + { "mye", "Myene" }, + { "myv", "Erzya" }, + { "mzn", "Mazanderani" }, + { "na", "Nauru" }, + { "nah", "Nahuatl" }, + { "nan", "Min Nan Chinese" }, + { "nap", "Neapolitan" }, + { "naq", "Nama" }, + { "nan", "Min Nan Chinese" }, + { "nb", "Norwegian Bokmål" }, + { "nd", "North Ndebele" }, + { "nds", "Low German" }, + { "ne", "Nepali" }, + { "new", "Newari" }, + { "nhn", "Central Nahuatl" }, + { "ng", "Ndonga" }, + { "nia", "Nias" }, + { "niu", "Niuean" }, + { "njo", "Ao Naga" }, + { "nl", "Dutch" }, + { "nmg", "Kwasio" }, + { "nn", "Norwegian Nynorsk" }, + { "nnh", "Ngiemboon" }, + { "nog", "Nogai" }, + { "non", "Old Norse" }, + { "nov", "Novial" }, + { "nqo", "N'ko" }, + { "nr", "South Ndebele" }, + { "nso", "Pedi" }, + { "nus", "Nuer" }, + { "nv", "Navajo" }, + { "nwc", "Classical Newari" }, + { "ny", "Nyanja" }, + { "nym", "Nyamwezi" }, + { "nyn", "Nyankole" }, + { "nyo", "Nyoro" }, + { "nzi", "Nzima" }, + { "oc", "Occitan" }, + { "oj", "Ojibwa" }, + { "om", "Oromo" }, + { "or", "Odia" }, + { "os", "Ossetic" }, + { "osa", "Osage" }, + { "ota", "Ottoman Turkish" }, + { "pa", "Panjabi" }, + { "pag", "Pangasinan" }, + { "pal", "Pahlavi" }, + { "pam", "Pampanga" }, + { "pap", "Papiamento" }, + { "pau", "Palauan" }, + { "pcd", "Picard" }, + { "pcm", "Nigerian Pidgin" }, + { "pdc", "Pennsylvania German" }, + { "pdt", "Plautdietsch" }, + { "peo", "Old Persian" }, + { "pfl", "Palatine German" }, + { "phn", "Phoenician" }, + { "pi", "Pali" }, + { "pl", "Polish" }, + { "pms", "Piedmontese" }, + { "pnt", "Pontic" }, + { "pon", "Pohnpeian" }, + { "pr", "Pirate" }, + { "prg", "Prussian" }, + { "pro", "Old Provençal" }, + { "prs", "Dari" }, + { "ps", "Pushto" }, + { "pt", "Portuguese" }, + { "qu", "Quechua" }, + { "quc", "K'iche" }, + { "qug", "Chimborazo Highland Quichua" }, + { "quy", "Ayacucho Quechua" }, + { "quz", "Cusco Quechua" }, + { "raj", "Rajasthani" }, + { "rap", "Rapanui" }, + { "rar", "Rarotongan" }, + { "rgn", "Romagnol" }, + { "rif", "Riffian" }, + { "rm", "Romansh" }, + { "rn", "Rundi" }, + { "ro", "Romanian" }, + { "rof", "Rombo" }, + { "rom", "Romany" }, + { "rtm", "Rotuman" }, + { "ru", "Russian" }, + { "rue", "Rusyn" }, + { "rug", "Roviana" }, + { "rup", "Aromanian" }, + { "rw", "Kinyarwanda" }, + { "rwk", "Rwa" }, + { "sa", "Sanskrit" }, + { "sad", "Sandawe" }, + { "sah", "Sakha" }, + { "sam", "Samaritan Aramaic" }, + { "saq", "Samburu" }, + { "sas", "Sasak" }, + { "sat", "Santali" }, + { "saz", "Saurashtra" }, + { "sba", "Ngambay" }, + { "sbp", "Sangu" }, + { "sc", "Sardinian" }, + { "scn", "Sicilian" }, + { "sco", "Scots" }, + { "sd", "Sindhi" }, + { "sdc", "Sassarese Sardinian" }, + { "sdh", "Southern Kurdish" }, + { "se", "Northern Sami" }, + { "see", "Seneca" }, + { "seh", "Sena" }, + { "sei", "Seri" }, + { "sel", "Selkup" }, + { "ses", "Koyraboro Senni" }, + { "sg", "Sango" }, + { "sga", "Old Irish" }, + { "sgs", "Samogitian" }, + { "sh", "Serbo-Croatian" }, + { "shi", "Tachelhit" }, + { "shn", "Shan" }, + { "shs", "Shuswap" }, + { "shu", "Chadian Arabic" }, + { "si", "Sinhala" }, + { "sid", "Sidamo" }, + { "sk", "Slovak" }, + { "sl", "Slovenian" }, + { "sli", "Lower Silesian" }, + { "sly", "Selayar" }, + { "sm", "Samoan" }, + { "sma", "Southern Sami" }, + { "smj", "Lule Sami" }, + { "smn", "Inari Sami" }, + { "sms", "Skolt Sami" }, + { "sn", "Shona" }, + { "snk", "Soninke" }, + { "so", "Somali" }, + { "sog", "Sogdien" }, + { "son", "Songhai" }, + { "sq", "Albanian" }, + { "sr", "Serbian" }, + { "srn", "Sranan Tongo" }, + { "srr", "Serer" }, + { "ss", "Swati" }, + { "ssy", "Saho" }, + { "st", "Southern Sotho" }, + { "stq", "Saterland Frisian" }, + { "su", "Sundanese" }, + { "suk", "Sukuma" }, + { "sus", "Susu" }, + { "sux", "Sumerian" }, + { "sv", "Swedish" }, + { "sw", "Swahili" }, + { "swb", "Comorian" }, + { "swc", "Congo Swahili" }, + { "syc", "Classical Syriac" }, + { "syr", "Syriac" }, + { "szl", "Silesian" }, + { "ta", "Tamil" }, + { "tcy", "Tulu" }, + { "te", "Telugu" }, + { "tem", "Timne" }, + { "teo", "Teso" }, + { "ter", "Tereno" }, + { "tet", "Tetum" }, + { "tg", "Tajik" }, + { "th", "Thai" }, + { "the", "Chitwania Tharu" }, + { "ti", "Tigrinya" }, + { "tig", "Tigre" }, + { "tiv", "Tiv" }, + { "tk", "Turkmen" }, + { "tkl", "Tokelau" }, + { "tkr", "Tsakhur" }, + { "tl", "Tagalog" }, + { "tlh", "Klingon" }, + { "tli", "Tlingit" }, + { "tly", "Talysh" }, + { "tmh", "Tamashek" }, + { "tn", "Tswana" }, + { "to", "Tongan" }, + { "tog", "Nyasa Tonga" }, + { "tpi", "Tok Pisin" }, + { "tr", "Turkish" }, + { "tru", "Turoyo" }, + { "trv", "Taroko" }, + { "ts", "Tsonga" }, + { "tsd", "Tsakonian" }, + { "tsi", "Tsimshian" }, + { "tt", "Tatar" }, + { "ttt", "Muslim Tat" }, + { "tum", "Tumbuka" }, + { "tvl", "Tuvalu" }, + { "tw", "Twi" }, + { "twq", "Tasawaq" }, + { "ty", "Tahitian" }, + { "tyv", "Tuvinian" }, + { "tzm", "Central Atlas Tamazight" }, + { "udm", "Udmurt" }, + { "ug", "Uyghur" }, + { "uga", "Ugaritic" }, + { "uk", "Ukrainian" }, + { "umb", "Umbundu" }, + { "unm", "Unami" }, + { "ur", "Urdu" }, + { "uz", "Uzbek" }, + { "vai", "Vai" }, + { "ve", "Venda" }, + { "vec", "Venetian" }, + { "vep", "Veps" }, + { "vi", "Vietnamese" }, + { "vls", "West Flemish" }, + { "vmf", "Main-Franconian" }, + { "vo", "Volapük" }, + { "vot", "Votic" }, + { "vro", "Võro" }, + { "vun", "Vunjo" }, + { "wa", "Walloon" }, + { "wae", "Walser" }, + { "wal", "Wolaytta" }, + { "war", "Waray" }, + { "was", "Washo" }, + { "wbp", "Warlpiri" }, + { "wo", "Wolof" }, + { "wuu", "Wu Chinese" }, + { "xal", "Kalmyk" }, + { "xh", "Xhosa" }, + { "xmf", "Mingrelian" }, + { "xog", "Soga" }, + { "yao", "Yao" }, + { "yap", "Yapese" }, + { "yav", "Yangben" }, + { "ybb", "Yemba" }, + { "yi", "Yiddish" }, + { "yo", "Yoruba" }, + { "yrl", "Nheengatu" }, + { "yue", "Yue Chinese" }, + { "yuw", "Papua New Guinea" }, + { "za", "Zhuang" }, + { "zap", "Zapotec" }, + { "zbl", "Blissymbols" }, + { "zea", "Zeelandic" }, + { "zen", "Zenaga" }, + { "zgh", "Standard Moroccan Tamazight" }, + { "zh", "Chinese" }, + { "zu", "Zulu" }, + { "zun", "Zuni" }, + { "zza", "Zaza" }, + { nullptr, nullptr } +}; + +// Additional regional variants. +// Variant name, supported languages. + +static const char *locale_variants[][2] = { + { "valencia", "ca" }, + { "iqtelif", "tt" }, + { "saaho", "aa" }, + { "tradnl", "es" }, + { nullptr, nullptr }, +}; + +// Script names and codes (excludes typographic variants, special codes, reserved codes and aliases for combined scripts). +// Reference: +// - https://en.wikipedia.org/wiki/ISO_15924 + +static const char *script_list[][2] = { + { "Adlam", "Adlm" }, + { "Afaka", "Afak" }, + { "Caucasian Albanian", "Aghb" }, + { "Ahom", "Ahom" }, + { "Arabic", "Arab" }, + { "Imperial Aramaic", "Armi" }, + { "Armenian", "Armn" }, + { "Avestan", "Avst" }, + { "Balinese", "Bali" }, + { "Bamum", "Bamu" }, + { "Bassa Vah", "Bass" }, + { "Batak", "Batk" }, + { "Bengali", "Beng" }, + { "Bhaiksuki", "Bhks" }, + { "Blissymbols", "Blis" }, + { "Bopomofo", "Bopo" }, + { "Brahmi", "Brah" }, + { "Braille", "Brai" }, + { "Buginese", "Bugi" }, + { "Buhid", "Buhd" }, + { "Chakma", "Cakm" }, + { "Unified Canadian Aboriginal", "Cans" }, + { "Carian", "Cari" }, + { "Cham", "Cham" }, + { "Cherokee", "Cher" }, + { "Chorasmian", "Chrs" }, + { "Cirth", "Cirt" }, + { "Coptic", "Copt" }, + { "Cypro-Minoan", "Cpmn" }, + { "Cypriot", "Cprt" }, + { "Cyrillic", "Cyrl" }, + { "Devanagari", "Deva" }, + { "Dives Akuru", "Diak" }, + { "Dogra", "Dogr" }, + { "Deseret", "Dsrt" }, + { "Duployan", "Dupl" }, + { "Egyptian demotic", "Egyd" }, + { "Egyptian hieratic", "Egyh" }, + { "Egyptian hieroglyphs", "Egyp" }, + { "Elbasan", "Elba" }, + { "Elymaic", "Elym" }, + { "Ethiopic", "Ethi" }, + { "Khutsuri", "Geok" }, + { "Georgian", "Geor" }, + { "Glagolitic", "Glag" }, + { "Gunjala Gondi", "Gong" }, + { "Masaram Gondi", "Gonm" }, + { "Gothic", "Goth" }, + { "Grantha", "Gran" }, + { "Greek", "Grek" }, + { "Gujarati", "Gujr" }, + { "Gurmukhi", "Guru" }, + { "Hangul", "Hang" }, + { "Han", "Hani" }, + { "Hanunoo", "Hano" }, + { "Simplified", "Hans" }, + { "Traditional", "Hant" }, + { "Hatran", "Hatr" }, + { "Hebrew", "Hebr" }, + { "Hiragana", "Hira" }, + { "Anatolian Hieroglyphs", "Hluw" }, + { "Pahawh Hmong", "Hmng" }, + { "Nyiakeng Puachue Hmong", "Hmnp" }, + { "Old Hungarian", "Hung" }, + { "Indus", "Inds" }, + { "Old Italic", "Ital" }, + { "Javanese", "Java" }, + { "Jurchen", "Jurc" }, + { "Kayah Li", "Kali" }, + { "Katakana", "Kana" }, + { "Kharoshthi", "Khar" }, + { "Khmer", "Khmr" }, + { "Khojki", "Khoj" }, + { "Khitan large script", "Kitl" }, + { "Khitan small script", "Kits" }, + { "Kannada", "Knda" }, + { "Kpelle", "Kpel" }, + { "Kaithi", "Kthi" }, + { "Tai Tham", "Lana" }, + { "Lao", "Laoo" }, + { "Latin", "Latn" }, + { "Leke", "Leke" }, + { "Lepcha", "Lepc" }, + { "Limbu", "Limb" }, + { "Linear A", "Lina" }, + { "Linear B", "Linb" }, + { "Lisu", "Lisu" }, + { "Loma", "Loma" }, + { "Lycian", "Lyci" }, + { "Lydian", "Lydi" }, + { "Mahajani", "Mahj" }, + { "Makasar", "Maka" }, + { "Mandaic", "Mand" }, + { "Manichaean", "Mani" }, + { "Marchen", "Marc" }, + { "Mayan Hieroglyphs", "Maya" }, + { "Medefaidrin", "Medf" }, + { "Mende Kikakui", "Mend" }, + { "Meroitic Cursive", "Merc" }, + { "Meroitic Hieroglyphs", "Mero" }, + { "Malayalam", "Mlym" }, + { "Modi", "Modi" }, + { "Mongolian", "Mong" }, + { "Moon", "Moon" }, + { "Mro", "Mroo" }, + { "Meitei Mayek", "Mtei" }, + { "Multani", "Mult" }, + { "Myanmar (Burmese)", "Mymr" }, + { "Nandinagari", "Nand" }, + { "Old North Arabian", "Narb" }, + { "Nabataean", "Nbat" }, + { "Newa", "Newa" }, + { "Naxi Dongba", "Nkdb" }, + { "Nakhi Geba", "Nkgb" }, + { "N'ko", "Nkoo" }, + { "Nüshu", "Nshu" }, + { "Ogham", "Ogam" }, + { "Ol Chiki", "Olck" }, + { "Old Turkic", "Orkh" }, + { "Oriya", "Orya" }, + { "Osage", "Osge" }, + { "Osmanya", "Osma" }, + { "Old Uyghur", "Ougr" }, + { "Palmyrene", "Palm" }, + { "Pau Cin Hau", "Pauc" }, + { "Proto-Cuneiform", "Pcun" }, + { "Proto-Elamite", "Pelm" }, + { "Old Permic", "Perm" }, + { "Phags-pa", "Phag" }, + { "Inscriptional Pahlavi", "Phli" }, + { "Psalter Pahlavi", "Phlp" }, + { "Book Pahlavi", "Phlv" }, + { "Phoenician", "Phnx" }, + { "Klingon", "Piqd" }, + { "Miao", "Plrd" }, + { "Inscriptional Parthian", "Prti" }, + { "Proto-Sinaitic", "Psin" }, + { "Ranjana", "Ranj" }, + { "Rejang", "Rjng" }, + { "Hanifi Rohingya", "Rohg" }, + { "Rongorongo", "Roro" }, + { "Runic", "Runr" }, + { "Samaritan", "Samr" }, + { "Sarati", "Sara" }, + { "Old South Arabian", "Sarb" }, + { "Saurashtra", "Saur" }, + { "SignWriting", "Sgnw" }, + { "Shavian", "Shaw" }, + { "Sharada", "Shrd" }, + { "Shuishu", "Shui" }, + { "Siddham", "Sidd" }, + { "Khudawadi", "Sind" }, + { "Sinhala", "Sinh" }, + { "Sogdian", "Sogd" }, + { "Old Sogdian", "Sogo" }, + { "Sora Sompeng", "Sora" }, + { "Soyombo", "Soyo" }, + { "Sundanese", "Sund" }, + { "Syloti Nagri", "Sylo" }, + { "Syriac", "Syrc" }, + { "Tagbanwa", "Tagb" }, + { "Takri", "Takr" }, + { "Tai Le", "Tale" }, + { "New Tai Lue", "Talu" }, + { "Tamil", "Taml" }, + { "Tangut", "Tang" }, + { "Tai Viet", "Tavt" }, + { "Telugu", "Telu" }, + { "Tengwar", "Teng" }, + { "Tifinagh", "Tfng" }, + { "Tagalog", "Tglg" }, + { "Thaana", "Thaa" }, + { "Thai", "Thai" }, + { "Tibetan", "Tibt" }, + { "Tirhuta", "Tirh" }, + { "Tangsa", "Tnsa" }, + { "Toto", "Toto" }, + { "Ugaritic", "Ugar" }, + { "Vai", "Vaii" }, + { "Visible Speech", "Visp" }, + { "Vithkuqi", "Vith" }, + { "Warang Citi", "Wara" }, + { "Wancho", "Wcho" }, + { "Woleai", "Wole" }, + { "Old Persian", "Xpeo" }, + { "Cuneiform", "Xsux" }, + { "Yezidi", "Yezi" }, + { "Yi", "Yiii" }, + { "Zanabazar Square", "Zanb" }, + { nullptr, nullptr } +}; + +#endif // LOCALES_H diff --git a/core/string/translation.cpp b/core/string/translation.cpp index 615ecf2432..355ee238e8 100644 --- a/core/string/translation.cpp +++ b/core/string/translation.cpp @@ -33,793 +33,12 @@ #include "core/config/project_settings.h" #include "core/io/resource_loader.h" #include "core/os/os.h" +#include "core/string/locales.h" #ifdef TOOLS_ENABLED #include "main/main.h" #endif -// ISO 639-1 language codes (and a couple of three-letter ISO 639-2 codes), -// with the addition of glibc locales with their regional identifiers. -// This list must match the language names (in English) of locale_names. -// -// References: -// - https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes -// - https://lh.2xlibre.net/locales/ -// - https://iso639-3.sil.org/ - -static const char *locale_list[] = { - "aa", // Afar - "aa_DJ", // Afar (Djibouti) - "aa_ER", // Afar (Eritrea) - "aa_ET", // Afar (Ethiopia) - "af", // Afrikaans - "af_ZA", // Afrikaans (South Africa) - "agr_PE", // Aguaruna (Peru) - "ak_GH", // Akan (Ghana) - "am_ET", // Amharic (Ethiopia) - "an_ES", // Aragonese (Spain) - "anp_IN", // Angika (India) - "ar", // Arabic - "ar_AE", // Arabic (United Arab Emirates) - "ar_BH", // Arabic (Bahrain) - "ar_DZ", // Arabic (Algeria) - "ar_EG", // Arabic (Egypt) - "ar_IN", // Arabic (India) - "ar_IQ", // Arabic (Iraq) - "ar_JO", // Arabic (Jordan) - "ar_KW", // Arabic (Kuwait) - "ar_LB", // Arabic (Lebanon) - "ar_LY", // Arabic (Libya) - "ar_MA", // Arabic (Morocco) - "ar_OM", // Arabic (Oman) - "ar_QA", // Arabic (Qatar) - "ar_SA", // Arabic (Saudi Arabia) - "ar_SD", // Arabic (Sudan) - "ar_SS", // Arabic (South Soudan) - "ar_SY", // Arabic (Syria) - "ar_TN", // Arabic (Tunisia) - "ar_YE", // Arabic (Yemen) - "as_IN", // Assamese (India) - "ast_ES", // Asturian (Spain) - "ayc_PE", // Southern Aymara (Peru) - "ay_PE", // Aymara (Peru) - "az", // Azerbaijani - "az_AZ", // Azerbaijani (Azerbaijan) - "be", // Belarusian - "be_BY", // Belarusian (Belarus) - "bem_ZM", // Bemba (Zambia) - "ber_DZ", // Berber languages (Algeria) - "ber_MA", // Berber languages (Morocco) - "bg", // Bulgarian - "bg_BG", // Bulgarian (Bulgaria) - "bhb_IN", // Bhili (India) - "bho_IN", // Bhojpuri (India) - "bi_TV", // Bislama (Tuvalu) - "bn", // Bengali - "bn_BD", // Bengali (Bangladesh) - "bn_IN", // Bengali (India) - "bo", // Tibetan - "bo_CN", // Tibetan (China) - "bo_IN", // Tibetan (India) - "br", // Breton - "br_FR", // Breton (France) - "brx_IN", // Bodo (India) - "bs_BA", // Bosnian (Bosnia and Herzegovina) - "byn_ER", // Bilin (Eritrea) - "ca", // Catalan - "ca_AD", // Catalan (Andorra) - "ca_ES", // Catalan (Spain) - "ca_FR", // Catalan (France) - "ca_IT", // Catalan (Italy) - "ce_RU", // Chechen (Russia) - "chr_US", // Cherokee (United States) - "cmn_TW", // Mandarin Chinese (Taiwan) - "crh_UA", // Crimean Tatar (Ukraine) - "csb_PL", // Kashubian (Poland) - "cs", // Czech - "cs_CZ", // Czech (Czech Republic) - "cv_RU", // Chuvash (Russia) - "cy_GB", // Welsh (United Kingdom) - "da", // Danish - "da_DK", // Danish (Denmark) - "de", // German - "de_AT", // German (Austria) - "de_BE", // German (Belgium) - "de_CH", // German (Switzerland) - "de_DE", // German (Germany) - "de_IT", // German (Italy) - "de_LU", // German (Luxembourg) - "doi_IN", // Dogri (India) - "dv_MV", // Dhivehi (Maldives) - "dz_BT", // Dzongkha (Bhutan) - "el", // Greek - "el_CY", // Greek (Cyprus) - "el_GR", // Greek (Greece) - "en", // English - "en_AG", // English (Antigua and Barbuda) - "en_AU", // English (Australia) - "en_BW", // English (Botswana) - "en_CA", // English (Canada) - "en_DK", // English (Denmark) - "en_GB", // English (United Kingdom) - "en_HK", // English (Hong Kong) - "en_IE", // English (Ireland) - "en_IL", // English (Israel) - "en_IN", // English (India) - "en_NG", // English (Nigeria) - "en_NZ", // English (New Zealand) - "en_PH", // English (Philippines) - "en_SG", // English (Singapore) - "en_US", // English (United States) - "en_ZA", // English (South Africa) - "en_ZM", // English (Zambia) - "en_ZW", // English (Zimbabwe) - "eo", // Esperanto - "es", // Spanish - "es_AR", // Spanish (Argentina) - "es_BO", // Spanish (Bolivia) - "es_CL", // Spanish (Chile) - "es_CO", // Spanish (Colombia) - "es_CR", // Spanish (Costa Rica) - "es_CU", // Spanish (Cuba) - "es_DO", // Spanish (Dominican Republic) - "es_EC", // Spanish (Ecuador) - "es_ES", // Spanish (Spain) - "es_GT", // Spanish (Guatemala) - "es_HN", // Spanish (Honduras) - "es_MX", // Spanish (Mexico) - "es_NI", // Spanish (Nicaragua) - "es_PA", // Spanish (Panama) - "es_PE", // Spanish (Peru) - "es_PR", // Spanish (Puerto Rico) - "es_PY", // Spanish (Paraguay) - "es_SV", // Spanish (El Salvador) - "es_US", // Spanish (United States) - "es_UY", // Spanish (Uruguay) - "es_VE", // Spanish (Venezuela) - "et", // Estonian - "et_EE", // Estonian (Estonia) - "eu", // Basque - "eu_ES", // Basque (Spain) - "fa", // Persian - "fa_IR", // Persian (Iran) - "ff_SN", // Fulah (Senegal) - "fi", // Finnish - "fi_FI", // Finnish (Finland) - "fil", // Filipino - "fil_PH", // Filipino (Philippines) - "fo_FO", // Faroese (Faroe Islands) - "fr", // French - "fr_BE", // French (Belgium) - "fr_CA", // French (Canada) - "fr_CH", // French (Switzerland) - "fr_FR", // French (France) - "fr_LU", // French (Luxembourg) - "fur_IT", // Friulian (Italy) - "fy_DE", // Western Frisian (Germany) - "fy_NL", // Western Frisian (Netherlands) - "ga", // Irish - "ga_IE", // Irish (Ireland) - "gd_GB", // Scottish Gaelic (United Kingdom) - "gez_ER", // Geez (Eritrea) - "gez_ET", // Geez (Ethiopia) - "gl", // Galician - "gl_ES", // Galician (Spain) - "gu_IN", // Gujarati (India) - "gv_GB", // Manx (United Kingdom) - "hak_TW", // Hakka Chinese (Taiwan) - "ha_NG", // Hausa (Nigeria) - "he", // Hebrew - "he_IL", // Hebrew (Israel) - "hi", // Hindi - "hi_IN", // Hindi (India) - "hne_IN", // Chhattisgarhi (India) - "hr", // Croatian - "hr_HR", // Croatian (Croatia) - "hsb_DE", // Upper Sorbian (Germany) - "ht_HT", // Haitian (Haiti) - "hu", // Hungarian - "hu_HU", // Hungarian (Hungary) - "hus_MX", // Huastec (Mexico) - "hy_AM", // Armenian (Armenia) - "ia_FR", // Interlingua (France) - "id", // Indonesian - "id_ID", // Indonesian (Indonesia) - "ig_NG", // Igbo (Nigeria) - "ik_CA", // Inupiaq (Canada) - "is", // Icelandic - "is_IS", // Icelandic (Iceland) - "it", // Italian - "it_CH", // Italian (Switzerland) - "it_IT", // Italian (Italy) - "iu_CA", // Inuktitut (Canada) - "ja", // Japanese - "ja_JP", // Japanese (Japan) - "kab_DZ", // Kabyle (Algeria) - "ka", // Georgian - "ka_GE", // Georgian (Georgia) - "kk_KZ", // Kazakh (Kazakhstan) - "kl_GL", // Kalaallisut (Greenland) - "km", // Central Khmer - "km_KH", // Central Khmer (Cambodia) - "kn_IN", // Kannada (India) - "kok_IN", // Konkani (India) - "ko", // Korean - "ko_KR", // Korean (South Korea) - "ks_IN", // Kashmiri (India) - "ku", // Kurdish - "ku_TR", // Kurdish (Turkey) - "kw_GB", // Cornish (United Kingdom) - "ky_KG", // Kirghiz (Kyrgyzstan) - "lb_LU", // Luxembourgish (Luxembourg) - "lg_UG", // Ganda (Uganda) - "li_BE", // Limburgan (Belgium) - "li_NL", // Limburgan (Netherlands) - "lij_IT", // Ligurian (Italy) - "ln_CD", // Lingala (Congo) - "lo_LA", // Lao (Laos) - "lt", // Lithuanian - "lt_LT", // Lithuanian (Lithuania) - "lv", // Latvian - "lv_LV", // Latvian (Latvia) - "lzh_TW", // Literary Chinese (Taiwan) - "mag_IN", // Magahi (India) - "mai_IN", // Maithili (India) - "mg_MG", // Malagasy (Madagascar) - "mh_MH", // Marshallese (Marshall Islands) - "mhr_RU", // Eastern Mari (Russia) - "mi", // Māori - "mi_NZ", // Māori (New Zealand) - "miq_NI", // Mískito (Nicaragua) - "mk", // Macedonian - "mk_MK", // Macedonian (Macedonia) - "ml", // Malayalam - "ml_IN", // Malayalam (India) - "mni_IN", // Manipuri (India) - "mn_MN", // Mongolian (Mongolia) - "mr", // Marathi - "mr_IN", // Marathi (India) - "ms", // Malay - "ms_MY", // Malay (Malaysia) - "mt", // Maltese - "mt_MT", // Maltese (Malta) - "my_MM", // Burmese (Myanmar) - "myv_RU", // Erzya (Russia) - "nah_MX", // Nahuatl languages (Mexico) - "nan_TW", // Min Nan Chinese (Taiwan) - "nb", // Norwegian Bokmål - "nb_NO", // Norwegian Bokmål (Norway) - "nds_DE", // Low German (Germany) - "nds_NL", // Low German (Netherlands) - "ne_NP", // Nepali (Nepal) - "nhn_MX", // Central Nahuatl (Mexico) - "niu_NU", // Niuean (Niue) - "niu_NZ", // Niuean (New Zealand) - "nl", // Dutch - "nl_AW", // Dutch (Aruba) - "nl_BE", // Dutch (Belgium) - "nl_NL", // Dutch (Netherlands) - "nn", // Norwegian Nynorsk - "nn_NO", // Norwegian Nynorsk (Norway) - "nr_ZA", // South Ndebele (South Africa) - "nso_ZA", // Pedi (South Africa) - "oc_FR", // Occitan (France) - "om", // Oromo - "om_ET", // Oromo (Ethiopia) - "om_KE", // Oromo (Kenya) - "or", // Oriya - "or_IN", // Oriya (India) - "os_RU", // Ossetian (Russia) - "pa_IN", // Panjabi (India) - "pap", // Papiamento - "pap_AN", // Papiamento (Netherlands Antilles) - "pap_AW", // Papiamento (Aruba) - "pap_CW", // Papiamento (Curaçao) - "pa_PK", // Panjabi (Pakistan) - "pl", // Polish - "pl_PL", // Polish (Poland) - "pr", // Pirate - "ps_AF", // Pushto (Afghanistan) - "pt", // Portuguese - "pt_BR", // Portuguese (Brazil) - "pt_PT", // Portuguese (Portugal) - "quy_PE", // Ayacucho Quechua (Peru) - "quz_PE", // Cusco Quechua (Peru) - "raj_IN", // Rajasthani (India) - "ro", // Romanian - "ro_RO", // Romanian (Romania) - "ru", // Russian - "ru_RU", // Russian (Russia) - "ru_UA", // Russian (Ukraine) - "rw_RW", // Kinyarwanda (Rwanda) - "sa_IN", // Sanskrit (India) - "sat_IN", // Santali (India) - "sc_IT", // Sardinian (Italy) - "sco", // Scots - "sd_IN", // Sindhi (India) - "se_NO", // Northern Sami (Norway) - "sgs_LT", // Samogitian (Lithuania) - "shs_CA", // Shuswap (Canada) - "sid_ET", // Sidamo (Ethiopia) - "si", // Sinhala - "si_LK", // Sinhala (Sri Lanka) - "sk", // Slovak - "sk_SK", // Slovak (Slovakia) - "sl", // Slovenian - "sl_SI", // Slovenian (Slovenia) - "so", // Somali - "so_DJ", // Somali (Djibouti) - "so_ET", // Somali (Ethiopia) - "so_KE", // Somali (Kenya) - "so_SO", // Somali (Somalia) - "son_ML", // Songhai languages (Mali) - "sq", // Albanian - "sq_AL", // Albanian (Albania) - "sq_KV", // Albanian (Kosovo) - "sq_MK", // Albanian (Macedonia) - "sr", // Serbian - "sr_Cyrl", // Serbian (Cyrillic) - "sr_Latn", // Serbian (Latin) - "sr_ME", // Serbian (Montenegro) - "sr_RS", // Serbian (Serbia) - "ss_ZA", // Swati (South Africa) - "st_ZA", // Southern Sotho (South Africa) - "sv", // Swedish - "sv_FI", // Swedish (Finland) - "sv_SE", // Swedish (Sweden) - "sw_KE", // Swahili (Kenya) - "sw_TZ", // Swahili (Tanzania) - "szl_PL", // Silesian (Poland) - "ta", // Tamil - "ta_IN", // Tamil (India) - "ta_LK", // Tamil (Sri Lanka) - "tcy_IN", // Tulu (India) - "te", // Telugu - "te_IN", // Telugu (India) - "tg_TJ", // Tajik (Tajikistan) - "the_NP", // Chitwania Tharu (Nepal) - "th", // Thai - "th_TH", // Thai (Thailand) - "ti", // Tigrinya - "ti_ER", // Tigrinya (Eritrea) - "ti_ET", // Tigrinya (Ethiopia) - "tig_ER", // Tigre (Eritrea) - "tk_TM", // Turkmen (Turkmenistan) - "tl_PH", // Tagalog (Philippines) - "tn_ZA", // Tswana (South Africa) - "tr", // Turkish - "tr_CY", // Turkish (Cyprus) - "tr_TR", // Turkish (Turkey) - "ts_ZA", // Tsonga (South Africa) - "tt", // Tatar - "tt_RU", // Tatar (Russia) - "tzm", // Central Atlas Tamazight - "tzm_MA", // Central Atlas Tamazight (Marrocos) - "ug_CN", // Uighur (China) - "uk", // Ukrainian - "uk_UA", // Ukrainian (Ukraine) - "unm_US", // Unami (United States) - "ur", // Urdu - "ur_IN", // Urdu (India) - "ur_PK", // Urdu (Pakistan) - "uz", // Uzbek - "uz_UZ", // Uzbek (Uzbekistan) - "ve_ZA", // Venda (South Africa) - "vi", // Vietnamese - "vi_VN", // Vietnamese (Vietnam) - "wa_BE", // Walloon (Belgium) - "wae_CH", // Walser (Switzerland) - "wal_ET", // Wolaytta (Ethiopia) - "wo_SN", // Wolof (Senegal) - "xh_ZA", // Xhosa (South Africa) - "yi_US", // Yiddish (United States) - "yo_NG", // Yoruba (Nigeria) - "yue_HK", // Yue Chinese (Hong Kong) - "zh", // Chinese - "zh_CN", // Chinese (China) - "zh_HK", // Chinese (Hong Kong) - "zh_SG", // Chinese (Singapore) - "zh_TW", // Chinese (Taiwan) - "zu_ZA", // Zulu (South Africa) - nullptr -}; - -static const char *locale_names[] = { - "Afar", - "Afar (Djibouti)", - "Afar (Eritrea)", - "Afar (Ethiopia)", - "Afrikaans", - "Afrikaans (South Africa)", - "Aguaruna (Peru)", - "Akan (Ghana)", - "Amharic (Ethiopia)", - "Aragonese (Spain)", - "Angika (India)", - "Arabic", - "Arabic (United Arab Emirates)", - "Arabic (Bahrain)", - "Arabic (Algeria)", - "Arabic (Egypt)", - "Arabic (India)", - "Arabic (Iraq)", - "Arabic (Jordan)", - "Arabic (Kuwait)", - "Arabic (Lebanon)", - "Arabic (Libya)", - "Arabic (Morocco)", - "Arabic (Oman)", - "Arabic (Qatar)", - "Arabic (Saudi Arabia)", - "Arabic (Sudan)", - "Arabic (South Soudan)", - "Arabic (Syria)", - "Arabic (Tunisia)", - "Arabic (Yemen)", - "Assamese (India)", - "Asturian (Spain)", - "Southern Aymara (Peru)", - "Aymara (Peru)", - "Azerbaijani", - "Azerbaijani (Azerbaijan)", - "Belarusian", - "Belarusian (Belarus)", - "Bemba (Zambia)", - "Berber languages (Algeria)", - "Berber languages (Morocco)", - "Bulgarian", - "Bulgarian (Bulgaria)", - "Bhili (India)", - "Bhojpuri (India)", - "Bislama (Tuvalu)", - "Bengali", - "Bengali (Bangladesh)", - "Bengali (India)", - "Tibetan", - "Tibetan (China)", - "Tibetan (India)", - "Breton", - "Breton (France)", - "Bodo (India)", - "Bosnian (Bosnia and Herzegovina)", - "Bilin (Eritrea)", - "Catalan", - "Catalan (Andorra)", - "Catalan (Spain)", - "Catalan (France)", - "Catalan (Italy)", - "Chechen (Russia)", - "Cherokee (United States)", - "Mandarin Chinese (Taiwan)", - "Crimean Tatar (Ukraine)", - "Kashubian (Poland)", - "Czech", - "Czech (Czech Republic)", - "Chuvash (Russia)", - "Welsh (United Kingdom)", - "Danish", - "Danish (Denmark)", - "German", - "German (Austria)", - "German (Belgium)", - "German (Switzerland)", - "German (Germany)", - "German (Italy)", - "German (Luxembourg)", - "Dogri (India)", - "Dhivehi (Maldives)", - "Dzongkha (Bhutan)", - "Greek", - "Greek (Cyprus)", - "Greek (Greece)", - "English", - "English (Antigua and Barbuda)", - "English (Australia)", - "English (Botswana)", - "English (Canada)", - "English (Denmark)", - "English (United Kingdom)", - "English (Hong Kong)", - "English (Ireland)", - "English (Israel)", - "English (India)", - "English (Nigeria)", - "English (New Zealand)", - "English (Philippines)", - "English (Singapore)", - "English (United States)", - "English (South Africa)", - "English (Zambia)", - "English (Zimbabwe)", - "Esperanto", - "Spanish", - "Spanish (Argentina)", - "Spanish (Bolivia)", - "Spanish (Chile)", - "Spanish (Colombia)", - "Spanish (Costa Rica)", - "Spanish (Cuba)", - "Spanish (Dominican Republic)", - "Spanish (Ecuador)", - "Spanish (Spain)", - "Spanish (Guatemala)", - "Spanish (Honduras)", - "Spanish (Mexico)", - "Spanish (Nicaragua)", - "Spanish (Panama)", - "Spanish (Peru)", - "Spanish (Puerto Rico)", - "Spanish (Paraguay)", - "Spanish (El Salvador)", - "Spanish (United States)", - "Spanish (Uruguay)", - "Spanish (Venezuela)", - "Estonian", - "Estonian (Estonia)", - "Basque", - "Basque (Spain)", - "Persian", - "Persian (Iran)", - "Fulah (Senegal)", - "Finnish", - "Finnish (Finland)", - "Filipino", - "Filipino (Philippines)", - "Faroese (Faroe Islands)", - "French", - "French (Belgium)", - "French (Canada)", - "French (Switzerland)", - "French (France)", - "French (Luxembourg)", - "Friulian (Italy)", - "Western Frisian (Germany)", - "Western Frisian (Netherlands)", - "Irish", - "Irish (Ireland)", - "Scottish Gaelic (United Kingdom)", - "Geez (Eritrea)", - "Geez (Ethiopia)", - "Galician", - "Galician (Spain)", - "Gujarati (India)", - "Manx (United Kingdom)", - "Hakka Chinese (Taiwan)", - "Hausa (Nigeria)", - "Hebrew", - "Hebrew (Israel)", - "Hindi", - "Hindi (India)", - "Chhattisgarhi (India)", - "Croatian", - "Croatian (Croatia)", - "Upper Sorbian (Germany)", - "Haitian (Haiti)", - "Hungarian", - "Hungarian (Hungary)", - "Huastec (Mexico)", - "Armenian (Armenia)", - "Interlingua (France)", - "Indonesian", - "Indonesian (Indonesia)", - "Igbo (Nigeria)", - "Inupiaq (Canada)", - "Icelandic", - "Icelandic (Iceland)", - "Italian", - "Italian (Switzerland)", - "Italian (Italy)", - "Inuktitut (Canada)", - "Japanese", - "Japanese (Japan)", - "Kabyle (Algeria)", - "Georgian", - "Georgian (Georgia)", - "Kazakh (Kazakhstan)", - "Kalaallisut (Greenland)", - "Central Khmer", - "Central Khmer (Cambodia)", - "Kannada (India)", - "Konkani (India)", - "Korean", - "Korean (South Korea)", - "Kashmiri (India)", - "Kurdish", - "Kurdish (Turkey)", - "Cornish (United Kingdom)", - "Kirghiz (Kyrgyzstan)", - "Luxembourgish (Luxembourg)", - "Ganda (Uganda)", - "Limburgan (Belgium)", - "Limburgan (Netherlands)", - "Ligurian (Italy)", - "Lingala (Congo)", - "Lao (Laos)", - "Lithuanian", - "Lithuanian (Lithuania)", - "Latvian", - "Latvian (Latvia)", - "Literary Chinese (Taiwan)", - "Magahi (India)", - "Maithili (India)", - "Malagasy (Madagascar)", - "Marshallese (Marshall Islands)", - "Eastern Mari (Russia)", - "Māori", - "Māori (New Zealand)", - "Mískito (Nicaragua)", - "Macedonian", - "Macedonian (Macedonia)", - "Malayalam", - "Malayalam (India)", - "Manipuri (India)", - "Mongolian (Mongolia)", - "Marathi", - "Marathi (India)", - "Malay", - "Malay (Malaysia)", - "Maltese", - "Maltese (Malta)", - "Burmese (Myanmar)", - "Erzya (Russia)", - "Nahuatl languages (Mexico)", - "Min Nan Chinese (Taiwan)", - "Norwegian Bokmål", - "Norwegian Bokmål (Norway)", - "Low German (Germany)", - "Low German (Netherlands)", - "Nepali (Nepal)", - "Central Nahuatl (Mexico)", - "Niuean (Niue)", - "Niuean (New Zealand)", - "Dutch", - "Dutch (Aruba)", - "Dutch (Belgium)", - "Dutch (Netherlands)", - "Norwegian Nynorsk", - "Norwegian Nynorsk (Norway)", - "South Ndebele (South Africa)", - "Pedi (South Africa)", - "Occitan (France)", - "Oromo", - "Oromo (Ethiopia)", - "Oromo (Kenya)", - "Oriya", - "Oriya (India)", - "Ossetian (Russia)", - "Panjabi (India)", - "Papiamento", - "Papiamento (Netherlands Antilles)", - "Papiamento (Aruba)", - "Papiamento (Curaçao)", - "Panjabi (Pakistan)", - "Polish", - "Polish (Poland)", - "Pirate", - "Pushto (Afghanistan)", - "Portuguese", - "Portuguese (Brazil)", - "Portuguese (Portugal)", - "Ayacucho Quechua (Peru)", - "Cusco Quechua (Peru)", - "Rajasthani (India)", - "Romanian", - "Romanian (Romania)", - "Russian", - "Russian (Russia)", - "Russian (Ukraine)", - "Kinyarwanda (Rwanda)", - "Sanskrit (India)", - "Santali (India)", - "Sardinian (Italy)", - "Scots (Scotland)", - "Sindhi (India)", - "Northern Sami (Norway)", - "Samogitian (Lithuania)", - "Shuswap (Canada)", - "Sidamo (Ethiopia)", - "Sinhala", - "Sinhala (Sri Lanka)", - "Slovak", - "Slovak (Slovakia)", - "Slovenian", - "Slovenian (Slovenia)", - "Somali", - "Somali (Djibouti)", - "Somali (Ethiopia)", - "Somali (Kenya)", - "Somali (Somalia)", - "Songhai languages (Mali)", - "Albanian", - "Albanian (Albania)", - "Albanian (Kosovo)", - "Albanian (Macedonia)", - "Serbian", - "Serbian (Cyrillic)", - "Serbian (Latin)", - "Serbian (Montenegro)", - "Serbian (Serbia)", - "Swati (South Africa)", - "Southern Sotho (South Africa)", - "Swedish", - "Swedish (Finland)", - "Swedish (Sweden)", - "Swahili (Kenya)", - "Swahili (Tanzania)", - "Silesian (Poland)", - "Tamil", - "Tamil (India)", - "Tamil (Sri Lanka)", - "Tulu (India)", - "Telugu", - "Telugu (India)", - "Tajik (Tajikistan)", - "Chitwania Tharu (Nepal)", - "Thai", - "Thai (Thailand)", - "Tigrinya", - "Tigrinya (Eritrea)", - "Tigrinya (Ethiopia)", - "Tigre (Eritrea)", - "Turkmen (Turkmenistan)", - "Tagalog (Philippines)", - "Tswana (South Africa)", - "Turkish", - "Turkish (Cyprus)", - "Turkish (Turkey)", - "Tsonga (South Africa)", - "Tatar", - "Tatar (Russia)", - "Central Atlas Tamazight", - "Central Atlas Tamazight (Marrocos)", - "Uighur (China)", - "Ukrainian", - "Ukrainian (Ukraine)", - "Unami (United States)", - "Urdu", - "Urdu (India)", - "Urdu (Pakistan)", - "Uzbek", - "Uzbek (Uzbekistan)", - "Venda (South Africa)", - "Vietnamese", - "Vietnamese (Vietnam)", - "Walloon (Belgium)", - "Walser (Switzerland)", - "Wolaytta (Ethiopia)", - "Wolof (Senegal)", - "Xhosa (South Africa)", - "Yiddish (United States)", - "Yoruba (Nigeria)", - "Yue Chinese (Hong Kong)", - "Chinese", - "Chinese (China)", - "Chinese (Hong Kong)", - "Chinese (Singapore)", - "Chinese (Taiwan)", - "Zulu (South Africa)", - nullptr -}; - -// Windows has some weird locale identifiers which do not honor the ISO 639-1 -// standardized nomenclature. Whenever those don't conflict with existing ISO -// identifiers, we override them. -// -// Reference: -// - https://msdn.microsoft.com/en-us/library/windows/desktop/ms693062(v=vs.85).aspx - -static const char *locale_renames[][2] = { - { "in", "id" }, // Indonesian - { "iw", "he" }, // Hebrew - { "no", "nb" }, // Norwegian Bokmål - { "C", "en" }, // "C" is the simple/default/untranslated Computer locale. - // ASCII-only, English, no currency symbols. Godot treats this as "en". - // See https://unix.stackexchange.com/a/87763/164141 "The C locale is"... - { nullptr, nullptr } -}; - -/////////////////////////////////////////////// - Dictionary Translation::_get_messages() const { Dictionary d; for (const KeyValue<StringName, StringName> &E : translation_map) { @@ -849,17 +68,7 @@ void Translation::_set_messages(const Dictionary &p_messages) { } void Translation::set_locale(const String &p_locale) { - String univ_locale = TranslationServer::standardize_locale(p_locale); - - if (!TranslationServer::is_locale_valid(univ_locale)) { - String trimmed_locale = TranslationServer::get_language_code(univ_locale); - - ERR_FAIL_COND_MSG(!TranslationServer::is_locale_valid(trimmed_locale), "Invalid locale: " + trimmed_locale + "."); - - locale = trimmed_locale; - } else { - locale = univ_locale; - } + locale = TranslationServer::get_singleton()->standardize_locale(p_locale); if (OS::get_singleton()->get_main_loop() && TranslationServer::get_singleton()->get_loaded_locales().has(this)) { OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_TRANSLATION_CHANGED); @@ -1004,124 +213,314 @@ static _character_accent_pair _character_to_accented[] = { { 'z', U"ź" }, }; -bool TranslationServer::is_locale_valid(const String &p_locale) { - const char **ptr = locale_list; +static _FORCE_INLINE_ bool is_upper_case(char32_t c) { + return (c >= 'A' && c <= 'Z'); +} + +static _FORCE_INLINE_ bool is_lower_case(char32_t c) { + return (c >= 'a' && c <= 'z'); +} + +Vector<TranslationServer::LocaleScriptInfo> TranslationServer::locale_script_info; + +Map<String, String> TranslationServer::language_map; +Map<String, String> TranslationServer::script_map; +Map<String, String> TranslationServer::locale_rename_map; +Map<String, String> TranslationServer::country_name_map; +Map<String, String> TranslationServer::variant_map; +Map<String, String> TranslationServer::country_rename_map; + +void TranslationServer::init_locale_info() { + // Init locale info. + language_map.clear(); + int idx = 0; + while (language_list[idx][0] != nullptr) { + language_map[language_list[idx][0]] = String::utf8(language_list[idx][1]); + idx++; + } - while (*ptr) { - if (*ptr == p_locale) { - return true; + // Init locale-script map. + locale_script_info.clear(); + idx = 0; + while (locale_scripts[idx][0] != nullptr) { + LocaleScriptInfo info; + info.name = locale_scripts[idx][0]; + info.script = locale_scripts[idx][1]; + info.default_country = locale_scripts[idx][2]; + Vector<String> supported_countries = String(locale_scripts[idx][3]).split(",", false); + for (int i = 0; i < supported_countries.size(); i++) { + info.supported_countries.insert(supported_countries[i]); } - ptr++; + locale_script_info.push_back(info); + idx++; } - return false; -} + // Init supported script list. + script_map.clear(); + idx = 0; + while (script_list[idx][0] != nullptr) { + script_map[script_list[idx][1]] = String::utf8(script_list[idx][0]); + idx++; + } -String TranslationServer::standardize_locale(const String &p_locale) { - // Replaces '-' with '_' for macOS Sierra-style locales - String univ_locale = p_locale.replace("-", "_"); + // Init regional variant map. + variant_map.clear(); + idx = 0; + while (locale_variants[idx][0] != nullptr) { + variant_map[locale_variants[idx][0]] = locale_variants[idx][1]; + idx++; + } - // Handles known non-ISO locale names used e.g. on Windows - int idx = 0; + // Init locale renames. + locale_rename_map.clear(); + idx = 0; while (locale_renames[idx][0] != nullptr) { - if (locale_renames[idx][0] == univ_locale) { - univ_locale = locale_renames[idx][1]; - break; + if (!String(locale_renames[idx][1]).is_empty()) { + locale_rename_map[locale_renames[idx][0]] = locale_renames[idx][1]; } idx++; } - return univ_locale; + // Init country names. + country_name_map.clear(); + idx = 0; + while (country_names[idx][0] != nullptr) { + country_name_map[String(country_names[idx][0])] = String::utf8(country_names[idx][1]); + idx++; + } + + // Init country renames. + country_rename_map.clear(); + idx = 0; + while (country_renames[idx][0] != nullptr) { + if (!String(country_renames[idx][1]).is_empty()) { + country_rename_map[country_renames[idx][0]] = country_renames[idx][1]; + } + idx++; + } } -String TranslationServer::get_language_code(const String &p_locale) { - ERR_FAIL_COND_V_MSG(p_locale.length() < 2, p_locale, "Invalid locale '" + p_locale + "'."); - // Most language codes are two letters, but some are three, - // so we have to look for a regional code separator ('_' or '-') - // to extract the left part. - // For example we get 'nah_MX' as input and should return 'nah'. - int split = p_locale.find("_"); - if (split == -1) { - split = p_locale.find("-"); +String TranslationServer::standardize_locale(const String &p_locale) const { + // Replaces '-' with '_' for macOS style locales. + String univ_locale = p_locale.replace("-", "_"); + + // Extract locale elements. + String lang, script, country, variant; + Vector<String> locale_elements = univ_locale.get_slice("@", 0).split("_"); + lang = locale_elements[0]; + if (locale_elements.size() >= 2) { + if (locale_elements[1].length() == 4 && is_upper_case(locale_elements[1][0]) && is_lower_case(locale_elements[1][1]) && is_lower_case(locale_elements[1][2]) && is_lower_case(locale_elements[1][3])) { + script = locale_elements[1]; + } + if (locale_elements[1].length() == 2 && is_upper_case(locale_elements[1][0]) && is_upper_case(locale_elements[1][1])) { + country = locale_elements[1]; + } + } + if (locale_elements.size() >= 3) { + if (locale_elements[2].length() == 2 && is_upper_case(locale_elements[2][0]) && is_upper_case(locale_elements[2][1])) { + country = locale_elements[2]; + } else if (variant_map.has(locale_elements[2].to_lower()) && variant_map[locale_elements[2].to_lower()] == lang) { + variant = locale_elements[2].to_lower(); + } } - if (split == -1) { // No separator, so the locale is already only a language code. - return p_locale; + if (locale_elements.size() >= 4) { + if (variant_map.has(locale_elements[3].to_lower()) && variant_map[locale_elements[3].to_lower()] == lang) { + variant = locale_elements[3].to_lower(); + } } - return p_locale.left(split); -} -void TranslationServer::set_locale(const String &p_locale) { - String univ_locale = standardize_locale(p_locale); + // Try extract script and variant from the extra part. + Vector<String> script_extra = univ_locale.get_slice("@", 1).split(";"); + for (int i = 0; i < script_extra.size(); i++) { + if (script_extra[i].to_lower() == "cyrillic") { + script = "Cyrl"; + break; + } else if (script_extra[i].to_lower() == "latin") { + script = "Latn"; + break; + } else if (script_extra[i].to_lower() == "devanagari") { + script = "Deva"; + break; + } else if (variant_map.has(script_extra[i].to_lower()) && variant_map[script_extra[i].to_lower()] == lang) { + variant = script_extra[i].to_lower(); + } + } - if (!is_locale_valid(univ_locale)) { - String trimmed_locale = get_language_code(univ_locale); - print_verbose(vformat("Unsupported locale '%s', falling back to '%s'.", p_locale, trimmed_locale)); + // Handles known non-ISO language names used e.g. on Windows. + if (locale_rename_map.has(lang)) { + lang = locale_rename_map[lang]; + } - if (!is_locale_valid(trimmed_locale)) { - ERR_PRINT(vformat("Unsupported locale '%s', falling back to 'en'.", trimmed_locale)); - locale = "en"; - } else { - locale = trimmed_locale; + // Handle country renames. + if (country_rename_map.has(country)) { + country = country_rename_map[country]; + } + + // Remove unsupported script codes. + if (!script_map.has(script)) { + script = ""; + } + + // Add script code base on language and country codes for some ambiguous cases. + if (script.is_empty()) { + for (int i = 0; i < locale_script_info.size(); i++) { + const LocaleScriptInfo &info = locale_script_info[i]; + if (info.name == lang) { + if (country.is_empty() || info.supported_countries.has(country)) { + script = info.script; + break; + } + } + } + } + if (!script.is_empty() && country.is_empty()) { + // Add conntry code based on script for some ambiguous cases. + for (int i = 0; i < locale_script_info.size(); i++) { + const LocaleScriptInfo &info = locale_script_info[i]; + if (info.name == lang && info.script == script) { + country = info.default_country; + break; + } + } + } + + // Combine results. + String locale = lang; + if (!script.is_empty()) { + locale = locale + "_" + script; + } + if (!country.is_empty()) { + locale = locale + "_" + country; + } + if (!variant.is_empty()) { + locale = locale + "_" + variant; + } + return locale; +} + +int TranslationServer::compare_locales(const String &p_locale_a, const String &p_locale_b) const { + String locale_a = standardize_locale(p_locale_a); + String locale_b = standardize_locale(p_locale_b); + + if (locale_a == locale_b) { + // Exact match. + return 10; + } + + Vector<String> locale_a_elements = locale_a.split("_"); + Vector<String> locale_b_elements = locale_b.split("_"); + if (locale_a_elements[0] == locale_b_elements[0]) { + // Matching language, both locales have extra parts. + // Return number of matching elements. + int matching_elements = 1; + for (int i = 1; i < locale_a_elements.size(); i++) { + for (int j = 1; j < locale_b_elements.size(); j++) { + if (locale_a_elements[i] == locale_b_elements[j]) { + matching_elements++; + } + } } + return matching_elements; } else { - locale = univ_locale; + // No match. + return 0; } +} - if (OS::get_singleton()->get_main_loop()) { - OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_TRANSLATION_CHANGED); +String TranslationServer::get_locale_name(const String &p_locale) const { + String locale = standardize_locale(p_locale); + + String lang, script, country; + Vector<String> locale_elements = locale.split("_"); + lang = locale_elements[0]; + if (locale_elements.size() >= 2) { + if (locale_elements[1].length() == 4 && is_upper_case(locale_elements[1][0]) && is_lower_case(locale_elements[1][1]) && is_lower_case(locale_elements[1][2]) && is_lower_case(locale_elements[1][3])) { + script = locale_elements[1]; + } + if (locale_elements[1].length() == 2 && is_upper_case(locale_elements[1][0]) && is_upper_case(locale_elements[1][1])) { + country = locale_elements[1]; + } + } + if (locale_elements.size() >= 3) { + if (locale_elements[2].length() == 2 && is_upper_case(locale_elements[2][0]) && is_upper_case(locale_elements[2][1])) { + country = locale_elements[2]; + } } - ResourceLoader::reload_translation_remaps(); + String name = language_map[lang]; + if (!script.is_empty()) { + name = name + " (" + script_map[script] + ")"; + } + if (!country.is_empty()) { + name = name + ", " + country_name_map[country]; + } + return name; } -String TranslationServer::get_locale() const { - return locale; +Vector<String> TranslationServer::get_all_languages() const { + Vector<String> languages; + + for (const Map<String, String>::Element *E = language_map.front(); E; E = E->next()) { + languages.push_back(E->key()); + } + + return languages; } -String TranslationServer::get_locale_name(const String &p_locale) const { - if (!locale_name_map.has(p_locale)) { - return String(); +String TranslationServer::get_language_name(const String &p_language) const { + return language_map[p_language]; +} + +Vector<String> TranslationServer::get_all_scripts() const { + Vector<String> scripts; + + for (const Map<String, String>::Element *E = script_map.front(); E; E = E->next()) { + scripts.push_back(E->key()); } - return locale_name_map[p_locale]; + + return scripts; } -Array TranslationServer::get_loaded_locales() const { - Array locales; - for (const Set<Ref<Translation>>::Element *E = translations.front(); E; E = E->next()) { - const Ref<Translation> &t = E->get(); - ERR_FAIL_COND_V(t.is_null(), Array()); - String l = t->get_locale(); +String TranslationServer::get_script_name(const String &p_script) const { + return script_map[p_script]; +} - if (!locales.has(l)) { - locales.push_back(l); - } +Vector<String> TranslationServer::get_all_countries() const { + Vector<String> countries; + + for (const Map<String, String>::Element *E = country_name_map.front(); E; E = E->next()) { + countries.push_back(E->key()); } - locales.sort(); - return locales; + return countries; } -Vector<String> TranslationServer::get_all_locales() { - Vector<String> locales; +String TranslationServer::get_country_name(const String &p_country) const { + return country_name_map[p_country]; +} - const char **ptr = locale_list; +void TranslationServer::set_locale(const String &p_locale) { + locale = standardize_locale(p_locale); - while (*ptr) { - locales.push_back(*ptr); - ptr++; + if (OS::get_singleton()->get_main_loop()) { + OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_TRANSLATION_CHANGED); } - return locales; + ResourceLoader::reload_translation_remaps(); } -Vector<String> TranslationServer::get_all_locale_names() { - Vector<String> locales; +String TranslationServer::get_locale() const { + return locale; +} - const char **ptr = locale_names; +Array TranslationServer::get_loaded_locales() const { + Array locales; + for (const Set<Ref<Translation>>::Element *E = translations.front(); E; E = E->next()) { + const Ref<Translation> &t = E->get(); + ERR_FAIL_COND_V(t.is_null(), Array()); + String l = t->get_locale(); - while (*ptr) { - locales.push_back(String::utf8(*ptr)); - ptr++; + locales.push_back(l); } return locales; @@ -1137,23 +536,20 @@ void TranslationServer::remove_translation(const Ref<Translation> &p_translation Ref<Translation> TranslationServer::get_translation_object(const String &p_locale) { Ref<Translation> res; - String lang = get_language_code(p_locale); - bool near_match_found = false; + int best_score = 0; for (const Set<Ref<Translation>>::Element *E = translations.front(); E; E = E->next()) { const Ref<Translation> &t = E->get(); ERR_FAIL_COND_V(t.is_null(), nullptr); String l = t->get_locale(); - // Exact match. - if (l == p_locale) { - return t; - } - - // If near match found, keep that match, but keep looking to try to look for perfect match. - if (get_language_code(l) == lang && !near_match_found) { + int score = compare_locales(p_locale, l); + if (score > 0 && score >= best_score) { res = t; - near_match_found = true; + best_score = score; + if (score == 10) { + break; // Exact match, skip the rest. + } } } return res; @@ -1170,8 +566,6 @@ StringName TranslationServer::translate(const StringName &p_message, const Strin return p_message; } - ERR_FAIL_COND_V_MSG(locale.length() < 2, p_message, "Could not translate message as configured locale '" + locale + "' is invalid."); - StringName res = _get_message_from_translations(p_message, p_context, locale, false); if (!res && fallback.length() >= 2) { @@ -1193,8 +587,6 @@ StringName TranslationServer::translate_plural(const StringName &p_message, cons return p_message_plural; } - ERR_FAIL_COND_V_MSG(locale.length() < 2, p_message, "Could not translate message as configured locale '" + locale + "' is invalid."); - StringName res = _get_message_from_translations(p_message, p_context, locale, true, p_message_plural, p_n); if (!res && fallback.length() >= 2) { @@ -1212,51 +604,30 @@ StringName TranslationServer::translate_plural(const StringName &p_message, cons } StringName TranslationServer::_get_message_from_translations(const StringName &p_message, const StringName &p_context, const String &p_locale, bool plural, const String &p_message_plural, int p_n) const { - // Locale can be of the form 'll_CC', i.e. language code and regional code, - // e.g. 'en_US', 'en_GB', etc. It might also be simply 'll', e.g. 'en'. - // To find the relevant translation, we look for those with locale starting - // with the language code, and then if any is an exact match for the long - // form. If not found, we fall back to a near match (another locale with - // same language code). - - // Note: ResourceLoader::_path_remap reproduces this locale near matching - // logic, so be sure to propagate changes there when changing things here. - StringName res; - String lang = get_language_code(p_locale); - bool near_match = false; + int best_score = 0; for (const Set<Ref<Translation>>::Element *E = translations.front(); E; E = E->next()) { const Ref<Translation> &t = E->get(); ERR_FAIL_COND_V(t.is_null(), p_message); String l = t->get_locale(); - bool exact_match = (l == p_locale); - if (!exact_match) { - if (near_match) { - continue; // Only near-match once, but keep looking for exact matches. + int score = compare_locales(p_locale, l); + if (score > 0 && score >= best_score) { + StringName r; + if (!plural) { + r = t->get_message(p_message, p_context); + } else { + r = t->get_plural_message(p_message, p_message_plural, p_n, p_context); } - if (get_language_code(l) != lang) { - continue; // Language code does not match. + if (!r) { + continue; + } + res = r; + best_score = score; + if (score == 10) { + break; // Exact match, skip the rest. } - } - - StringName r; - if (!plural) { - r = t->get_message(p_message, p_context); - } else { - r = t->get_plural_message(p_message, p_message_plural, p_n, p_context); - } - - if (!r) { - continue; - } - res = r; - - if (exact_match) { - break; - } else { - near_match = true; } } @@ -1308,18 +679,7 @@ void TranslationServer::setup() { pseudolocalization_skip_placeholders_enabled = GLOBAL_DEF("internationalization/pseudolocalization/skip_placeholders", true); #ifdef TOOLS_ENABLED - { - String options = ""; - int idx = 0; - while (locale_list[idx]) { - if (idx > 0) { - options += ","; - } - options += locale_list[idx]; - idx++; - } - ProjectSettings::get_singleton()->set_custom_property_info("internationalization/locale/fallback", PropertyInfo(Variant::STRING, "internationalization/locale/fallback", PROPERTY_HINT_ENUM, options)); - } + ProjectSettings::get_singleton()->set_custom_property_info("internationalization/locale/fallback", PropertyInfo(Variant::STRING, "internationalization/locale/fallback", PROPERTY_HINT_LOCALE_ID, "")); #endif } @@ -1574,6 +934,18 @@ void TranslationServer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_locale", "locale"), &TranslationServer::set_locale); ClassDB::bind_method(D_METHOD("get_locale"), &TranslationServer::get_locale); + ClassDB::bind_method(D_METHOD("compare_locales", "locale_a", "locale_b"), &TranslationServer::compare_locales); + ClassDB::bind_method(D_METHOD("standardize_locale", "locale"), &TranslationServer::standardize_locale); + + ClassDB::bind_method(D_METHOD("get_all_languages"), &TranslationServer::get_all_languages); + ClassDB::bind_method(D_METHOD("get_language_name", "language"), &TranslationServer::get_language_name); + + ClassDB::bind_method(D_METHOD("get_all_scripts"), &TranslationServer::get_all_scripts); + ClassDB::bind_method(D_METHOD("get_script_name", "script"), &TranslationServer::get_script_name); + + ClassDB::bind_method(D_METHOD("get_all_countries"), &TranslationServer::get_all_countries); + ClassDB::bind_method(D_METHOD("get_country_name", "country"), &TranslationServer::get_country_name); + ClassDB::bind_method(D_METHOD("get_locale_name", "locale"), &TranslationServer::get_locale_name); ClassDB::bind_method(D_METHOD("translate", "message", "context"), &TranslationServer::translate, DEFVAL("")); @@ -1606,8 +978,5 @@ void TranslationServer::load_translations() { TranslationServer::TranslationServer() { singleton = this; - - for (int i = 0; locale_list[i]; ++i) { - locale_name_map.insert(locale_list[i], String::utf8(locale_names[i])); - } + init_locale_info(); } diff --git a/core/string/translation.h b/core/string/translation.h index e95d15e2ab..947ca4c6d8 100644 --- a/core/string/translation.h +++ b/core/string/translation.h @@ -78,8 +78,6 @@ class TranslationServer : public Object { Ref<Translation> tool_translation; Ref<Translation> doc_translation; - Map<String, String> locale_name_map; - bool enabled = true; bool pseudolocalization_enabled = false; @@ -109,6 +107,23 @@ class TranslationServer : public Object { static void _bind_methods(); + struct LocaleScriptInfo { + String name; + String script; + String default_country; + Set<String> supported_countries; + }; + static Vector<LocaleScriptInfo> locale_script_info; + + static Map<String, String> language_map; + static Map<String, String> script_map; + static Map<String, String> locale_rename_map; + static Map<String, String> country_name_map; + static Map<String, String> country_rename_map; + static Map<String, String> variant_map; + + void init_locale_info(); + public: _FORCE_INLINE_ static TranslationServer *get_singleton() { return singleton; } @@ -119,6 +134,15 @@ public: String get_locale() const; Ref<Translation> get_translation_object(const String &p_locale); + Vector<String> get_all_languages() const; + String get_language_name(const String &p_language) const; + + Vector<String> get_all_scripts() const; + String get_script_name(const String &p_script) const; + + Vector<String> get_all_countries() const; + String get_country_name(const String &p_country) const; + String get_locale_name(const String &p_locale) const; Array get_loaded_locales() const; @@ -136,11 +160,9 @@ public: void set_editor_pseudolocalization(bool p_enabled); void reload_pseudolocalization(); - static Vector<String> get_all_locales(); - static Vector<String> get_all_locale_names(); - static bool is_locale_valid(const String &p_locale); - static String standardize_locale(const String &p_locale); - static String get_language_code(const String &p_locale); + String standardize_locale(const String &p_locale) const; + + int compare_locales(const String &p_locale_a, const String &p_locale_b) const; String get_tool_locale(); void set_tool_translation(const Ref<Translation> &p_translation); diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 658dbc98cf..93b2060155 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -1632,7 +1632,7 @@ String String::utf8(const char *p_utf8, int p_len) { } bool String::parse_utf8(const char *p_utf8, int p_len) { -#define _UNICERROR(m_err) print_error("Unicode parsing error: " + String(m_err) + ". Is the string valid UTF-8?"); +#define UNICERROR(m_err) print_error("Unicode parsing error: " + String(m_err) + ". Is the string valid UTF-8?"); if (!p_utf8) { return true; @@ -1673,12 +1673,12 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { } else if ((c & 0xf8) == 0xf0) { skip = 3; } else { - _UNICERROR("invalid skip at " + num_int64(cstr_size)); + UNICERROR("invalid skip at " + num_int64(cstr_size)); return true; //invalid utf8 } if (skip == 1 && (c & 0x1e) == 0) { - _UNICERROR("overlong rejected at " + num_int64(cstr_size)); + UNICERROR("overlong rejected at " + num_int64(cstr_size)); return true; //reject overlong } @@ -1693,7 +1693,7 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { } if (skip) { - _UNICERROR("no space left"); + UNICERROR("no space left"); return true; //not enough space } } @@ -1720,17 +1720,17 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { } else if ((*p_utf8 & 0xf8) == 0xf0) { len = 4; } else { - _UNICERROR("invalid len"); + UNICERROR("invalid len"); return true; //invalid UTF8 } if (len > cstr_size) { - _UNICERROR("no space left"); + UNICERROR("no space left"); return true; //not enough space } if (len == 2 && (*p_utf8 & 0x1E) == 0) { - _UNICERROR("no space left"); + UNICERROR("no space left"); return true; //reject overlong } @@ -1745,18 +1745,18 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { for (int i = 1; i < len; i++) { if ((p_utf8[i] & 0xc0) != 0x80) { - _UNICERROR("invalid utf8"); + UNICERROR("invalid utf8"); return true; //invalid utf8 } if (unichar == 0 && i == 2 && ((p_utf8[i] & 0x7f) >> (7 - len)) == 0) { - _UNICERROR("invalid utf8 overlong"); + UNICERROR("invalid utf8 overlong"); return true; //no overlong } unichar = (unichar << 6) | (p_utf8[i] & 0x3f); } } if (unichar >= 0xd800 && unichar <= 0xdfff) { - _UNICERROR("invalid code point"); + UNICERROR("invalid code point"); return CharString(); } @@ -1766,7 +1766,7 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { } return false; -#undef _UNICERROR +#undef UNICERROR } CharString String::utf8() const { @@ -1840,7 +1840,7 @@ String String::utf16(const char16_t *p_utf16, int p_len) { } bool String::parse_utf16(const char16_t *p_utf16, int p_len) { -#define _UNICERROR(m_err) print_error("Unicode parsing error: " + String(m_err) + ". Is the string valid UTF-16?"); +#define UNICERROR(m_err) print_error("Unicode parsing error: " + String(m_err) + ". Is the string valid UTF-16?"); if (!p_utf16) { return true; @@ -1880,7 +1880,7 @@ bool String::parse_utf16(const char16_t *p_utf16, int p_len) { if ((c & 0xfffffc00) == 0xd800) { skip = 1; // lead surrogate } else if ((c & 0xfffffc00) == 0xdc00) { - _UNICERROR("invalid utf16 surrogate at " + num_int64(cstr_size)); + UNICERROR("invalid utf16 surrogate at " + num_int64(cstr_size)); return true; // invalid UTF16 } else { skip = 0; @@ -1890,7 +1890,7 @@ bool String::parse_utf16(const char16_t *p_utf16, int p_len) { if ((c & 0xfffffc00) == 0xdc00) { // trail surrogate --skip; } else { - _UNICERROR("invalid utf16 surrogate at " + num_int64(cstr_size)); + UNICERROR("invalid utf16 surrogate at " + num_int64(cstr_size)); return true; // invalid UTF16 } } @@ -1900,7 +1900,7 @@ bool String::parse_utf16(const char16_t *p_utf16, int p_len) { } if (skip) { - _UNICERROR("no space left"); + UNICERROR("no space left"); return true; // not enough space } } @@ -1925,7 +1925,7 @@ bool String::parse_utf16(const char16_t *p_utf16, int p_len) { } if (len > cstr_size) { - _UNICERROR("no space left"); + UNICERROR("no space left"); return true; //not enough space } @@ -1943,7 +1943,7 @@ bool String::parse_utf16(const char16_t *p_utf16, int p_len) { } return false; -#undef _UNICERROR +#undef UNICERROR } Char16String String::utf16() const { diff --git a/core/typedefs.h b/core/typedefs.h index e6034eb375..5929b5123b 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -71,6 +71,17 @@ #endif #endif +// No discard allows the compiler to flag warnings if we don't use the return value of functions / classes +#ifndef _NO_DISCARD_ +#define _NO_DISCARD_ [[nodiscard]] +#endif + +// In some cases _NO_DISCARD_ will get false positives, +// we can prevent the warning in specific cases by preceding the call with a cast. +#ifndef _ALLOW_DISCARD_ +#define _ALLOW_DISCARD_ (void) +#endif + // Windows badly defines a lot of stuff we'll never use. Undefine it. #ifdef _WIN32 #undef min // override standard definition diff --git a/core/variant/array.cpp b/core/variant/array.cpp index 3d2f337442..1b39558dff 100644 --- a/core/variant/array.cpp +++ b/core/variant/array.cpp @@ -631,7 +631,7 @@ Variant Array::max() const { } const void *Array::id() const { - return _p->array.ptr(); + return _p; } Array::Array(const Array &p_from, uint32_t p_type, const StringName &p_class_name, const Variant &p_script) { diff --git a/core/variant/dictionary.cpp b/core/variant/dictionary.cpp index cc04ae712b..0f2f8fc8ed 100644 --- a/core/variant/dictionary.cpp +++ b/core/variant/dictionary.cpp @@ -350,7 +350,7 @@ void Dictionary::operator=(const Dictionary &p_dictionary) { } const void *Dictionary::id() const { - return _p->variant_map.id(); + return _p; } Dictionary::Dictionary(const Dictionary &p_from) { diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index db198da54a..38610c4f29 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -1692,8 +1692,6 @@ String Variant::stringify(int recursion_count) const { pairs.push_back(sp); } - pairs.sort(); - for (int i = 0; i < pairs.size(); i++) { if (i > 0) { str += ", "; @@ -3256,7 +3254,7 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const return false; } -bool Variant::is_ref() const { +bool Variant::is_ref_counted() const { return type == OBJECT && _get_obj().id.is_ref_counted(); } diff --git a/core/variant/variant.h b/core/variant/variant.h index 0860e7fdc3..17988a46d7 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -287,7 +287,7 @@ public: static bool can_convert(Type p_type_from, Type p_type_to); static bool can_convert_strict(Type p_type_from, Type p_type_to); - bool is_ref() const; + bool is_ref_counted() const; _FORCE_INLINE_ bool is_num() const { return type == INT || type == FLOAT; } diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp index 571181f665..57875bf50f 100644 --- a/core/variant/variant_parser.cpp +++ b/core/variant/variant_parser.cpp @@ -1649,12 +1649,13 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str dict.get_key_list(&keys); keys.sort(); + if (keys.is_empty()) { // Avoid unnecessary line break. + p_store_string_func(p_store_string_ud, "{}"); + break; + } + p_store_string_func(p_store_string_ud, "{\n"); for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - /* - if (!_check_type(dict[E->get()])) - continue; - */ write(E->get(), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, recursion_count); p_store_string_func(p_store_string_ud, ": "); write(dict[E->get()], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, recursion_count); diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 3fd8eb5474..60950099d2 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -433,7 +433,7 @@ struct VariantUtilityFunctions { static inline Variant weakref(const Variant &obj, Callable::CallError &r_error) { if (obj.get_type() == Variant::OBJECT) { r_error.error = Callable::CallError::CALL_OK; - if (obj.is_ref()) { + if (obj.is_ref_counted()) { Ref<WeakRef> wref = memnew(WeakRef); REF r = obj; if (r.is_valid()) { diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index be7ac1164e..d8c9ca08e8 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -2493,7 +2493,10 @@ </constant> <constant name="PROPERTY_HINT_ARRAY_TYPE" value="39" enum="PropertyHint"> </constant> - <constant name="PROPERTY_HINT_MAX" value="41" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LOCALE_ID" value="41" enum="PropertyHint"> + Hints that a string property is a locale code. Editing it will show a locale dialog for picking language and country. + </constant> + <constant name="PROPERTY_HINT_MAX" value="42" enum="PropertyHint"> </constant> <constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags"> </constant> diff --git a/doc/classes/ArrayMesh.xml b/doc/classes/ArrayMesh.xml index c986947dfb..fa980d9f75 100644 --- a/doc/classes/ArrayMesh.xml +++ b/doc/classes/ArrayMesh.xml @@ -62,8 +62,7 @@ <argument index="0" name="primitive" type="int" enum="Mesh.PrimitiveType" /> <argument index="1" name="arrays" type="Array" /> <argument index="2" name="blend_shapes" type="Array" default="[]" /> - <argument index="3" name="lods" type="Dictionary" default="{ -}" /> + <argument index="3" name="lods" type="Dictionary" default="{}" /> <argument index="4" name="compress_flags" type="int" default="0" /> <description> Creates a new surface. diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml index 1b77a5b4d8..714af426b3 100644 --- a/doc/classes/BaseButton.xml +++ b/doc/classes/BaseButton.xml @@ -38,7 +38,7 @@ <return type="void" /> <argument index="0" name="pressed" type="bool" /> <description> - Changes the [member pressed] state of the button, without emitting [signal toggled]. Use when you just want to change the state of the button without sending the pressed event (e.g. when initializing scene). Only works if [member toggle_mode] is [code]true[/code]. + Changes the [member button_pressed] state of the button, without emitting [signal toggled]. Use when you just want to change the state of the button without sending the pressed event (e.g. when initializing scene). Only works if [member toggle_mode] is [code]true[/code]. [b]Note:[/b] This method doesn't unpress other buttons in [member button_group]. </description> </method> @@ -54,6 +54,10 @@ Binary mask to choose which mouse buttons this button will respond to. To allow both left-click and right-click, use [code]MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT[/code]. </member> + <member name="button_pressed" type="bool" setter="set_pressed" getter="is_pressed" default="false"> + If [code]true[/code], the button's state is pressed. Means the button is pressed down or toggled (if [member toggle_mode] is active). Only works if [member toggle_mode] is [code]true[/code]. + [b]Note:[/b] Setting [member button_pressed] will result in [signal toggled] to be emitted. If you want to change the pressed state without emitting that signal, use [method set_pressed_no_signal]. + </member> <member name="disabled" type="bool" setter="set_disabled" getter="is_disabled" default="false"> If [code]true[/code], the button is in disabled state and can't be clicked or toggled. </member> @@ -62,10 +66,6 @@ If [code]true[/code], the button stays pressed when moving the cursor outside the button while pressing it. [b]Note:[/b] This property only affects the button's visual appearance. Signals will be emitted at the same moment regardless of this property's value. </member> - <member name="pressed" type="bool" setter="set_pressed" getter="is_pressed" default="false"> - If [code]true[/code], the button's state is pressed. Means the button is pressed down or toggled (if [member toggle_mode] is active). Only works if [member toggle_mode] is [code]true[/code]. - [b]Note:[/b] Setting [member pressed] will result in [signal toggled] to be emitted. If you want to change the pressed state without emitting that signal, use [method set_pressed_no_signal]. - </member> <member name="shortcut" type="Shortcut" setter="set_shortcut" getter="get_shortcut"> [Shortcut] associated to the button. </member> diff --git a/doc/classes/Button.xml b/doc/classes/Button.xml index 65b66b2fd5..ef4eba62b2 100644 --- a/doc/classes/Button.xml +++ b/doc/classes/Button.xml @@ -94,16 +94,16 @@ </member> </members> <theme_items> - <theme_item name="font_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 1)"> + <theme_item name="font_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> Default text [Color] of the [Button]. </theme_item> - <theme_item name="font_disabled_color" data_type="color" type="Color" default="Color(0.9, 0.9, 0.9, 0.2)"> + <theme_item name="font_disabled_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 0.5)"> Text [Color] used when the [Button] is disabled. </theme_item> - <theme_item name="font_focus_color" data_type="color" type="Color" default="Color(0.94, 0.94, 0.94, 1)"> + <theme_item name="font_focus_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> Text [Color] used when the [Button] is focused. Only replaces the normal text color of the button. Disabled, hovered, and pressed states take precedence over this color. </theme_item> - <theme_item name="font_hover_color" data_type="color" type="Color" default="Color(0.94, 0.94, 0.94, 1)"> + <theme_item name="font_hover_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> Text [Color] used when the [Button] is being hovered. </theme_item> <theme_item name="font_hover_pressed_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> diff --git a/doc/classes/CharacterBody2D.xml b/doc/classes/CharacterBody2D.xml index 28a9107db6..1c4475dd70 100644 --- a/doc/classes/CharacterBody2D.xml +++ b/doc/classes/CharacterBody2D.xml @@ -165,9 +165,6 @@ If [code]true[/code], the body will not slide on slopes when calling [method move_and_slide] when the body is standing still. If [code]false[/code], the body will slide on floor's slopes when [member motion_velocity] applies a downward force. </member> - <member name="free_mode_min_slide_angle" type="float" setter="set_free_mode_min_slide_angle" getter="get_free_mode_min_slide_angle" default="0.261799"> - Minimum angle (in radians) where the body is allowed to slide when it encounters a slope. The default value equals 15 degrees. - </member> <member name="max_slides" type="int" setter="set_max_slides" getter="get_max_slides" default="4"> Maximum number of times the body can change direction before it stops when calling [method move_and_slide]. </member> @@ -192,12 +189,15 @@ <member name="up_direction" type="Vector2" setter="set_up_direction" getter="get_up_direction" default="Vector2(0, -1)"> Direction vector used to determine what is a wall and what is a floor (or a ceiling), rather than a wall, when calling [method move_and_slide]. Defaults to [code]Vector2.UP[/code]. If set to [code]Vector2(0, 0)[/code], everything is considered a wall. This is useful for topdown games. </member> + <member name="wall_min_slide_angle" type="float" setter="set_wall_min_slide_angle" getter="get_wall_min_slide_angle" default="0.261799"> + Minimum angle (in radians) where the body is allowed to slide when it encounters a slope. The default value equals 15 degrees. This property only affects movement when [member motion_mode] is [constant MOTION_MODE_FLOATING]. + </member> </members> <constants> <constant name="MOTION_MODE_GROUNDED" value="0" enum="MotionMode"> Apply when notions of walls, ceiling and floor are relevant. In this mode the body motion will react to slopes (acceleration/slowdown). This mode is suitable for sided games like platformers. </constant> - <constant name="MOTION_MODE_FREE" value="1" enum="MotionMode"> + <constant name="MOTION_MODE_FLOATING" value="1" enum="MotionMode"> Apply when there is no notion of floor or ceiling. All collisions will be reported as [code]on_wall[/code]. In this mode, when you slide, the speed will always be constant. This mode is suitable for top-down games. </constant> <constant name="PLATFORM_VEL_ON_LEAVE_ALWAYS" value="0" enum="MovingPlatformApplyVelocityOnLeave"> diff --git a/doc/classes/CharacterBody3D.xml b/doc/classes/CharacterBody3D.xml index 819190fd69..a5df0fd97e 100644 --- a/doc/classes/CharacterBody3D.xml +++ b/doc/classes/CharacterBody3D.xml @@ -175,14 +175,14 @@ Direction vector used to determine what is a wall and what is a floor (or a ceiling), rather than a wall, when calling [method move_and_slide]. Defaults to [code]Vector3.UP[/code]. If set to [code]Vector3(0, 0, 0)[/code], everything is considered a wall. This is useful for topdown games. </member> <member name="wall_min_slide_angle" type="float" setter="set_wall_min_slide_angle" getter="get_wall_min_slide_angle" default="0.261799"> - Minimum angle (in radians) where the body is allowed to slide when it encounters a slope. The default value equals 15 degrees. In [code]MOTION_MODE_GROUNDED[/code], it works only when [member floor_block_on_wall] is [code]true[/code]. + Minimum angle (in radians) where the body is allowed to slide when it encounters a slope. The default value equals 15 degrees. When [member motion_mode] is [constant MOTION_MODE_GROUNDED], it only affects movement if [member floor_block_on_wall] is [code]true[/code]. </member> </members> <constants> <constant name="MOTION_MODE_GROUNDED" value="0" enum="MotionMode"> Apply when notions of walls, ceiling and floor are relevant. In this mode the body motion will react to slopes (acceleration/slowdown). This mode is suitable for grounded games like platformers. </constant> - <constant name="MOTION_MODE_FREE" value="1" enum="MotionMode"> + <constant name="MOTION_MODE_FLOATING" value="1" enum="MotionMode"> Apply when there is no notion of floor or ceiling. All collisions will be reported as [code]on_wall[/code]. In this mode, when you slide, the speed will always be constant. This mode is suitable for games without ground like space games. </constant> <constant name="PLATFORM_VEL_ON_LEAVE_ALWAYS" value="0" enum="MovingPlatformApplyVelocityOnLeave"> diff --git a/doc/classes/CheckBox.xml b/doc/classes/CheckBox.xml index 6180f56858..3626420589 100644 --- a/doc/classes/CheckBox.xml +++ b/doc/classes/CheckBox.xml @@ -14,16 +14,16 @@ <member name="toggle_mode" type="bool" setter="set_toggle_mode" getter="is_toggle_mode" overrides="BaseButton" default="true" /> </members> <theme_items> - <theme_item name="font_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 1)"> + <theme_item name="font_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> The [CheckBox] text's font color. </theme_item> - <theme_item name="font_disabled_color" data_type="color" type="Color" default="Color(0.9, 0.9, 0.9, 0.2)"> + <theme_item name="font_disabled_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 0.5)"> The [CheckBox] text's font color when it's disabled. </theme_item> - <theme_item name="font_focus_color" data_type="color" type="Color" default="Color(0.94, 0.94, 0.94, 1)"> + <theme_item name="font_focus_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> The [CheckBox] text's font color when it's focused. Only replaces the normal text color of the checkbox. Disabled, hovered, and pressed states take precedence over this color. </theme_item> - <theme_item name="font_hover_color" data_type="color" type="Color" default="Color(0.94, 0.94, 0.94, 1)"> + <theme_item name="font_hover_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> The [CheckBox] text's font color when it's hovered. </theme_item> <theme_item name="font_hover_pressed_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> diff --git a/doc/classes/CheckButton.xml b/doc/classes/CheckButton.xml index 659fb5126f..74d438f24e 100644 --- a/doc/classes/CheckButton.xml +++ b/doc/classes/CheckButton.xml @@ -14,16 +14,16 @@ <member name="toggle_mode" type="bool" setter="set_toggle_mode" getter="is_toggle_mode" overrides="BaseButton" default="true" /> </members> <theme_items> - <theme_item name="font_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 1)"> + <theme_item name="font_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> The [CheckButton] text's font color. </theme_item> - <theme_item name="font_disabled_color" data_type="color" type="Color" default="Color(0.9, 0.9, 0.9, 0.2)"> + <theme_item name="font_disabled_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 0.5)"> The [CheckButton] text's font color when it's disabled. </theme_item> - <theme_item name="font_focus_color" data_type="color" type="Color" default="Color(0.94, 0.94, 0.94, 1)"> + <theme_item name="font_focus_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> The [CheckButton] text's font color when it's focused. Only replaces the normal text color of the button. Disabled, hovered, and pressed states take precedence over this color. </theme_item> - <theme_item name="font_hover_color" data_type="color" type="Color" default="Color(0.94, 0.94, 0.94, 1)"> + <theme_item name="font_hover_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> The [CheckButton] text's font color when it's hovered. </theme_item> <theme_item name="font_hover_pressed_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> diff --git a/doc/classes/CodeEdit.xml b/doc/classes/CodeEdit.xml index 697b0443f1..b3add6cfa2 100644 --- a/doc/classes/CodeEdit.xml +++ b/doc/classes/CodeEdit.xml @@ -345,7 +345,7 @@ <return type="void" /> <argument index="0" name="force" type="bool" default="false" /> <description> - Emits [signal request_code_completion], if [code]force[/code] is true will bypass all checks. Otherwise will check that the caret is in a word or in front of a prefix. Will ignore the request if all current options are of type file path, node path or signal. + Emits [signal code_completion_requested], if [code]force[/code] is true will bypass all checks. Otherwise will check that the caret is in a word or in front of a prefix. Will ignore the request if all current options are of type file path, node path or signal. </description> </method> <method name="set_code_completion_selected_index"> @@ -442,7 +442,7 @@ <member name="auto_brace_completion_highlight_matching" type="bool" setter="set_highlight_matching_braces_enabled" getter="is_highlight_matching_braces_enabled" default="false"> Highlight mismatching brace pairs. </member> - <member name="auto_brace_completion_pairs" type="Dictionary" setter="set_auto_brace_completion_pairs" getter="get_auto_brace_completion_pairs" default="{"\"": "\"","'": "'","(": ")","[": "]","{": "}"}"> + <member name="auto_brace_completion_pairs" type="Dictionary" setter="set_auto_brace_completion_pairs" getter="get_auto_brace_completion_pairs" default="{ "\"": "\"", "'": "'", "(": ")", "[": "]", "{": "}" }"> Sets the brace pairs to be autocompleted. </member> <member name="code_completion_enabled" type="bool" setter="set_code_completion_enabled" getter="is_code_completion_enabled" default="false"> @@ -506,7 +506,7 @@ Emitted when a breakpoint is added or removed from a line. If the line is moved via backspace a removed is emitted at the old line. </description> </signal> - <signal name="request_code_completion"> + <signal name="code_completion_requested"> <description> Emitted when the user requests code completion. </description> @@ -574,7 +574,7 @@ <theme_item name="caret_background_color" data_type="color" type="Color" default="Color(0, 0, 0, 1)"> [Color] of the text behind the caret when block caret is enabled. </theme_item> - <theme_item name="caret_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 1)"> + <theme_item name="caret_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> [Color] of the caret. </theme_item> <theme_item name="code_folding_color" data_type="color" type="Color" default="Color(0.8, 0.8, 0.8, 0.8)"> @@ -601,13 +601,13 @@ <theme_item name="executing_line_color" data_type="color" type="Color" default="Color(0.98, 0.89, 0.27, 1)"> [Color] of the executing icon for executing lines. </theme_item> - <theme_item name="font_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 1)"> + <theme_item name="font_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> Sets the font [Color]. </theme_item> <theme_item name="font_outline_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> The tint of text outline of the [CodeEdit]. </theme_item> - <theme_item name="font_readonly_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 0.5)"> + <theme_item name="font_readonly_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 0.5)"> Sets the font [Color] when [member TextEdit.editable] is disabled. </theme_item> <theme_item name="font_selected_color" data_type="color" type="Color" default="Color(0, 0, 0, 1)"> @@ -625,7 +625,7 @@ <theme_item name="search_result_color" data_type="color" type="Color" default="Color(0.3, 0.3, 0.3, 1)"> [Color] behind the text that matches the search query. </theme_item> - <theme_item name="selection_color" data_type="color" type="Color" default="Color(0.49, 0.49, 0.49, 1)"> + <theme_item name="selection_color" data_type="color" type="Color" default="Color(0.5, 0.5, 0.5, 1)"> Sets the highlight [Color] of text selections. </theme_item> <theme_item name="word_highlighted_color" data_type="color" type="Color" default="Color(0.8, 0.9, 0.9, 0.15)"> diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index f34b8c342f..6e06bf454c 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -20,6 +20,12 @@ [b]Note:[/b] This method is only implemented on Linux. </description> </method> + <method name="clipboard_has" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if there is content on the user's clipboard. + </description> + </method> <method name="clipboard_set"> <return type="void" /> <argument index="0" name="clipboard" type="String" /> @@ -321,11 +327,6 @@ [b]Note:[/b] This method is implemented on Linux, macOS and Windows. </description> </method> - <method name="mouse_get_absolute_position" qualifiers="const"> - <return type="Vector2i" /> - <description> - </description> - </method> <method name="mouse_get_button_state" qualifiers="const"> <return type="int" enum="MouseButton" /> <description> diff --git a/doc/classes/EditorInspector.xml b/doc/classes/EditorInspector.xml index 39589138fa..27dab3d422 100644 --- a/doc/classes/EditorInspector.xml +++ b/doc/classes/EditorInspector.xml @@ -13,6 +13,11 @@ <member name="horizontal_scroll_mode" type="int" setter="set_horizontal_scroll_mode" getter="get_horizontal_scroll_mode" overrides="ScrollContainer" enum="ScrollContainer.ScrollMode" default="0" /> </members> <signals> + <signal name="edited_object_changed"> + <description> + Emitted when the object being edited by the inspector has changed. + </description> + </signal> <signal name="object_id_selected"> <argument index="0" name="id" type="int" /> <description> diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml index 2090672acc..b31162f10f 100644 --- a/doc/classes/Environment.xml +++ b/doc/classes/Environment.xml @@ -168,10 +168,11 @@ </member> <member name="sdfgi_cascade0_distance" type="float" setter="set_sdfgi_cascade0_distance" getter="get_sdfgi_cascade0_distance" default="12.8"> </member> - <member name="sdfgi_cascades" type="int" setter="set_sdfgi_cascades" getter="get_sdfgi_cascades" enum="Environment.SDFGICascades" default="1"> + <member name="sdfgi_cascades" type="int" setter="set_sdfgi_cascades" getter="get_sdfgi_cascades" default="6"> + The number of cascades to use for SDFGI (between 1 and 8). A higher number of cascades allows displaying SDFGI further away while preserving detail up close, at the cost of performance. When using SDFGI on small-scale levels, [member sdfgi_cascades] can often be decreased between [code]1[/code] and [code]4[/code] to improve performance. </member> <member name="sdfgi_enabled" type="bool" setter="set_sdfgi_enabled" getter="is_sdfgi_enabled" default="false"> - If [code]true[/code], enables signed distance field global illumination for meshes that have their [member GeometryInstance3D.gi_mode] set to [constant GeometryInstance3D.GI_MODE_BAKED]. SDFGI is a real-time global illumination technique that works well with procedurally generated and user-built levels, including in situations where geometry is created during gameplay. The signed distance field is automatically generated around the camera as it moves. Dynamic lights are supported, but dynamic occluders and emissive surfaces are not. + If [code]true[/code], enables signed distance field global illumination for meshes that have their [member GeometryInstance3D.gi_mode] set to [constant GeometryInstance3D.GI_MODE_STATIC]. SDFGI is a real-time global illumination technique that works well with procedurally generated and user-built levels, including in situations where geometry is created during gameplay. The signed distance field is automatically generated around the camera as it moves. Dynamic lights are supported, but dynamic occluders and emissive surfaces are not. [b]Performance:[/b] SDFGI is relatively demanding on the GPU and is not suited to low-end hardware such as integrated graphics (consider [LightmapGI] instead). To improve SDFGI performance, enable [member ProjectSettings.rendering/global_illumination/gi/use_half_resolution] in the Project Settings. [b]Note:[/b] Meshes should have sufficiently thick walls to avoid light leaks (avoid one-sided walls). For interior levels, enclose your level geometry in a sufficiently large box and bridge the loops to close the mesh. </member> @@ -371,12 +372,6 @@ <constant name="GLOW_BLEND_MODE_MIX" value="4" enum="GlowBlendMode"> Mixes the glow with the underlying color to avoid increasing brightness as much while still maintaining a glow effect. </constant> - <constant name="SDFGI_CASCADES_4" value="0" enum="SDFGICascades"> - </constant> - <constant name="SDFGI_CASCADES_6" value="1" enum="SDFGICascades"> - </constant> - <constant name="SDFGI_CASCADES_8" value="2" enum="SDFGICascades"> - </constant> <constant name="SDFGI_Y_SCALE_DISABLED" value="0" enum="SDFGIYScale"> </constant> <constant name="SDFGI_Y_SCALE_75_PERCENT" value="1" enum="SDFGIYScale"> diff --git a/doc/classes/FlowContainer.xml b/doc/classes/FlowContainer.xml new file mode 100644 index 0000000000..482d879b09 --- /dev/null +++ b/doc/classes/FlowContainer.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="FlowContainer" inherits="Container" version="4.0"> + <brief_description> + Base class for flow containers. + </brief_description> + <description> + Arranges child [Control] nodes vertically or horizontally in a left-to-right or top-to-bottom flow. + A line is filled with [Control] nodes until no more fit on the same line, similar to text in an autowrapped label. + </description> + <tutorials> + </tutorials> + <methods> + <method name="get_line_count" qualifiers="const"> + <return type="int" /> + <description> + Returns the current line count. + </description> + </method> + </methods> +</class> diff --git a/doc/classes/GeometryInstance3D.xml b/doc/classes/GeometryInstance3D.xml index cecd1e518f..c03a2b8b7c 100644 --- a/doc/classes/GeometryInstance3D.xml +++ b/doc/classes/GeometryInstance3D.xml @@ -41,7 +41,8 @@ The texel density to use for lightmapping in [LightmapGI]. Greater scale values provide higher resolution in the lightmap, which can result in sharper shadows for lights that have both direct and indirect light baked. However, greater scale values will also increase the space taken by the mesh in the lightmap texture, which increases the memory, storage, and bake time requirements. When using a single mesh at different scales, consider adjusting this value to keep the lightmap texel density consistent across meshes. </member> <member name="gi_mode" type="int" setter="set_gi_mode" getter="get_gi_mode" enum="GeometryInstance3D.GIMode" default="0"> - The global illumination mode to use for the whole geometry. Use a mode that matches the purpose + The global illumination mode to use for the whole geometry. To avoid inconsistent results, use a mode that matches the purpose of the mesh during gameplay (static/dynamic). + [b]Note:[/b] Lights' bake mode will also affect the global illumination rendering. See [member Light3D.light_bake_mode]. </member> <member name="ignore_occlusion_culling" type="bool" setter="set_ignore_occlusion_culling" getter="is_ignoring_occlusion_culling" default="false"> </member> @@ -93,13 +94,13 @@ In other words, the actual mesh will not be visible, only the shadows casted from the mesh will be. </constant> <constant name="GI_MODE_DISABLED" value="0" enum="GIMode"> - Disabled global illumination mode. Use for dynamic objects that do not contribute to global illumination (such as characters). When using [VoxelGI] and SDFGI, the geometry will [i]receive[/i] indirect lighting and reflections but will not be considered in GI baking. When using [LightmapGI], the object will receive indirect lighting using lightmap probes instead of using the lightmap texture. + Disabled global illumination mode. Use for dynamic objects that do not contribute to global illumination (such as characters). When using [VoxelGI] and SDFGI, the geometry will [i]receive[/i] indirect lighting and reflections but the geometry will not be considered in GI baking. When using [LightmapGI], the object will receive indirect lighting using lightmap probes instead of using the baked lightmap texture. </constant> - <constant name="GI_MODE_BAKED" value="1" enum="GIMode"> + <constant name="GI_MODE_STATIC" value="1" enum="GIMode"> Baked global illumination mode. Use for static objects that contribute to global illumination (such as level geometry). This GI mode is effective when using [VoxelGI], SDFGI and [LightmapGI]. </constant> <constant name="GI_MODE_DYNAMIC" value="2" enum="GIMode"> - Dynamic global illumination mode. Use for dynamic objects that contribute to global illumination. This GI mode is only effective when using [VoxelGI], but it has a higher performance impact than [constant GI_MODE_BAKED]. + Dynamic global illumination mode. Use for dynamic objects that contribute to global illumination. This GI mode is only effective when using [VoxelGI], but it has a higher performance impact than [constant GI_MODE_STATIC]. When using other GI methods, this will act the same as [constant GI_MODE_DISABLED]. </constant> <constant name="LIGHTMAP_SCALE_1X" value="0" enum="LightmapScale"> The standard texel density for lightmapping with [LightmapGI]. diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml index d5780dce2d..c8606cf67f 100644 --- a/doc/classes/GraphNode.xml +++ b/doc/classes/GraphNode.xml @@ -292,25 +292,25 @@ </constant> </constants> <theme_items> - <theme_item name="close_color" data_type="color" type="Color" default="Color(0, 0, 0, 1)"> + <theme_item name="close_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> The color modulation applied to the close button icon. </theme_item> - <theme_item name="resizer_color" data_type="color" type="Color" default="Color(0, 0, 0, 1)"> + <theme_item name="resizer_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> The color modulation applied to the resizer icon. </theme_item> - <theme_item name="title_color" data_type="color" type="Color" default="Color(0, 0, 0, 1)"> + <theme_item name="title_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> Color of the title text. </theme_item> - <theme_item name="close_offset" data_type="constant" type="int" default="18"> + <theme_item name="close_offset" data_type="constant" type="int" default="22"> The vertical offset of the close button. </theme_item> - <theme_item name="port_offset" data_type="constant" type="int" default="3"> + <theme_item name="port_offset" data_type="constant" type="int" default="0"> Horizontal offset for the ports. </theme_item> - <theme_item name="separation" data_type="constant" type="int" default="1"> + <theme_item name="separation" data_type="constant" type="int" default="2"> The vertical distance between ports. </theme_item> - <theme_item name="title_offset" data_type="constant" type="int" default="20"> + <theme_item name="title_offset" data_type="constant" type="int" default="26"> Vertical offset of the title text. </theme_item> <theme_item name="title_font" data_type="font" type="Font"> @@ -334,10 +334,6 @@ <theme_item name="commentfocus" data_type="style" type="StyleBox"> The [StyleBox] used when [member comment] is enabled and the [GraphNode] is focused. </theme_item> - <theme_item name="defaultfocus" data_type="style" type="StyleBox"> - </theme_item> - <theme_item name="defaultframe" data_type="style" type="StyleBox"> - </theme_item> <theme_item name="frame" data_type="style" type="StyleBox"> The default background for [GraphNode]. </theme_item> diff --git a/doc/classes/HFlowContainer.xml b/doc/classes/HFlowContainer.xml new file mode 100644 index 0000000000..8ee2da69b7 --- /dev/null +++ b/doc/classes/HFlowContainer.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="HFlowContainer" inherits="FlowContainer" version="4.0"> + <brief_description> + Horizontal flow container. + </brief_description> + <description> + Horizontal version of [FlowContainer]. + </description> + <tutorials> + </tutorials> + <theme_items> + <theme_item name="hseparation" data_type="constant" type="int" default="4"> + The horizontal separation of children nodes. + </theme_item> + <theme_item name="vseparation" data_type="constant" type="int" default="4"> + The vertical separation of children nodes. + </theme_item> + </theme_items> +</class> diff --git a/doc/classes/HSplitContainer.xml b/doc/classes/HSplitContainer.xml index f2c505b1bc..6ba079bc66 100644 --- a/doc/classes/HSplitContainer.xml +++ b/doc/classes/HSplitContainer.xml @@ -18,7 +18,5 @@ <theme_item name="grabber" data_type="icon" type="Texture2D"> The icon used for the grabber drawn in the middle area. </theme_item> - <theme_item name="bg" data_type="style" type="StyleBox"> - </theme_item> </theme_items> </class> diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index e7bb1b9825..60d4b664d2 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -452,7 +452,7 @@ </method> </methods> <members> - <member name="data" type="Dictionary" setter="_set_data" getter="_get_data" default="{"data": PackedByteArray(),"format": "Lum8","height": 0,"mipmaps": false,"width": 0}"> + <member name="data" type="Dictionary" setter="_set_data" getter="_get_data" default="{ "data": PackedByteArray(), "format": "Lum8", "height": 0, "mipmaps": false, "width": 0 }"> Holds all the image's color data in a given format. See [enum Format] constants. </member> </members> diff --git a/doc/classes/ImporterMesh.xml b/doc/classes/ImporterMesh.xml index ab344f908c..4c323156c9 100644 --- a/doc/classes/ImporterMesh.xml +++ b/doc/classes/ImporterMesh.xml @@ -23,8 +23,7 @@ <argument index="0" name="primitive" type="int" enum="Mesh.PrimitiveType" /> <argument index="1" name="arrays" type="Array" /> <argument index="2" name="blend_shapes" type="Array" default="[]" /> - <argument index="3" name="lods" type="Dictionary" default="{ -}" /> + <argument index="3" name="lods" type="Dictionary" default="{}" /> <argument index="4" name="material" type="Material" default="null" /> <argument index="5" name="name" type="String" default="""" /> <argument index="6" name="flags" type="int" default="0" /> @@ -178,7 +177,7 @@ </method> </methods> <members> - <member name="_data" type="Dictionary" setter="_set_data" getter="_get_data" default="{"surfaces": []}"> + <member name="_data" type="Dictionary" setter="_set_data" getter="_get_data" default="{ "surfaces": [] }"> </member> </members> </class> diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index 45b15331d2..423e58f5c6 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -209,6 +209,12 @@ [b]Note:[/b] Due to keyboard ghosting, [method is_action_pressed] may return [code]false[/code] even if one of the action's keys is pressed. See [url=$DOCS_URL/tutorials/inputs/input_examples.html#keyboard-events]Input examples[/url] in the documentation for more information. </description> </method> + <method name="is_anything_pressed" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if any action, key, joypad button, or mouse button is being pressed. This will also return [code]true[/code] if any action is simulated via code by calling [method action_press]. + </description> + </method> <method name="is_joy_button_pressed" qualifiers="const"> <return type="bool" /> <argument index="0" name="device" type="int" /> diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml index 593d0c9523..c87c5d2868 100644 --- a/doc/classes/ItemList.xml +++ b/doc/classes/ItemList.xml @@ -463,7 +463,7 @@ </constant> </constants> <theme_items> - <theme_item name="font_color" data_type="color" type="Color" default="Color(0.63, 0.63, 0.63, 1)"> + <theme_item name="font_color" data_type="color" type="Color" default="Color(0.65, 0.65, 0.65, 1)"> Default text [Color] of the item. </theme_item> <theme_item name="font_outline_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> diff --git a/doc/classes/JSON.xml b/doc/classes/JSON.xml index 63e6307b39..fed9df8bd8 100644 --- a/doc/classes/JSON.xml +++ b/doc/classes/JSON.xml @@ -66,7 +66,7 @@ Converts a [Variant] var to JSON text and returns the result. Useful for serializing data to store or send over the network. [b]Note:[/b] The JSON specification does not define integer or float types, but only a [i]number[/i] type. Therefore, converting a Variant to JSON text will convert all numerical values to [float] types. [b]Note:[/b] If [code]full_precision[/code] is true, when stringifying floats, the unreliable digits are stringified in addition to the reliable digits to guarantee exact decoding. - Use [code]indent[/code] parameter to pretty stringify the output. + The [code]indent[/code] parameter controls if and how something is indented, the string used for this parameter will be used where there should be an indent in the output, even spaces like [code]" "[/code] will work. [code]\t[/code] and [code]\n[/code] can also be used for a tab indent, or to make a newline for each indent respectively. [b]Example output:[/b] [codeblock] ## JSON.stringify(my_dictionary) @@ -74,18 +74,34 @@ ## JSON.stringify(my_dictionary, "\t") { - "name": "my_dictionary", - "version": "1.0.0", - "entities": [ - { - "name": "entity_0", - "value": "value_0" - }, - { - "name": "entity_1", - "value": "value_1" - } - ] + "name": "my_dictionary", + "version": "1.0.0", + "entities": [ + { + "name": "entity_0", + "value": "value_0" + }, + { + "name": "entity_1", + "value": "value_1" + } + ] + } + + ## JSON.stringify(my_dictionary, "...") + { + ..."name": "my_dictionary", + ..."version": "1.0.0", + ..."entities": [ + ......{ + ........."name": "entity_0", + ........."value": "value_0" + ......}, + ......{ + ........."name": "entity_1", + ........."value": "value_1" + ......} + ...] } [/codeblock] </description> diff --git a/doc/classes/Light3D.xml b/doc/classes/Light3D.xml index 009ad1f609..b8d46755c7 100644 --- a/doc/classes/Light3D.xml +++ b/doc/classes/Light3D.xml @@ -34,8 +34,9 @@ <member name="light_angular_distance" type="float" setter="set_param" getter="get_param" default="0.0"> The light's angular size in degrees. Increasing this will make shadows softer at greater distances. Only available for [DirectionalLight3D]s. For reference, the Sun from the Earth is approximately [code]0.5[/code]. </member> - <member name="light_bake_mode" type="int" setter="set_bake_mode" getter="get_bake_mode" enum="Light3D.BakeMode" default="1"> - The light's bake mode. See [enum BakeMode]. + <member name="light_bake_mode" type="int" setter="set_bake_mode" getter="get_bake_mode" enum="Light3D.BakeMode" default="2"> + The light's bake mode. This will affect the global illumination techniques that have an effect on the light's rendering. See [enum BakeMode]. + [b]Note:[/b] Meshes' global illumination mode will also affect the global illumination rendering. See [member GeometryInstance3D.gi_mode]. </member> <member name="light_color" type="Color" setter="set_color" getter="get_color" default="Color(1, 1, 1, 1)"> The light's color. An [i]overbright[/i] color can be used to achieve a result equivalent to increasing the light's [member light_energy]. @@ -146,12 +147,14 @@ Represents the size of the [enum Param] enum. </constant> <constant name="BAKE_DISABLED" value="0" enum="BakeMode"> - Light is ignored when baking. - [b]Note:[/b] Hiding a light does [i]not[/i] affect baking. + Light is ignored when baking. This is the fastest mode, but the light will be taken into account when baking global illumination. This mode should generally be used for dynamic lights that change quickly, as the effect of global illumination is less noticeable on those lights. + [b]Note:[/b] Hiding a light does [i]not[/i] affect baking [LightmapGI]. Hiding a light will still affect baking [VoxelGI] and SDFGI (see [member Environment.sdfgi_enabled). </constant> - <constant name="BAKE_DYNAMIC" value="1" enum="BakeMode"> + <constant name="BAKE_STATIC" value="1" enum="BakeMode"> + Light is taken into account in static baking ([VoxelGI], [LightmapGI], SDFGI ([member Environment.sdfgi_enabled])). The light can be moved around or modified, but its global illumination will not update in real-time. This is suitable for subtle changes (such as flickering torches), but generally not large changes such as toggling a light on and off. </constant> - <constant name="BAKE_STATIC" value="2" enum="BakeMode"> + <constant name="BAKE_DYNAMIC" value="2" enum="BakeMode"> + Light is taken into account in dynamic baking ([VoxelGI] and SDFGI ([member Environment.sdfgi_enabled]) only). The light can be moved around or modified with global illumination updating in real-time. The light's global illumination appearance will be slightly different compared to [constant BAKE_STATIC]. This has a greater performance cost compared to [constant BAKE_STATIC]. </constant> </constants> </class> diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml index ff01ad72fd..224579e8c5 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -382,28 +382,28 @@ </constant> </constants> <theme_items> - <theme_item name="caret_color" data_type="color" type="Color" default="Color(0.94, 0.94, 0.94, 1)"> + <theme_item name="caret_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> Color of the [LineEdit]'s caret (text cursor). This can be set to a fully transparent color to hide the caret entirely. </theme_item> - <theme_item name="clear_button_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 1)"> + <theme_item name="clear_button_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> Color used as default tint for the clear button. </theme_item> <theme_item name="clear_button_color_pressed" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> Color used for the clear button when it's pressed. </theme_item> - <theme_item name="font_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 1)"> + <theme_item name="font_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> Default font color. </theme_item> <theme_item name="font_outline_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> The tint of text outline of the [LineEdit]. </theme_item> - <theme_item name="font_selected_color" data_type="color" type="Color" default="Color(0, 0, 0, 1)"> + <theme_item name="font_selected_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> Font color for selected text (inside the selection rectangle). </theme_item> - <theme_item name="font_uneditable_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 0.5)"> + <theme_item name="font_uneditable_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 0.5)"> Font color when editing is disabled. </theme_item> - <theme_item name="selection_color" data_type="color" type="Color" default="Color(0.49, 0.49, 0.49, 1)"> + <theme_item name="selection_color" data_type="color" type="Color" default="Color(0.5, 0.5, 0.5, 1)"> Color of the selection rectangle. </theme_item> <theme_item name="caret_width" data_type="constant" type="int" default="1"> diff --git a/doc/classes/LinkButton.xml b/doc/classes/LinkButton.xml index a20db4d7e9..4377fc1036 100644 --- a/doc/classes/LinkButton.xml +++ b/doc/classes/LinkButton.xml @@ -66,13 +66,13 @@ </constant> </constants> <theme_items> - <theme_item name="font_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 1)"> + <theme_item name="font_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> Default text [Color] of the [LinkButton]. </theme_item> - <theme_item name="font_focus_color" data_type="color" type="Color" default="Color(0.94, 0.94, 0.94, 1)"> + <theme_item name="font_focus_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> Text [Color] used when the [LinkButton] is focused. Only replaces the normal text color of the button. Disabled, hovered, and pressed states take precedence over this color. </theme_item> - <theme_item name="font_hover_color" data_type="color" type="Color" default="Color(0.94, 0.94, 0.94, 1)"> + <theme_item name="font_hover_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> Text [Color] used when the [LinkButton] is being hovered. </theme_item> <theme_item name="font_outline_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> diff --git a/doc/classes/MenuButton.xml b/doc/classes/MenuButton.xml index 632b22c1de..79d1c05be4 100644 --- a/doc/classes/MenuButton.xml +++ b/doc/classes/MenuButton.xml @@ -46,16 +46,16 @@ </signal> </signals> <theme_items> - <theme_item name="font_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 1)"> + <theme_item name="font_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> Default text [Color] of the [MenuButton]. </theme_item> <theme_item name="font_disabled_color" data_type="color" type="Color" default="Color(1, 1, 1, 0.3)"> Text [Color] used when the [MenuButton] is disabled. </theme_item> - <theme_item name="font_focus_color" data_type="color" type="Color" default="Color(0.94, 0.94, 0.94, 1)"> + <theme_item name="font_focus_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> Text [Color] used when the [MenuButton] is focused. Only replaces the normal text color of the button. Disabled, hovered, and pressed states take precedence over this color. </theme_item> - <theme_item name="font_hover_color" data_type="color" type="Color" default="Color(0.94, 0.94, 0.94, 1)"> + <theme_item name="font_hover_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> Text [Color] used when the [MenuButton] is being hovered. </theme_item> <theme_item name="font_outline_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> diff --git a/doc/classes/OptionButton.xml b/doc/classes/OptionButton.xml index 87561917f3..7bb67be4c4 100644 --- a/doc/classes/OptionButton.xml +++ b/doc/classes/OptionButton.xml @@ -182,16 +182,16 @@ </signal> </signals> <theme_items> - <theme_item name="font_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 1)"> + <theme_item name="font_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> Default text [Color] of the [OptionButton]. </theme_item> - <theme_item name="font_disabled_color" data_type="color" type="Color" default="Color(0.9, 0.9, 0.9, 0.2)"> + <theme_item name="font_disabled_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 0.5)"> Text [Color] used when the [OptionButton] is disabled. </theme_item> - <theme_item name="font_focus_color" data_type="color" type="Color" default="Color(0.94, 0.94, 0.94, 1)"> + <theme_item name="font_focus_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> Text [Color] used when the [OptionButton] is focused. Only replaces the normal text color of the button. Disabled, hovered, and pressed states take precedence over this color. </theme_item> - <theme_item name="font_hover_color" data_type="color" type="Color" default="Color(0.94, 0.94, 0.94, 1)"> + <theme_item name="font_hover_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> Text [Color] used when the [OptionButton] is being hovered. </theme_item> <theme_item name="font_outline_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> @@ -200,7 +200,7 @@ <theme_item name="font_pressed_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> Text [Color] used when the [OptionButton] is being pressed. </theme_item> - <theme_item name="arrow_margin" data_type="constant" type="int" default="2"> + <theme_item name="arrow_margin" data_type="constant" type="int" default="4"> The horizontal space between the arrow icon and the right edge of the button. </theme_item> <theme_item name="hseparation" data_type="constant" type="int" default="2"> diff --git a/doc/classes/PackedScene.xml b/doc/classes/PackedScene.xml index d3a770b35b..4bba6563bb 100644 --- a/doc/classes/PackedScene.xml +++ b/doc/classes/PackedScene.xml @@ -104,7 +104,7 @@ </method> </methods> <members> - <member name="_bundled" type="Dictionary" setter="_set_bundled_scene" getter="_get_bundled_scene" default="{"conn_count": 0,"conns": PackedInt32Array(),"editable_instances": [],"names": PackedStringArray(),"node_count": 0,"node_paths": [],"nodes": PackedInt32Array(),"variants": [],"version": 2}"> + <member name="_bundled" type="Dictionary" setter="_set_bundled_scene" getter="_get_bundled_scene" default="{ "conn_count": 0, "conns": PackedInt32Array(), "editable_instances": [], "names": PackedStringArray(), "node_count": 0, "node_paths": [], "nodes": PackedInt32Array(), "variants": [], "version": 2 }"> A dictionary representation of the scene contents. Available keys include "rnames" and "variants" for resources, "node_count", "nodes", "node_paths" for nodes, "editable_instances" for base scene children overrides, "conn_count" and "conns" for signal connections, and "version" for the format style of the PackedScene. </member> diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml index b45f62394d..108c674ef7 100644 --- a/doc/classes/PopupMenu.xml +++ b/doc/classes/PopupMenu.xml @@ -538,19 +538,19 @@ <theme_item name="font_accelerator_color" data_type="color" type="Color" default="Color(0.7, 0.7, 0.7, 0.8)"> The text [Color] used for shortcuts and accelerators that show next to the menu item name when defined. See [method get_item_accelerator] for more info on accelerators. </theme_item> - <theme_item name="font_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 1)"> + <theme_item name="font_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> The default text [Color] for menu items' names. </theme_item> <theme_item name="font_disabled_color" data_type="color" type="Color" default="Color(0.4, 0.4, 0.4, 0.8)"> [Color] used for disabled menu items' text. </theme_item> - <theme_item name="font_hover_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 1)"> + <theme_item name="font_hover_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> [Color] used for the hovered text. </theme_item> <theme_item name="font_outline_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> The tint of text outline of the menu item. </theme_item> - <theme_item name="font_separator_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 1)"> + <theme_item name="font_separator_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> [Color] used for labeled separators' text. See [method add_separator]. </theme_item> <theme_item name="hseparation" data_type="constant" type="int" default="4"> diff --git a/doc/classes/ProgressBar.xml b/doc/classes/ProgressBar.xml index 24cc490ce7..923ce0c53e 100644 --- a/doc/classes/ProgressBar.xml +++ b/doc/classes/ProgressBar.xml @@ -16,7 +16,7 @@ <member name="step" type="float" setter="set_step" getter="get_step" overrides="Range" default="0.01" /> </members> <theme_items> - <theme_item name="font_color" data_type="color" type="Color" default="Color(0.94, 0.94, 0.94, 1)"> + <theme_item name="font_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> The color of the text. </theme_item> <theme_item name="font_outline_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 357186b917..a92afb7ea7 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -562,8 +562,7 @@ <member name="gui/theme/custom_font" type="String" setter="" getter="" default=""""> Path to a custom [Font] resource to use as default for all GUI elements of the project. </member> - <member name="gui/theme/use_hidpi" type="bool" setter="" getter="" default="false"> - If [code]true[/code], makes sure the theme used works with HiDPI. + <member name="gui/theme/default_theme_scale" type="float" setter="" getter="" default="1.0"> </member> <member name="gui/timers/incremental_search_max_interval_msec" type="int" setter="" getter="" default="2000"> Timer setting for incremental search in [Tree], [ItemList], etc. controls (in milliseconds). diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml index 909a8337cc..d6510993d8 100644 --- a/doc/classes/RenderingDevice.xml +++ b/doc/classes/RenderingDevice.xml @@ -305,7 +305,7 @@ <description> </description> </method> - <method name="free"> + <method name="free_rid"> <return type="void" /> <argument index="0" name="rid" type="RID" /> <description> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 5127455b4d..ff370bd953 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -1001,7 +1001,7 @@ <return type="void" /> <argument index="0" name="env" type="RID" /> <argument index="1" name="enable" type="bool" /> - <argument index="2" name="cascades" type="int" enum="RenderingServer.EnvironmentSDFGICascades" /> + <argument index="2" name="cascades" type="int" /> <argument index="3" name="min_cell_size" type="float" /> <argument index="4" name="y_scale" type="int" enum="RenderingServer.EnvironmentSDFGIYScale" /> <argument index="5" name="use_occlusion" type="bool" /> @@ -1838,8 +1838,7 @@ <argument index="1" name="primitive" type="int" enum="RenderingServer.PrimitiveType" /> <argument index="2" name="arrays" type="Array" /> <argument index="3" name="blend_shapes" type="Array" default="[]" /> - <argument index="4" name="lods" type="Dictionary" default="{ -}" /> + <argument index="4" name="lods" type="Dictionary" default="{}" /> <argument index="5" name="compress_format" type="int" default="0" /> <description> </description> @@ -3758,9 +3757,9 @@ </constant> <constant name="LIGHT_BAKE_DISABLED" value="0" enum="LightBakeMode"> </constant> - <constant name="LIGHT_BAKE_DYNAMIC" value="1" enum="LightBakeMode"> + <constant name="LIGHT_BAKE_STATIC" value="1" enum="LightBakeMode"> </constant> - <constant name="LIGHT_BAKE_STATIC" value="2" enum="LightBakeMode"> + <constant name="LIGHT_BAKE_DYNAMIC" value="2" enum="LightBakeMode"> </constant> <constant name="LIGHT_OMNI_SHADOW_DUAL_PARABOLOID" value="0" enum="LightOmniShadowMode"> Use a dual paraboloid shadow map for omni lights. @@ -4180,12 +4179,6 @@ <constant name="ENV_SSIL_QUALITY_ULTRA" value="4" enum="EnvironmentSSILQuality"> Highest quality screen-space indirect lighting. Uses the adaptive target setting which can be dynamically adjusted to smoothly balance performance and visual quality. </constant> - <constant name="ENV_SDFGI_CASCADES_4" value="0" enum="EnvironmentSDFGICascades"> - </constant> - <constant name="ENV_SDFGI_CASCADES_6" value="1" enum="EnvironmentSDFGICascades"> - </constant> - <constant name="ENV_SDFGI_CASCADES_8" value="2" enum="EnvironmentSDFGICascades"> - </constant> <constant name="ENV_SDFGI_Y_SCALE_DISABLED" value="0" enum="EnvironmentSDFGIYScale"> </constant> <constant name="ENV_SDFGI_Y_SCALE_75_PERCENT" value="1" enum="EnvironmentSDFGIYScale"> diff --git a/doc/classes/SoftDynamicBody3D.xml b/doc/classes/SoftDynamicBody3D.xml index fceebddf35..801b25f1b0 100644 --- a/doc/classes/SoftDynamicBody3D.xml +++ b/doc/classes/SoftDynamicBody3D.xml @@ -5,6 +5,7 @@ </brief_description> <description> A deformable physics body. Used to create elastic or deformable objects such as cloth, rubber, or other flexible materials. + [b]Note:[/b] There are many known bugs in [SoftDynamicBody3D]. Therefore, it's not recommended to use them for things that can affect gameplay (such as a player character made entirely out of soft bodies). </description> <tutorials> <link title="SoftBody">$DOCS_URL/tutorials/physics/soft_body.html</link> diff --git a/doc/classes/TabBar.xml b/doc/classes/TabBar.xml index 71df40a693..59a4743d80 100644 --- a/doc/classes/TabBar.xml +++ b/doc/classes/TabBar.xml @@ -282,16 +282,16 @@ </constant> </constants> <theme_items> - <theme_item name="font_disabled_color" data_type="color" type="Color" default="Color(0.9, 0.9, 0.9, 0.2)"> + <theme_item name="font_disabled_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 0.5)"> Font color of disabled tabs. </theme_item> <theme_item name="font_outline_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> The tint of text outline of the tab name. </theme_item> - <theme_item name="font_selected_color" data_type="color" type="Color" default="Color(0.94, 0.94, 0.94, 1)"> + <theme_item name="font_selected_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> Font color of the currently selected tab. </theme_item> - <theme_item name="font_unselected_color" data_type="color" type="Color" default="Color(0.69, 0.69, 0.69, 1)"> + <theme_item name="font_unselected_color" data_type="color" type="Color" default="Color(0.7, 0.7, 0.7, 1)"> Font color of the other, unselected tabs. </theme_item> <theme_item name="hseparation" data_type="constant" type="int" default="4"> diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml index d6e1e13505..3b814b6177 100644 --- a/doc/classes/TabContainer.xml +++ b/doc/classes/TabContainer.xml @@ -178,16 +178,16 @@ </constant> </constants> <theme_items> - <theme_item name="font_disabled_color" data_type="color" type="Color" default="Color(0.9, 0.9, 0.9, 0.2)"> + <theme_item name="font_disabled_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 0.5)"> Font color of disabled tabs. </theme_item> <theme_item name="font_outline_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> The tint of text outline of the tab name. </theme_item> - <theme_item name="font_selected_color" data_type="color" type="Color" default="Color(0.94, 0.94, 0.94, 1)"> + <theme_item name="font_selected_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> Font color of the currently selected tab. </theme_item> - <theme_item name="font_unselected_color" data_type="color" type="Color" default="Color(0.69, 0.69, 0.69, 1)"> + <theme_item name="font_unselected_color" data_type="color" type="Color" default="Color(0.7, 0.7, 0.7, 1)"> Font color of the other, unselected tabs. </theme_item> <theme_item name="icon_separation" data_type="constant" type="int" default="4"> diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index 3197e59248..6d602d58ee 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -729,8 +729,7 @@ <method name="set_gutter_custom_draw"> <return type="void" /> <argument index="0" name="column" type="int" /> - <argument index="1" name="object" type="Object" /> - <argument index="2" name="callback" type="StringName" /> + <argument index="1" name="draw_callback" type="Callable" /> <description> Set a custom draw method for the gutter. The callback method must take the following args: [code]line: int, gutter: int, Area: Rect2[/code]. </description> @@ -907,11 +906,9 @@ </method> <method name="set_tooltip_request_func"> <return type="void" /> - <argument index="0" name="object" type="Object" /> - <argument index="1" name="callback" type="StringName" /> - <argument index="2" name="data" type="Variant" /> + <argument index="0" name="callback" type="Callable" /> <description> - Provide custom tooltip text. The callback method must take the following args: [code]hovered_word: String, data: Variant[/code] + Provide custom tooltip text. The callback method must take the following args: [code]hovered_word: String[/code] </description> </method> <method name="swap_lines"> @@ -995,6 +992,12 @@ <member name="override_selected_font_color" type="bool" setter="set_override_selected_font_color" getter="is_overriding_selected_font_color" default="false"> If [code]true[/code], custom [code]font_selected_color[/code] will be used for selected text. </member> + <member name="placeholder_alpha" type="float" setter="set_placeholder_alpha" getter="get_placeholder_alpha" default="0.6"> + Opacity of the [member placeholder_text]. From [code]0[/code] to [code]1[/code]. + </member> + <member name="placeholder_text" type="String" setter="set_placeholder" getter="get_placeholder" default=""""> + Text shown when the [TextEdit] is empty. It is [b]not[/b] the [TextEdit]'s default value (see [member text]). + </member> <member name="scroll_horizontal" type="int" setter="set_h_scroll" getter="get_h_scroll" default="0"> If there is a horizontal scrollbar, this determines the current horizontal scroll value in pixels. </member> @@ -1222,22 +1225,22 @@ <theme_item name="caret_background_color" data_type="color" type="Color" default="Color(0, 0, 0, 1)"> [Color] of the text behind the caret when using a block caret. </theme_item> - <theme_item name="caret_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 1)"> + <theme_item name="caret_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> [Color] of the caret. This can be set to a fully transparent color to hide the caret entirely. </theme_item> <theme_item name="current_line_color" data_type="color" type="Color" default="Color(0.25, 0.25, 0.26, 0.8)"> Background [Color] of the line containing the caret. </theme_item> - <theme_item name="font_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 1)"> + <theme_item name="font_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> Sets the font [Color]. </theme_item> <theme_item name="font_outline_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> The tint of text outline of the [TextEdit]. </theme_item> - <theme_item name="font_readonly_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 0.5)"> + <theme_item name="font_readonly_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 0.5)"> Sets the font [Color] when [member editable] is disabled. </theme_item> - <theme_item name="font_selected_color" data_type="color" type="Color" default="Color(0, 0, 0, 1)"> + <theme_item name="font_selected_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> Sets the [Color] of the selected text. [member override_selected_font_color] has to be enabled. </theme_item> <theme_item name="search_result_border_color" data_type="color" type="Color" default="Color(0.3, 0.3, 0.3, 0.4)"> @@ -1246,10 +1249,10 @@ <theme_item name="search_result_color" data_type="color" type="Color" default="Color(0.3, 0.3, 0.3, 1)"> [Color] behind the text that matches the search query. </theme_item> - <theme_item name="selection_color" data_type="color" type="Color" default="Color(0.49, 0.49, 0.49, 1)"> + <theme_item name="selection_color" data_type="color" type="Color" default="Color(0.5, 0.5, 0.5, 1)"> Sets the highlight [Color] of text selections. </theme_item> - <theme_item name="word_highlighted_color" data_type="color" type="Color" default="Color(0.8, 0.9, 0.9, 0.15)"> + <theme_item name="word_highlighted_color" data_type="color" type="Color" default="Color(0.5, 0.5, 0.5, 0.25)"> Sets the highlight [Color] of multiple occurrences. [member highlight_all_occurrences] has to be enabled. </theme_item> <theme_item name="caret_width" data_type="constant" type="int" default="1"> diff --git a/doc/classes/TextLine.xml b/doc/classes/TextLine.xml index 1eaccf4604..bf1abf86ae 100644 --- a/doc/classes/TextLine.xml +++ b/doc/classes/TextLine.xml @@ -24,8 +24,7 @@ <argument index="0" name="text" type="String" /> <argument index="1" name="fonts" type="Font" /> <argument index="2" name="size" type="int" /> - <argument index="3" name="opentype_features" type="Dictionary" default="{ -}" /> + <argument index="3" name="opentype_features" type="Dictionary" default="{}" /> <argument index="4" name="language" type="String" default="""" /> <description> Adds text span and font to draw it. diff --git a/doc/classes/TextParagraph.xml b/doc/classes/TextParagraph.xml index ff193a0e4b..3d3c0dd6ff 100644 --- a/doc/classes/TextParagraph.xml +++ b/doc/classes/TextParagraph.xml @@ -24,8 +24,7 @@ <argument index="0" name="text" type="String" /> <argument index="1" name="fonts" type="Font" /> <argument index="2" name="size" type="int" /> - <argument index="3" name="opentype_features" type="Dictionary" default="{ -}" /> + <argument index="3" name="opentype_features" type="Dictionary" default="{}" /> <argument index="4" name="language" type="String" default="""" /> <description> Adds text span and font to draw it. @@ -259,8 +258,7 @@ <argument index="1" name="fonts" type="Font" /> <argument index="2" name="size" type="int" /> <argument index="3" name="dropcap_margins" type="Rect2" default="Rect2(0, 0, 0, 0)" /> - <argument index="4" name="opentype_features" type="Dictionary" default="{ -}" /> + <argument index="4" name="opentype_features" type="Dictionary" default="{}" /> <argument index="5" name="language" type="String" default="""" /> <description> Sets drop cap, overrides previously set drop cap. Drop cap (dropped capital) is a decorative element at the beginning of a paragraph that is larger than the rest of the text. diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml index 5be6113dda..61024ef0c8 100644 --- a/doc/classes/TextServer.xml +++ b/doc/classes/TextServer.xml @@ -913,8 +913,7 @@ <argument index="1" name="text" type="String" /> <argument index="2" name="fonts" type="Array" /> <argument index="3" name="size" type="int" /> - <argument index="4" name="opentype_features" type="Dictionary" default="{ -}" /> + <argument index="4" name="opentype_features" type="Dictionary" default="{}" /> <argument index="5" name="language" type="String" default="""" /> <description> Adds text span and font to draw it to the text buffer. diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml index e37031f3fd..07b9543823 100644 --- a/doc/classes/TileMap.xml +++ b/doc/classes/TileMap.xml @@ -202,7 +202,8 @@ <return type="Vector2" /> <argument index="0" name="map_position" type="Vector2i" /> <description> - Returns the local position corresponding to the given tilemap (grid-based) coordinates. + Returns a local position of the center of the cell at the given tilemap (grid-based) coordinates. + [b]Note:[/b] This doesn't correspond to the visual position of the tile, i.e. it ignores the [member TileData.texture_offset] property of individual tiles. </description> </method> <method name="move_layer"> diff --git a/doc/classes/TranslationServer.xml b/doc/classes/TranslationServer.xml index a1b4404079..c90cb2987c 100644 --- a/doc/classes/TranslationServer.xml +++ b/doc/classes/TranslationServer.xml @@ -24,6 +24,46 @@ Clears the server from all translations. </description> </method> + <method name="compare_locales" qualifiers="const"> + <return type="int" /> + <argument index="0" name="locale_a" type="String" /> + <argument index="1" name="locale_b" type="String" /> + <description> + Compares two locales and return similarity score between [code]0[/code](no match) and [code]10[/code](full match). + </description> + </method> + <method name="get_all_countries" qualifiers="const"> + <return type="PackedStringArray" /> + <description> + Returns array of known country codes. + </description> + </method> + <method name="get_all_languages" qualifiers="const"> + <return type="PackedStringArray" /> + <description> + Returns array of known language codes. + </description> + </method> + <method name="get_all_scripts" qualifiers="const"> + <return type="PackedStringArray" /> + <description> + Returns array of known script codes. + </description> + </method> + <method name="get_country_name" qualifiers="const"> + <return type="String" /> + <argument index="0" name="country" type="String" /> + <description> + Returns readable country name for the [code]country[/code] code. + </description> + </method> + <method name="get_language_name" qualifiers="const"> + <return type="String" /> + <argument index="0" name="language" type="String" /> + <description> + Returns readable language name for the [code]language[/code] code. + </description> + </method> <method name="get_loaded_locales" qualifiers="const"> <return type="Array" /> <description> @@ -44,6 +84,13 @@ Returns a locale's language and its variant (e.g. [code]"en_US"[/code] would return [code]"English (United States)"[/code]). </description> </method> + <method name="get_script_name" qualifiers="const"> + <return type="String" /> + <argument index="0" name="script" type="String" /> + <description> + Returns readable script name for the [code]script[/code] code. + </description> + </method> <method name="get_translation_object"> <return type="Translation" /> <argument index="0" name="locale" type="String" /> @@ -80,6 +127,13 @@ If translations have been loaded beforehand for the new locale, they will be applied. </description> </method> + <method name="standardize_locale" qualifiers="const"> + <return type="String" /> + <argument index="0" name="locale" type="String" /> + <description> + Retunrs [code]locale[/code] string standardized to match known locales (e.g. [code]en-US[/code] would be matched to [code]en_US[/code]). + </description> + </method> <method name="translate" qualifiers="const"> <return type="StringName" /> <argument index="0" name="message" type="StringName" /> diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml index 10bbdc0301..106bcf9d37 100644 --- a/doc/classes/Tree.xml +++ b/doc/classes/Tree.xml @@ -357,6 +357,13 @@ Emitted when a cell is selected. </description> </signal> + <signal name="check_propagated_to_item"> + <argument index="0" name="item" type="TreeItem" /> + <argument index="1" name="column" type="int" /> + <description> + Emitted when [method TreeItem.propagate_check] is called. Connect to this signal to process the items that are affected when [method TreeItem.propagate_check] is invoked. The order that the items affected will be processed is as follows: the item that invoked the method, children of that item, and finally parents of that item. + </description> + </signal> <signal name="column_title_pressed"> <argument index="0" name="column" type="int" /> <description> @@ -467,13 +474,13 @@ <theme_item name="children_hl_line_color" data_type="color" type="Color" default="Color(0.27, 0.27, 0.27, 1)"> The [Color] of the relationship lines between the selected [TreeItem] and its children. </theme_item> - <theme_item name="custom_button_font_highlight" data_type="color" type="Color" default="Color(0.94, 0.94, 0.94, 1)"> + <theme_item name="custom_button_font_highlight" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> Text [Color] for a [constant TreeItem.CELL_MODE_CUSTOM] mode cell when it's hovered. </theme_item> <theme_item name="drop_position_color" data_type="color" type="Color" default="Color(1, 0.3, 0.2, 1)"> [Color] used to draw possible drop locations. See [enum DropModeFlags] constants for further description of drop locations. </theme_item> - <theme_item name="font_color" data_type="color" type="Color" default="Color(0.69, 0.69, 0.69, 1)"> + <theme_item name="font_color" data_type="color" type="Color" default="Color(0.7, 0.7, 0.7, 1)"> Default text [Color] of the item. </theme_item> <theme_item name="font_outline_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> @@ -482,7 +489,7 @@ <theme_item name="font_selected_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> Text [Color] used when the item is selected. </theme_item> - <theme_item name="guide_color" data_type="color" type="Color" default="Color(0, 0, 0, 0.1)"> + <theme_item name="guide_color" data_type="color" type="Color" default="Color(0.7, 0.7, 0.7, 0.25)"> [Color] of the guideline. </theme_item> <theme_item name="parent_hl_line_color" data_type="color" type="Color" default="Color(0.27, 0.27, 0.27, 1)"> @@ -491,7 +498,7 @@ <theme_item name="relationship_line_color" data_type="color" type="Color" default="Color(0.27, 0.27, 0.27, 1)"> The default [Color] of the relationship lines. </theme_item> - <theme_item name="title_button_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 1)"> + <theme_item name="title_button_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> Default text [Color] of the title button. </theme_item> <theme_item name="button_margin" data_type="constant" type="int" default="4"> @@ -509,7 +516,7 @@ <theme_item name="hseparation" data_type="constant" type="int" default="4"> The horizontal space between item cells. This is also used as the margin at the start of an item when folding is disabled. </theme_item> - <theme_item name="item_margin" data_type="constant" type="int" default="12"> + <theme_item name="item_margin" data_type="constant" type="int" default="16"> The horizontal margin at the start of an item. This is used when folding is enabled for the item. </theme_item> <theme_item name="outline_size" data_type="constant" type="int" default="0"> diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml index 7da98788bb..13f2c7120c 100644 --- a/doc/classes/TreeItem.xml +++ b/doc/classes/TreeItem.xml @@ -385,6 +385,14 @@ [b]Note:[/b] You can't move to the root or move the root. </description> </method> + <method name="propagate_check"> + <return type="void" /> + <argument index="0" name="column" type="int" /> + <argument index="1" name="emit_signal" type="bool" default="true" /> + <description> + Propagates this item's checked status to its children and parents for the given [code]column[/code]. It is possible to process the items affected by this method call by connecting to [signal Tree.check_propagated_to_item]. The order that the items affected will be processed is as follows: the item invoking this method, children of that item, and finally parents of that item. If [code]emit_signal[/code] is [code]false[/code], then [signal Tree.check_propagated_to_item] will not be emitted. + </description> + </method> <method name="remove_child"> <return type="void" /> <argument index="0" name="child" type="Object" /> diff --git a/doc/classes/VFlowContainer.xml b/doc/classes/VFlowContainer.xml new file mode 100644 index 0000000000..f58075a140 --- /dev/null +++ b/doc/classes/VFlowContainer.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VFlowContainer" inherits="FlowContainer" version="4.0"> + <brief_description> + Vertical flow container. + </brief_description> + <description> + Vertical version of [FlowContainer]. + </description> + <tutorials> + </tutorials> + <theme_items> + <theme_item name="hseparation" data_type="constant" type="int" default="4"> + The horizontal separation of children nodes. + </theme_item> + <theme_item name="vseparation" data_type="constant" type="int" default="4"> + The vertical separation of children nodes. + </theme_item> + </theme_items> +</class> diff --git a/doc/classes/VSplitContainer.xml b/doc/classes/VSplitContainer.xml index 6316068e9d..33470ac7be 100644 --- a/doc/classes/VSplitContainer.xml +++ b/doc/classes/VSplitContainer.xml @@ -18,7 +18,5 @@ <theme_item name="grabber" data_type="icon" type="Texture2D"> The icon used for the grabber drawn in the middle area. </theme_item> - <theme_item name="bg" data_type="style" type="StyleBox"> - </theme_item> </theme_items> </class> diff --git a/doc/classes/VoxelGI.xml b/doc/classes/VoxelGI.xml index 2c3605aa1c..ac6f026a37 100644 --- a/doc/classes/VoxelGI.xml +++ b/doc/classes/VoxelGI.xml @@ -7,7 +7,7 @@ [VoxelGI]s are used to provide high-quality real-time indirect light and reflections to scenes. They precompute the effect of objects that emit light and the effect of static geometry to simulate the behavior of complex light in real-time. [VoxelGI]s need to be baked before having a visible effect. However, once baked, dynamic objects will receive light from them. Furthermore, lights can be fully dynamic or baked. [b]Procedural generation:[/b] [VoxelGI] can be baked in an exported project, which makes it suitable for procedurally generated or user-built levels as long as all the geometry is generated in advance. For games where geometry is generated at any time during gameplay, SDFGI is more suitable (see [member Environment.sdfgi_enabled]). [b]Performance:[/b] [VoxelGI] is relatively demanding on the GPU and is not suited to low-end hardware such as integrated graphics (consider [LightmapGI] instead). To improve performance, adjust [member ProjectSettings.rendering/global_illumination/voxel_gi/quality] and enable [member ProjectSettings.rendering/global_illumination/gi/use_half_resolution] in the Project Settings. To provide a fallback for low-end hardware, consider adding an option to disable [VoxelGI] in your project's options menus. A [VoxelGI] node can be disabled by hiding it. - [b]Note:[/b] Meshes should have sufficiently thick walls to avoid light leaks (avoid one-sided walls). For interior levels, enclose your level geometry in a sufficiently large box and bridge the loops to close the mesh. To further prevent light leaks, you can also strategically place temporary [MeshInstance3D] nodes with their [member GeometryInstance3D.gi_mode] set to [constant GeometryInstance3D.GI_MODE_BAKED]. These temporary nodes can then be hidden after baking the [VoxelGI] node. + [b]Note:[/b] Meshes should have sufficiently thick walls to avoid light leaks (avoid one-sided walls). For interior levels, enclose your level geometry in a sufficiently large box and bridge the loops to close the mesh. To further prevent light leaks, you can also strategically place temporary [MeshInstance3D] nodes with their [member GeometryInstance3D.gi_mode] set to [constant GeometryInstance3D.GI_MODE_STATIC]. These temporary nodes can then be hidden after baking the [VoxelGI] node. </description> <tutorials> <link title="GI probes">$DOCS_URL/tutorials/3d/gi_probes.html</link> @@ -19,7 +19,7 @@ <argument index="0" name="from_node" type="Node" default="null" /> <argument index="1" name="create_visual_debug" type="bool" default="false" /> <description> - Bakes the effect from all [GeometryInstance3D]s marked with [constant GeometryInstance3D.GI_MODE_BAKED] and [Light3D]s marked with either [constant Light3D.BAKE_DYNAMIC] or [constant Light3D.BAKE_STATIC]. If [code]create_visual_debug[/code] is [code]true[/code], after baking the light, this will generate a [MultiMesh] that has a cube representing each solid cell with each cube colored to the cell's albedo color. This can be used to visualize the [VoxelGI]'s data and debug any issues that may be occurring. + Bakes the effect from all [GeometryInstance3D]s marked with [constant GeometryInstance3D.GI_MODE_STATIC] and [Light3D]s marked with either [constant Light3D.BAKE_STATIC] or [constant Light3D.BAKE_DYNAMIC]. If [code]create_visual_debug[/code] is [code]true[/code], after baking the light, this will generate a [MultiMesh] that has a cube representing each solid cell with each cube colored to the cell's albedo color. This can be used to visualize the [VoxelGI]'s data and debug any issues that may be occurring. [b]Note:[/b] [method bake] works from the editor and in exported projects. This makes it suitable for procedurally generated or user-built levels. Baking a [VoxelGI] node generally takes from 5 to 20 seconds in most scenes. Reducing [member subdiv] can speed up baking. </description> </method> diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml index 75161d3c5b..3bb6603646 100644 --- a/doc/classes/Window.xml +++ b/doc/classes/Window.xml @@ -368,6 +368,10 @@ <description> </description> </signal> + <signal name="theme_changed"> + <description> + </description> + </signal> <signal name="visibility_changed"> <description> </description> @@ -439,20 +443,20 @@ </constant> </constants> <theme_items> - <theme_item name="title_color" data_type="color" type="Color" default="Color(0, 0, 0, 1)"> + <theme_item name="title_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)"> </theme_item> <theme_item name="title_outline_modulate" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> The color of the title outline. </theme_item> <theme_item name="close_h_ofs" data_type="constant" type="int" default="18"> </theme_item> - <theme_item name="close_v_ofs" data_type="constant" type="int" default="18"> + <theme_item name="close_v_ofs" data_type="constant" type="int" default="24"> </theme_item> <theme_item name="resize_margin" data_type="constant" type="int" default="4"> </theme_item> <theme_item name="scaleborder_size" data_type="constant" type="int" default="4"> </theme_item> - <theme_item name="title_height" data_type="constant" type="int" default="20"> + <theme_item name="title_height" data_type="constant" type="int" default="36"> </theme_item> <theme_item name="title_outline_size" data_type="constant" type="int" default="0"> The size of the title outline. diff --git a/doc/classes/XRPose.xml b/doc/classes/XRPose.xml index 0de2bc9e48..4a09122b40 100644 --- a/doc/classes/XRPose.xml +++ b/doc/classes/XRPose.xml @@ -34,8 +34,22 @@ - [code]grip[/code] defines the location where the user grips the controller - [code]skeleton[/code] defines the root location a hand mesh should be placed when using hand tracking and the animated skeleton supplied by the XR runtime. </member> + <member name="tracking_confidence" type="int" setter="set_tracking_confidence" getter="get_tracking_confidence" enum="XRPose.TrackingConfidence" default="0"> + The tracking confidence for this pose, provides insight on how accurate the spatial positioning of this record is. + </member> <member name="transform" type="Transform3D" setter="set_transform" getter="get_transform" default="Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)"> The transform containing the original and transform as reported by the XR runtime. </member> </members> + <constants> + <constant name="XR_TRACKING_CONFIDENCE_NONE" value="0" enum="TrackingConfidence"> + No tracking information is available for this pose. + </constant> + <constant name="XR_TRACKING_CONFIDENCE_LOW" value="1" enum="TrackingConfidence"> + Tracking information may be inaccurate or estimated. For instance with inside out tracking this would indicate a controller may be (partially) obscured. + </constant> + <constant name="XR_TRACKING_CONFIDENCE_HIGH" value="2" enum="TrackingConfidence"> + Tracking information is deemed accurate and up to date. + </constant> + </constants> </class> diff --git a/doc/classes/XRPositionalTracker.xml b/doc/classes/XRPositionalTracker.xml index 439bcfc382..c39a4aa7a7 100644 --- a/doc/classes/XRPositionalTracker.xml +++ b/doc/classes/XRPositionalTracker.xml @@ -54,8 +54,9 @@ <argument index="1" name="transform" type="Transform3D" /> <argument index="2" name="linear_velocity" type="Vector3" /> <argument index="3" name="angular_velocity" type="Vector3" /> + <argument index="4" name="tracking_confidence" type="int" enum="XRPose.TrackingConfidence" /> <description> - Sets the transform, linear velocity and angular velocity for the given pose. This method is called by a [XRInterface] implementation and should not be used directly. + Sets the transform, linear velocity, angular velocity and tracking confidence for the given pose. This method is called by a [XRInterface] implementation and should not be used directly. </description> </method> </methods> diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py index 9e18866ca3..68f3b66f43 100755 --- a/doc/tools/make_rst.py +++ b/doc/tools/make_rst.py @@ -438,7 +438,7 @@ def main(): # type: () -> None for path in args.path: # Cut off trailing slashes so os.path.basename doesn't choke. - if path.endswith(os.sep): + if path.endswith("/") or path.endswith("\\"): path = path[:-1] if os.path.basename(path) == "modules": diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 9e7d4f5435..31dda16b26 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -234,7 +234,7 @@ void RasterizerSceneGLES3::environment_set_ssil(RID p_env, bool p_enable, float void RasterizerSceneGLES3::environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) { } -void RasterizerSceneGLES3::environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) { +void RasterizerSceneGLES3::environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) { } void RasterizerSceneGLES3::environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) { diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index b73c053bc7..0f8c2e88b4 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -126,7 +126,7 @@ public: void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override; void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override; - void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override; + void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override; void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override; void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override; diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 4d742a36d9..ba623eb298 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -7518,6 +7518,9 @@ Error RenderingDeviceVulkan::draw_list_switch_to_next_pass_split(uint32_t p_spli } Error RenderingDeviceVulkan::_draw_list_allocate(const Rect2i &p_viewport, uint32_t p_splits, uint32_t p_subpass) { + // Lock while draw_list is active + _THREAD_SAFE_LOCK_ + if (p_splits == 0) { draw_list = memnew(DrawList); draw_list->command_buffer = frames[frame].draw_command_buffer; @@ -7628,6 +7631,9 @@ void RenderingDeviceVulkan::_draw_list_free(Rect2i *r_last_viewport) { memdelete(draw_list); draw_list = nullptr; } + + // draw_list is no longer active + _THREAD_SAFE_UNLOCK_ } void RenderingDeviceVulkan::draw_list_end(uint32_t p_post_barrier) { @@ -7741,6 +7747,9 @@ RenderingDevice::ComputeListID RenderingDeviceVulkan::compute_list_begin(bool p_ ERR_FAIL_COND_V_MSG(!p_allow_draw_overlap && draw_list != nullptr, INVALID_ID, "Only one draw list can be active at the same time."); ERR_FAIL_COND_V_MSG(compute_list != nullptr, INVALID_ID, "Only one draw/compute list can be active at the same time."); + // Lock while compute_list is active + _THREAD_SAFE_LOCK_ + compute_list = memnew(ComputeList); compute_list->command_buffer = frames[frame].draw_command_buffer; compute_list->state.allow_draw_overlap = p_allow_draw_overlap; @@ -8214,6 +8223,9 @@ void RenderingDeviceVulkan::compute_list_end(uint32_t p_post_barrier) { memdelete(compute_list); compute_list = nullptr; + + // compute_list is no longer active + _THREAD_SAFE_UNLOCK_ } void RenderingDeviceVulkan::barrier(uint32_t p_from, uint32_t p_to) { @@ -8372,11 +8384,11 @@ void RenderingDeviceVulkan::_free_internal(RID p_id) { } else if (uniform_set_owner.owns(p_id)) { UniformSet *uniform_set = uniform_set_owner.get_or_null(p_id); frames[frame].uniform_sets_to_dispose_of.push_back(*uniform_set); + uniform_set_owner.free(p_id); + if (uniform_set->invalidated_callback != nullptr) { - uniform_set->invalidated_callback(p_id, uniform_set->invalidated_callback_userdata); + uniform_set->invalidated_callback(uniform_set->invalidated_callback_userdata); } - - uniform_set_owner.free(p_id); } else if (render_pipeline_owner.owns(p_id)) { RenderPipeline *pipeline = render_pipeline_owner.get_or_null(p_id); frames[frame].render_pipelines_to_dispose_of.push_back(*pipeline); diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 3678642521..da376c588e 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -218,7 +218,7 @@ void AnimationBezierTrackEdit::_draw_line_clipped(const Vector2 &p_from, const V void AnimationBezierTrackEdit::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { - panner->set_control_scheme((ViewPanner::ControlScheme)EDITOR_GET("interface/editors/animation_editors_panning_scheme").operator int()); + panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/animation_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EditorSettings::get_singleton()->get("editors/panning/simple_panning"))); } if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_ENTER_TREE) { close_button->set_icon(get_theme_icon(SNAME("Close"), SNAME("EditorIcons"))); @@ -632,27 +632,6 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed()) { - // Alternate zoom (doesn't affect timeline). - if (mb->get_button_index() == MouseButton::WHEEL_DOWN) { - const float v_zoom_orig = v_zoom; - if (v_zoom < 100000) { - v_zoom *= 1.2; - } - v_scroll = v_scroll + (mb->get_position().y - get_size().y / 2) * (v_zoom - v_zoom_orig); - update(); - } - - if (mb->get_button_index() == MouseButton::WHEEL_UP) { - const float v_zoom_orig = v_zoom; - if (v_zoom > 0.000001) { - v_zoom /= 1.2; - } - v_scroll = v_scroll + (mb->get_position().y - get_size().y / 2) * (v_zoom - v_zoom_orig); - update(); - } - } - if (mb.is_valid() && mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) { menu_insert_key = mb->get_position(); if (menu_insert_key.x >= timeline->get_name_limit() && menu_insert_key.x <= get_size().width - timeline->get_buttons_width()) { @@ -1015,7 +994,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } } -void AnimationBezierTrackEdit::_scroll_callback(Vector2 p_scroll_vec) { +void AnimationBezierTrackEdit::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) { _pan_callback(-p_scroll_vec * 32); } @@ -1026,12 +1005,21 @@ void AnimationBezierTrackEdit::_pan_callback(Vector2 p_scroll_vec) { update(); } -void AnimationBezierTrackEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin) { +void AnimationBezierTrackEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) { const float v_zoom_orig = v_zoom; - if (p_scroll_vec.y > 0) { - timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05); + if (p_alt) { + // Alternate zoom (doesn't affect timeline). + if (p_scroll_vec.y > 0) { + v_zoom = MIN(v_zoom * 1.2, 100000); + } else { + v_zoom = MAX(v_zoom / 1.2, 0.000001); + } } else { - timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05); + if (p_scroll_vec.y > 0) { + timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05); + } else { + timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05); + } } v_scroll = v_scroll + (p_origin.y - get_size().y / 2) * (v_zoom - v_zoom_orig); update(); @@ -1172,8 +1160,6 @@ void AnimationBezierTrackEdit::_bind_methods() { AnimationBezierTrackEdit::AnimationBezierTrackEdit() { panner.instantiate(); panner->set_callbacks(callable_mp(this, &AnimationBezierTrackEdit::_scroll_callback), callable_mp(this, &AnimationBezierTrackEdit::_pan_callback), callable_mp(this, &AnimationBezierTrackEdit::_zoom_callback)); - panner->set_disable_rmb(true); - panner->set_control_scheme(ViewPanner::SCROLL_PANS); play_position = memnew(Control); play_position->set_mouse_filter(MOUSE_FILTER_PASS); diff --git a/editor/animation_bezier_editor.h b/editor/animation_bezier_editor.h index 6a5b97a7da..cf719a0355 100644 --- a/editor/animation_bezier_editor.h +++ b/editor/animation_bezier_editor.h @@ -126,9 +126,9 @@ class AnimationBezierTrackEdit : public Control { Set<int> selection; Ref<ViewPanner> panner; - void _scroll_callback(Vector2 p_scroll_vec); + void _scroll_callback(Vector2 p_scroll_vec, bool p_alt); void _pan_callback(Vector2 p_scroll_vec); - void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin); + void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt); void _draw_line_clipped(const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, int p_clip_left, int p_clip_right); void _draw_track(int p_track, const Color &p_color); diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 13e9d58744..dbbdd85706 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -1459,7 +1459,7 @@ int AnimationTimelineEdit::get_name_limit() const { void AnimationTimelineEdit::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { - panner->set_control_scheme((ViewPanner::ControlScheme)EDITOR_GET("interface/editors/animation_editors_panning_scheme").operator int()); + panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/animation_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EditorSettings::get_singleton()->get("editors/panning/simple_panning"))); } if (p_what == NOTIFICATION_ENTER_TREE) { @@ -1799,7 +1799,7 @@ void AnimationTimelineEdit::gui_input(const Ref<InputEvent> &p_event) { int x = mb->get_position().x - get_name_limit(); float ofs = x / get_zoom_scale() + get_value(); - emit_signal(SNAME("timeline_changed"), ofs, false, Input::get_singleton()->is_key_pressed(Key::ALT)); + emit_signal(SNAME("timeline_changed"), ofs, false, mb->is_alt_pressed()); dragging_timeline = true; } } @@ -1833,7 +1833,7 @@ void AnimationTimelineEdit::gui_input(const Ref<InputEvent> &p_event) { } } -void AnimationTimelineEdit::_scroll_callback(Vector2 p_scroll_vec) { +void AnimationTimelineEdit::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) { // Timeline has no vertical scroll, so we change it to horizontal. p_scroll_vec.x += p_scroll_vec.y; _pan_callback(-p_scroll_vec * 32); @@ -1843,7 +1843,7 @@ void AnimationTimelineEdit::_pan_callback(Vector2 p_scroll_vec) { set_value(get_value() - p_scroll_vec.x / get_zoom_scale()); } -void AnimationTimelineEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin) { +void AnimationTimelineEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) { if (p_scroll_vec.y < 0) { get_zoom()->set_value(get_zoom()->get_value() * 1.05); } else { @@ -1872,7 +1872,7 @@ void AnimationTimelineEdit::_track_added(int p_track) { void AnimationTimelineEdit::_bind_methods() { ADD_SIGNAL(MethodInfo("zoom_changed")); ADD_SIGNAL(MethodInfo("name_limit_changed")); - ADD_SIGNAL(MethodInfo("timeline_changed", PropertyInfo(Variant::FLOAT, "position"), PropertyInfo(Variant::BOOL, "drag"))); + ADD_SIGNAL(MethodInfo("timeline_changed", PropertyInfo(Variant::FLOAT, "position"), PropertyInfo(Variant::BOOL, "drag"), PropertyInfo(Variant::BOOL, "timeline_only"))); ADD_SIGNAL(MethodInfo("track_added", PropertyInfo(Variant::INT, "track"))); ADD_SIGNAL(MethodInfo("length_changed", PropertyInfo(Variant::FLOAT, "size"))); } @@ -1932,8 +1932,6 @@ AnimationTimelineEdit::AnimationTimelineEdit() { panner.instantiate(); panner->set_callbacks(callable_mp(this, &AnimationTimelineEdit::_scroll_callback), callable_mp(this, &AnimationTimelineEdit::_pan_callback), callable_mp(this, &AnimationTimelineEdit::_zoom_callback)); - panner->set_disable_rmb(true); - panner->set_control_scheme(ViewPanner::SCROLL_PANS); set_layout_direction(Control::LAYOUT_DIRECTION_LTR); } @@ -3123,7 +3121,7 @@ void AnimationTrackEdit::append_to_selection(const Rect2 &p_box, bool p_deselect } void AnimationTrackEdit::_bind_methods() { - ADD_SIGNAL(MethodInfo("timeline_changed", PropertyInfo(Variant::FLOAT, "position"), PropertyInfo(Variant::BOOL, "drag"))); + ADD_SIGNAL(MethodInfo("timeline_changed", PropertyInfo(Variant::FLOAT, "position"), PropertyInfo(Variant::BOOL, "drag"), PropertyInfo(Variant::BOOL, "timeline_only"))); ADD_SIGNAL(MethodInfo("remove_request", PropertyInfo(Variant::INT, "track"))); ADD_SIGNAL(MethodInfo("dropped", PropertyInfo(Variant::INT, "from_track"), PropertyInfo(Variant::INT, "to_track"))); ADD_SIGNAL(MethodInfo("insert_key", PropertyInfo(Variant::FLOAT, "ofs"))); @@ -3375,7 +3373,13 @@ Node *AnimationTrackEditor::get_root() const { } void AnimationTrackEditor::update_keying() { - bool keying_enabled = is_visible_in_tree() && animation.is_valid(); + bool keying_enabled = false; + + EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history(); + if (is_visible_in_tree() && animation.is_valid() && editor_history->get_path_size() > 0) { + Object *obj = ObjectDB::get_instance(editor_history->get_path_object(0)); + keying_enabled = Object::cast_to<Node>(obj) != nullptr; + } if (keying_enabled == keying) { return; @@ -3644,7 +3648,7 @@ void AnimationTrackEditor::_insert_track(bool p_create_reset, bool p_create_bezi pos = animation->get_length(); } set_anim_pos(pos); - emit_signal(SNAME("timeline_changed"), pos, true); + emit_signal(SNAME("timeline_changed"), pos, true, false); } } @@ -4506,7 +4510,7 @@ MenuButton *AnimationTrackEditor::get_edit_menu() { void AnimationTrackEditor::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { - panner->set_control_scheme((ViewPanner::ControlScheme)EDITOR_GET("interface/editors/animation_editors_panning_scheme").operator int()); + panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/animation_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EditorSettings::get_singleton()->get("editors/panning/simple_panning"))); } if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_ENTER_TREE) { @@ -4525,8 +4529,6 @@ void AnimationTrackEditor::_notification(int p_what) { if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { update_keying(); - EditorNode::get_singleton()->update_keying(); - emit_signal(SNAME("keying_changed")); } } @@ -5008,7 +5010,7 @@ struct _AnimMoveRestore { void AnimationTrackEditor::_clear_key_edit() { if (key_edit) { // If key edit is the object being inspected, remove it first. - if (EditorNode::get_singleton()->get_inspector()->get_edited_object() == key_edit) { + if (InspectorDock::get_inspector_singleton()->get_edited_object() == key_edit) { EditorNode::get_singleton()->push_item(nullptr); } @@ -5018,7 +5020,7 @@ void AnimationTrackEditor::_clear_key_edit() { } if (multi_key_edit) { - if (EditorNode::get_singleton()->get_inspector()->get_edited_object() == multi_key_edit) { + if (InspectorDock::get_inspector_singleton()->get_edited_object() == multi_key_edit) { EditorNode::get_singleton()->push_item(nullptr); } @@ -5228,16 +5230,6 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP) { - goto_prev_step(true); - scroll->accept_event(); - } - - if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed() && mb->get_button_index() == MouseButton::WHEEL_DOWN) { - goto_next_step(true); - scroll->accept_event(); - } - if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { box_selecting = true; @@ -5302,8 +5294,16 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) { } } -void AnimationTrackEditor::_scroll_callback(Vector2 p_scroll_vec) { - _pan_callback(-p_scroll_vec * 32); +void AnimationTrackEditor::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) { + if (p_alt) { + if (p_scroll_vec.x < 0 || p_scroll_vec.y < 0) { + goto_prev_step(true); + } else { + goto_next_step(true); + } + } else { + _pan_callback(-p_scroll_vec * 32); + } } void AnimationTrackEditor::_pan_callback(Vector2 p_scroll_vec) { @@ -5311,7 +5311,7 @@ void AnimationTrackEditor::_pan_callback(Vector2 p_scroll_vec) { scroll->set_v_scroll(scroll->get_v_scroll() - p_scroll_vec.y); } -void AnimationTrackEditor::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin) { +void AnimationTrackEditor::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) { if (p_scroll_vec.y < 0) { timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05); } else { @@ -5445,7 +5445,7 @@ void AnimationTrackEditor::goto_prev_step(bool p_from_mouse_event) { pos = 0; } set_anim_pos(pos); - emit_signal(SNAME("timeline_changed"), pos, true); + emit_signal(SNAME("timeline_changed"), pos, true, false); } void AnimationTrackEditor::goto_next_step(bool p_from_mouse_event) { @@ -5472,7 +5472,7 @@ void AnimationTrackEditor::goto_next_step(bool p_from_mouse_event) { } set_anim_pos(pos); - emit_signal(SNAME("timeline_changed"), pos, true); + emit_signal(SNAME("timeline_changed"), pos, true, false); } void AnimationTrackEditor::_edit_menu_pressed(int p_option) { @@ -5696,16 +5696,16 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { to_restore.push_back(amr); } -#define _NEW_POS(m_ofs) (((s > 0) ? m_ofs : from_t + (len - (m_ofs - from_t))) - pivot) * ABS(s) + from_t +#define NEW_POS(m_ofs) (((s > 0) ? m_ofs : from_t + (len - (m_ofs - from_t))) - pivot) * ABS(s) + from_t // 3 - Move the keys (re insert them). for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { - float newpos = _NEW_POS(E->get().pos); + float newpos = NEW_POS(E->get().pos); undo_redo->add_do_method(animation.ptr(), "track_insert_key", E->key().track, newpos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key)); } // 4 - (Undo) Remove inserted keys. for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { - float newpos = _NEW_POS(E->get().pos); + float newpos = NEW_POS(E->get().pos); undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", E->key().track, newpos); } @@ -5725,13 +5725,13 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { // 7-reselect. for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) { float oldpos = E->get().pos; - float newpos = _NEW_POS(oldpos); + float newpos = NEW_POS(oldpos); if (newpos >= 0) { undo_redo->add_do_method(this, "_select_at_anim", animation, E->key().track, newpos); } undo_redo->add_undo_method(this, "_select_at_anim", animation, E->key().track, oldpos); } -#undef _NEW_POS +#undef NEW_POS undo_redo->commit_action(); } break; case EDIT_DUPLICATE_SELECTION: { @@ -5996,7 +5996,7 @@ void AnimationTrackEditor::_bind_methods() { ClassDB::bind_method("_key_deselected", &AnimationTrackEditor::_key_deselected); // Still used by some connect_compat. ClassDB::bind_method("_clear_selection", &AnimationTrackEditor::_clear_selection); // Still used by some connect_compat. - ADD_SIGNAL(MethodInfo("timeline_changed", PropertyInfo(Variant::FLOAT, "position"), PropertyInfo(Variant::BOOL, "drag"))); + ADD_SIGNAL(MethodInfo("timeline_changed", PropertyInfo(Variant::FLOAT, "position"), PropertyInfo(Variant::BOOL, "drag"), PropertyInfo(Variant::BOOL, "timeline_only"))); ADD_SIGNAL(MethodInfo("keying_changed")); ADD_SIGNAL(MethodInfo("animation_len_changed", PropertyInfo(Variant::FLOAT, "len"))); ADD_SIGNAL(MethodInfo("animation_step_changed", PropertyInfo(Variant::FLOAT, "step"))); @@ -6107,8 +6107,6 @@ AnimationTrackEditor::AnimationTrackEditor() { panner.instantiate(); panner->set_callbacks(callable_mp(this, &AnimationTrackEditor::_scroll_callback), callable_mp(this, &AnimationTrackEditor::_pan_callback), callable_mp(this, &AnimationTrackEditor::_zoom_callback)); - panner->set_disable_rmb(true); - panner->set_control_scheme(ViewPanner::SCROLL_PANS); scroll = memnew(ScrollContainer); timeline_vbox->add_child(scroll); @@ -6116,7 +6114,9 @@ AnimationTrackEditor::AnimationTrackEditor() { VScrollBar *sb = scroll->get_v_scroll_bar(); scroll->remove_child(sb); timeline_scroll->add_child(sb); // Move here so timeline and tracks are always aligned. + scroll->set_focus_mode(FOCUS_CLICK); scroll->connect("gui_input", callable_mp(this, &AnimationTrackEditor::_scroll_input)); + scroll->connect("focus_exited", callable_mp(panner.ptr(), &ViewPanner::release_pan_key)); bezier_edit = memnew(AnimationBezierTrackEdit); timeline_vbox->add_child(bezier_edit); diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index 2a2b20ada9..50c5c692c0 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -82,9 +82,9 @@ class AnimationTimelineEdit : public Range { bool use_fps; Ref<ViewPanner> panner; - void _scroll_callback(Vector2 p_scroll_vec); + void _scroll_callback(Vector2 p_scroll_vec, bool p_alt); void _pan_callback(Vector2 p_scroll_vec); - void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin); + void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt); bool dragging_timeline; bool dragging_hsize; @@ -316,7 +316,7 @@ class AnimationTrackEditor : public VBoxContainer { void _update_tracks(); void _name_limit_changed(); - void _timeline_changed(float p_new_pos, bool p_drag, bool p_timeline_only = false); + void _timeline_changed(float p_new_pos, bool p_drag, bool p_timeline_only); void _track_remove_request(int p_track); void _track_grab_focus(int p_track); @@ -377,9 +377,9 @@ class AnimationTrackEditor : public VBoxContainer { PropertyInfo _find_hint_for_track(int p_idx, NodePath &r_base_path, Variant *r_current_val = nullptr); Ref<ViewPanner> panner; - void _scroll_callback(Vector2 p_scroll_vec); + void _scroll_callback(Vector2 p_scroll_vec, bool p_alt); void _pan_callback(Vector2 p_scroll_vec); - void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin); + void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt); void _timeline_value_changed(double); diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 4669e56e20..fb36bfc5e5 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -1909,7 +1909,7 @@ CodeTextEditor::CodeTextEditor() { text_editor->connect("gui_input", callable_mp(this, &CodeTextEditor::_text_editor_gui_input)); text_editor->connect("caret_changed", callable_mp(this, &CodeTextEditor::_line_col_changed)); text_editor->connect("text_changed", callable_mp(this, &CodeTextEditor::_text_changed)); - text_editor->connect("request_code_completion", callable_mp(this, &CodeTextEditor::_complete_request)); + text_editor->connect("code_completion_requested", callable_mp(this, &CodeTextEditor::_complete_request)); TypedArray<String> cs; cs.push_back("."); cs.push_back(","); diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index c23fd6a943..bda558bb72 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -649,8 +649,8 @@ void ConnectionsDock::_connect(ConnectDialog::ConnectionData p_cd) { undo_redo->add_undo_method(source, "disconnect", p_cd.signal, callable); undo_redo->add_do_method(this, "update_tree"); undo_redo->add_undo_method(this, "update_tree"); - undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); // To force redraw of scene tree. - undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + undo_redo->add_do_method(SceneTreeDock::get_singleton()->get_tree_editor(), "update_tree"); // To force redraw of scene tree. + undo_redo->add_undo_method(SceneTreeDock::get_singleton()->get_tree_editor(), "update_tree"); undo_redo->commit_action(); } @@ -671,8 +671,8 @@ void ConnectionsDock::_disconnect(TreeItem &p_item) { undo_redo->add_undo_method(selected_node, "connect", cd.signal, callable, cd.binds, cd.flags); undo_redo->add_do_method(this, "update_tree"); undo_redo->add_undo_method(this, "update_tree"); - undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); // To force redraw of scene tree. - undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + undo_redo->add_do_method(SceneTreeDock::get_singleton()->get_tree_editor(), "update_tree"); // To force redraw of scene tree. + undo_redo->add_undo_method(SceneTreeDock::get_singleton()->get_tree_editor(), "update_tree"); undo_redo->commit_action(); } @@ -702,8 +702,8 @@ void ConnectionsDock::_disconnect_all() { undo_redo->add_do_method(this, "update_tree"); undo_redo->add_undo_method(this, "update_tree"); - undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); - undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + undo_redo->add_do_method(SceneTreeDock::get_singleton()->get_tree_editor(), "update_tree"); + undo_redo->add_undo_method(SceneTreeDock::get_singleton()->get_tree_editor(), "update_tree"); undo_redo->commit_action(); } diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp index e9d275895f..79853b6809 100644 --- a/editor/debugger/editor_debugger_node.cpp +++ b/editor/debugger/editor_debugger_node.cpp @@ -75,8 +75,8 @@ EditorDebuggerNode::EditorDebuggerNode() { remote_scene_tree = memnew(EditorDebuggerTree); remote_scene_tree->connect("object_selected", callable_mp(this, &EditorDebuggerNode::_remote_object_requested)); remote_scene_tree->connect("save_node", callable_mp(this, &EditorDebuggerNode::_save_node_requested)); - EditorNode::get_singleton()->get_scene_tree_dock()->add_remote_tree_editor(remote_scene_tree); - EditorNode::get_singleton()->get_scene_tree_dock()->connect("remote_tree_selected", callable_mp(this, &EditorDebuggerNode::request_remote_tree)); + SceneTreeDock::get_singleton()->add_remote_tree_editor(remote_scene_tree); + SceneTreeDock::get_singleton()->connect("remote_tree_selected", callable_mp(this, &EditorDebuggerNode::request_remote_tree)); remote_scene_tree_timeout = EDITOR_DEF("debugger/remote_scene_tree_refresh_interval", 1.0); inspect_edited_object_timeout = EDITOR_DEF("debugger/remote_inspect_refresh_interval", 0.2); @@ -332,10 +332,10 @@ void EditorDebuggerNode::_notification(int p_what) { // Switch to remote tree view if so desired. auto_switch_remote_scene_tree = (bool)EditorSettings::get_singleton()->get("debugger/auto_switch_to_remote_scene_tree"); if (auto_switch_remote_scene_tree) { - EditorNode::get_singleton()->get_scene_tree_dock()->show_remote_tree(); + SceneTreeDock::get_singleton()->show_remote_tree(); } // Good to go. - EditorNode::get_singleton()->get_scene_tree_dock()->show_tab_buttons(); + SceneTreeDock::get_singleton()->show_tab_buttons(); debugger->set_editor_remote_tree(remote_scene_tree); debugger->start(server->take_connection()); // Send breakpoints. @@ -361,8 +361,8 @@ void EditorDebuggerNode::_debugger_stopped(int p_id) { if (!found) { EditorNode::get_singleton()->get_pause_button()->set_pressed(false); EditorNode::get_singleton()->get_pause_button()->set_disabled(true); - EditorNode::get_singleton()->get_scene_tree_dock()->hide_remote_tree(); - EditorNode::get_singleton()->get_scene_tree_dock()->hide_tab_buttons(); + SceneTreeDock::get_singleton()->hide_remote_tree(); + SceneTreeDock::get_singleton()->hide_tab_buttons(); EditorNode::get_singleton()->notify_all_debug_sessions_exited(); } } @@ -576,7 +576,7 @@ void EditorDebuggerNode::_remote_object_property_updated(ObjectID p_id, const St if (obj->remote_object_id != p_id) { return; } - EditorNode::get_singleton()->get_inspector()->update_property(p_property); + InspectorDock::get_inspector_singleton()->update_property(p_property); } } diff --git a/editor/debugger/editor_debugger_tree.cpp b/editor/debugger/editor_debugger_tree.cpp index 70d64615ae..29d0014b8a 100644 --- a/editor/debugger/editor_debugger_tree.cpp +++ b/editor/debugger/editor_debugger_tree.cpp @@ -128,7 +128,7 @@ void EditorDebuggerTree::_scene_tree_rmb_selected(const Vector2 &p_position) { void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int p_debugger) { updating_scene_tree = true; const String last_path = get_selected_path(); - const String filter = EditorNode::get_singleton()->get_scene_tree_dock()->get_filter(); + const String filter = SceneTreeDock::get_singleton()->get_filter(); bool filter_changed = filter != last_filter; TreeItem *scroll_item = nullptr; diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index 4349ffc75b..ee844fff64 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -1121,7 +1121,7 @@ void ScriptEditorDebugger::_property_changed(Object *p_base, const StringName &p NodePath path = editor->get_edited_scene()->get_path_to(node); int pathid = _get_node_path_cache(path); - if (p_value.is_ref()) { + if (p_value.is_ref_counted()) { Ref<Resource> res = p_value; if (res.is_valid() && !res->get_path().is_empty()) { Array msg; @@ -1147,7 +1147,7 @@ void ScriptEditorDebugger::_property_changed(Object *p_base, const StringName &p String respath = res->get_path(); int pathid = _get_res_path_cache(respath); - if (p_value.is_ref()) { + if (p_value.is_ref_counted()) { Ref<Resource> res2 = p_value; if (res2.is_valid() && !res2->get_path().is_empty()) { Array msg; diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp index a71e16b66c..6acf654b04 100644 --- a/editor/doc_tools.cpp +++ b/editor/doc_tools.cpp @@ -350,7 +350,7 @@ void DocTools::generate(bool p_basic_types) { List<PropertyInfo> properties; List<PropertyInfo> own_properties; if (name == "ProjectSettings") { - //special case for project settings, so settings can be documented + // Special case for project settings, so settings can be documented. ProjectSettings::get_singleton()->get_property_list(&properties); own_properties = properties; } else { @@ -358,9 +358,12 @@ void DocTools::generate(bool p_basic_types) { ClassDB::get_property_list(name, &own_properties, true); } + properties.sort(); + own_properties.sort(); + List<PropertyInfo>::Element *EO = own_properties.front(); for (const PropertyInfo &E : properties) { - bool inherited = EO == nullptr; + bool inherited = true; if (EO && EO->get() == E) { inherited = false; EO = EO->next(); @@ -410,7 +413,7 @@ void DocTools::generate(bool p_basic_types) { //used to track uninitialized values using valgrind //print_line("getting default value for " + String(name) + "." + String(E.name)); if (default_value_valid && default_value.get_type() != Variant::OBJECT) { - prop.default_value = default_value.get_construct_string().replace("\n", ""); + prop.default_value = default_value.get_construct_string().replace("\n", " "); } StringName setter = ClassDB::get_property_setter(name, E.name); @@ -522,7 +525,7 @@ void DocTools::generate(bool p_basic_types) { int darg_idx = i - (E.arguments.size() - E.default_arguments.size()); if (darg_idx >= 0) { Variant default_arg = E.default_arguments[darg_idx]; - argument.default_value = default_arg.get_construct_string(); + argument.default_value = default_arg.get_construct_string().replace("\n", " "); } method.arguments.push_back(argument); @@ -585,7 +588,7 @@ void DocTools::generate(bool p_basic_types) { tid.name = E; tid.type = "Color"; tid.data_type = "color"; - tid.default_value = Variant(Theme::get_default()->get_color(E, cname)).get_construct_string(); + tid.default_value = Variant(Theme::get_default()->get_color(E, cname)).get_construct_string().replace("\n", " "); c.theme_properties.push_back(tid); } @@ -757,7 +760,7 @@ void DocTools::generate(bool p_basic_types) { int darg_idx = mi.default_arguments.size() - mi.arguments.size() + j; if (darg_idx >= 0) { Variant default_arg = mi.default_arguments[darg_idx]; - ad.default_value = default_arg.get_construct_string(); + ad.default_value = default_arg.get_construct_string().replace("\n", " "); } method.arguments.push_back(ad); @@ -801,7 +804,7 @@ void DocTools::generate(bool p_basic_types) { DocData::PropertyDoc property; property.name = pi.name; property.type = Variant::get_type_name(pi.type); - property.default_value = v.get(pi.name).get_construct_string(); + property.default_value = v.get(pi.name).get_construct_string().replace("\n", " "); c.properties.push_back(property); } @@ -813,7 +816,7 @@ void DocTools::generate(bool p_basic_types) { DocData::ConstantDoc constant; constant.name = E; Variant value = Variant::get_constant_value(Variant::Type(i), E); - constant.value = value.get_type() == Variant::INT ? itos(value) : value.get_construct_string(); + constant.value = value.get_type() == Variant::INT ? itos(value) : value.get_construct_string().replace("\n", " "); constant.is_value_valid = true; c.constants.push_back(constant); } @@ -930,7 +933,7 @@ void DocTools::generate(bool p_basic_types) { int darg_idx = j - (mi.arguments.size() - mi.default_arguments.size()); if (darg_idx >= 0) { Variant default_arg = mi.default_arguments[darg_idx]; - ad.default_value = default_arg.get_construct_string(); + ad.default_value = default_arg.get_construct_string().replace("\n", " "); } md.arguments.push_back(ad); diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp index 5d4c746785..76c0811166 100644 --- a/editor/editor_asset_installer.cpp +++ b/editor/editor_asset_installer.cpp @@ -36,45 +36,6 @@ #include "editor_node.h" #include "progress_dialog.h" -void EditorAssetInstaller::_update_subitems(TreeItem *p_item, bool p_check, bool p_first) { - if (p_check) { - if (p_item->get_custom_color(0) == Color()) { - p_item->set_checked(0, true); - } - } else { - p_item->set_checked(0, false); - } - - if (p_item->get_first_child()) { - _update_subitems(p_item->get_first_child(), p_check); - } - - if (!p_first && p_item->get_next()) { - _update_subitems(p_item->get_next(), p_check); - } -} - -void EditorAssetInstaller::_uncheck_parent(TreeItem *p_item) { - if (!p_item) { - return; - } - - bool any_checked = false; - TreeItem *item = p_item->get_first_child(); - while (item) { - if (item->is_checked(0)) { - any_checked = true; - break; - } - item = item->get_next(); - } - - if (!any_checked) { - p_item->set_checked(0, false); - _uncheck_parent(p_item->get_parent()); - } -} - void EditorAssetInstaller::_item_edited() { if (updating) { return; @@ -85,22 +46,17 @@ void EditorAssetInstaller::_item_edited() { return; } - String path = item->get_metadata(0); - updating = true; - if (path.is_empty() || item == tree->get_root()) { //a dir or root - _update_subitems(item, item->is_checked(0), true); - } + item->propagate_check(0); + updating = false; +} - if (item->is_checked(0)) { - while (item) { - item->set_checked(0, true); - item = item->get_parent(); - } - } else { - _uncheck_parent(item->get_parent()); +void EditorAssetInstaller::_check_propagated_to_item(Object *p_obj, int column) { + TreeItem *affected_item = Object::cast_to<TreeItem>(p_obj); + if (affected_item && affected_item->get_custom_color(0) != Color()) { + affected_item->set_checked(0, false); + affected_item->propagate_check(0, false); } - updating = false; } void EditorAssetInstaller::open(const String &p_path, int p_depth) { @@ -259,6 +215,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { ti->set_custom_color(0, tree->get_theme_color(SNAME("error_color"), SNAME("Editor"))); ti->set_tooltip(0, vformat(TTR("%s (already exists)"), res_path)); ti->set_checked(0, false); + ti->propagate_check(0); } else { ti->set_tooltip(0, res_path); } @@ -275,7 +232,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { asset_contents->set_text(vformat(TTR("Contents of asset \"%s\" - No files conflict with your project:"), asset_name)); } - popup_centered_ratio(); + popup_centered_ratio(0.5); updating = false; } @@ -304,7 +261,7 @@ void EditorAssetInstaller::ok_pressed() { String name = String::utf8(fname); - if (status_map.has(name) && status_map[name]->is_checked(0)) { + if (status_map.has(name) && (status_map[name]->is_checked(0) || status_map[name]->is_indeterminate(0))) { String path = status_map[name]->get_metadata(0); if (path.is_empty()) { // a dir @@ -392,6 +349,7 @@ EditorAssetInstaller::EditorAssetInstaller() { tree = memnew(Tree); tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); tree->connect("item_edited", callable_mp(this, &EditorAssetInstaller::_item_edited)); + tree->connect("check_propagated_to_item", callable_mp(this, &EditorAssetInstaller::_check_propagated_to_item)); vb->add_child(tree); error = memnew(AcceptDialog); diff --git a/editor/editor_asset_installer.h b/editor/editor_asset_installer.h index 2f59250933..f5993f73e7 100644 --- a/editor/editor_asset_installer.h +++ b/editor/editor_asset_installer.h @@ -43,9 +43,8 @@ class EditorAssetInstaller : public ConfirmationDialog { AcceptDialog *error; Map<String, TreeItem *> status_map; bool updating; - void _update_subitems(TreeItem *p_item, bool p_check, bool p_first = false); - void _uncheck_parent(TreeItem *p_item); void _item_edited(); + void _check_propagated_to_item(Object *p_obj, int column); virtual void ok_pressed() override; protected: diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index 8e4bbbb99b..5e4e375db4 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -1163,7 +1163,7 @@ void EditorAudioBuses::_server_save() { } void EditorAudioBuses::_select_layout() { - EditorNode::get_singleton()->get_filesystem_dock()->select_file(edited_path); + FileSystemDock::get_singleton()->select_file(edited_path); } void EditorAudioBuses::_save_as_layout() { diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index d556255a8f..0c9a7b2972 100644 --- a/editor/editor_fonts.cpp +++ b/editor/editor_fonts.cpp @@ -269,7 +269,10 @@ void editor_register_fonts(Ref<Theme> p_theme) { /* Hack */ - Ref<FontData> dfmono = load_cached_internal_font(_font_Hack_Regular, _font_Hack_Regular_size, font_hinting, font_antialiased, true); + Ref<FontData> dfmono = load_cached_internal_font(_font_JetBrainsMono_Regular, _font_JetBrainsMono_Regular_size, font_hinting, font_antialiased, true); + Dictionary opentype_features; + opentype_features["calt"] = 0; + dfmono->set_opentype_feature_overrides(opentype_features); // Disable contextual alternates (coding ligatures). // Default font MAKE_DEFAULT_FONT(df, String()); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 06e3a63f4a..6d5e56184a 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -44,18 +44,25 @@ DocTools *EditorHelp::doc = nullptr; -void EditorHelp::_init_colors() { - title_color = get_theme_color(SNAME("accent_color"), SNAME("Editor")); - text_color = get_theme_color(SNAME("default_color"), SNAME("RichTextLabel")); - headline_color = get_theme_color(SNAME("headline_color"), SNAME("EditorHelp")); - base_type_color = title_color.lerp(text_color, 0.5); - comment_color = text_color * Color(1, 1, 1, 0.6); - symbol_color = comment_color; - value_color = text_color * Color(1, 1, 1, 0.6); - qualifier_color = text_color * Color(1, 1, 1, 0.8); - type_color = get_theme_color(SNAME("accent_color"), SNAME("Editor")).lerp(text_color, 0.5); - class_desc->add_theme_color_override("selection_color", get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.4)); - class_desc->add_theme_constant_override("line_separation", Math::round(5 * EDSCALE)); +void EditorHelp::_update_theme() { + text_color = get_theme_color("text_color", "EditorHelp"); + title_color = get_theme_color("title_color", "EditorHelp"); + headline_color = get_theme_color("headline_color", "EditorHelp"); + comment_color = get_theme_color("comment_color", "EditorHelp"); + symbol_color = get_theme_color("symbol_color", "EditorHelp"); + value_color = get_theme_color("value_color", "EditorHelp"); + qualifier_color = get_theme_color("qualifier_color", "EditorHelp"); + type_color = get_theme_color("type_color", "EditorHelp"); + + class_desc->add_theme_color_override("selection_color", get_theme_color("selection_color", "EditorHelp")); + class_desc->add_theme_constant_override("line_separation", get_theme_constant("line_separation", "EditorHelp")); + class_desc->add_theme_constant_override("table_hseparation", get_theme_constant("table_hseparation", "EditorHelp")); + class_desc->add_theme_constant_override("table_vseparation", get_theme_constant("table_vseparation", "EditorHelp")); + + doc_font = get_theme_font(SNAME("doc"), SNAME("EditorFonts")); + doc_bold_font = get_theme_font(SNAME("doc_bold"), SNAME("EditorFonts")); + doc_title_font = get_theme_font(SNAME("doc_title"), SNAME("EditorFonts")); + doc_code_font = get_theme_font(SNAME("doc_source"), SNAME("EditorFonts")); } void EditorHelp::_search(bool p_search_previous) { @@ -162,12 +169,15 @@ void EditorHelp::_class_desc_resized() { Ref<Font> doc_code_font = get_theme_font(SNAME("doc_source"), SNAME("EditorFonts")); int font_size = get_theme_font_size(SNAME("doc_source_size"), SNAME("EditorFonts")); real_t char_width = doc_code_font->get_char_size('x', 0, font_size).width; - const int display_margin = MAX(30 * EDSCALE, get_parent_anchorable_rect().size.width - char_width * 120 * EDSCALE) * 0.5; - - Ref<StyleBox> class_desc_stylebox = EditorNode::get_singleton()->get_theme_base()->get_theme_stylebox(SNAME("normal"), SNAME("RichTextLabel"))->duplicate(); - class_desc_stylebox->set_default_margin(SIDE_LEFT, display_margin); - class_desc_stylebox->set_default_margin(SIDE_RIGHT, display_margin); - class_desc->add_theme_style_override("normal", class_desc_stylebox); + const int new_display_margin = MAX(30 * EDSCALE, get_parent_anchorable_rect().size.width - char_width * 120 * EDSCALE) * 0.5; + if (display_margin != new_display_margin) { + display_margin = new_display_margin; + + Ref<StyleBox> class_desc_stylebox = EditorNode::get_singleton()->get_theme_base()->get_theme_stylebox(SNAME("normal"), SNAME("RichTextLabel"))->duplicate(); + class_desc_stylebox->set_default_margin(SIDE_LEFT, display_margin); + class_desc_stylebox->set_default_margin(SIDE_RIGHT, display_margin); + class_desc->add_theme_style_override("normal", class_desc_stylebox); + } } void EditorHelp::_add_type(const String &p_type, const String &p_enum) { @@ -184,8 +194,7 @@ void EditorHelp::_add_type(const String &p_type, const String &p_enum) { t = p_enum.get_slice(".", 0); } } - const Color text_color = get_theme_color(SNAME("default_color"), SNAME("RichTextLabel")); - const Color type_color = get_theme_color(SNAME("accent_color"), SNAME("Editor")).lerp(text_color, 0.5); + class_desc->push_color(type_color); bool add_array = false; if (can_ref) { @@ -496,16 +505,11 @@ void EditorHelp::_update_doc() { method_line.clear(); section_line.clear(); - _init_colors(); - - DocData::ClassDoc cd = doc->class_list[edited_class]; //make a copy, so we can sort without worrying - - Ref<Font> doc_font = get_theme_font(SNAME("doc"), SNAME("EditorFonts")); - Ref<Font> doc_bold_font = get_theme_font(SNAME("doc_bold"), SNAME("EditorFonts")); - Ref<Font> doc_title_font = get_theme_font(SNAME("doc_title"), SNAME("EditorFonts")); - Ref<Font> doc_code_font = get_theme_font(SNAME("doc_source"), SNAME("EditorFonts")); + _update_theme(); String link_color_text = title_color.to_html(false); + DocData::ClassDoc cd = doc->class_list[edited_class]; // Make a copy, so we can sort without worrying. + // Class name section_line.push_back(Pair<String, int>(TTR("Top"), 0)); class_desc->push_font(doc_title_font); @@ -1476,11 +1480,9 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { Ref<Font> doc_kbd_font = p_rt->get_theme_font(SNAME("doc_keyboard"), SNAME("EditorFonts")); Color headline_color = p_rt->get_theme_color(SNAME("headline_color"), SNAME("EditorHelp")); - Color accent_color = p_rt->get_theme_color(SNAME("accent_color"), SNAME("Editor")); - Color property_color = p_rt->get_theme_color(SNAME("property_color"), SNAME("Editor")); - Color link_color = accent_color.lerp(headline_color, 0.8); - Color code_color = accent_color.lerp(headline_color, 0.6); - Color kbd_color = accent_color.lerp(property_color, 0.6); + Color link_color = p_rt->get_theme_color(SNAME("link_color"), SNAME("EditorHelp")); + Color code_color = p_rt->get_theme_color(SNAME("code_color"), SNAME("EditorHelp")); + Color kbd_color = p_rt->get_theme_color(SNAME("kbd_color"), SNAME("EditorHelp")); String bbcode = p_bbcode.dedent().replace("\t", "").replace("\r", "").strip_edges(); @@ -1600,24 +1602,28 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { pos = brk_pos + 1; } else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ") || tag.begins_with("theme_item ")) { - int tag_end = tag.find(" "); - - String link_tag = tag.substr(0, tag_end); - String link_target = tag.substr(tag_end + 1, tag.length()).lstrip(" "); + const int tag_end = tag.find(" "); + const String link_tag = tag.substr(0, tag_end); + const String link_target = tag.substr(tag_end + 1, tag.length()).lstrip(" "); + p_rt->push_font(doc_code_font); p_rt->push_color(link_color); p_rt->push_meta("@" + link_tag + " " + link_target); p_rt->add_text(link_target + (tag.begins_with("method ") ? "()" : "")); p_rt->pop(); p_rt->pop(); + p_rt->pop(); pos = brk_end + 1; } else if (doc->class_list.has(tag)) { + // Class reference tag such as [Node2D] or [SceneTree]. + p_rt->push_font(doc_code_font); p_rt->push_color(link_color); p_rt->push_meta("#" + tag); p_rt->add_text(tag); p_rt->pop(); p_rt->pop(); + p_rt->pop(); pos = brk_end + 1; } else if (tag == "b") { @@ -1941,16 +1947,16 @@ void EditorHelpBit::_bind_methods() { void EditorHelpBit::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + rich_text->add_theme_color_override("selection_color", get_theme_color(SNAME("selection_color"), SNAME("EditorHelp"))); + } break; + case NOTIFICATION_READY: { rich_text->clear(); _add_text_to_rt(text, rich_text); } break; - case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - rich_text->add_theme_color_override("selection_color", get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.4)); - } break; - default: - break; } } @@ -1964,7 +1970,6 @@ EditorHelpBit::EditorHelpBit() { rich_text = memnew(RichTextLabel); add_child(rich_text); rich_text->connect("meta_clicked", callable_mp(this, &EditorHelpBit::_meta_clicked)); - rich_text->add_theme_color_override("selection_color", get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.4)); rich_text->set_override_selected_font_color(false); set_custom_minimum_size(Size2(0, 70 * EDSCALE)); } diff --git a/editor/editor_help.h b/editor/editor_help.h index eb879c6d39..237cf4f347 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -126,17 +126,21 @@ class EditorHelp : public VBoxContainer { String base_path; - Color title_color; Color text_color; + Color title_color; Color headline_color; - Color base_type_color; - Color type_color; Color comment_color; Color symbol_color; Color value_color; Color qualifier_color; + Color type_color; + + Ref<Font> doc_font; + Ref<Font> doc_bold_font; + Ref<Font> doc_title_font; + Ref<Font> doc_code_font; - void _init_colors(); + void _update_theme(); void _help_callback(const String &p_topic); void _add_text(const String &p_bbcode); @@ -152,6 +156,7 @@ class EditorHelp : public VBoxContainer { void _class_desc_select(const String &p_select); void _class_desc_input(const Ref<InputEvent> &p_input); void _class_desc_resized(); + int display_margin = 0; Error _goto_desc(const String &p_class, int p_vscr = -1); //void _update_history_buttons(); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 75e518e050..a3538d3381 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -623,14 +623,17 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) { if (property == "frame_coords" && (object->is_class("Sprite2D") || object->is_class("Sprite3D"))) { Vector2i new_coords = object->get(property); new_coords.x++; - if (new_coords.x >= object->get("hframes").operator int64_t()) { + if (new_coords.x >= int64_t(object->get("hframes"))) { new_coords.x = 0; new_coords.y++; } - - call_deferred(SNAME("emit_changed"), property, new_coords, "", false); + if (new_coords.x < int64_t(object->get("hframes")) && new_coords.y < int64_t(object->get("vframes"))) { + call_deferred(SNAME("emit_changed"), property, new_coords, "", false); + } } else { - call_deferred(SNAME("emit_changed"), property, object->get(property).operator int64_t() + 1, "", false); + if (int64_t(object->get(property)) + 1 < (int64_t(object->get("hframes")) * int64_t(object->get("vframes")))) { + call_deferred(SNAME("emit_changed"), property, object->get(property).operator int64_t() + 1, "", false); + } } call_deferred(SNAME("update_property")); @@ -861,10 +864,10 @@ String EditorProperty::get_tooltip_text() const { void EditorProperty::menu_option(int p_option) { switch (p_option) { case MENU_COPY_PROPERTY: { - EditorNode::get_singleton()->get_inspector()->set_property_clipboard(object->get(property)); + InspectorDock::get_inspector_singleton()->set_property_clipboard(object->get(property)); } break; case MENU_PASTE_PROPERTY: { - emit_changed(property, EditorNode::get_singleton()->get_inspector()->get_property_clipboard()); + emit_changed(property, InspectorDock::get_inspector_singleton()->get_property_clipboard()); } break; case MENU_COPY_PROPERTY_PATH: { DisplayServer::get_singleton()->clipboard_set(property); @@ -2905,6 +2908,7 @@ void EditorInspector::edit(Object *p_object) { object->connect("property_list_changed", callable_mp(this, &EditorInspector::_changed_callback)); update_tree(); } + emit_signal("edited_object_changed"); } void EditorInspector::set_keying(bool p_active) { @@ -3543,6 +3547,7 @@ void EditorInspector::_bind_methods() { ADD_SIGNAL(MethodInfo("object_id_selected", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("property_edited", PropertyInfo(Variant::STRING, "property"))); ADD_SIGNAL(MethodInfo("property_toggled", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::BOOL, "checked"))); + ADD_SIGNAL(MethodInfo("edited_object_changed")); ADD_SIGNAL(MethodInfo("restart_requested")); } diff --git a/editor/editor_locale_dialog.cpp b/editor/editor_locale_dialog.cpp new file mode 100644 index 0000000000..5c4ece7065 --- /dev/null +++ b/editor/editor_locale_dialog.cpp @@ -0,0 +1,563 @@ +/*************************************************************************/ +/* editor_locale_dialog.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "editor_locale_dialog.h" + +#include "editor/editor_node.h" +#include "editor/editor_scale.h" +#include "scene/gui/check_button.h" +#include "scene/gui/line_edit.h" +#include "scene/gui/option_button.h" +#include "scene/gui/tree.h" + +static _FORCE_INLINE_ bool is_upper_case(char32_t c) { + return (c >= 'A' && c <= 'Z'); +} + +static _FORCE_INLINE_ bool is_lower_case(char32_t c) { + return (c >= 'a' && c <= 'z'); +} + +void EditorLocaleDialog::_bind_methods() { + ADD_SIGNAL(MethodInfo("locale_selected", PropertyInfo(Variant::STRING, "locale"))); +} + +void EditorLocaleDialog::ok_pressed() { + if (edit_filters->is_pressed()) { + return; // Do not update, if in filter edit mode. + } + + String locale; + if (lang_code->get_text().is_empty()) { + return; // Language code is required. + } + locale = lang_code->get_text(); + + if (!script_code->get_text().is_empty()) { + locale += "_" + script_code->get_text(); + } + if (!country_code->get_text().is_empty()) { + locale += "_" + country_code->get_text(); + } + if (!variant_code->get_text().is_empty()) { + locale += "_" + variant_code->get_text(); + } + + emit_signal(SNAME("locale_selected"), TranslationServer::get_singleton()->standardize_locale(locale)); + hide(); +} + +void EditorLocaleDialog::_item_selected() { + if (updating_lists) { + return; + } + + if (edit_filters->is_pressed()) { + return; // Do not update, if in filter edit mode. + } + + TreeItem *l = lang_list->get_selected(); + if (l) { + lang_code->set_text(l->get_metadata(0).operator String()); + } + + TreeItem *s = script_list->get_selected(); + if (s) { + script_code->set_text(s->get_metadata(0).operator String()); + } + + TreeItem *c = cnt_list->get_selected(); + if (c) { + country_code->set_text(c->get_metadata(0).operator String()); + } +} + +void EditorLocaleDialog::_toggle_advanced(bool p_checked) { + if (!p_checked) { + script_code->set_text(""); + variant_code->set_text(""); + } + _update_tree(); +} + +void EditorLocaleDialog::_post_popup() { + ConfirmationDialog::_post_popup(); + + if (!locale_set) { + lang_code->set_text(""); + script_code->set_text(""); + country_code->set_text(""); + variant_code->set_text(""); + } + edit_filters->set_pressed(false); + _update_tree(); +} + +void EditorLocaleDialog::_filter_lang_option_changed() { + TreeItem *t = lang_list->get_edited(); + String lang = t->get_metadata(0); + bool checked = t->is_checked(0); + + Variant prev; + Array f_lang_all; + + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/language_filter")) { + f_lang_all = ProjectSettings::get_singleton()->get("internationalization/locale/language_filter"); + prev = f_lang_all; + } + + int l_idx = f_lang_all.find(lang); + + if (checked) { + if (l_idx == -1) { + f_lang_all.append(lang); + } + } else { + if (l_idx != -1) { + f_lang_all.remove_at(l_idx); + } + } + + f_lang_all.sort(); + + undo_redo->create_action(TTR("Changed Locale Language Filter")); + undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/language_filter", f_lang_all); + undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/language_filter", prev); + undo_redo->commit_action(); +} + +void EditorLocaleDialog::_filter_script_option_changed() { + TreeItem *t = script_list->get_edited(); + String script = t->get_metadata(0); + bool checked = t->is_checked(0); + + Variant prev; + Array f_script_all; + + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/script_filter")) { + f_script_all = ProjectSettings::get_singleton()->get("internationalization/locale/script_filter"); + prev = f_script_all; + } + + int l_idx = f_script_all.find(script); + + if (checked) { + if (l_idx == -1) { + f_script_all.append(script); + } + } else { + if (l_idx != -1) { + f_script_all.remove_at(l_idx); + } + } + + f_script_all.sort(); + + undo_redo->create_action(TTR("Changed Locale Script Filter")); + undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/script_filter", f_script_all); + undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/script_filter", prev); + undo_redo->commit_action(); +} + +void EditorLocaleDialog::_filter_cnt_option_changed() { + TreeItem *t = cnt_list->get_edited(); + String cnt = t->get_metadata(0); + bool checked = t->is_checked(0); + + Variant prev; + Array f_cnt_all; + + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/country_filter")) { + f_cnt_all = ProjectSettings::get_singleton()->get("internationalization/locale/country_filter"); + prev = f_cnt_all; + } + + int l_idx = f_cnt_all.find(cnt); + + if (checked) { + if (l_idx == -1) { + f_cnt_all.append(cnt); + } + } else { + if (l_idx != -1) { + f_cnt_all.remove_at(l_idx); + } + } + + f_cnt_all.sort(); + + undo_redo->create_action(TTR("Changed Locale Country Filter")); + undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/country_filter", f_cnt_all); + undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/country_filter", prev); + undo_redo->commit_action(); +} + +void EditorLocaleDialog::_filter_mode_changed(int p_mode) { + int f_mode = filter_mode->get_selected_id(); + Variant prev; + + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter_mode")) { + prev = ProjectSettings::get_singleton()->get("internationalization/locale/locale_filter_mode"); + } + + undo_redo->create_action(TTR("Changed Locale Filter Mode")); + undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter_mode", f_mode); + undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter_mode", prev); + undo_redo->commit_action(); + + _update_tree(); +} + +void EditorLocaleDialog::_edit_filters(bool p_checked) { + _update_tree(); +} + +void EditorLocaleDialog::_update_tree() { + updating_lists = true; + + int filter = SHOW_ALL_LOCALES; + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter_mode")) { + filter = ProjectSettings::get_singleton()->get("internationalization/locale/locale_filter_mode"); + } + Array f_lang_all; + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/language_filter")) { + f_lang_all = ProjectSettings::get_singleton()->get("internationalization/locale/language_filter"); + } + Array f_cnt_all; + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/country_filter")) { + f_cnt_all = ProjectSettings::get_singleton()->get("internationalization/locale/country_filter"); + } + Array f_script_all; + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/script_filter")) { + f_script_all = ProjectSettings::get_singleton()->get("internationalization/locale/script_filter"); + } + bool is_edit_mode = edit_filters->is_pressed(); + + filter_mode->select(filter); + + // Hide text advanced edit and disable OK button if in filter edit mode. + advanced->set_visible(!is_edit_mode); + hb_locale->set_visible(!is_edit_mode && advanced->is_pressed()); + vb_script_list->set_visible(advanced->is_pressed()); + get_ok_button()->set_disabled(is_edit_mode); + + // Update language list. + lang_list->clear(); + TreeItem *l_root = lang_list->create_item(nullptr); + lang_list->set_hide_root(true); + + Vector<String> languages = TranslationServer::get_singleton()->get_all_languages(); + for (const String &E : languages) { + if (is_edit_mode || (filter == SHOW_ALL_LOCALES) || f_lang_all.has(E) || f_lang_all.is_empty()) { + const String &lang = TranslationServer::get_singleton()->get_language_name(E); + TreeItem *t = lang_list->create_item(l_root); + if (is_edit_mode) { + t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); + t->set_editable(0, true); + t->set_checked(0, f_lang_all.has(E)); + } else if (lang_code->get_text() == E) { + t->select(0); + } + t->set_text(0, vformat("%s [%s]", lang, E)); + t->set_metadata(0, E); + } + } + + // Update script list. + script_list->clear(); + TreeItem *s_root = script_list->create_item(nullptr); + script_list->set_hide_root(true); + + if (!is_edit_mode) { + TreeItem *t = script_list->create_item(s_root); + t->set_text(0, "[Default]"); + t->set_metadata(0, ""); + } + + Vector<String> scripts = TranslationServer::get_singleton()->get_all_scripts(); + for (const String &E : scripts) { + if (is_edit_mode || (filter == SHOW_ALL_LOCALES) || f_script_all.has(E) || f_script_all.is_empty()) { + const String &script = TranslationServer::get_singleton()->get_script_name(E); + TreeItem *t = script_list->create_item(s_root); + if (is_edit_mode) { + t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); + t->set_editable(0, true); + t->set_checked(0, f_script_all.has(E)); + } else if (script_code->get_text() == E) { + t->select(0); + } + t->set_text(0, vformat("%s [%s]", script, E)); + t->set_metadata(0, E); + } + } + + // Update country list. + cnt_list->clear(); + TreeItem *c_root = cnt_list->create_item(nullptr); + cnt_list->set_hide_root(true); + + if (!is_edit_mode) { + TreeItem *t = cnt_list->create_item(c_root); + t->set_text(0, "[Default]"); + t->set_metadata(0, ""); + } + + Vector<String> countries = TranslationServer::get_singleton()->get_all_countries(); + for (const String &E : countries) { + if (is_edit_mode || (filter == SHOW_ALL_LOCALES) || f_cnt_all.has(E) || f_cnt_all.is_empty()) { + const String &cnt = TranslationServer::get_singleton()->get_country_name(E); + TreeItem *t = cnt_list->create_item(c_root); + if (is_edit_mode) { + t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); + t->set_editable(0, true); + t->set_checked(0, f_cnt_all.has(E)); + } else if (country_code->get_text() == E) { + t->select(0); + } + t->set_text(0, vformat("%s [%s]", cnt, E)); + t->set_metadata(0, E); + } + } + updating_lists = false; +} + +void EditorLocaleDialog::set_locale(const String &p_locale) { + const String &locale = TranslationServer::get_singleton()->standardize_locale(p_locale); + if (locale.is_empty()) { + locale_set = false; + + lang_code->set_text(""); + script_code->set_text(""); + country_code->set_text(""); + variant_code->set_text(""); + } else { + locale_set = true; + + Vector<String> locale_elements = p_locale.split("_"); + lang_code->set_text(locale_elements[0]); + if (locale_elements.size() >= 2) { + if (locale_elements[1].length() == 4 && is_upper_case(locale_elements[1][0]) && is_lower_case(locale_elements[1][1]) && is_lower_case(locale_elements[1][2]) && is_lower_case(locale_elements[1][3])) { + script_code->set_text(locale_elements[1]); + advanced->set_pressed(true); + } + if (locale_elements[1].length() == 2 && is_upper_case(locale_elements[1][0]) && is_upper_case(locale_elements[1][1])) { + country_code->set_text(locale_elements[1]); + } + } + if (locale_elements.size() >= 3) { + if (locale_elements[2].length() == 2 && is_upper_case(locale_elements[2][0]) && is_upper_case(locale_elements[2][1])) { + country_code->set_text(locale_elements[2]); + } else { + variant_code->set_text(locale_elements[2].to_lower()); + advanced->set_pressed(true); + } + } + if (locale_elements.size() >= 4) { + variant_code->set_text(locale_elements[3].to_lower()); + advanced->set_pressed(true); + } + } +} + +void EditorLocaleDialog::popup_locale_dialog() { + popup_centered_clamped(Size2(1050, 700) * EDSCALE, 0.8); +} + +EditorLocaleDialog::EditorLocaleDialog() { + undo_redo = EditorNode::get_undo_redo(); + + set_title(TTR("Select a Locale")); + + VBoxContainer *vb = memnew(VBoxContainer); + { + HBoxContainer *hb_filter = memnew(HBoxContainer); + { + filter_mode = memnew(OptionButton); + filter_mode->add_item(TTR("Show All Locales"), SHOW_ALL_LOCALES); + filter_mode->set_h_size_flags(Control::SIZE_EXPAND_FILL); + filter_mode->add_item(TTR("Show Selected Locales Only"), SHOW_ONLY_SELECTED_LOCALES); + filter_mode->select(0); + filter_mode->connect("item_selected", callable_mp(this, &EditorLocaleDialog::_filter_mode_changed)); + hb_filter->add_child(filter_mode); + } + { + edit_filters = memnew(CheckButton); + edit_filters->set_text("Edit Filters"); + edit_filters->set_toggle_mode(true); + edit_filters->set_pressed(false); + edit_filters->connect("toggled", callable_mp(this, &EditorLocaleDialog::_edit_filters)); + hb_filter->add_child(edit_filters); + } + { + advanced = memnew(CheckButton); + advanced->set_text("Advanced"); + advanced->set_toggle_mode(true); + advanced->set_pressed(false); + advanced->connect("toggled", callable_mp(this, &EditorLocaleDialog::_toggle_advanced)); + hb_filter->add_child(advanced); + } + vb->add_child(hb_filter); + } + { + HBoxContainer *hb_lists = memnew(HBoxContainer); + hb_lists->set_v_size_flags(Control::SIZE_EXPAND_FILL); + { + VBoxContainer *vb_lang_list = memnew(VBoxContainer); + vb_lang_list->set_h_size_flags(Control::SIZE_EXPAND_FILL); + { + Label *lang_lbl = memnew(Label); + lang_lbl->set_text(TTR("Language:")); + vb_lang_list->add_child(lang_lbl); + } + { + lang_list = memnew(Tree); + lang_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); + lang_list->connect("cell_selected", callable_mp(this, &EditorLocaleDialog::_item_selected)); + lang_list->set_columns(1); + lang_list->connect("item_edited", callable_mp(this, &EditorLocaleDialog::_filter_lang_option_changed)); + vb_lang_list->add_child(lang_list); + } + hb_lists->add_child(vb_lang_list); + } + { + vb_script_list = memnew(VBoxContainer); + vb_script_list->set_h_size_flags(Control::SIZE_EXPAND_FILL); + { + Label *script_lbl = memnew(Label); + script_lbl->set_text(TTR("Script:")); + vb_script_list->add_child(script_lbl); + } + { + script_list = memnew(Tree); + script_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); + script_list->connect("cell_selected", callable_mp(this, &EditorLocaleDialog::_item_selected)); + script_list->set_columns(1); + script_list->connect("item_edited", callable_mp(this, &EditorLocaleDialog::_filter_script_option_changed)); + vb_script_list->add_child(script_list); + } + hb_lists->add_child(vb_script_list); + } + { + VBoxContainer *vb_cnt_list = memnew(VBoxContainer); + vb_cnt_list->set_h_size_flags(Control::SIZE_EXPAND_FILL); + { + Label *cnt_lbl = memnew(Label); + cnt_lbl->set_text(TTR("Country:")); + vb_cnt_list->add_child(cnt_lbl); + } + { + cnt_list = memnew(Tree); + cnt_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); + cnt_list->connect("cell_selected", callable_mp(this, &EditorLocaleDialog::_item_selected)); + cnt_list->set_columns(1); + cnt_list->connect("item_edited", callable_mp(this, &EditorLocaleDialog::_filter_cnt_option_changed)); + vb_cnt_list->add_child(cnt_list); + } + hb_lists->add_child(vb_cnt_list); + } + vb->add_child(hb_lists); + } + { + hb_locale = memnew(HBoxContainer); + hb_locale->set_h_size_flags(Control::SIZE_EXPAND_FILL); + { + { + VBoxContainer *vb_language = memnew(VBoxContainer); + vb_language->set_h_size_flags(Control::SIZE_EXPAND_FILL); + { + Label *language_lbl = memnew(Label); + language_lbl->set_text(TTR("Language")); + vb_language->add_child(language_lbl); + } + { + lang_code = memnew(LineEdit); + lang_code->set_max_length(3); + lang_code->set_tooltip("Language"); + vb_language->add_child(lang_code); + } + hb_locale->add_child(vb_language); + } + { + VBoxContainer *vb_script = memnew(VBoxContainer); + vb_script->set_h_size_flags(Control::SIZE_EXPAND_FILL); + { + Label *script_lbl = memnew(Label); + script_lbl->set_text(TTR("Script")); + vb_script->add_child(script_lbl); + } + { + script_code = memnew(LineEdit); + script_code->set_max_length(4); + script_code->set_tooltip("Script"); + vb_script->add_child(script_code); + } + hb_locale->add_child(vb_script); + } + { + VBoxContainer *vb_country = memnew(VBoxContainer); + vb_country->set_h_size_flags(Control::SIZE_EXPAND_FILL); + { + Label *country_lbl = memnew(Label); + country_lbl->set_text(TTR("Country")); + vb_country->add_child(country_lbl); + } + { + country_code = memnew(LineEdit); + country_code->set_max_length(2); + country_code->set_tooltip("Country"); + vb_country->add_child(country_code); + } + hb_locale->add_child(vb_country); + } + { + VBoxContainer *vb_variant = memnew(VBoxContainer); + vb_variant->set_h_size_flags(Control::SIZE_EXPAND_FILL); + { + Label *variant_lbl = memnew(Label); + variant_lbl->set_text(TTR("Variant")); + vb_variant->add_child(variant_lbl); + } + { + variant_code = memnew(LineEdit); + variant_code->set_h_size_flags(Control::SIZE_EXPAND_FILL); + variant_code->set_placeholder("Variant"); + variant_code->set_tooltip("Variant"); + vb_variant->add_child(variant_code); + } + hb_locale->add_child(vb_variant); + } + } + vb->add_child(hb_locale); + } + add_child(vb); + _update_tree(); + + get_ok_button()->set_text(TTR("Select")); +} diff --git a/editor/editor_locale_dialog.h b/editor/editor_locale_dialog.h new file mode 100644 index 0000000000..7a4828e83a --- /dev/null +++ b/editor/editor_locale_dialog.h @@ -0,0 +1,93 @@ +/*************************************************************************/ +/* editor_locale_dialog.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef EDITOR_LOCALE_DIALOG_H +#define EDITOR_LOCALE_DIALOG_H + +#include "core/string/translation.h" +#include "scene/gui/dialogs.h" + +class Button; +class HBoxContainer; +class VBoxContainer; +class LineEdit; +class Tree; +class OptionButton; +class UndoRedo; + +class EditorLocaleDialog : public ConfirmationDialog { + GDCLASS(EditorLocaleDialog, ConfirmationDialog); + + enum LocaleFilter { + SHOW_ALL_LOCALES, + SHOW_ONLY_SELECTED_LOCALES, + }; + + HBoxContainer *hb_locale = nullptr; + VBoxContainer *vb_script_list = nullptr; + OptionButton *filter_mode = nullptr; + Button *edit_filters = nullptr; + Button *advanced = nullptr; + LineEdit *lang_code = nullptr; + LineEdit *script_code = nullptr; + LineEdit *country_code = nullptr; + LineEdit *variant_code = nullptr; + Tree *lang_list = nullptr; + Tree *script_list = nullptr; + Tree *cnt_list = nullptr; + + UndoRedo *undo_redo = nullptr; + + bool locale_set = false; + bool updating_lists = false; + +protected: + static void _bind_methods(); + virtual void _post_popup() override; + virtual void ok_pressed() override; + + void _item_selected(); + void _filter_lang_option_changed(); + void _filter_script_option_changed(); + void _filter_cnt_option_changed(); + void _filter_mode_changed(int p_mode); + void _edit_filters(bool p_checked); + void _toggle_advanced(bool p_checked); + + void _update_tree(); + +public: + EditorLocaleDialog(); + + void set_locale(const String &p_locale); + void popup_locale_dialog(); +}; + +#endif // EDITOR_LOCALE_DIALOG_H diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 11efe7202e..a1f259c864 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -429,7 +429,7 @@ void EditorNode::unhandled_input(const Ref<InputEvent> &p_event) { _scene_tab_changed(next_tab); } if (ED_IS_SHORTCUT("editor/filter_files", p_event)) { - filesystem_dock->focus_on_filter(); + FileSystemDock::get_singleton()->focus_on_filter(); } if (ED_IS_SHORTCUT("editor/editor_2d", p_event)) { @@ -957,9 +957,10 @@ void EditorNode::_fs_changed() { if (!export_error.is_empty()) { ERR_PRINT(export_error); - OS::get_singleton()->set_exit_code(EXIT_FAILURE); + _exit_editor(EXIT_FAILURE); + } else { + _exit_editor(EXIT_SUCCESS); } - _exit_editor(); } } @@ -1099,8 +1100,8 @@ void EditorNode::_version_button_pressed() { } void EditorNode::_node_renamed() { - if (get_inspector()) { - get_inspector()->update_tree(); + if (InspectorDock::get_inspector_singleton()) { + InspectorDock::get_inspector_singleton()->update_tree(); } } @@ -1161,7 +1162,7 @@ Error EditorNode::load_resource(const String &p_resource, bool p_ignore_broken_d return ERR_FILE_MISSING_DEPENDENCIES; } - inspector_dock->edit_resource(res); + InspectorDock::get_singleton()->edit_resource(res); return OK; } @@ -1775,7 +1776,7 @@ void EditorNode::restart_editor() { to_reopen = get_tree()->get_edited_scene_root()->get_scene_file_path(); } - _exit_editor(); + _exit_editor(EXIT_SUCCESS); List<String> args; args.push_back("--path"); @@ -2069,10 +2070,10 @@ void EditorNode::edit_item(Object *p_object) { void EditorNode::push_item(Object *p_object, const String &p_property, bool p_inspector_only) { if (!p_object) { - get_inspector()->edit(nullptr); - node_dock->set_node(nullptr); - scene_tree_dock->set_selected(nullptr); - inspector_dock->update(nullptr); + InspectorDock::get_inspector_singleton()->edit(nullptr); + NodeDock::get_singleton()->set_node(nullptr); + SceneTreeDock::get_singleton()->set_selected(nullptr); + InspectorDock::get_singleton()->update(nullptr); _display_top_editors(false); return; } @@ -2145,17 +2146,17 @@ void EditorNode::_edit_current(bool p_skip_foreign) { this->current = current_obj; if (!current_obj) { - scene_tree_dock->set_selected(nullptr); - get_inspector()->edit(nullptr); - node_dock->set_node(nullptr); - inspector_dock->update(nullptr); + SceneTreeDock::get_singleton()->set_selected(nullptr); + InspectorDock::get_inspector_singleton()->edit(nullptr); + NodeDock::get_singleton()->set_node(nullptr); + InspectorDock::get_singleton()->update(nullptr); _display_top_editors(false); return; } - Object *prev_inspected_object = get_inspector()->get_edited_object(); + Object *prev_inspected_object = InspectorDock::get_inspector_singleton()->get_edited_object(); bool disable_folding = bool(EDITOR_GET("interface/inspector/disable_folding")); bool is_resource = current_obj->is_class("Resource"); @@ -2166,11 +2167,11 @@ void EditorNode::_edit_current(bool p_skip_foreign) { if (is_resource) { Resource *current_res = Object::cast_to<Resource>(current_obj); ERR_FAIL_COND(!current_res); - get_inspector()->edit(current_res); - scene_tree_dock->set_selected(nullptr); - node_dock->set_node(nullptr); - inspector_dock->update(nullptr); - EditorNode::get_singleton()->get_import_dock()->set_edit_path(current_res->get_path()); + InspectorDock::get_inspector_singleton()->edit(current_res); + SceneTreeDock::get_singleton()->set_selected(nullptr); + NodeDock::get_singleton()->set_node(nullptr); + InspectorDock::get_singleton()->update(nullptr); + ImportDock::get_singleton()->set_edit_path(current_res->get_path()); int subr_idx = current_res->get_path().find("::"); if (subr_idx != -1) { @@ -2191,15 +2192,15 @@ void EditorNode::_edit_current(bool p_skip_foreign) { Node *current_node = Object::cast_to<Node>(current_obj); ERR_FAIL_COND(!current_node); - get_inspector()->edit(current_node); + InspectorDock::get_inspector_singleton()->edit(current_node); if (current_node->is_inside_tree()) { - node_dock->set_node(current_node); - scene_tree_dock->set_selected(current_node); - inspector_dock->update(current_node); + NodeDock::get_singleton()->set_node(current_node); + SceneTreeDock::get_singleton()->set_selected(current_node); + InspectorDock::get_singleton()->update(current_node); } else { - node_dock->set_node(nullptr); - scene_tree_dock->set_selected(nullptr); - inspector_dock->update(nullptr); + NodeDock::get_singleton()->set_node(nullptr); + SceneTreeDock::get_singleton()->set_selected(nullptr); + InspectorDock::get_singleton()->update(nullptr); } if (get_edited_scene() && !get_edited_scene()->get_scene_file_path().is_empty()) { @@ -2237,21 +2238,21 @@ void EditorNode::_edit_current(bool p_skip_foreign) { } } - get_inspector()->edit(current_obj); - node_dock->set_node(nullptr); - scene_tree_dock->set_selected(selected_node); - inspector_dock->update(nullptr); + InspectorDock::get_inspector_singleton()->edit(current_obj); + NodeDock::get_singleton()->set_node(nullptr); + SceneTreeDock::get_singleton()->set_selected(selected_node); + InspectorDock::get_singleton()->update(nullptr); } if (current_obj == prev_inspected_object) { // Make sure inspected properties are restored. - get_inspector()->update_tree(); + InspectorDock::get_inspector_singleton()->update_tree(); } - inspector_dock->set_warning(editable_warning); + InspectorDock::get_singleton()->set_warning(editable_warning); - if (get_inspector()->is_using_folding() == disable_folding) { - get_inspector()->set_use_folding(!disable_folding); + if (InspectorDock::get_inspector_singleton()->is_using_folding() == disable_folding) { + InspectorDock::get_inspector_singleton()->set_use_folding(!disable_folding); } /* Take care of PLUGIN EDITOR */ @@ -2305,8 +2306,7 @@ void EditorNode::_edit_current(bool p_skip_foreign) { } } - inspector_dock->update(current_obj); - inspector_dock->update_keying(); + InspectorDock::get_singleton()->update(current_obj); } void EditorNode::_run(bool p_current, const String &p_custom) { @@ -2764,7 +2764,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { case FILE_SHOW_IN_FILESYSTEM: { String path = editor_data.get_scene_path(editor_data.get_edited_scene()); if (!path.is_empty()) { - filesystem_dock->navigate_to_path(path); + FileSystemDock::get_singleton()->navigate_to_path(path); } } break; @@ -3000,7 +3000,7 @@ int EditorNode::_next_unsaved_scene(bool p_valid_filename, int p_start) { return -1; } -void EditorNode::_exit_editor() { +void EditorNode::_exit_editor(int p_exit_code) { exiting = true; resource_preview->stop(); // stop early to avoid crashes _save_docks(); @@ -3008,7 +3008,7 @@ void EditorNode::_exit_editor() { // Dim the editor window while it's quitting to make it clearer that it's busy dim_editor(true); - get_tree()->quit(); + get_tree()->quit(p_exit_code); } void EditorNode::_discard_changes(const String &p_str) { @@ -3058,12 +3058,12 @@ void EditorNode::_discard_changes(const String &p_str) { } break; case FILE_QUIT: { _menu_option_confirm(RUN_STOP, true); - _exit_editor(); + _exit_editor(EXIT_SUCCESS); } break; case RUN_PROJECT_MANAGER: { _menu_option_confirm(RUN_STOP, true); - _exit_editor(); + _exit_editor(EXIT_SUCCESS); String exec = OS::get_singleton()->get_executable_path(); List<String> args; @@ -3361,7 +3361,7 @@ void EditorNode::set_edited_scene(Node *p_scene) { if (Object::cast_to<Popup>(p_scene)) { Object::cast_to<Popup>(p_scene)->show(); // show popups } - scene_tree_dock->set_edited_scene(p_scene); + SceneTreeDock::get_singleton()->set_edited_scene(p_scene); if (get_tree()) { get_tree()->set_edited_scene_root(p_scene); } @@ -3386,10 +3386,10 @@ int EditorNode::_get_current_main_editor() { Dictionary EditorNode::_get_main_scene_state() { Dictionary state; state["main_tab"] = _get_current_main_editor(); - state["scene_tree_offset"] = scene_tree_dock->get_tree_editor()->get_scene_tree()->get_vscroll_bar()->get_value(); - state["property_edit_offset"] = get_inspector()->get_scroll_offset(); + state["scene_tree_offset"] = SceneTreeDock::get_singleton()->get_tree_editor()->get_scene_tree()->get_vscroll_bar()->get_value(); + state["property_edit_offset"] = InspectorDock::get_inspector_singleton()->get_scroll_offset(); state["saved_version"] = saved_version; - state["node_filter"] = scene_tree_dock->get_filter(); + state["node_filter"] = SceneTreeDock::get_singleton()->get_filter(); return state; } @@ -3431,14 +3431,14 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) { } if (p_state.has("scene_tree_offset")) { - scene_tree_dock->get_tree_editor()->get_scene_tree()->get_vscroll_bar()->set_value(p_state["scene_tree_offset"]); + SceneTreeDock::get_singleton()->get_tree_editor()->get_scene_tree()->get_vscroll_bar()->set_value(p_state["scene_tree_offset"]); } if (p_state.has("property_edit_offset")) { - get_inspector()->set_scroll_offset(p_state["property_edit_offset"]); + InspectorDock::get_inspector_singleton()->set_scroll_offset(p_state["property_edit_offset"]); } if (p_state.has("node_filter")) { - scene_tree_dock->set_filter(p_state["node_filter"]); + SceneTreeDock::get_singleton()->set_filter(p_state["node_filter"]); } // this should only happen at the very end @@ -3493,7 +3493,7 @@ void EditorNode::set_current_scene(int p_idx) { Object::cast_to<Popup>(new_scene)->show(); // show popups } - scene_tree_dock->set_edited_scene(new_scene); + SceneTreeDock::get_singleton()->set_edited_scene(new_scene); if (get_tree()) { get_tree()->set_edited_scene_root(new_scene); } @@ -3673,7 +3673,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b prev_scene->set_disabled(previous_scenes.size() == 0); opening_prev = false; - scene_tree_dock->set_selected(new_scene); + SceneTreeDock::get_singleton()->set_selected(new_scene); EditorDebuggerNode::get_singleton()->update_live_edit_root(); @@ -3698,27 +3698,11 @@ void EditorNode::open_request(const String &p_path) { } void EditorNode::request_instance_scene(const String &p_path) { - scene_tree_dock->instantiate(p_path); + SceneTreeDock::get_singleton()->instantiate(p_path); } void EditorNode::request_instantiate_scenes(const Vector<String> &p_files) { - scene_tree_dock->instantiate_scenes(p_files); -} - -ImportDock *EditorNode::get_import_dock() { - return import_dock; -} - -FileSystemDock *EditorNode::get_filesystem_dock() { - return filesystem_dock; -} - -SceneTreeDock *EditorNode::get_scene_tree_dock() { - return scene_tree_dock; -} - -InspectorDock *EditorNode::get_inspector_dock() { - return inspector_dock; + SceneTreeDock::get_singleton()->instantiate_scenes(p_files); } void EditorNode::_inherit_request(String p_file) { @@ -4514,10 +4498,10 @@ void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String &p } } - p_layout->set_value(p_section, "dock_filesystem_split", filesystem_dock->get_split_offset()); - p_layout->set_value(p_section, "dock_filesystem_display_mode", filesystem_dock->get_display_mode()); - p_layout->set_value(p_section, "dock_filesystem_file_sort", filesystem_dock->get_file_sort()); - p_layout->set_value(p_section, "dock_filesystem_file_list_display_mode", filesystem_dock->get_file_list_display_mode()); + p_layout->set_value(p_section, "dock_filesystem_split", FileSystemDock::get_singleton()->get_split_offset()); + p_layout->set_value(p_section, "dock_filesystem_display_mode", FileSystemDock::get_singleton()->get_display_mode()); + p_layout->set_value(p_section, "dock_filesystem_file_sort", FileSystemDock::get_singleton()->get_file_sort()); + p_layout->set_value(p_section, "dock_filesystem_file_list_display_mode", FileSystemDock::get_singleton()->get_file_list_display_mode()); for (int i = 0; i < vsplits.size(); i++) { if (vsplits[i]->is_visible_in_tree()) { @@ -4703,22 +4687,22 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String if (p_layout->has_section_key(p_section, "dock_filesystem_split")) { int fs_split_ofs = p_layout->get_value(p_section, "dock_filesystem_split"); - filesystem_dock->set_split_offset(fs_split_ofs); + FileSystemDock::get_singleton()->set_split_offset(fs_split_ofs); } if (p_layout->has_section_key(p_section, "dock_filesystem_display_mode")) { FileSystemDock::DisplayMode dock_filesystem_display_mode = FileSystemDock::DisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_display_mode"))); - filesystem_dock->set_display_mode(dock_filesystem_display_mode); + FileSystemDock::get_singleton()->set_display_mode(dock_filesystem_display_mode); } if (p_layout->has_section_key(p_section, "dock_filesystem_file_sort")) { FileSystemDock::FileSortOption dock_filesystem_file_sort = FileSystemDock::FileSortOption(int(p_layout->get_value(p_section, "dock_filesystem_file_sort"))); - filesystem_dock->set_file_sort(dock_filesystem_file_sort); + FileSystemDock::get_singleton()->set_file_sort(dock_filesystem_file_sort); } if (p_layout->has_section_key(p_section, "dock_filesystem_file_list_display_mode")) { FileSystemDock::FileListDisplayMode dock_filesystem_file_list_display_mode = FileSystemDock::FileListDisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_file_list_display_mode"))); - filesystem_dock->set_file_list_display_mode(dock_filesystem_file_list_display_mode); + FileSystemDock::get_singleton()->set_file_list_display_mode(dock_filesystem_file_list_display_mode); } for (int i = 0; i < vsplits.size(); i++) { @@ -4972,7 +4956,7 @@ void EditorNode::_layout_menu_option(int p_id) { void EditorNode::_scene_tab_script_edited(int p_tab) { Ref<Script> script = editor_data.get_scene_root_script(p_tab); if (script.is_valid()) { - inspector_dock->edit_resource(script); + InspectorDock::get_singleton()->edit_resource(script); } } @@ -5437,7 +5421,7 @@ void EditorNode::_global_menu_new_window(const Variant &p_tag) { } void EditorNode::_dropped_files(const Vector<String> &p_files, int p_screen) { - String to_path = ProjectSettings::get_singleton()->globalize_path(get_filesystem_dock()->get_selected_path()); + String to_path = ProjectSettings::get_singleton()->globalize_path(FileSystemDock::get_singleton()->get_selected_path()); _add_dropped_files_recursive(p_files, to_path); @@ -5643,15 +5627,15 @@ void EditorNode::_resource_loaded(RES p_resource, const String &p_path) { void EditorNode::_feature_profile_changed() { Ref<EditorFeatureProfile> profile = feature_profile_manager->get_current_profile(); - TabContainer *import_tabs = cast_to<TabContainer>(import_dock->get_parent()); - TabContainer *node_tabs = cast_to<TabContainer>(node_dock->get_parent()); - TabContainer *fs_tabs = cast_to<TabContainer>(filesystem_dock->get_parent()); + TabContainer *import_tabs = cast_to<TabContainer>(ImportDock::get_singleton()->get_parent()); + TabContainer *node_tabs = cast_to<TabContainer>(NodeDock::get_singleton()->get_parent()); + TabContainer *fs_tabs = cast_to<TabContainer>(FileSystemDock::get_singleton()->get_parent()); if (profile.is_valid()) { - node_tabs->set_tab_hidden(node_dock->get_index(), profile->is_feature_disabled(EditorFeatureProfile::FEATURE_NODE_DOCK)); + node_tabs->set_tab_hidden(NodeDock::get_singleton()->get_index(), profile->is_feature_disabled(EditorFeatureProfile::FEATURE_NODE_DOCK)); // The Import dock is useless without the FileSystem dock. Ensure the configuration is valid. bool fs_dock_disabled = profile->is_feature_disabled(EditorFeatureProfile::FEATURE_FILESYSTEM_DOCK); - fs_tabs->set_tab_hidden(filesystem_dock->get_index(), fs_dock_disabled); - import_tabs->set_tab_hidden(import_dock->get_index(), fs_dock_disabled || profile->is_feature_disabled(EditorFeatureProfile::FEATURE_IMPORT_DOCK)); + fs_tabs->set_tab_hidden(FileSystemDock::get_singleton()->get_index(), fs_dock_disabled); + import_tabs->set_tab_hidden(ImportDock::get_singleton()->get_index(), fs_dock_disabled || profile->is_feature_disabled(EditorFeatureProfile::FEATURE_IMPORT_DOCK)); main_editor_buttons[EDITOR_3D]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D)); main_editor_buttons[EDITOR_SCRIPT]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCRIPT)); @@ -5664,12 +5648,12 @@ void EditorNode::_feature_profile_changed() { _editor_select(EDITOR_2D); } } else { - import_tabs->set_tab_hidden(import_dock->get_index(), false); - node_tabs->set_tab_hidden(node_dock->get_index(), false); - fs_tabs->set_tab_hidden(filesystem_dock->get_index(), false); - import_dock->set_visible(true); - node_dock->set_visible(true); - filesystem_dock->set_visible(true); + import_tabs->set_tab_hidden(ImportDock::get_singleton()->get_index(), false); + node_tabs->set_tab_hidden(NodeDock::get_singleton()->get_index(), false); + fs_tabs->set_tab_hidden(FileSystemDock::get_singleton()->get_index(), false); + ImportDock::get_singleton()->set_visible(true); + NodeDock::get_singleton()->set_visible(true); + FileSystemDock::get_singleton()->set_visible(true); main_editor_buttons[EDITOR_3D]->set_visible(true); main_editor_buttons[EDITOR_SCRIPT]->set_visible(true); if (StreamPeerSSL::is_available()) { @@ -5697,8 +5681,6 @@ void EditorNode::_bind_methods() { ClassDB::bind_method("stop_child_process", &EditorNode::stop_child_process); - ClassDB::bind_method("get_script_create_dialog", &EditorNode::get_script_create_dialog); - ClassDB::bind_method("set_current_scene", &EditorNode::set_current_scene); ClassDB::bind_method("set_current_version", &EditorNode::set_current_version); ClassDB::bind_method("_thumbnail_done", &EditorNode::_thumbnail_done); @@ -6043,11 +6025,8 @@ EditorNode::EditorNode() { EDITOR_DEF("interface/inspector/default_color_picker_shape", (int32_t)ColorPicker::SHAPE_VHS_CIRCLE); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_shape", PROPERTY_HINT_ENUM, "HSV Rectangle,HSV Rectangle Wheel,VHS Circle", PROPERTY_USAGE_DEFAULT)); EDITOR_DEF("run/auto_save/save_before_running", true); - EDITOR_DEF("interface/editors/sub_editor_panning_scheme", 0); - EDITOR_DEF("interface/editors/animation_editors_panning_scheme", 1); - // Should be in sync with ControlScheme in ViewPanner. - EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/editors/sub_editor_panning_scheme", PROPERTY_HINT_ENUM, "Scroll Zooms,Scroll Pans", PROPERTY_USAGE_DEFAULT)); - EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/editors/animation_editors_panning_scheme", PROPERTY_HINT_ENUM, "Scroll Zooms,Scroll Pans", PROPERTY_USAGE_DEFAULT)); + + ED_SHORTCUT("canvas_item_editor/pan_view", TTR("Pan View"), Key::SPACE); const Vector<String> textfile_ext = ((String)(EditorSettings::get_singleton()->get("docks/filesystem/textfile_extensions"))).split(",", false); for (const String &E : textfile_ext) { @@ -6701,35 +6680,35 @@ EditorNode::EditorNode() { // Instantiate and place editor docks - scene_tree_dock = memnew(SceneTreeDock(this, scene_root, editor_selection, editor_data)); - inspector_dock = memnew(InspectorDock(this, editor_data)); - import_dock = memnew(ImportDock); - node_dock = memnew(NodeDock); + memnew(SceneTreeDock(this, scene_root, editor_selection, editor_data)); + memnew(InspectorDock(this, editor_data)); + memnew(ImportDock); + memnew(NodeDock); - filesystem_dock = memnew(FileSystemDock(this)); + FileSystemDock *filesystem_dock = memnew(FileSystemDock(this)); filesystem_dock->connect("inherit", callable_mp(this, &EditorNode::_inherit_request)); filesystem_dock->connect("instance", callable_mp(this, &EditorNode::_instantiate_request)); filesystem_dock->connect("display_mode_changed", callable_mp(this, &EditorNode::_save_docks)); // Scene: Top left - dock_slot[DOCK_SLOT_LEFT_UR]->add_child(scene_tree_dock); - dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(scene_tree_dock->get_index(), TTR("Scene")); + dock_slot[DOCK_SLOT_LEFT_UR]->add_child(SceneTreeDock::get_singleton()); + dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(SceneTreeDock::get_singleton()->get_index(), TTR("Scene")); // Import: Top left, behind Scene - dock_slot[DOCK_SLOT_LEFT_UR]->add_child(import_dock); - dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(import_dock->get_index(), TTR("Import")); + dock_slot[DOCK_SLOT_LEFT_UR]->add_child(ImportDock::get_singleton()); + dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(ImportDock::get_singleton()->get_index(), TTR("Import")); // FileSystem: Bottom left - dock_slot[DOCK_SLOT_LEFT_BR]->add_child(filesystem_dock); - dock_slot[DOCK_SLOT_LEFT_BR]->set_tab_title(filesystem_dock->get_index(), TTR("FileSystem")); + dock_slot[DOCK_SLOT_LEFT_BR]->add_child(FileSystemDock::get_singleton()); + dock_slot[DOCK_SLOT_LEFT_BR]->set_tab_title(FileSystemDock::get_singleton()->get_index(), TTR("FileSystem")); // Inspector: Full height right - dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(inspector_dock); - dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(inspector_dock->get_index(), TTR("Inspector")); + dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(InspectorDock::get_singleton()); + dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(InspectorDock::get_singleton()->get_index(), TTR("Inspector")); // Node: Full height right, behind Inspector - dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(node_dock); - dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(node_dock->get_index(), TTR("Node")); + dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(NodeDock::get_singleton()); + dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(NodeDock::get_singleton()->get_index(), TTR("Node")); // Hide unused dock slots and vsplits dock_slot[DOCK_SLOT_LEFT_UL]->hide(); @@ -7173,7 +7152,7 @@ EditorNode::EditorNode() { editor_data.set_edited_scene(0); _update_scene_tabs(); - import_dock->initialize_import_options(); + ImportDock::get_singleton()->initialize_import_options(); FileAccess::set_file_close_fail_notify_callback(_file_access_close_error_notify); diff --git a/editor/editor_node.h b/editor/editor_node.h index 7f5d23dbde..f8489777bd 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -302,11 +302,6 @@ private: Ref<Theme> theme; PopupMenu *recent_scenes; - SceneTreeDock *scene_tree_dock; - InspectorDock *inspector_dock; - NodeDock *node_dock; - ImportDock *import_dock; - FileSystemDock *filesystem_dock; EditorRunNative *run_native; ConfirmationDialog *confirmation; @@ -535,7 +530,7 @@ private: void _add_dropped_files_recursive(const Vector<String> &p_files, String to_path); String _recent_scene; - void _exit_editor(); + void _exit_editor(int p_exit_code); bool convert_old; @@ -717,9 +712,6 @@ public: EditorPluginList *get_editor_plugins_over() { return editor_plugins_over; } EditorPluginList *get_editor_plugins_force_over() { return editor_plugins_force_over; } EditorPluginList *get_editor_plugins_force_input_forwarding() { return editor_plugins_force_input_forwarding; } - EditorInspector *get_inspector() { return inspector_dock->get_inspector(); } - Container *get_inspector_dock_addon_area() { return inspector_dock->get_addon_area(); } - ScriptCreateDialog *get_script_create_dialog() { return scene_tree_dock->get_script_create_dialog(); } ProjectSettingsEditor *get_project_settings() { return project_settings; } @@ -743,8 +735,7 @@ public: bool is_addon_plugin_enabled(const String &p_addon) const; void edit_node(Node *p_node); - void edit_resource(const Ref<Resource> &p_resource) { inspector_dock->edit_resource(p_resource); }; - void open_resource(const String &p_type) { inspector_dock->open_resource(p_type); }; + void edit_resource(const Ref<Resource> &p_resource) { InspectorDock::get_singleton()->edit_resource(p_resource); }; void save_resource_in_path(const Ref<Resource> &p_resource, const String &p_path); void save_resource(const Ref<Resource> &p_resource); @@ -795,10 +786,6 @@ public: void request_instance_scene(const String &p_path); void request_instantiate_scenes(const Vector<String> &p_files); - FileSystemDock *get_filesystem_dock(); - ImportDock *get_import_dock(); - SceneTreeDock *get_scene_tree_dock(); - InspectorDock *get_inspector_dock(); static UndoRedo *get_undo_redo() { return &singleton->editor_data.get_undo_redo(); } EditorSelection *get_editor_selection() { return editor_selection; } @@ -884,7 +871,6 @@ public: void edit_current() { _edit_current(); }; - void update_keying() const { inspector_dock->update_keying(); }; bool has_scenes_in_session(); int execute_and_show_output(const String &p_title, const String &p_path, const List<String> &p_arguments, bool p_close_on_ok = true, bool p_close_on_errors = false); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index aeca340cb1..29f6079fcf 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -233,15 +233,15 @@ ScriptEditor *EditorInterface::get_script_editor() { } void EditorInterface::select_file(const String &p_file) { - EditorNode::get_singleton()->get_filesystem_dock()->select_file(p_file); + FileSystemDock::get_singleton()->select_file(p_file); } String EditorInterface::get_selected_path() const { - return EditorNode::get_singleton()->get_filesystem_dock()->get_selected_path(); + return FileSystemDock::get_singleton()->get_selected_path(); } String EditorInterface::get_current_path() const { - return EditorNode::get_singleton()->get_filesystem_dock()->get_current_path(); + return FileSystemDock::get_singleton()->get_current_path(); } void EditorInterface::inspect_object(Object *p_obj, const String &p_for_property, bool p_inspector_only) { @@ -253,7 +253,7 @@ EditorFileSystem *EditorInterface::get_resource_file_system() { } FileSystemDock *EditorInterface::get_file_system_dock() { - return EditorNode::get_singleton()->get_filesystem_dock(); + return FileSystemDock::get_singleton(); } EditorSelection *EditorInterface::get_selection() { @@ -288,7 +288,7 @@ bool EditorInterface::is_plugin_enabled(const String &p_plugin) const { } EditorInspector *EditorInterface::get_inspector() const { - return EditorNode::get_singleton()->get_inspector(); + return InspectorDock::get_inspector_singleton(); } Error EditorInterface::save_scene() { @@ -421,14 +421,10 @@ void EditorPlugin::add_control_to_container(CustomControlContainer p_location, C } break; case CONTAINER_SPATIAL_EDITOR_SIDE_LEFT: { - Node3DEditor::get_singleton()->get_palette_split()->add_child(p_control); - Node3DEditor::get_singleton()->get_palette_split()->move_child(p_control, 0); - + Node3DEditor::get_singleton()->add_control_to_left_panel(p_control); } break; case CONTAINER_SPATIAL_EDITOR_SIDE_RIGHT: { - Node3DEditor::get_singleton()->get_palette_split()->add_child(p_control); - Node3DEditor::get_singleton()->get_palette_split()->move_child(p_control, 1); - + Node3DEditor::get_singleton()->add_control_to_right_panel(p_control); } break; case CONTAINER_SPATIAL_EDITOR_BOTTOM: { Node3DEditor::get_singleton()->get_shader_split()->add_child(p_control); @@ -439,21 +435,17 @@ void EditorPlugin::add_control_to_container(CustomControlContainer p_location, C } break; case CONTAINER_CANVAS_EDITOR_SIDE_LEFT: { - CanvasItemEditor::get_singleton()->get_palette_split()->add_child(p_control); - CanvasItemEditor::get_singleton()->get_palette_split()->move_child(p_control, 0); - + CanvasItemEditor::get_singleton()->add_control_to_left_panel(p_control); } break; case CONTAINER_CANVAS_EDITOR_SIDE_RIGHT: { - CanvasItemEditor::get_singleton()->get_palette_split()->add_child(p_control); - CanvasItemEditor::get_singleton()->get_palette_split()->move_child(p_control, 1); - + CanvasItemEditor::get_singleton()->add_control_to_right_panel(p_control); } break; case CONTAINER_CANVAS_EDITOR_BOTTOM: { CanvasItemEditor::get_singleton()->get_bottom_split()->add_child(p_control); } break; case CONTAINER_PROPERTY_EDITOR_BOTTOM: { - EditorNode::get_singleton()->get_inspector_dock_addon_area()->add_child(p_control); + InspectorDock::get_singleton()->get_addon_area()->add_child(p_control); } break; case CONTAINER_PROJECT_SETTING_TAB_LEFT: { @@ -481,10 +473,11 @@ void EditorPlugin::remove_control_from_container(CustomControlContainer p_locati Node3DEditor::get_singleton()->remove_control_from_menu_panel(p_control); } break; - case CONTAINER_SPATIAL_EDITOR_SIDE_LEFT: + case CONTAINER_SPATIAL_EDITOR_SIDE_LEFT: { + Node3DEditor::get_singleton()->remove_control_from_left_panel(p_control); + } break; case CONTAINER_SPATIAL_EDITOR_SIDE_RIGHT: { - Node3DEditor::get_singleton()->get_palette_split()->remove_child(p_control); - + Node3DEditor::get_singleton()->remove_control_from_right_panel(p_control); } break; case CONTAINER_SPATIAL_EDITOR_BOTTOM: { Node3DEditor::get_singleton()->get_shader_split()->remove_child(p_control); @@ -494,17 +487,18 @@ void EditorPlugin::remove_control_from_container(CustomControlContainer p_locati CanvasItemEditor::get_singleton()->remove_control_from_menu_panel(p_control); } break; - case CONTAINER_CANVAS_EDITOR_SIDE_LEFT: + case CONTAINER_CANVAS_EDITOR_SIDE_LEFT: { + CanvasItemEditor::get_singleton()->remove_control_from_left_panel(p_control); + } break; case CONTAINER_CANVAS_EDITOR_SIDE_RIGHT: { - CanvasItemEditor::get_singleton()->get_palette_split()->remove_child(p_control); - + CanvasItemEditor::get_singleton()->remove_control_from_right_panel(p_control); } break; case CONTAINER_CANVAS_EDITOR_BOTTOM: { CanvasItemEditor::get_singleton()->get_bottom_split()->remove_child(p_control); } break; case CONTAINER_PROPERTY_EDITOR_BOTTOM: { - EditorNode::get_singleton()->get_inspector_dock_addon_area()->remove_child(p_control); + InspectorDock::get_singleton()->get_addon_area()->remove_child(p_control); } break; case CONTAINER_PROJECT_SETTING_TAB_LEFT: @@ -839,7 +833,7 @@ EditorInterface *EditorPlugin::get_editor_interface() { } ScriptCreateDialog *EditorPlugin::get_script_create_dialog() { - return EditorNode::get_singleton()->get_script_create_dialog(); + return SceneTreeDock::get_singleton()->get_script_create_dialog(); } void EditorPlugin::add_debugger_plugin(const Ref<Script> &p_script) { diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 97a38b9200..6bb4b5e81b 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -343,6 +343,64 @@ EditorPropertyTextEnum::EditorPropertyTextEnum() { add_focusable(cancel_button); } +//////////////////// LOCALE //////////////////////// + +void EditorPropertyLocale::_locale_selected(const String &p_locale) { + emit_changed(get_edited_property(), p_locale); + update_property(); +} + +void EditorPropertyLocale::_locale_pressed() { + if (!dialog) { + dialog = memnew(EditorLocaleDialog); + dialog->connect("locale_selected", callable_mp(this, &EditorPropertyLocale::_locale_selected)); + add_child(dialog); + } + + String locale_code = get_edited_object()->get(get_edited_property()); + dialog->set_locale(locale_code); + dialog->popup_locale_dialog(); +} + +void EditorPropertyLocale::update_property() { + String locale_code = get_edited_object()->get(get_edited_property()); + locale->set_text(locale_code); + locale->set_tooltip(locale_code); +} + +void EditorPropertyLocale::setup(const String &p_hint_text) { +} + +void EditorPropertyLocale::_notification(int p_what) { + if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { + locale_edit->set_icon(get_theme_icon(SNAME("Translation"), SNAME("EditorIcons"))); + } +} + +void EditorPropertyLocale::_locale_focus_exited() { + _locale_selected(locale->get_text()); +} + +void EditorPropertyLocale::_bind_methods() { +} + +EditorPropertyLocale::EditorPropertyLocale() { + HBoxContainer *locale_hb = memnew(HBoxContainer); + add_child(locale_hb); + locale = memnew(LineEdit); + locale_hb->add_child(locale); + locale->connect("text_submitted", callable_mp(this, &EditorPropertyLocale::_locale_selected)); + locale->connect("focus_exited", callable_mp(this, &EditorPropertyLocale::_locale_focus_exited)); + locale->set_h_size_flags(SIZE_EXPAND_FILL); + + locale_edit = memnew(Button); + locale_edit->set_clip_text(true); + locale_hb->add_child(locale_edit); + add_focusable(locale); + dialog = nullptr; + locale_edit->connect("pressed", callable_mp(this, &EditorPropertyLocale::_locale_pressed)); +} + ///////////////////// PATH ///////////////////////// void EditorPropertyPath::_set_read_only(bool p_read_only) { @@ -3379,6 +3437,10 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ EditorPropertyClassName *editor = memnew(EditorPropertyClassName); editor->setup("Object", p_hint_text); return editor; + } else if (p_hint == PROPERTY_HINT_LOCALE_ID) { + EditorPropertyLocale *editor = memnew(EditorPropertyLocale); + editor->setup(p_hint_text); + return editor; } else if (p_hint == PROPERTY_HINT_DIR || p_hint == PROPERTY_HINT_FILE || p_hint == PROPERTY_HINT_SAVE_FILE || p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE) { Vector<String> extensions = p_hint_text.split(","); bool global = p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE; diff --git a/editor/editor_properties.h b/editor/editor_properties.h index e62f6823a3..fdb0360d6b 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -33,6 +33,7 @@ #include "editor/create_dialog.h" #include "editor/editor_inspector.h" +#include "editor/editor_locale_dialog.h" #include "editor/editor_resource_picker.h" #include "editor/editor_spin_slider.h" #include "editor/property_selector.h" @@ -153,6 +154,26 @@ public: EditorPropertyPath(); }; +class EditorPropertyLocale : public EditorProperty { + GDCLASS(EditorPropertyLocale, EditorProperty); + EditorLocaleDialog *dialog; + LineEdit *locale; + Button *locale_edit; + + void _locale_selected(const String &p_locale); + void _locale_pressed(); + void _locale_focus_exited(); + +protected: + static void _bind_methods(); + void _notification(int p_what); + +public: + void setup(const String &p_hit_string); + virtual void update_property() override; + EditorPropertyLocale(); +}; + class EditorPropertyClassName : public EditorProperty { GDCLASS(EditorPropertyClassName, EditorProperty); diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index 36203bca36..71a855b22c 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -627,7 +627,7 @@ void EditorPropertyArray::_reorder_button_gui_input(const Ref<InputEvent> &p_eve } vbox->move_child(reorder_selected_element_hbox, reorder_to_index % page_length + 2); // Ensure the moving element is visible. - EditorNode::get_singleton()->get_inspector()->ensure_control_visible(reorder_selected_element_hbox); + InspectorDock::get_inspector_singleton()->ensure_control_visible(reorder_selected_element_hbox); } } } diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index 6002bcfadc..716643f812 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -328,7 +328,7 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) { } break; case OBJ_MENU_SHOW_IN_FILE_SYSTEM: { - FileSystemDock *file_system_dock = EditorNode::get_singleton()->get_filesystem_dock(); + FileSystemDock *file_system_dock = FileSystemDock::get_singleton(); file_system_dock->navigate_to_path(edited_resource->get_path()); // Ensure that the FileSystem dock is visible. @@ -862,6 +862,7 @@ void EditorResourcePicker::_ensure_resource_menu() { edit_menu->connect("id_pressed", callable_mp(this, &EditorResourcePicker::_edit_menu_cbk)); edit_menu->connect("popup_hide", callable_mp((BaseButton *)edit_button, &BaseButton::set_pressed), varray(false)); } + EditorResourcePicker::EditorResourcePicker() { assign_button = memnew(Button); assign_button->set_flat(true); @@ -906,14 +907,14 @@ bool EditorScriptPicker::handle_menu_selected(int p_which) { switch (p_which) { case OBJ_MENU_NEW_SCRIPT: { if (script_owner) { - EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(script_owner, false); + SceneTreeDock::get_singleton()->open_script_dialog(script_owner, false); } return true; } case OBJ_MENU_EXTEND_SCRIPT: { if (script_owner) { - EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(script_owner, true); + SceneTreeDock::get_singleton()->open_script_dialog(script_owner, true); } return true; } @@ -958,7 +959,7 @@ bool EditorShaderPicker::handle_menu_selected(int p_which) { switch (p_which) { case OBJ_MENU_NEW_SHADER: { if (material.is_valid()) { - EditorNode::get_singleton()->get_scene_tree_dock()->open_shader_dialog(material, preferred_mode); + SceneTreeDock::get_singleton()->open_shader_dialog(material, preferred_mode); return true; } } break; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index b662eb8b1c..8146f48f91 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -339,7 +339,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { { String lang_hint = "en"; String host_lang = OS::get_singleton()->get_locale(); - host_lang = TranslationServer::standardize_locale(host_lang); // Skip locales if Text server lack required features. Vector<String> locales_to_skip; @@ -365,6 +364,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { } String best; + int best_score = 0; for (const String &locale : get_editor_locales()) { // Skip locales which we can't render properly (see above comment). // Test against language code without regional variants (e.g. ur_PK). @@ -376,16 +376,16 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { lang_hint += ","; lang_hint += locale; - if (host_lang == locale) { - best = locale; - } - - if (best.is_empty() && host_lang.begins_with(locale)) { + int score = TranslationServer::get_singleton()->compare_locales(host_lang, locale); + if (score > 0 && score >= best_score) { best = locale; + best_score = score; + if (score == 10) { + break; // Exact match, skip the rest. + } } } - - if (best.is_empty()) { + if (best_score == 0) { best = "en"; } @@ -643,10 +643,15 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("editors/2d/bone_outline_size", 2); _initial_set("editors/2d/viewport_border_color", Color(0.4, 0.4, 1.0, 0.4)); _initial_set("editors/2d/constrain_editor_view", true); - _initial_set("editors/2d/warped_mouse_panning", true); - _initial_set("editors/2d/simple_panning", false); - _initial_set("editors/2d/scroll_to_pan", false); - _initial_set("editors/2d/pan_speed", 20); + + // Panning + // Enum should be in sync with ControlScheme in ViewPanner. + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "editors/panning/2d_editor_panning_scheme", 0, "Scroll Zooms,Scroll Pans"); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "editors/panning/sub_editors_panning_scheme", 0, "Scroll Zooms,Scroll Pans"); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "editors/panning/animation_editors_panning_scheme", 1, "Scroll Zooms,Scroll Pans"); + _initial_set("editors/panning/simple_panning", false); + _initial_set("editors/panning/warped_mouse_panning", true); + _initial_set("editors/panning/2d_editor_pan_speed", 20); // Tiles editor _initial_set("editors/tiles_editor/display_grid", true); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 5b7ea65b04..db4161fc3d 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -112,6 +112,7 @@ static Ref<Texture2D> flip_icon(Ref<Texture2D> p_texture, bool p_flip_y = false, } #ifdef MODULE_SVG_ENABLED +// See also `generate_icon()` in `scene/resources/default_theme.cpp`. static Ref<ImageTexture> editor_generate_icon(int p_index, bool p_convert_color, float p_scale = EDSCALE, float p_saturation = 1.0, Dictionary p_convert_colors = Dictionary()) { Ref<ImageTexture> icon = memnew(ImageTexture); Ref<Image> img = memnew(Image); @@ -1123,6 +1124,12 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_constant("margin_bottom", "MarginContainer", 0); theme->set_constant("hseparation", "GridContainer", default_margin_size * EDSCALE); theme->set_constant("vseparation", "GridContainer", default_margin_size * EDSCALE); + theme->set_constant("hseparation", "FlowContainer", default_margin_size * EDSCALE); + theme->set_constant("vseparation", "FlowContainer", default_margin_size * EDSCALE); + theme->set_constant("hseparation", "HFlowContainer", default_margin_size * EDSCALE); + theme->set_constant("vseparation", "HFlowContainer", default_margin_size * EDSCALE); + theme->set_constant("hseparation", "VFlowContainer", default_margin_size * EDSCALE); + theme->set_constant("vseparation", "VFlowContainer", default_margin_size * EDSCALE); // Window @@ -1213,7 +1220,22 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("focus", "RichTextLabel", make_empty_stylebox()); theme->set_stylebox("normal", "RichTextLabel", style_tree_bg); + // Editor help. + theme->set_color("title_color", "EditorHelp", accent_color); theme->set_color("headline_color", "EditorHelp", mono_color); + theme->set_color("text_color", "EditorHelp", font_color); + theme->set_color("comment_color", "EditorHelp", font_color * Color(1, 1, 1, 0.6)); + theme->set_color("symbol_color", "EditorHelp", font_color * Color(1, 1, 1, 0.6)); + theme->set_color("value_color", "EditorHelp", font_color * Color(1, 1, 1, 0.6)); + theme->set_color("qualifier_color", "EditorHelp", font_color * Color(1, 1, 1, 0.8)); + theme->set_color("type_color", "EditorHelp", accent_color.lerp(font_color, 0.5)); + theme->set_color("selection_color", "EditorHelp", accent_color * Color(1, 1, 1, 0.4)); + theme->set_color("link_color", "EditorHelp", accent_color.lerp(mono_color, 0.8)); + theme->set_color("code_color", "EditorHelp", accent_color.lerp(mono_color, 0.6)); + theme->set_color("kbd_color", "EditorHelp", accent_color.lerp(property_color, 0.6)); + theme->set_constant("line_separation", "EditorHelp", Math::round(6 * EDSCALE)); + theme->set_constant("table_hseparation", "EditorHelp", 16 * EDSCALE); + theme->set_constant("table_vseparation", "EditorHelp", 6 * EDSCALE); // Panel theme->set_stylebox("panel", "Panel", make_flat_stylebox(dark_color_1, 6, 4, 6, 4, corner_width)); @@ -1421,6 +1443,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { style_info_3d_viewport->set_border_width_all(0); theme->set_stylebox("Information3dViewport", "EditorStyles", style_info_3d_viewport); + // Asset Library. + theme->set_stylebox("panel", "AssetLib", style_content_panel); + theme->set_color("status_color", "AssetLib", Color(0.5, 0.5, 0.5)); + theme->set_icon("dismiss", "AssetLib", theme->get_icon("Close", "EditorIcons")); + // Theme editor. theme->set_color("preview_picker_overlay_color", "ThemeEditor", Color(0.1, 0.1, 0.1, 0.25)); Color theme_preview_picker_bg_color = accent_color; diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index d71861e72d..cd29a3e617 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -48,6 +48,8 @@ #include "servers/display_server.h" #include "shader_create_dialog.h" +FileSystemDock *FileSystemDock::singleton = nullptr; + Ref<Texture2D> FileSystemDock::_get_tree_item_icon(bool p_is_valid, String p_file_type) { Ref<Texture2D> file_icon; if (!p_is_valid) { @@ -2335,7 +2337,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data, String to_dir; bool favorite; _get_drag_target_folder(to_dir, favorite, p_point, p_from); - EditorNode::get_singleton()->get_scene_tree_dock()->save_branch_to_file(to_dir); + SceneTreeDock::get_singleton()->save_branch_to_file(to_dir); } } @@ -2506,6 +2508,7 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str String fpath = p_paths[0]; String item_text = fpath.ends_with("/") ? TTR("Open in File Manager") : TTR("Show in File Manager"); p_popup->add_icon_item(get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons")), item_text, FILE_SHOW_IN_EXPLORER); + path = fpath; } } @@ -2542,6 +2545,9 @@ void FileSystemDock::_tree_rmb_empty(const Vector2 &p_pos) { tree_popup->add_icon_item(get_theme_icon(SNAME("Script"), SNAME("EditorIcons")), TTR("New Script..."), FILE_NEW_SCRIPT); tree_popup->add_icon_item(get_theme_icon(SNAME("Object"), SNAME("EditorIcons")), TTR("New Resource..."), FILE_NEW_RESOURCE); tree_popup->add_icon_item(get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons")), TTR("New TextFile..."), FILE_NEW_TEXTFILE); + tree_popup->add_separator(); + tree_popup->add_icon_item(get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons")), TTR("Open in File Manager"), FILE_SHOW_IN_EXPLORER); + tree_popup->set_position(tree->get_screen_position() + p_pos); tree_popup->reset_size(); tree_popup->popup(); @@ -2581,6 +2587,8 @@ void FileSystemDock::_file_list_rmb_pressed(const Vector2 &p_pos) { return; } + path = current_path->get_text(); + file_list_popup->clear(); file_list_popup->reset_size(); @@ -2737,11 +2745,11 @@ void FileSystemDock::_update_import_dock() { } if (imports.size() == 0) { - EditorNode::get_singleton()->get_import_dock()->clear(); + ImportDock::get_singleton()->clear(); } else if (imports.size() == 1) { - EditorNode::get_singleton()->get_import_dock()->set_edit_path(imports[0]); + ImportDock::get_singleton()->set_edit_path(imports[0]); } else { - EditorNode::get_singleton()->get_import_dock()->set_edit_multiple_paths(imports); + ImportDock::get_singleton()->set_edit_multiple_paths(imports); } import_dock_needs_update = false; @@ -2810,6 +2818,7 @@ void FileSystemDock::_bind_methods() { } FileSystemDock::FileSystemDock(EditorNode *p_editor) { + singleton = this; set_name("FileSystem"); editor = p_editor; path = "res://"; @@ -3045,4 +3054,5 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { } FileSystemDock::~FileSystemDock() { + singleton = nullptr; } diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 8d50f05da9..1dc986dcb2 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -304,6 +304,12 @@ private: void _feature_profile_changed(); Vector<String> _remove_self_included_paths(Vector<String> selected_strings); +private: + static FileSystemDock *singleton; + +public: + static FileSystemDock *get_singleton() { return singleton; } + protected: void _notification(int p_what); static void _bind_methods(); diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp index ff24339f9f..15455b759b 100644 --- a/editor/groups_editor.cpp +++ b/editor/groups_editor.cpp @@ -144,8 +144,8 @@ void GroupDialog::_add_pressed() { undo_redo->add_undo_method(this, "emit_signal", "group_edited"); // To force redraw of scene tree. - undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); - undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + undo_redo->add_do_method(SceneTreeDock::get_singleton()->get_tree_editor(), "update_tree"); + undo_redo->add_undo_method(SceneTreeDock::get_singleton()->get_tree_editor(), "update_tree"); undo_redo->commit_action(); } @@ -173,8 +173,8 @@ void GroupDialog::_removed_pressed() { undo_redo->add_undo_method(this, "emit_signal", "group_edited"); // To force redraw of scene tree. - undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); - undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + undo_redo->add_do_method(SceneTreeDock::get_singleton()->get_tree_editor(), "update_tree"); + undo_redo->add_undo_method(SceneTreeDock::get_singleton()->get_tree_editor(), "update_tree"); undo_redo->commit_action(); } @@ -211,6 +211,10 @@ void GroupDialog::_add_group(String p_name) { groups->ensure_cursor_is_visible(); } +void GroupDialog::_add_group_text_changed(const String &p_new_text) { + add_group_button->set_disabled(p_new_text.strip_edges().is_empty()); +} + void GroupDialog::_group_renamed() { TreeItem *renamed_group = groups->get_edited(); if (!renamed_group) { @@ -333,8 +337,8 @@ void GroupDialog::_modify_group_pressed(Object *p_item, int p_column, int p_id) undo_redo->add_undo_method(this, "emit_signal", "group_edited"); // To force redraw of scene tree. - undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); - undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + undo_redo->add_do_method(SceneTreeDock::get_singleton()->get_tree_editor(), "update_tree"); + undo_redo->add_undo_method(SceneTreeDock::get_singleton()->get_tree_editor(), "update_tree"); undo_redo->commit_action(); } break; @@ -457,8 +461,9 @@ GroupDialog::GroupDialog() { chbc->add_child(add_group_text); add_group_text->set_h_size_flags(Control::SIZE_EXPAND_FILL); add_group_text->connect("text_submitted", callable_mp(this, &GroupDialog::_add_group_pressed)); + add_group_text->connect("text_changed", callable_mp(this, &GroupDialog::_add_group_text_changed)); - Button *add_group_button = memnew(Button); + add_group_button = memnew(Button); add_group_button->set_text(TTR("Add")); chbc->add_child(add_group_button); add_group_button->connect("pressed", callable_mp(this, &GroupDialog::_add_group_pressed), varray(String())); @@ -557,6 +562,8 @@ GroupDialog::GroupDialog() { error = memnew(ConfirmationDialog); add_child(error); error->get_ok_button()->set_text(TTR("Close")); + + _add_group_text_changed(""); } //////////////////////////////////////////////////////////////////////////////// @@ -571,6 +578,7 @@ void GroupsEditor::_add_group(const String &p_group) { return; } + group_name->clear(); if (node->is_in_group(name)) { return; } @@ -583,12 +591,10 @@ void GroupsEditor::_add_group(const String &p_group) { undo_redo->add_undo_method(this, "update_tree"); // To force redraw of scene tree. - undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); - undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + undo_redo->add_do_method(SceneTreeDock::get_singleton()->get_tree_editor(), "update_tree"); + undo_redo->add_undo_method(SceneTreeDock::get_singleton()->get_tree_editor(), "update_tree"); undo_redo->commit_action(); - - group_name->clear(); } void GroupsEditor::_modify_group(Object *p_item, int p_column, int p_id) { @@ -611,8 +617,8 @@ void GroupsEditor::_modify_group(Object *p_item, int p_column, int p_id) { undo_redo->add_undo_method(this, "update_tree"); // To force redraw of scene tree. - undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); - undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + undo_redo->add_do_method(SceneTreeDock::get_singleton()->get_tree_editor(), "update_tree"); + undo_redo->add_undo_method(SceneTreeDock::get_singleton()->get_tree_editor(), "update_tree"); undo_redo->commit_action(); } break; @@ -622,6 +628,10 @@ void GroupsEditor::_modify_group(Object *p_item, int p_column, int p_id) { } } +void GroupsEditor::_group_name_changed(const String &p_new_text) { + add->set_disabled(p_new_text.strip_edges().is_empty()); +} + struct _GroupInfoComparator { bool operator()(const Node::GroupInfo &p_a, const Node::GroupInfo &p_b) const { return p_a.name.operator String() < p_b.name.operator String(); @@ -711,6 +721,7 @@ GroupsEditor::GroupsEditor() { group_name->set_h_size_flags(Control::SIZE_EXPAND_FILL); hbc->add_child(group_name); group_name->connect("text_submitted", callable_mp(this, &GroupsEditor::_add_group)); + group_name->connect("text_changed", callable_mp(this, &GroupsEditor::_group_name_changed)); add = memnew(Button); add->set_text(TTR("Add")); @@ -724,6 +735,8 @@ GroupsEditor::GroupsEditor() { tree->connect("button_pressed", callable_mp(this, &GroupsEditor::_modify_group)); tree->add_theme_constant_override("draw_guides", 1); add_theme_constant_override("separation", 3 * EDSCALE); + + _group_name_changed(""); } GroupsEditor::~GroupsEditor() { diff --git a/editor/groups_editor.h b/editor/groups_editor.h index 677ef14a1f..aa70ac5bc4 100644 --- a/editor/groups_editor.h +++ b/editor/groups_editor.h @@ -49,6 +49,7 @@ class GroupDialog : public AcceptDialog { TreeItem *groups_root; LineEdit *add_group_text; + Button *add_group_button; Tree *groups; @@ -77,6 +78,7 @@ class GroupDialog : public AcceptDialog { void _add_pressed(); void _removed_pressed(); void _add_group_pressed(const String &p_name); + void _add_group_text_changed(const String &p_new_text); void _group_renamed(); void _rename_group_item(const String &p_old_name, const String &p_new_name); @@ -122,6 +124,7 @@ class GroupsEditor : public VBoxContainer { void update_tree(); void _add_group(const String &p_group = ""); void _modify_group(Object *p_item, int p_column, int p_id); + void _group_name_changed(const String &p_new_text); void _show_group_dialog(); diff --git a/editor/icons/GizmoGIProbe.svg b/editor/icons/GizmoVoxelGI.svg index ff3cafa1f5..ff3cafa1f5 100644 --- a/editor/icons/GizmoGIProbe.svg +++ b/editor/icons/GizmoVoxelGI.svg diff --git a/editor/icons/HFlowContainer.svg b/editor/icons/HFlowContainer.svg new file mode 100644 index 0000000000..0ab03f686e --- /dev/null +++ b/editor/icons/HFlowContainer.svg @@ -0,0 +1 @@ +<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M3 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2H3zm0 2h10v10H3V3zm2 1c-.554 0-1 .446-1 1s.446 1 1 1h2c.554 0 1-.446 1-1s-.446-1-1-1H5zm4.996 0c-.554 0-1 .446-1 1s.446 1 1 1H11c.554 0 1-.446 1-1s-.446-1-1-1H9.996zM5 7c-.554 0-1 .446-1 1s.446 1 1 1 1-.446 1-1-.446-1-1-1zm3 0c-.554 0-1 .446-1 1s.446 1 1 1h3c.554 0 1-.446 1-1s-.446-1-1-1H8zm-3.004 3c-.554 0-1 .446-1 1s.446 1 1 1H9c.554 0 1-.446 1-1s-.446-1-1-1H4.996z" style="fill:#8eef97;fill-opacity:1"/></svg> diff --git a/editor/icons/VFlowContainer.svg b/editor/icons/VFlowContainer.svg new file mode 100644 index 0000000000..9023bf2245 --- /dev/null +++ b/editor/icons/VFlowContainer.svg @@ -0,0 +1 @@ +<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M3 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2H3zm0 2h10v10H3V3zm7.998.998c-.554 0-1 .446-1 1v4.004c0 .554.446 1 1 1s1-.446 1-1V4.998c0-.554-.446-1-1-1zm-6 .004c-.554 0-1 .446-1 1v2c0 .554.446 1 1 1s1-.446 1-1v-2c0-.554-.446-1-1-1zm3 0c-.554 0-1 .446-1 1s.446 1 1 1 1-.446 1-1-.446-1-1-1zm0 3c-.554 0-1 .446-1 1v3c0 .554.446 1 1 1s1-.446 1-1v-3c0-.554-.446-1-1-1zm-3 1.996c-.554 0-1 .446-1 1v1.004c0 .554.446 1 1 1s1-.446 1-1V9.998c0-.554-.446-1-1-1z" style="fill:#8eef97;fill-opacity:1"/></svg> diff --git a/editor/icons/editor_icons_builders.py b/editor/icons/editor_icons_builders.py index d7145abe50..fb9a57c429 100644 --- a/editor/icons/editor_icons_builders.py +++ b/editor/icons/editor_icons_builders.py @@ -8,7 +8,7 @@ import os from io import StringIO from platform_methods import subprocess_main - +# See also `scene/resources/default_theme/default_theme_icons_builders.py`. def make_editor_icons_action(target, source, env): dst = target[0] diff --git a/editor/import/dynamicfont_import_settings.cpp b/editor/import/dynamicfont_import_settings.cpp index 3151496bec..81b98c1d45 100644 --- a/editor/import/dynamicfont_import_settings.cpp +++ b/editor/import/dynamicfont_import_settings.cpp @@ -427,6 +427,7 @@ void DynamicFontImportSettings::_add_glyph_range_item(int32_t p_start, int32_t p for (int i = 0; i < pages; i++) { TreeItem *item = glyph_tree->create_item(glyph_root); ERR_FAIL_NULL(item); + item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); item->set_text(0, _pad_zeros(String::num_int64(start, 16)) + " - " + _pad_zeros(String::num_int64(start + page_size, 16))); item->set_text(1, p_name); item->set_metadata(0, Vector2i(start, start + page_size)); @@ -435,6 +436,7 @@ void DynamicFontImportSettings::_add_glyph_range_item(int32_t p_start, int32_t p if (remain > 0) { TreeItem *item = glyph_tree->create_item(glyph_root); ERR_FAIL_NULL(item); + item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); item->set_text(0, _pad_zeros(String::num_int64(start, 16)) + " - " + _pad_zeros(String::num_int64(p_end, 16))); item->set_text(1, p_name); item->set_metadata(0, Vector2i(start, p_end)); @@ -442,398 +444,6 @@ void DynamicFontImportSettings::_add_glyph_range_item(int32_t p_start, int32_t p } /*************************************************************************/ -/* Languages and scripts */ -/*************************************************************************/ - -struct CodeInfo { - String name; - String code; -}; - -static CodeInfo langs[] = { - { U"Custom", U"xx" }, - { U"-", U"-" }, - { U"Abkhazian", U"ab" }, - { U"Afar", U"aa" }, - { U"Afrikaans", U"af" }, - { U"Akan", U"ak" }, - { U"Albanian", U"sq" }, - { U"Amharic", U"am" }, - { U"Arabic", U"ar" }, - { U"Aragonese", U"an" }, - { U"Armenian", U"hy" }, - { U"Assamese", U"as" }, - { U"Avaric", U"av" }, - { U"Avestan", U"ae" }, - { U"Aymara", U"ay" }, - { U"Azerbaijani", U"az" }, - { U"Bambara", U"bm" }, - { U"Bashkir", U"ba" }, - { U"Basque", U"eu" }, - { U"Belarusian", U"be" }, - { U"Bengali", U"bn" }, - { U"Bihari", U"bh" }, - { U"Bislama", U"bi" }, - { U"Bosnian", U"bs" }, - { U"Breton", U"br" }, - { U"Bulgarian", U"bg" }, - { U"Burmese", U"my" }, - { U"Catalan", U"ca" }, - { U"Chamorro", U"ch" }, - { U"Chechen", U"ce" }, - { U"Chichewa", U"ny" }, - { U"Chinese", U"zh" }, - { U"Chuvash", U"cv" }, - { U"Cornish", U"kw" }, - { U"Corsican", U"co" }, - { U"Cree", U"cr" }, - { U"Croatian", U"hr" }, - { U"Czech", U"cs" }, - { U"Danish", U"da" }, - { U"Divehi", U"dv" }, - { U"Dutch", U"nl" }, - { U"Dzongkha", U"dz" }, - { U"English", U"en" }, - { U"Esperanto", U"eo" }, - { U"Estonian", U"et" }, - { U"Ewe", U"ee" }, - { U"Faroese", U"fo" }, - { U"Fijian", U"fj" }, - { U"Finnish", U"fi" }, - { U"French", U"fr" }, - { U"Fulah", U"ff" }, - { U"Galician", U"gl" }, - { U"Georgian", U"ka" }, - { U"German", U"de" }, - { U"Greek", U"el" }, - { U"Guarani", U"gn" }, - { U"Gujarati", U"gu" }, - { U"Haitian", U"ht" }, - { U"Hausa", U"ha" }, - { U"Hebrew", U"he" }, - { U"Herero", U"hz" }, - { U"Hindi", U"hi" }, - { U"Hiri Motu", U"ho" }, - { U"Hungarian", U"hu" }, - { U"Interlingua", U"ia" }, - { U"Indonesian", U"id" }, - { U"Interlingue", U"ie" }, - { U"Irish", U"ga" }, - { U"Igbo", U"ig" }, - { U"Inupiaq", U"ik" }, - { U"Ido", U"io" }, - { U"Icelandic", U"is" }, - { U"Italian", U"it" }, - { U"Inuktitut", U"iu" }, - { U"Japanese", U"ja" }, - { U"Javanese", U"jv" }, - { U"Kalaallisut", U"kl" }, - { U"Kannada", U"kn" }, - { U"Kanuri", U"kr" }, - { U"Kashmiri", U"ks" }, - { U"Kazakh", U"kk" }, - { U"Central Khmer", U"km" }, - { U"Kikuyu", U"ki" }, - { U"Kinyarwanda", U"rw" }, - { U"Kirghiz", U"ky" }, - { U"Komi", U"kv" }, - { U"Kongo", U"kg" }, - { U"Korean", U"ko" }, - { U"Kurdish", U"ku" }, - { U"Kuanyama", U"kj" }, - { U"Latin", U"la" }, - { U"Luxembourgish", U"lb" }, - { U"Ganda", U"lg" }, - { U"Limburgan", U"li" }, - { U"Lingala", U"ln" }, - { U"Lao", U"lo" }, - { U"Lithuanian", U"lt" }, - { U"Luba-Katanga", U"lu" }, - { U"Latvian", U"lv" }, - { U"Man", U"gv" }, - { U"Macedonian", U"mk" }, - { U"Malagasy", U"mg" }, - { U"Malay", U"ms" }, - { U"Malayalam", U"ml" }, - { U"Maltese", U"mt" }, - { U"Maori", U"mi" }, - { U"Marathi", U"mr" }, - { U"Marshallese", U"mh" }, - { U"Mongolian", U"mn" }, - { U"Nauru", U"na" }, - { U"Navajo", U"nv" }, - { U"North Ndebele", U"nd" }, - { U"Nepali", U"ne" }, - { U"Ndonga", U"ng" }, - { U"Norwegian Bokmål", U"nb" }, - { U"Norwegian Nynorsk", U"nn" }, - { U"Norwegian", U"no" }, - { U"Sichuan Yi, Nuosu", U"ii" }, - { U"South Ndebele", U"nr" }, - { U"Occitan", U"oc" }, - { U"Ojibwa", U"oj" }, - { U"Church Slavic", U"cu" }, - { U"Oromo", U"om" }, - { U"Oriya", U"or" }, - { U"Ossetian", U"os" }, - { U"Punjabi", U"pa" }, - { U"Pali", U"pi" }, - { U"Persian", U"fa" }, - { U"Polish", U"pl" }, - { U"Pashto", U"ps" }, - { U"Portuguese", U"pt" }, - { U"Quechua", U"qu" }, - { U"Romansh", U"rm" }, - { U"Rundi", U"rn" }, - { U"Romanian", U"ro" }, - { U"Russian", U"ru" }, - { U"Sanskrit", U"sa" }, - { U"Sardinian", U"sc" }, - { U"Sindhi", U"sd" }, - { U"Northern Sami", U"se" }, - { U"Samoan", U"sm" }, - { U"Sango", U"sg" }, - { U"Serbian", U"sr" }, - { U"Gaelic", U"gd" }, - { U"Shona", U"sn" }, - { U"Sinhala", U"si" }, - { U"Slovak", U"sk" }, - { U"Slovenian", U"sl" }, - { U"Somali", U"so" }, - { U"Southern Sotho", U"st" }, - { U"Spanish", U"es" }, - { U"Sundanese", U"su" }, - { U"Swahili", U"sw" }, - { U"Swati", U"ss" }, - { U"Swedish", U"sv" }, - { U"Tamil", U"ta" }, - { U"Telugu", U"te" }, - { U"Tajik", U"tg" }, - { U"Thai", U"th" }, - { U"Tigrinya", U"ti" }, - { U"Tibetan", U"bo" }, - { U"Turkmen", U"tk" }, - { U"Tagalog", U"tl" }, - { U"Tswana", U"tn" }, - { U"Tonga", U"to" }, - { U"Turkish", U"tr" }, - { U"Tsonga", U"ts" }, - { U"Tatar", U"tt" }, - { U"Twi", U"tw" }, - { U"Tahitian", U"ty" }, - { U"Uighur", U"ug" }, - { U"Ukrainian", U"uk" }, - { U"Urdu", U"ur" }, - { U"Uzbek", U"uz" }, - { U"Venda", U"ve" }, - { U"Vietnamese", U"vi" }, - { U"Volapük", U"vo" }, - { U"Walloon", U"wa" }, - { U"Welsh", U"cy" }, - { U"Wolof", U"wo" }, - { U"Western Frisian", U"fy" }, - { U"Xhosa", U"xh" }, - { U"Yiddish", U"yi" }, - { U"Yoruba", U"yo" }, - { U"Zhuang", U"za" }, - { U"Zulu", U"zu" }, - { String(), String() } -}; - -static CodeInfo scripts[] = { - { U"Custom", U"Qaaa" }, - { U"-", U"-" }, - { U"Adlam", U"Adlm" }, - { U"Afaka", U"Afak" }, - { U"Caucasian Albanian", U"Aghb" }, - { U"Ahom", U"Ahom" }, - { U"Arabic", U"Arab" }, - { U"Imperial Aramaic", U"Armi" }, - { U"Armenian", U"Armn" }, - { U"Avestan", U"Avst" }, - { U"Balinese", U"Bali" }, - { U"Bamum", U"Bamu" }, - { U"Bassa Vah", U"Bass" }, - { U"Batak", U"Batk" }, - { U"Bengali", U"Beng" }, - { U"Bhaiksuki", U"Bhks" }, - { U"Blissymbols", U"Blis" }, - { U"Bopomofo", U"Bopo" }, - { U"Brahmi", U"Brah" }, - { U"Braille", U"Brai" }, - { U"Buginese", U"Bugi" }, - { U"Buhid", U"Buhd" }, - { U"Chakma", U"Cakm" }, - { U"Unified Canadian Aboriginal", U"Cans" }, - { U"Carian", U"Cari" }, - { U"Cham", U"Cham" }, - { U"Cherokee", U"Cher" }, - { U"Chorasmian", U"Chrs" }, - { U"Cirth", U"Cirt" }, - { U"Coptic", U"Copt" }, - { U"Cypro-Minoan", U"Cpmn" }, - { U"Cypriot", U"Cprt" }, - { U"Cyrillic", U"Cyrl" }, - { U"Devanagari", U"Deva" }, - { U"Dives Akuru", U"Diak" }, - { U"Dogra", U"Dogr" }, - { U"Deseret", U"Dsrt" }, - { U"Duployan", U"Dupl" }, - { U"Egyptian demotic", U"Egyd" }, - { U"Egyptian hieratic", U"Egyh" }, - { U"Egyptian hieroglyphs", U"Egyp" }, - { U"Elbasan", U"Elba" }, - { U"Elymaic", U"Elym" }, - { U"Ethiopic", U"Ethi" }, - { U"Khutsuri", U"Geok" }, - { U"Georgian", U"Geor" }, - { U"Glagolitic", U"Glag" }, - { U"Gunjala Gondi", U"Gong" }, - { U"Masaram Gondi", U"Gonm" }, - { U"Gothic", U"Goth" }, - { U"Grantha", U"Gran" }, - { U"Greek", U"Grek" }, - { U"Gujarati", U"Gujr" }, - { U"Gurmukhi", U"Guru" }, - { U"Hangul", U"Hang" }, - { U"Han", U"Hani" }, - { U"Hanunoo", U"Hano" }, - { U"Hatran", U"Hatr" }, - { U"Hebrew", U"Hebr" }, - { U"Hiragana", U"Hira" }, - { U"Anatolian Hieroglyphs", U"Hluw" }, - { U"Pahawh Hmong", U"Hmng" }, - { U"Nyiakeng Puachue Hmong", U"Hmnp" }, - { U"Old Hungarian", U"Hung" }, - { U"Indus", U"Inds" }, - { U"Old Italic", U"Ital" }, - { U"Javanese", U"Java" }, - { U"Jurchen", U"Jurc" }, - { U"Kayah Li", U"Kali" }, - { U"Katakana", U"Kana" }, - { U"Kharoshthi", U"Khar" }, - { U"Khmer", U"Khmr" }, - { U"Khojki", U"Khoj" }, - { U"Khitan large script", U"Kitl" }, - { U"Khitan small script", U"Kits" }, - { U"Kannada", U"Knda" }, - { U"Kpelle", U"Kpel" }, - { U"Kaithi", U"Kthi" }, - { U"Tai Tham", U"Lana" }, - { U"Lao", U"Laoo" }, - { U"Latin", U"Latn" }, - { U"Leke", U"Leke" }, - { U"Lepcha", U"Lepc" }, - { U"Limbu", U"Limb" }, - { U"Linear A", U"Lina" }, - { U"Linear B", U"Linb" }, - { U"Lisu", U"Lisu" }, - { U"Loma", U"Loma" }, - { U"Lycian", U"Lyci" }, - { U"Lydian", U"Lydi" }, - { U"Mahajani", U"Mahj" }, - { U"Makasar", U"Maka" }, - { U"Mandaic", U"Mand" }, - { U"Manichaean", U"Mani" }, - { U"Marchen", U"Marc" }, - { U"Mayan Hieroglyphs", U"Maya" }, - { U"Medefaidrin", U"Medf" }, - { U"Mende Kikakui", U"Mend" }, - { U"Meroitic Cursive", U"Merc" }, - { U"Meroitic Hieroglyphs", U"Mero" }, - { U"Malayalam", U"Mlym" }, - { U"Modi", U"Modi" }, - { U"Mongolian", U"Mong" }, - { U"Moon", U"Moon" }, - { U"Mro", U"Mroo" }, - { U"Meitei Mayek", U"Mtei" }, - { U"Multani", U"Mult" }, - { U"Myanmar (Burmese)", U"Mymr" }, - { U"Nandinagari", U"Nand" }, - { U"Old North Arabian", U"Narb" }, - { U"Nabataean", U"Nbat" }, - { U"Newa", U"Newa" }, - { U"Naxi Dongba", U"Nkdb" }, - { U"Nakhi Geba", U"Nkgb" }, - { U"N’Ko", U"Nkoo" }, - { U"Nüshu", U"Nshu" }, - { U"Ogham", U"Ogam" }, - { U"Ol Chiki", U"Olck" }, - { U"Old Turkic", U"Orkh" }, - { U"Oriya", U"Orya" }, - { U"Osage", U"Osge" }, - { U"Osmanya", U"Osma" }, - { U"Old Uyghur", U"Ougr" }, - { U"Palmyrene", U"Palm" }, - { U"Pau Cin Hau", U"Pauc" }, - { U"Proto-Cuneiform", U"Pcun" }, - { U"Proto-Elamite", U"Pelm" }, - { U"Old Permic", U"Perm" }, - { U"Phags-pa", U"Phag" }, - { U"Inscriptional Pahlavi", U"Phli" }, - { U"Psalter Pahlavi", U"Phlp" }, - { U"Book Pahlavi", U"Phlv" }, - { U"Phoenician", U"Phnx" }, - { U"Klingon", U"Piqd" }, - { U"Miao", U"Plrd" }, - { U"Inscriptional Parthian", U"Prti" }, - { U"Proto-Sinaitic", U"Psin" }, - { U"Ranjana", U"Ranj" }, - { U"Rejang", U"Rjng" }, - { U"Hanifi Rohingya", U"Rohg" }, - { U"Rongorongo", U"Roro" }, - { U"Runic", U"Runr" }, - { U"Samaritan", U"Samr" }, - { U"Sarati", U"Sara" }, - { U"Old South Arabian", U"Sarb" }, - { U"Saurashtra", U"Saur" }, - { U"SignWriting", U"Sgnw" }, - { U"Shavian", U"Shaw" }, - { U"Sharada", U"Shrd" }, - { U"Shuishu", U"Shui" }, - { U"Siddham", U"Sidd" }, - { U"Khudawadi", U"Sind" }, - { U"Sinhala", U"Sinh" }, - { U"Sogdian", U"Sogd" }, - { U"Old Sogdian", U"Sogo" }, - { U"Sora Sompeng", U"Sora" }, - { U"Soyombo", U"Soyo" }, - { U"Sundanese", U"Sund" }, - { U"Syloti Nagri", U"Sylo" }, - { U"Syriac", U"Syrc" }, - { U"Tagbanwa", U"Tagb" }, - { U"Takri", U"Takr" }, - { U"Tai Le", U"Tale" }, - { U"New Tai Lue", U"Talu" }, - { U"Tamil", U"Taml" }, - { U"Tangut", U"Tang" }, - { U"Tai Viet", U"Tavt" }, - { U"Telugu", U"Telu" }, - { U"Tengwar", U"Teng" }, - { U"Tifinagh", U"Tfng" }, - { U"Tagalog", U"Tglg" }, - { U"Thaana", U"Thaa" }, - { U"Thai", U"Thai" }, - { U"Tibetan", U"Tibt" }, - { U"Tirhuta", U"Tirh" }, - { U"Tangsa", U"Tnsa" }, - { U"Toto", U"Toto" }, - { U"Ugaritic", U"Ugar" }, - { U"Vai", U"Vaii" }, - { U"Visible Speech", U"Visp" }, - { U"Vithkuqi", U"Vith" }, - { U"Warang Citi", U"Wara" }, - { U"Wancho", U"Wcho" }, - { U"Woleai", U"Wole" }, - { U"Old Persian", U"Xpeo" }, - { U"Cuneiform", U"Xsux" }, - { U"Yezidi", U"Yezi" }, - { U"Yi", U"Yiii" }, - { U"Zanabazar Square", U"Zanb" }, - { String(), String() } -}; - -/*************************************************************************/ /* Page 1 callbacks: Rendering Options */ /*************************************************************************/ @@ -1048,6 +658,30 @@ void DynamicFontImportSettings::_glyph_selected() { } } label_glyphs->set_text(TTR("Preloaded glyphs: ") + itos(selected_glyphs.size())); + + item = glyph_tree->get_selected(); + ERR_FAIL_NULL(item); + Vector2i range = item->get_metadata(0); + + int total_chars = range.y - range.x; + int selected_count = 0; + for (int i = range.x; i < range.y; i++) { + if (!font_main->has_char(i)) { + total_chars--; + } + + if (selected_chars.has(i)) { + selected_count++; + } + } + + if (selected_count == total_chars) { + item->set_checked(0, true); + } else if (selected_count > 0) { + item->set_indeterminate(0, true); + } else { + item->set_checked(0, false); + } } void DynamicFontImportSettings::_range_edited() { @@ -1152,6 +786,10 @@ void DynamicFontImportSettings::_range_update(int32_t p_start, int32_t p_end) { } } _edit_range(p_start, p_end); + + TreeItem *item = glyph_tree->get_selected(); + ERR_FAIL_NULL(item); + item->set_checked(0, !all_selected); } /*************************************************************************/ @@ -1159,19 +797,17 @@ void DynamicFontImportSettings::_range_update(int32_t p_start, int32_t p_end) { /*************************************************************************/ void DynamicFontImportSettings::_lang_add() { - menu_langs->set_position(lang_list->get_screen_position() + lang_list->get_local_mouse_position()); - menu_langs->reset_size(); - menu_langs->popup(); + locale_select->popup_locale_dialog(); } -void DynamicFontImportSettings::_lang_add_item(int p_option) { +void DynamicFontImportSettings::_lang_add_item(const String &p_locale) { TreeItem *lang_item = lang_list->create_item(lang_list_root); ERR_FAIL_NULL(lang_item); lang_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); lang_item->set_editable(0, true); lang_item->set_checked(0, false); - lang_item->set_text(1, langs[p_option].code); + lang_item->set_text(1, p_locale); lang_item->set_editable(1, true); lang_item->add_button(2, lang_list->get_theme_icon("Remove", "EditorIcons"), BUTTON_REMOVE_VAR, false, TTR("Remove")); lang_item->set_button_color(2, 0, Color(1, 1, 1, 0.75)); @@ -1230,7 +866,7 @@ void DynamicFontImportSettings::_script_add_item(int p_option) { script_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); script_item->set_editable(0, true); script_item->set_checked(0, false); - script_item->set_text(1, scripts[p_option].code); + script_item->set_text(1, script_codes[p_option]); script_item->set_editable(1, true); script_item->add_button(2, lang_list->get_theme_icon("Remove", "EditorIcons"), BUTTON_REMOVE_VAR, false, TTR("Remove")); script_item->set_button_color(2, 0, Color(1, 1, 1, 0.75)); @@ -1688,26 +1324,15 @@ DynamicFontImportSettings::DynamicFontImportSettings() { // Popup menus - menu_langs = memnew(PopupMenu); - menu_langs->set_name("Language"); - for (int i = 0; !langs[i].name.is_empty(); i++) { - if (langs[i].name == "-") { - menu_langs->add_separator(); - } else { - menu_langs->add_item(langs[i].name + " (" + langs[i].code + ")", i); - } - } - add_child(menu_langs); - menu_langs->connect("id_pressed", callable_mp(this, &DynamicFontImportSettings::_lang_add_item)); + locale_select = memnew(EditorLocaleDialog); + locale_select->connect("locale_selected", callable_mp(this, &DynamicFontImportSettings::_lang_add_item)); + add_child(locale_select); menu_scripts = memnew(PopupMenu); menu_scripts->set_name("Script"); - for (int i = 0; !scripts[i].name.is_empty(); i++) { - if (scripts[i].name == "-") { - menu_scripts->add_separator(); - } else { - menu_scripts->add_item(scripts[i].name + " (" + scripts[i].code + ")", i); - } + script_codes = TranslationServer::get_singleton()->get_all_scripts(); + for (int i = 0; i < script_codes.size(); i++) { + menu_scripts->add_item(TranslationServer::get_singleton()->get_script_name(script_codes[i]) + " (" + script_codes[i] + ")", i); } add_child(menu_scripts); menu_scripts->connect("id_pressed", callable_mp(this, &DynamicFontImportSettings::_script_add_item)); diff --git a/editor/import/dynamicfont_import_settings.h b/editor/import/dynamicfont_import_settings.h index 89665ae476..5d37f58b9b 100644 --- a/editor/import/dynamicfont_import_settings.h +++ b/editor/import/dynamicfont_import_settings.h @@ -33,6 +33,7 @@ #include "editor/editor_file_dialog.h" #include "editor/editor_inspector.h" +#include "editor/editor_locale_dialog.h" #include "editor/import/resource_importer_dynamicfont.h" @@ -67,6 +68,9 @@ class DynamicFontImportSettings : public ConfirmationDialog { List<ResourceImporter::ImportOption> options_variations; List<ResourceImporter::ImportOption> options_general; + EditorLocaleDialog *locale_select; + Vector<String> script_codes; + // Root layout Label *label_warn = nullptr; TabContainer *main_pages = nullptr; @@ -122,7 +126,6 @@ class DynamicFontImportSettings : public ConfirmationDialog { Button *add_script = nullptr; Button *add_ot = nullptr; - PopupMenu *menu_langs = nullptr; PopupMenu *menu_scripts = nullptr; PopupMenu *menu_ot = nullptr; PopupMenu *menu_ot_ss = nullptr; @@ -142,7 +145,7 @@ class DynamicFontImportSettings : public ConfirmationDialog { Label *label_ot = nullptr; void _lang_add(); - void _lang_add_item(int p_option); + void _lang_add_item(const String &p_locale); void _lang_remove(Object *p_item, int p_column, int p_id); void _script_add(); diff --git a/editor/import/resource_importer_csv_translation.cpp b/editor/import/resource_importer_csv_translation.cpp index 448b318c64..f0ee14bdcb 100644 --- a/editor/import/resource_importer_csv_translation.cpp +++ b/editor/import/resource_importer_csv_translation.cpp @@ -99,8 +99,7 @@ Error ResourceImporterCSVTranslation::import(const String &p_source_file, const Vector<Ref<Translation>> translations; for (int i = 1; i < line.size(); i++) { - String locale = line[i]; - ERR_FAIL_COND_V_MSG(!TranslationServer::is_locale_valid(locale), ERR_PARSE_ERROR, "Error importing CSV translation: '" + locale + "' is not a valid locale."); + String locale = TranslationServer::get_singleton()->standardize_locale(line[i]); locales.push_back(locale); Ref<Translation> translation; diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index e801cd4553..af9a2f9ebe 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -370,16 +370,17 @@ static void _pre_gen_shape_list(Ref<ImporterMesh> &mesh, Vector<Ref<Shape3D>> &r } } -Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map) { - // children first +Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, List<Pair<NodePath, Node *>> &r_node_renames) { + // Children first. for (int i = 0; i < p_node->get_child_count(); i++) { - Node *r = _pre_fix_node(p_node->get_child(i), p_root, collision_map); + Node *r = _pre_fix_node(p_node->get_child(i), p_root, collision_map, r_node_renames); if (!r) { - i--; //was erased + i--; // Was erased. } } String name = p_node->get_name(); + NodePath original_path = p_root->get_path_to(p_node); // Used to detect renames due to import hints. bool isroot = p_node == p_root; @@ -414,14 +415,21 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I } if (Object::cast_to<AnimationPlayer>(p_node)) { - //remove animations referencing non-importable nodes AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node); + // Node paths in animation tracks are relative to the following path (this is used to fix node paths below). + Node *ap_root = ap->get_node(ap->get_root()); + NodePath path_prefix = p_root->get_path_to(ap_root); + + bool nodes_were_renamed = r_node_renames.size() != 0; + List<StringName> anims; ap->get_animation_list(&anims); for (const StringName &E : anims) { Ref<Animation> anim = ap->get_animation(E); ERR_CONTINUE(anim.is_null()); + + // Remove animation tracks referencing non-importable nodes. for (int i = 0; i < anim->get_track_count(); i++) { NodePath path = anim->track_get_path(i); @@ -435,6 +443,27 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I } } + // Fix node paths in animations, in case nodes were renamed earlier due to import hints. + if (nodes_were_renamed) { + for (int i = 0; i < anim->get_track_count(); i++) { + NodePath path = anim->track_get_path(i); + // Convert track path to absolute node path without subnames (some manual work because we are not in the scene tree). + Vector<StringName> absolute_path_names = path_prefix.get_names(); + absolute_path_names.append_array(path.get_names()); + NodePath absolute_path(absolute_path_names, false); + absolute_path.simplify(); + // Fix paths to renamed nodes. + for (const Pair<NodePath, Node *> &F : r_node_renames) { + if (F.first == absolute_path) { + NodePath new_path(ap_root->get_path_to(F.second).get_names(), path.get_subnames(), false); + print_verbose(vformat("Fix: Correcting node path in animation track: %s should be %s", path, new_path)); + anim->track_set_path(i, new_path); + break; // Only one match is possible. + } + } + } + } + String animname = E; const int loop_string_count = 3; static const char *loop_strings[loop_string_count] = { "loop_mode", "loop", "cycle" }; @@ -452,13 +481,22 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I if (isroot) { return p_node; } + + String fixed_name; + if (_teststr(name, "colonly")) { + fixed_name = _fixstr(name, "colonly"); + } else if (_teststr(name, "convcolonly")) { + fixed_name = _fixstr(name, "convcolonly"); + } + + ERR_FAIL_COND_V(fixed_name.is_empty(), nullptr); + ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node); if (mi) { Ref<ImporterMesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { Vector<Ref<Shape3D>> shapes; - String fixed_name; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; } else if (_teststr(name, "colonly")) { @@ -469,14 +507,6 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I collision_map[mesh] = shapes; } - if (_teststr(name, "colonly")) { - fixed_name = _fixstr(name, "colonly"); - } else if (_teststr(name, "convcolonly")) { - fixed_name = _fixstr(name, "convcolonly"); - } - - ERR_FAIL_COND_V(fixed_name.is_empty(), nullptr); - if (shapes.size()) { StaticBody3D *col = memnew(StaticBody3D); col->set_transform(mi->get_transform()); @@ -492,11 +522,11 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I } else if (p_node->has_meta("empty_draw_type")) { String empty_draw_type = String(p_node->get_meta("empty_draw_type")); StaticBody3D *sb = memnew(StaticBody3D); - sb->set_name(_fixstr(name, "colonly")); + sb->set_name(fixed_name); Object::cast_to<Node3D>(sb)->set_transform(Object::cast_to<Node3D>(p_node)->get_transform()); p_node->replace_by(sb); memdelete(p_node); - p_node = nullptr; + p_node = sb; CollisionShape3D *colshape = memnew(CollisionShape3D); if (empty_draw_type == "CUBE") { BoxShape3D *boxShape = memnew(BoxShape3D); @@ -635,6 +665,14 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I } } + if (p_node) { + NodePath new_path = p_root->get_path_to(p_node); + if (new_path != original_path) { + print_verbose(vformat("Fix: Renamed %s to %s", original_path, new_path)); + r_node_renames.push_back({ original_path, p_node }); + } + } + return p_node; } @@ -1438,7 +1476,7 @@ void ResourceImporterScene::get_import_options(const String &p_path, List<Import r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/ensure_tangents"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/generate_lods"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/create_shadow_meshes"), true)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Dynamic,Static,Static Lightmaps", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 2)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Static (VoxelGI/SDFGI),Static Lightmaps,Dynamic (VoxelGI only)", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 1)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.1)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "skins/use_named_skins"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import"), true)); @@ -1622,7 +1660,7 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m } break; case LIGHT_BAKE_STATIC: case LIGHT_BAKE_STATIC_LIGHTMAPS: { - mesh_node->set_gi_mode(GeometryInstance3D::GI_MODE_BAKED); + mesh_node->set_gi_mode(GeometryInstance3D::GI_MODE_STATIC); } break; } @@ -1738,7 +1776,8 @@ void ResourceImporterScene::_optimize_track_usage(AnimationPlayer *p_player, Ani if (bone_idx == -1) { continue; } - skel->get_bone_pose(bone_idx); + // Note that this is using get_bone_pose to update the bone pose cache. + _ALLOW_DISCARD_ skel->get_bone_pose(bone_idx); loc = skel->get_bone_pose_position(bone_idx); rot = skel->get_bone_pose_rotation(bone_idx); scale = skel->get_bone_pose_scale(bone_idx); @@ -1828,8 +1867,8 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file) { } Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> collision_map; - - _pre_fix_node(scene, scene, collision_map); + List<Pair<NodePath, Node *>> node_renames; + _pre_fix_node(scene, scene, collision_map, node_renames); return scene; } @@ -1904,8 +1943,9 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p Set<Ref<ImporterMesh>> scanned_meshes; Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> collision_map; + List<Pair<NodePath, Node *>> node_renames; - _pre_fix_node(scene, scene, collision_map); + _pre_fix_node(scene, scene, collision_map, node_renames); for (int i = 0; i < post_importer_plugins.size(); i++) { post_importer_plugins.write[i]->pre_process(scene, p_options); diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index 00d095eac1..13b55b5754 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -159,9 +159,9 @@ class ResourceImporterScene : public ResourceImporter { enum LightBakeMode { LIGHT_BAKE_DISABLED, - LIGHT_BAKE_DYNAMIC, LIGHT_BAKE_STATIC, - LIGHT_BAKE_STATIC_LIGHTMAPS + LIGHT_BAKE_STATIC_LIGHTMAPS, + LIGHT_BAKE_DYNAMIC, }; enum MeshPhysicsMode { @@ -261,7 +261,7 @@ public: // Import scenes *after* everything else (such as textures). virtual int get_import_order() const override { return ResourceImporter::IMPORT_ORDER_SCENE; } - Node *_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map); + Node *_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, List<Pair<NodePath, Node *>> &r_node_renames); Node *_post_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Set<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps); Ref<Animation> _save_animation_to_file(Ref<Animation> anim, bool p_save_to_file, String p_save_to_path, bool p_keep_custom_tracks); diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index 10654cfe43..419688fd9f 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -91,6 +91,8 @@ public: } }; +ImportDock *ImportDock::singleton = nullptr; + void ImportDock::set_edit_path(const String &p_path) { Ref<ConfigFile> config; config.instantiate(); @@ -606,6 +608,7 @@ void ImportDock::initialize_import_options() const { } ImportDock::ImportDock() { + singleton = this; set_name("Import"); content = memnew(VBoxContainer); @@ -687,5 +690,6 @@ ImportDock::ImportDock() { } ImportDock::~ImportDock() { + singleton = nullptr; memdelete(params); } diff --git a/editor/import_dock.h b/editor/import_dock.h index 33fc23f1b4..c5cdc4ac40 100644 --- a/editor/import_dock.h +++ b/editor/import_dock.h @@ -85,6 +85,12 @@ class ImportDock : public VBoxContainer { ITEM_CLEAR_DEFAULT, }; +private: + static ImportDock *singleton; + +public: + static ImportDock *get_singleton() { return singleton; } + protected: static void _bind_methods(); void _notification(int p_what); diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index f56e868286..e36c86fb10 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -33,6 +33,8 @@ #include "editor/editor_scale.h" #include "editor/plugins/animation_player_editor_plugin.h" +InspectorDock *InspectorDock::singleton = nullptr; + void InspectorDock::_menu_option(int p_option) { _menu_option_confirm(p_option, false); } @@ -108,7 +110,7 @@ void InspectorDock::_menu_option_confirm(int p_option, bool p_confirmed) { Variant v = current->get(E->get().name); REF ref = v; RES res = ref; - if (v.is_ref() && ref.is_valid() && res.is_valid()) { + if (v.is_ref_counted() && ref.is_valid() && res.is_valid()) { // Valid resource which would be duplicated if action is confirmed. resource_propnames.append(E->get().name); } @@ -145,7 +147,7 @@ void InspectorDock::_menu_option_confirm(int p_option, bool p_confirmed) { } Variant v = current->get(prop_info.name); - if (v.is_ref()) { + if (v.is_ref_counted()) { REF ref = v; if (ref.is_valid()) { RES res = ref; @@ -156,7 +158,7 @@ void InspectorDock::_menu_option_confirm(int p_option, bool p_confirmed) { res = duplicates[res]; current->set(prop_info.name, res); - editor->get_inspector()->update_property(prop_info.name); + get_inspector_singleton()->update_property(prop_info.name); } } } @@ -382,20 +384,6 @@ void InspectorDock::_menu_expandall() { inspector->expand_all_folding(); } -void InspectorDock::_property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance) { - AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_value_key(p_keyed, p_value, p_advance); -} - -void InspectorDock::_transform_keyed(Object *sp, const String &p_sub, const Transform3D &p_key) { - Node3D *s = Object::cast_to<Node3D>(sp); - if (!s) { - return; - } - AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_transform_key(s, p_sub, Animation::TYPE_POSITION_3D, p_key.origin); - AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_transform_key(s, p_sub, Animation::TYPE_ROTATION_3D, p_key.basis.get_rotation_quaternion()); - AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_transform_key(s, p_sub, Animation::TYPE_SCALE_3D, p_key.basis.get_scale()); -} - void InspectorDock::_warning_pressed() { warning_dialog->popup_centered(); } @@ -440,9 +428,6 @@ void InspectorDock::_notification(int p_what) { } void InspectorDock::_bind_methods() { - ClassDB::bind_method("update_keying", &InspectorDock::update_keying); - ClassDB::bind_method("_transform_keyed", &InspectorDock::_transform_keyed); // Still used by some connect_compat. - ClassDB::bind_method("_unref_resource", &InspectorDock::_unref_resource); ClassDB::bind_method("_paste_resource", &InspectorDock::_paste_resource); ClassDB::bind_method("_copy_resource", &InspectorDock::_copy_resource); @@ -547,23 +532,8 @@ void InspectorDock::go_back() { _edit_back(); } -void InspectorDock::update_keying() { - bool valid = false; - - if (AnimationPlayerEditor::get_singleton()->get_track_editor()->has_keying()) { - EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history(); - if (editor_history->get_path_size() >= 1) { - Object *obj = ObjectDB::get_instance(editor_history->get_path_object(0)); - if (Object::cast_to<Node>(obj)) { - valid = true; - } - } - } - - inspector->set_keying(valid); -} - InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { + singleton = this; set_name("Inspector"); editor = p_editor; @@ -716,8 +686,8 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { inspector->set_use_filter(true); // TODO: check me inspector->connect("resource_selected", callable_mp(this, &InspectorDock::_resource_selected)); - inspector->connect("property_keyed", callable_mp(this, &InspectorDock::_property_keyed)); } InspectorDock::~InspectorDock() { + singleton = nullptr; } diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h index 94e4f67348..9dd3fa2070 100644 --- a/editor/inspector_dock.h +++ b/editor/inspector_dock.h @@ -117,8 +117,12 @@ class InspectorDock : public VBoxContainer { void _select_history(int p_idx); void _prepare_history(); - void _property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance); - void _transform_keyed(Object *sp, const String &p_sub, const Transform3D &p_key); +private: + static InspectorDock *singleton; + +public: + static InspectorDock *get_singleton() { return singleton; } + static EditorInspector *get_inspector_singleton() { return singleton->inspector; } protected: static void _bind_methods(); @@ -126,7 +130,6 @@ protected: public: void go_back(); - void update_keying(); void edit_resource(const Ref<Resource> &p_resource); void open_resource(const String &p_type); void clear(); diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp index a902b070f4..1e9e2fc09b 100644 --- a/editor/localization_editor.cpp +++ b/editor/localization_editor.cpp @@ -32,6 +32,7 @@ #include "core/string/translation.h" #include "editor_node.h" +#include "editor_scale.h" #include "editor_translation_parser.h" #include "pot_generator.h" #include "scene/gui/control.h" @@ -175,10 +176,27 @@ void LocalizationEditor::_translation_res_select() { if (updating_translations) { return; } - call_deferred(SNAME("update_translations")); } +void LocalizationEditor::_translation_res_option_popup(bool p_arrow_clicked) { + TreeItem *ed = translation_remap_options->get_edited(); + ERR_FAIL_COND(!ed); + + locale_select->set_locale(ed->get_tooltip(1)); + locale_select->popup_locale_dialog(); +} + +void LocalizationEditor::_translation_res_option_selected(const String &p_locale) { + TreeItem *ed = translation_remap_options->get_edited(); + ERR_FAIL_COND(!ed); + + ed->set_text(1, TranslationServer::get_singleton()->get_locale_name(p_locale)); + ed->set_tooltip(1, p_locale); + + LocalizationEditor::_translation_res_option_changed(); +} + void LocalizationEditor::_translation_res_option_changed() { if (updating_translations) { return; @@ -198,20 +216,11 @@ void LocalizationEditor::_translation_res_option_changed() { String key = k->get_metadata(0); int idx = ed->get_metadata(0); String path = ed->get_metadata(1); - int which = ed->get_range(1); - - Vector<String> langs = TranslationServer::get_all_locales(); - - ERR_FAIL_INDEX(which, langs.size()); + String locale = ed->get_tooltip(1); ERR_FAIL_COND(!remaps.has(key)); PackedStringArray r = remaps[key]; - ERR_FAIL_INDEX(idx, r.size()); - if (translation_locales_idxs_remap.size() > which) { - r.set(idx, path + ":" + langs[translation_locales_idxs_remap[which]]); - } else { - r.set(idx, path + ":" + langs[which]); - } + r.set(idx, path + ":" + locale); remaps[key] = r; updating_translations = true; @@ -289,86 +298,6 @@ void LocalizationEditor::_translation_res_option_delete(Object *p_item, int p_co undo_redo->commit_action(); } -void LocalizationEditor::_translation_filter_option_changed() { - int sel_id = translation_locale_filter_mode->get_selected_id(); - TreeItem *t = translation_filter->get_edited(); - String locale = t->get_tooltip(0); - bool checked = t->is_checked(0); - - Variant prev; - Array f_locales_all; - - if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter")) { - f_locales_all = ProjectSettings::get_singleton()->get("internationalization/locale/locale_filter"); - prev = f_locales_all; - - if (f_locales_all.size() != 2) { - f_locales_all.clear(); - f_locales_all.append(sel_id); - f_locales_all.append(Array()); - } - } else { - f_locales_all.append(sel_id); - f_locales_all.append(Array()); - } - - Array f_locales = f_locales_all[1]; - int l_idx = f_locales.find(locale); - - if (checked) { - if (l_idx == -1) { - f_locales.append(locale); - } - } else { - if (l_idx != -1) { - f_locales.remove_at(l_idx); - } - } - - f_locales.sort(); - - undo_redo->create_action(TTR("Changed Locale Filter")); - undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter", f_locales_all); - undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter", prev); - undo_redo->add_do_method(this, "update_translations"); - undo_redo->add_undo_method(this, "update_translations"); - undo_redo->add_do_method(this, "emit_signal", localization_changed); - undo_redo->add_undo_method(this, "emit_signal", localization_changed); - undo_redo->commit_action(); -} - -void LocalizationEditor::_translation_filter_mode_changed(int p_mode) { - int sel_id = translation_locale_filter_mode->get_selected_id(); - - Variant prev; - Array f_locales_all; - - if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter")) { - f_locales_all = ProjectSettings::get_singleton()->get("internationalization/locale/locale_filter"); - prev = f_locales_all; - - if (f_locales_all.size() != 2) { - f_locales_all.clear(); - f_locales_all.append(sel_id); - f_locales_all.append(Array()); - } else { - f_locales_all[0] = sel_id; - } - } else { - f_locales_all.append(sel_id); - f_locales_all.append(Array()); - } - - undo_redo->create_action(TTR("Changed Locale Filter Mode")); - undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter", f_locales_all); - undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter", prev); - undo_redo->add_do_method(this, "update_translations"); - undo_redo->add_undo_method(this, "update_translations"); - undo_redo->add_do_method(this, "emit_signal", localization_changed); - undo_redo->add_undo_method(this, "emit_signal", localization_changed); - undo_redo->commit_action(); -} - void LocalizationEditor::_pot_add(const PackedStringArray &p_paths) { PackedStringArray pot_translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations_pot_files"); for (int i = 0; i < p_paths.size(); i++) { @@ -452,64 +381,6 @@ void LocalizationEditor::update_translations() { } } - Vector<String> langs = TranslationServer::get_all_locales(); - Vector<String> names = TranslationServer::get_all_locale_names(); - - // Update filter tab - Array l_filter_all; - - bool is_arr_empty = true; - if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter")) { - l_filter_all = ProjectSettings::get_singleton()->get("internationalization/locale/locale_filter"); - - if (l_filter_all.size() == 2) { - translation_locale_filter_mode->select(l_filter_all[0]); - is_arr_empty = false; - } - } - if (is_arr_empty) { - l_filter_all.append(0); - l_filter_all.append(Array()); - translation_locale_filter_mode->select(0); - } - - int filter_mode = l_filter_all[0]; - Array l_filter = l_filter_all[1]; - - int s = names.size(); - bool is_short_list_when_show_all_selected = filter_mode == SHOW_ALL_LOCALES && translation_filter_treeitems.size() < s; - bool is_full_list_when_show_only_selected = filter_mode == SHOW_ONLY_SELECTED_LOCALES && translation_filter_treeitems.size() == s; - bool should_recreate_locales_list = is_short_list_when_show_all_selected || is_full_list_when_show_only_selected; - - if (!translation_locales_list_created || should_recreate_locales_list) { - translation_locales_list_created = true; - translation_filter->clear(); - root = translation_filter->create_item(nullptr); - translation_filter->set_hide_root(true); - translation_filter_treeitems.clear(); - for (int i = 0; i < s; i++) { - String n = names[i]; - String l = langs[i]; - bool is_checked = l_filter.has(l); - if (filter_mode == SHOW_ONLY_SELECTED_LOCALES && !is_checked) { - continue; - } - - TreeItem *t = translation_filter->create_item(root); - t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); - t->set_text(0, vformat("[%s] %s", l, n)); - t->set_editable(0, true); - t->set_tooltip(0, l); - t->set_checked(0, is_checked); - translation_filter_treeitems.push_back(t); - } - } else { - for (int i = 0; i < translation_filter_treeitems.size(); i++) { - TreeItem *t = translation_filter_treeitems[i]; - t->set_checked(0, l_filter.has(t->get_tooltip(0))); - } - } - // Update translation remaps. String remap_selected; if (translation_remap->get_selected()) { @@ -524,32 +395,6 @@ void LocalizationEditor::update_translations() { translation_remap_options->set_hide_root(true); translation_res_option_add_button->set_disabled(true); - translation_locales_idxs_remap.clear(); - translation_locales_idxs_remap.resize(l_filter.size()); - int fl_idx_count = translation_locales_idxs_remap.size(); - - String langnames = ""; - int l_idx = 0; - for (int i = 0; i < names.size(); i++) { - if (filter_mode == SHOW_ONLY_SELECTED_LOCALES && fl_idx_count != 0) { - if (l_filter.size() > 0) { - if (l_filter.find(langs[i]) != -1) { - if (langnames.length() > 0) { - langnames += ","; - } - langnames += vformat("[%s] %s", langs[i], names[i]); - translation_locales_idxs_remap.write[l_idx] = i; - l_idx++; - } - } - } else { - if (i > 0) { - langnames += ","; - } - langnames += vformat("[%s] %s", langs[i], names[i]); - } - } - if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps")) { Dictionary remaps = ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps"); List<Variant> rk; @@ -584,21 +429,11 @@ void LocalizationEditor::update_translations() { t2->set_tooltip(0, path); t2->set_metadata(0, j); t2->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), 0, false, TTR("Remove")); - t2->set_cell_mode(1, TreeItem::CELL_MODE_RANGE); - t2->set_text(1, langnames); + t2->set_cell_mode(1, TreeItem::CELL_MODE_CUSTOM); + t2->set_text(1, TranslationServer::get_singleton()->get_locale_name(locale)); t2->set_editable(1, true); t2->set_metadata(1, path); - int idx = langs.find(locale); - if (idx < 0) { - idx = 0; - } - - int f_idx = translation_locales_idxs_remap.find(idx); - if (f_idx != -1 && fl_idx_count > 0 && filter_mode == SHOW_ONLY_SELECTED_LOCALES) { - t2->set_range(1, f_idx); - } else { - t2->set_range(1, idx); - } + t2->set_tooltip(1, locale); } } } @@ -637,9 +472,6 @@ LocalizationEditor::LocalizationEditor() { updating_translations = false; localization_changed = "localization_changed"; - translation_locales_idxs_remap = Vector<int>(); - translation_locales_list_created = false; - TabContainer *translations = memnew(TabContainer); translations->set_tab_alignment(TabContainer::ALIGNMENT_LEFT); translations->set_v_size_flags(Control::SIZE_EXPAND_FILL); @@ -669,6 +501,10 @@ LocalizationEditor::LocalizationEditor() { translation_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); tmc->add_child(translation_list); + locale_select = memnew(EditorLocaleDialog); + locale_select->connect("locale_selected", callable_mp(this, &LocalizationEditor::_translation_res_option_selected)); + add_child(locale_select); + translation_file_open = memnew(EditorFileDialog); translation_file_open->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILES); translation_file_open->connect("files_selected", callable_mp(this, &LocalizationEditor::_translation_add)); @@ -731,10 +567,11 @@ LocalizationEditor::LocalizationEditor() { translation_remap_options->set_column_expand(0, true); translation_remap_options->set_column_clip_content(0, true); translation_remap_options->set_column_expand(1, false); - translation_remap_options->set_column_clip_content(1, true); - translation_remap_options->set_column_custom_minimum_width(1, 200); + translation_remap_options->set_column_clip_content(1, false); + translation_remap_options->set_column_custom_minimum_width(1, 250); translation_remap_options->connect("item_edited", callable_mp(this, &LocalizationEditor::_translation_res_option_changed)); translation_remap_options->connect("button_pressed", callable_mp(this, &LocalizationEditor::_translation_res_option_delete)); + translation_remap_options->connect("custom_popup_edited", callable_mp(this, &LocalizationEditor::_translation_res_option_popup)); tmc->add_child(translation_remap_options); translation_res_option_file_open_dialog = memnew(EditorFileDialog); @@ -745,32 +582,6 @@ LocalizationEditor::LocalizationEditor() { { VBoxContainer *tvb = memnew(VBoxContainer); - tvb->set_name(TTR("Locales Filter")); - translations->add_child(tvb); - - VBoxContainer *tmc = memnew(VBoxContainer); - tmc->set_v_size_flags(Control::SIZE_EXPAND_FILL); - tvb->add_child(tmc); - - translation_locale_filter_mode = memnew(OptionButton); - translation_locale_filter_mode->add_item(TTR("Show All Locales"), SHOW_ALL_LOCALES); - translation_locale_filter_mode->add_item(TTR("Show Selected Locales Only"), SHOW_ONLY_SELECTED_LOCALES); - translation_locale_filter_mode->select(0); - translation_locale_filter_mode->connect("item_selected", callable_mp(this, &LocalizationEditor::_translation_filter_mode_changed)); - tmc->add_margin_child(TTR("Filter mode:"), translation_locale_filter_mode); - - Label *l = memnew(Label(TTR("Locales:"))); - l->set_theme_type_variation("HeaderSmall"); - tmc->add_child(l); - translation_filter = memnew(Tree); - translation_filter->set_v_size_flags(Control::SIZE_EXPAND_FILL); - translation_filter->set_columns(1); - translation_filter->connect("item_edited", callable_mp(this, &LocalizationEditor::_translation_filter_option_changed)); - tmc->add_child(translation_filter); - } - - { - VBoxContainer *tvb = memnew(VBoxContainer); tvb->set_name(TTR("POT Generation")); translations->add_child(tvb); diff --git a/editor/localization_editor.h b/editor/localization_editor.h index 4c77aca397..cad07dd336 100644 --- a/editor/localization_editor.h +++ b/editor/localization_editor.h @@ -33,18 +33,15 @@ #include "core/object/undo_redo.h" #include "editor_file_dialog.h" +#include "editor_locale_dialog.h" #include "scene/gui/tree.h" class LocalizationEditor : public VBoxContainer { GDCLASS(LocalizationEditor, VBoxContainer); - enum LocaleFilter { - SHOW_ALL_LOCALES, - SHOW_ONLY_SELECTED_LOCALES, - }; - Tree *translation_list; + EditorLocaleDialog *locale_select; EditorFileDialog *translation_file_open; Button *translation_res_option_add_button; @@ -52,11 +49,6 @@ class LocalizationEditor : public VBoxContainer { EditorFileDialog *translation_res_option_file_open_dialog; Tree *translation_remap; Tree *translation_remap_options; - Tree *translation_filter; - bool translation_locales_list_created; - OptionButton *translation_locale_filter_mode; - Vector<TreeItem *> translation_filter_treeitems; - Vector<int> translation_locales_idxs_remap; Tree *translation_pot_list; EditorFileDialog *pot_file_open_dialog; @@ -78,9 +70,8 @@ class LocalizationEditor : public VBoxContainer { void _translation_res_option_add(const PackedStringArray &p_paths); void _translation_res_option_changed(); void _translation_res_option_delete(Object *p_item, int p_column, int p_button); - - void _translation_filter_option_changed(); - void _translation_filter_mode_changed(int p_mode); + void _translation_res_option_popup(bool p_arrow_clicked); + void _translation_res_option_selected(const String &p_locale); void _pot_add(const PackedStringArray &p_paths); void _pot_delete(Object *p_item, int p_column, int p_button); diff --git a/editor/multi_node_edit.cpp b/editor/multi_node_edit.cpp index 59fc473d73..c61380684a 100644 --- a/editor/multi_node_edit.cpp +++ b/editor/multi_node_edit.cpp @@ -87,8 +87,8 @@ bool MultiNodeEdit::_set_impl(const StringName &p_name, const Variant &p_value, ur->add_undo_property(n, name, n->get(name)); } - ur->add_do_method(EditorNode::get_singleton()->get_inspector(), "refresh"); - ur->add_undo_method(EditorNode::get_singleton()->get_inspector(), "refresh"); + ur->add_do_method(InspectorDock::get_inspector_singleton(), "refresh"); + ur->add_undo_method(InspectorDock::get_inspector_singleton(), "refresh"); ur->commit_action(); return true; diff --git a/editor/node_dock.cpp b/editor/node_dock.cpp index d8f16b367a..1246ebe0dd 100644 --- a/editor/node_dock.cpp +++ b/editor/node_dock.cpp @@ -134,3 +134,7 @@ NodeDock::NodeDock() { select_a_node->set_autowrap_mode(Label::AUTOWRAP_WORD_SMART); add_child(select_a_node); } + +NodeDock::~NodeDock() { + singleton = nullptr; +} diff --git a/editor/node_dock.h b/editor/node_dock.h index b35be8de8a..4c814ab65f 100644 --- a/editor/node_dock.h +++ b/editor/node_dock.h @@ -48,13 +48,17 @@ class NodeDock : public VBoxContainer { Label *select_a_node; +private: + static NodeDock *singleton; + +public: + static NodeDock *get_singleton() { return singleton; } + protected: static void _bind_methods(); void _notification(int p_what); public: - static NodeDock *singleton; - void set_node(Node *p_node); void show_groups(); @@ -63,6 +67,7 @@ public: void update_lists(); NodeDock(); + ~NodeDock(); }; #endif // NODE_DOCK_H diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index 71db40a829..b889742b19 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -40,6 +40,7 @@ #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" #include "scene/gui/progress_bar.h" +#include "scene/gui/view_panner.h" #include "scene/main/window.h" void AnimationNodeBlendTreeEditor::add_custom_type(const String &p_name, const Ref<Script> &p_script) { @@ -733,7 +734,8 @@ void AnimationNodeBlendTreeEditor::_removed_from_graph() { void AnimationNodeBlendTreeEditor::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { - graph->set_panning_scheme((GraphEdit::PanningScheme)EDITOR_GET("interface/editors/sub_editor_panning_scheme").operator int()); + graph->get_panner()->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/sub_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EditorSettings::get_singleton()->get("editors/panning/simple_panning"))); + graph->set_warped_panning(bool(EditorSettings::get_singleton()->get("editors/panning/warped_mouse_panning"))); } if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index d7c0ba7540..83c2b53241 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -301,7 +301,6 @@ void AnimationPlayerEditor::_animation_selected(int p_which) { autoplay->set_pressed(current == player->get_autoplay()); AnimationPlayerEditor::get_singleton()->get_track_editor()->update_keying(); - EditorNode::get_singleton()->update_keying(); _animation_key_editor_seek(timeline_position, false); } @@ -829,7 +828,6 @@ void AnimationPlayerEditor::_update_player() { if (!player) { AnimationPlayerEditor::get_singleton()->get_track_editor()->update_keying(); - EditorNode::get_singleton()->update_keying(); return; } @@ -1507,7 +1505,7 @@ void AnimationPlayerEditor::_stop_onion_skinning() { } void AnimationPlayerEditor::_pin_pressed() { - EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->update_tree(); + SceneTreeDock::get_singleton()->get_tree_editor()->update_tree(); } void AnimationPlayerEditor::_bind_methods() { @@ -1795,11 +1793,39 @@ AnimationPlayerEditor::~AnimationPlayerEditor() { void AnimationPlayerEditorPlugin::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { + Node3DEditor::get_singleton()->connect("transform_key_request", callable_mp(this, &AnimationPlayerEditorPlugin::_transform_key_request)); + InspectorDock::get_inspector_singleton()->connect("property_keyed", callable_mp(this, &AnimationPlayerEditorPlugin::_property_keyed)); + anim_editor->get_track_editor()->connect("keying_changed", callable_mp(this, &AnimationPlayerEditorPlugin::_update_keying)); + InspectorDock::get_inspector_singleton()->connect("edited_object_changed", callable_mp(anim_editor->get_track_editor(), &AnimationTrackEditor::update_keying)); set_force_draw_over_forwarding_enabled(); } break; } } +void AnimationPlayerEditorPlugin::_property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance) { + if (!anim_editor->get_track_editor()->has_keying()) { + return; + } + anim_editor->get_track_editor()->insert_value_key(p_keyed, p_value, p_advance); +} + +void AnimationPlayerEditorPlugin::_transform_key_request(Object *sp, const String &p_sub, const Transform3D &p_key) { + if (!anim_editor->get_track_editor()->has_keying()) { + return; + } + Node3D *s = Object::cast_to<Node3D>(sp); + if (!s) { + return; + } + anim_editor->get_track_editor()->insert_transform_key(s, p_sub, Animation::TYPE_POSITION_3D, p_key.origin); + anim_editor->get_track_editor()->insert_transform_key(s, p_sub, Animation::TYPE_ROTATION_3D, p_key.basis.get_rotation_quaternion()); + anim_editor->get_track_editor()->insert_transform_key(s, p_sub, Animation::TYPE_SCALE_3D, p_key.basis.get_scale()); +} + +void AnimationPlayerEditorPlugin::_update_keying() { + InspectorDock::get_inspector_singleton()->set_keying(anim_editor->get_track_editor()->has_keying()); +} + void AnimationPlayerEditorPlugin::edit(Object *p_object) { anim_editor->set_undo_redo(&get_undo_redo()); if (!p_object) { diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h index 626d31f439..06dca11aff 100644 --- a/editor/plugins/animation_player_editor_plugin.h +++ b/editor/plugins/animation_player_editor_plugin.h @@ -255,6 +255,10 @@ class AnimationPlayerEditorPlugin : public EditorPlugin { protected: void _notification(int p_what); + void _property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance); + void _transform_key_request(Object *sp, const String &p_sub, const Transform3D &p_key); + void _update_keying(); + public: virtual Dictionary get_state() const override { return anim_editor->get_state(); } virtual void set_state(const Dictionary &p_state) override { anim_editor->set_state(p_state); } diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 31ef13a2eb..7199f69f0b 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -369,19 +369,19 @@ void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int download_error->set_text(TTR("Asset Download Error:") + "\n" + error_text); download_error->popup_centered(); // Let the user retry the download. - retry->show(); + retry_button->show(); return; } - install->set_disabled(false); - status->set_text(TTR("Success!")); + install_button->set_disabled(false); + status->set_text(TTR("Ready to install!")); // Make the progress bar invisible but don't reflow other Controls around it. progress->set_modulate(Color(0, 0, 0, 0)); set_process(false); // Automatically prompt for installation once the download is completed. - _install(); + install(); } void EditorAssetLibraryItemDownload::configure(const String &p_title, int p_asset_id, const Ref<Texture2D> &p_preview, const String &p_download_url, const String &p_sha256_hash) { @@ -400,8 +400,9 @@ void EditorAssetLibraryItemDownload::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TabContainer"))); - dismiss->set_normal_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons"))); + panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("AssetLib"))); + status->add_theme_color_override("font_color", get_theme_color(SNAME("status_color"), SNAME("AssetLib"))); + dismiss_button->set_normal_texture(get_theme_icon(SNAME("dismiss"), SNAME("AssetLib"))); } break; case NOTIFICATION_PROCESS: { // Make the progress bar visible again when retrying the download. @@ -461,7 +462,11 @@ void EditorAssetLibraryItemDownload::_close() { queue_delete(); } -void EditorAssetLibraryItemDownload::_install() { +bool EditorAssetLibraryItemDownload::can_install() const { + return !install_button->is_disabled(); +} + +void EditorAssetLibraryItemDownload::install() { String file = download->get_download_file(); if (external_install) { @@ -475,7 +480,7 @@ void EditorAssetLibraryItemDownload::_install() { void EditorAssetLibraryItemDownload::_make_request() { // Hide the Retry button if we've just pressed it. - retry->hide(); + retry_button->hide(); download->cancel_request(); download->set_download_file(EditorPaths::get_singleton()->get_cache_dir().plus_file("tmp_asset_" + itos(asset_id)) + ".zip"); @@ -499,6 +504,8 @@ EditorAssetLibraryItemDownload::EditorAssetLibraryItemDownload() { HBoxContainer *hb = memnew(HBoxContainer); panel->add_child(hb); icon = memnew(TextureRect); + icon->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED); + icon->set_v_size_flags(0); hb->add_child(icon); VBoxContainer *vb = memnew(VBoxContainer); @@ -511,9 +518,9 @@ EditorAssetLibraryItemDownload::EditorAssetLibraryItemDownload() { title_hb->add_child(title); title->set_h_size_flags(Control::SIZE_EXPAND_FILL); - dismiss = memnew(TextureButton); - dismiss->connect("pressed", callable_mp(this, &EditorAssetLibraryItemDownload::_close)); - title_hb->add_child(dismiss); + dismiss_button = memnew(TextureButton); + dismiss_button->connect("pressed", callable_mp(this, &EditorAssetLibraryItemDownload::_close)); + title_hb->add_child(dismiss_button); title->set_clip_text(true); @@ -521,7 +528,6 @@ EditorAssetLibraryItemDownload::EditorAssetLibraryItemDownload() { status = memnew(Label(TTR("Idle"))); vb->add_child(status); - status->add_theme_color_override("font_color", Color(0.5, 0.5, 0.5)); progress = memnew(ProgressBar); vb->add_child(progress); @@ -529,19 +535,19 @@ EditorAssetLibraryItemDownload::EditorAssetLibraryItemDownload() { vb->add_child(hb2); hb2->add_spacer(); - install = memnew(Button); - install->set_text(TTR("Install...")); - install->set_disabled(true); - install->connect("pressed", callable_mp(this, &EditorAssetLibraryItemDownload::_install)); + install_button = memnew(Button); + install_button->set_text(TTR("Install...")); + install_button->set_disabled(true); + install_button->connect("pressed", callable_mp(this, &EditorAssetLibraryItemDownload::install)); - retry = memnew(Button); - retry->set_text(TTR("Retry")); - retry->connect("pressed", callable_mp(this, &EditorAssetLibraryItemDownload::_make_request)); + retry_button = memnew(Button); + retry_button->set_text(TTR("Retry")); + retry_button->connect("pressed", callable_mp(this, &EditorAssetLibraryItemDownload::_make_request)); // Only show the Retry button in case of a failure. - retry->hide(); + retry_button->hide(); - hb2->add_child(retry); - hb2->add_child(install); + hb2->add_child(retry_button); + hb2->add_child(install_button); set_custom_minimum_size(Size2(310, 0) * EDSCALE); download = memnew(HTTPRequest); @@ -606,6 +612,7 @@ void EditorAssetLibrary::_notification(int p_what) { } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { _update_repository_options(); + setup_http_request(request); } break; } } @@ -640,14 +647,10 @@ void EditorAssetLibrary::unhandled_key_input(const Ref<InputEvent> &p_event) { void EditorAssetLibrary::_install_asset() { ERR_FAIL_COND(!description); - for (int i = 0; i < downloads_hb->get_child_count(); i++) { - EditorAssetLibraryItemDownload *d = Object::cast_to<EditorAssetLibraryItemDownload>(downloads_hb->get_child(i)); - if (d && d->get_asset_id() == description->get_asset_id()) { - if (EditorNode::get_singleton() != nullptr) { - EditorNode::get_singleton()->show_warning(TTR("Download for this asset is already in progress!")); - } - return; - } + EditorAssetLibraryItemDownload *d = _get_asset_in_progress(description->get_asset_id()); + if (d) { + d->install(); + return; } EditorAssetLibraryItemDownload *download = memnew(EditorAssetLibraryItemDownload); @@ -1265,6 +1268,20 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const description->configure(r["title"], r["asset_id"], category_map[r["category_id"]], r["category_id"], r["author"], r["author_id"], r["cost"], r["version"], r["version_string"], r["description"], r["download_url"], r["browse_url"], r["download_hash"]); + EditorAssetLibraryItemDownload *download_item = _get_asset_in_progress(description->get_asset_id()); + if (download_item) { + if (download_item->can_install()) { + description->get_ok_button()->set_text(TTR("Install")); + description->get_ok_button()->set_disabled(false); + } else { + description->get_ok_button()->set_text(TTR("Downloading...")); + description->get_ok_button()->set_disabled(true); + } + } else { + description->get_ok_button()->set_text(TTR("Download")); + description->get_ok_button()->set_disabled(false); + } + if (r.has("icon_url") && !r["icon_url"].operator String().is_empty()) { _request_image(description->get_instance_id(), r["icon_url"], IMAGE_QUEUE_ICON, 0); } @@ -1322,6 +1339,17 @@ void EditorAssetLibrary::_manage_plugins() { ProjectSettingsEditor::get_singleton()->set_plugins_page(); } +EditorAssetLibraryItemDownload *EditorAssetLibrary::_get_asset_in_progress(int p_asset_id) const { + for (int i = 0; i < downloads_hb->get_child_count(); i++) { + EditorAssetLibraryItemDownload *d = Object::cast_to<EditorAssetLibraryItemDownload>(downloads_hb->get_child(i)); + if (d && d->get_asset_id() == p_asset_id) { + return d; + } + } + + return nullptr; +} + void EditorAssetLibrary::_install_external_asset(String p_zip_path, String p_title) { emit_signal(SNAME("install_asset"), p_zip_path, p_title); } diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h index 8d6c0eb76e..29d26411f3 100644 --- a/editor/plugins/asset_library_editor_plugin.h +++ b/editor/plugins/asset_library_editor_plugin.h @@ -39,6 +39,7 @@ #include "scene/gui/grid_container.h" #include "scene/gui/line_edit.h" #include "scene/gui/link_button.h" +#include "scene/gui/margin_container.h" #include "scene/gui/option_button.h" #include "scene/gui/panel_container.h" #include "scene/gui/progress_bar.h" @@ -126,16 +127,16 @@ public: EditorAssetLibraryItemDescription(); }; -class EditorAssetLibraryItemDownload : public Control { - GDCLASS(EditorAssetLibraryItemDownload, Control); +class EditorAssetLibraryItemDownload : public MarginContainer { + GDCLASS(EditorAssetLibraryItemDownload, MarginContainer); PanelContainer *panel; TextureRect *icon; Label *title; ProgressBar *progress; - Button *install; - Button *retry; - TextureButton *dismiss; + Button *install_button; + Button *retry_button; + TextureButton *dismiss_button; AcceptDialog *download_error; HTTPRequest *download; @@ -152,7 +153,6 @@ class EditorAssetLibraryItemDownload : public Control { EditorAssetInstaller *asset_installer; void _close(); - void _install(); void _make_request(); void _http_download_completed(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data); @@ -164,6 +164,10 @@ public: void set_external_install(bool p_enable) { external_install = p_enable; } int get_asset_id() { return asset_id; } void configure(const String &p_title, int p_asset_id, const Ref<Texture2D> &p_preview, const String &p_download_url, const String &p_sha256_hash); + + bool can_install() const; + void install(); + EditorAssetLibraryItemDownload(); }; @@ -287,6 +291,7 @@ class EditorAssetLibrary : public PanelContainer { void _api_request(const String &p_request, RequestType p_request_type, const String &p_arguments = ""); void _http_request_completed(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data); void _filter_debounce_timer_timeout(); + EditorAssetLibraryItemDownload *_get_asset_in_progress(int p_asset_id) const; void _repository_changed(int p_repository_id); void _support_toggled(int p_support); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 970d53a137..4093c70c47 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -51,6 +51,7 @@ #include "scene/gui/grid_container.h" #include "scene/gui/nine_patch_rect.h" #include "scene/gui/subviewport_container.h" +#include "scene/gui/view_panner.h" #include "scene/main/canvas_layer.h" #include "scene/main/window.h" #include "scene/resources/packed_scene.h" @@ -882,9 +883,9 @@ void CanvasItemEditor::_selection_menu_hide() { void CanvasItemEditor::_add_node_pressed(int p_result) { if (p_result == AddNodeOption::ADD_NODE) { - editor->get_scene_tree_dock()->open_add_child_dialog(); + SceneTreeDock::get_singleton()->open_add_child_dialog(); } else if (p_result == AddNodeOption::ADD_INSTANCE) { - editor->get_scene_tree_dock()->open_instance_child_dialog(); + SceneTreeDock::get_singleton()->open_instance_child_dialog(); } } @@ -1116,77 +1117,14 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve } bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bool p_already_accepted) { - Ref<InputEventMouseButton> b = p_event; - if (b.is_valid() && !p_already_accepted) { - const bool pan_on_scroll = bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan")) && !b->is_ctrl_pressed(); - - if (pan_on_scroll) { - // Perform horizontal scrolling first so we can check for Shift being held. - if (b->is_pressed() && - (b->get_button_index() == MouseButton::WHEEL_LEFT || (b->is_shift_pressed() && b->get_button_index() == MouseButton::WHEEL_UP))) { - // Pan left - view_offset.x -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); - update_viewport(); - return true; - } - - if (b->is_pressed() && - (b->get_button_index() == MouseButton::WHEEL_RIGHT || (b->is_shift_pressed() && b->get_button_index() == MouseButton::WHEEL_DOWN))) { - // Pan right - view_offset.x += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); - update_viewport(); - return true; - } - } - - if (b->is_pressed() && b->get_button_index() == MouseButton::WHEEL_DOWN) { - // Scroll or pan down - if (pan_on_scroll) { - view_offset.y += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); - update_viewport(); - } else { - zoom_widget->set_zoom_by_increments(-1, Input::get_singleton()->is_key_pressed(Key::ALT)); - if (!Math::is_equal_approx(b->get_factor(), 1.0f)) { - // Handle high-precision (analog) scrolling. - zoom_widget->set_zoom(zoom * ((zoom_widget->get_zoom() / zoom - 1.f) * b->get_factor() + 1.f)); - } - _zoom_on_position(zoom_widget->get_zoom(), b->get_position()); - } - return true; - } - - if (b->is_pressed() && b->get_button_index() == MouseButton::WHEEL_UP) { - // Scroll or pan up - if (pan_on_scroll) { - view_offset.y -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); - update_viewport(); - } else { - zoom_widget->set_zoom_by_increments(1, Input::get_singleton()->is_key_pressed(Key::ALT)); - if (!Math::is_equal_approx(b->get_factor(), 1.0f)) { - // Handle high-precision (analog) scrolling. - zoom_widget->set_zoom(zoom * ((zoom_widget->get_zoom() / zoom - 1.f) * b->get_factor() + 1.f)); - } - _zoom_on_position(zoom_widget->get_zoom(), b->get_position()); - } - return true; - } - - if (!panning) { - if (b->is_pressed() && - (b->get_button_index() == MouseButton::MIDDLE || - (b->get_button_index() == MouseButton::LEFT && tool == TOOL_PAN) || - (b->get_button_index() == MouseButton::LEFT && !EditorSettings::get_singleton()->get("editors/2d/simple_panning") && pan_pressed))) { - // Pan the viewport - panning = true; - } - } + bool panner_active = panner->gui_input(p_event, warped_panning ? viewport->get_global_rect() : Rect2()); + if (panner->is_panning() != pan_pressed) { + pan_pressed = panner->is_panning(); + _update_cursor(); + } - if (panning) { - if (!b->is_pressed() && (pan_on_scroll || (b->get_button_index() != MouseButton::WHEEL_DOWN && b->get_button_index() != MouseButton::WHEEL_UP))) { - // Stop panning the viewport (for any mouse button press except zooming) - panning = false; - } - } + if (panner_active) { + return true; } Ref<InputEventKey> k = p_event; @@ -1214,44 +1152,6 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo _update_zoom(16.0 * MAX(1, EDSCALE)); } } - - bool is_pan_key = pan_view_shortcut.is_valid() && pan_view_shortcut->matches_event(p_event); - - if (is_pan_key && (EditorSettings::get_singleton()->get("editors/2d/simple_panning") || drag_type != DRAG_NONE)) { - if (!panning) { - if (k->is_pressed() && !k->is_echo()) { - //Pan the viewport - panning = true; - } - } else { - if (!k->is_pressed()) { - // Stop panning the viewport (for any mouse button press) - panning = false; - } - } - } - - if (is_pan_key && pan_pressed != k->is_pressed()) { - pan_pressed = k->is_pressed(); - _update_cursor(); - } - } - - Ref<InputEventMouseMotion> m = p_event; - if (m.is_valid()) { - if (panning) { - // Pan the viewport - Point2i relative; - if (bool(EditorSettings::get_singleton()->get("editors/2d/warped_mouse_panning"))) { - relative = Input::get_singleton()->warp_mouse_motion(m, viewport->get_global_rect()); - } else { - relative = m->get_relative(); - } - view_offset.x -= relative.x / zoom; - view_offset.y -= relative.y / zoom; - update_viewport(); - return true; - } } Ref<InputEventMagnifyGesture> magnify_gesture = p_event; @@ -1277,7 +1177,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo } // Pan gesture - const Vector2 delta = (int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom) * pan_gesture->get_delta(); + const Vector2 delta = (pan_speed / zoom) * pan_gesture->get_delta(); view_offset.x += delta.x; view_offset.y += delta.y; update_viewport(); @@ -1287,6 +1187,25 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo return false; } +void CanvasItemEditor::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) { + _pan_callback(-p_scroll_vec * pan_speed); +} + +void CanvasItemEditor::_pan_callback(Vector2 p_scroll_vec) { + view_offset.x -= p_scroll_vec.x / zoom; + view_offset.y -= p_scroll_vec.y / zoom; + update_viewport(); +} + +void CanvasItemEditor::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) { + zoom_widget->set_zoom_by_increments(-1, p_alt); + if (!Math::is_equal_approx(p_scroll_vec.y, (real_t)1.0)) { + // Handle high-precision (analog) scrolling. + zoom_widget->set_zoom(zoom * ((zoom_widget->get_zoom() / zoom - 1.f) * p_scroll_vec.y + 1.f)); + } + _zoom_on_position(zoom_widget->get_zoom(), p_origin); +} + bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) { Ref<InputEventMouseMotion> m = p_event; Ref<InputEventMouseButton> b = p_event; @@ -2281,7 +2200,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { return true; } - if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed() && tool == TOOL_SELECT) { + if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed() && tool == TOOL_SELECT && !panner->is_panning()) { // Single item selection Point2 click = transform.affine_inverse().xform(b->get_position()); @@ -2498,31 +2417,34 @@ bool CanvasItemEditor::_gui_input_hover(const Ref<InputEvent> &p_event) { void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) { bool accepted = false; - if (EditorSettings::get_singleton()->get("editors/2d/simple_panning") || !pan_pressed) { + Ref<InputEventMouseButton> mb = p_event; + bool release_lmb = (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT); // Required to properly release some stuff (e.g. selection box) while panning. + + if (EditorSettings::get_singleton()->get("editors/panning/simple_panning") || !pan_pressed || release_lmb) { if ((accepted = _gui_input_rulers_and_guides(p_event))) { - //printf("Rulers and guides\n"); + // print_line("Rulers and guides"); } else if ((accepted = editor->get_editor_plugins_over()->forward_gui_input(p_event))) { - //printf("Plugin\n"); + // print_line("Plugin"); } else if ((accepted = _gui_input_open_scene_on_double_click(p_event))) { - //printf("Open scene on double click\n"); + // print_line("Open scene on double click"); } else if ((accepted = _gui_input_scale(p_event))) { - //printf("Set scale\n"); + // print_line("Set scale"); } else if ((accepted = _gui_input_pivot(p_event))) { - //printf("Set pivot\n"); + // print_line("Set pivot"); } else if ((accepted = _gui_input_resize(p_event))) { - //printf("Resize\n"); + // print_line("Resize"); } else if ((accepted = _gui_input_rotate(p_event))) { - //printf("Rotate\n"); + // print_line("Rotate"); } else if ((accepted = _gui_input_move(p_event))) { - //printf("Move\n"); + // print_line("Move"); } else if ((accepted = _gui_input_anchors(p_event))) { - //printf("Anchors\n"); + // print_line("Anchors"); } else if ((accepted = _gui_input_select(p_event))) { - //printf("Selection\n"); + // print_line("Selection"); } else if ((accepted = _gui_input_ruler_tool(p_event))) { - //printf("Measure\n"); + // print_line("Measure"); } else { - //printf("Not accepted\n"); + // print_line("Not accepted"); } } @@ -3935,6 +3857,10 @@ void CanvasItemEditor::_notification(int p_what) { anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignWide"), SNAME("EditorIcons")), TTR("Full Rect"), ANCHORS_PRESET_WIDE); anchor_mode_button->set_icon(get_theme_icon(SNAME("Anchor"), SNAME("EditorIcons"))); + + panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/2d_editor_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EditorSettings::get_singleton()->get("editors/panning/simple_panning"))); + pan_speed = int(EditorSettings::get_singleton()->get("editors/panning/2d_editor_pan_speed")); + warped_panning = bool(EditorSettings::get_singleton()->get("editors/panning/warped_mouse_panning")); } if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { @@ -5129,8 +5055,22 @@ void CanvasItemEditor::remove_control_from_menu_panel(Control *p_control) { hbc_context_menu->remove_child(p_control); } -HSplitContainer *CanvasItemEditor::get_palette_split() { - return palette_split; +void CanvasItemEditor::add_control_to_left_panel(Control *p_control) { + left_panel_split->add_child(p_control); + left_panel_split->move_child(p_control, 0); +} + +void CanvasItemEditor::add_control_to_right_panel(Control *p_control) { + right_panel_split->add_child(p_control); + right_panel_split->move_child(p_control, 1); +} + +void CanvasItemEditor::remove_control_from_left_panel(Control *p_control) { + left_panel_split->remove_child(p_control); +} + +void CanvasItemEditor::remove_control_from_right_panel(Control *p_control) { + right_panel_split->remove_child(p_control); } VSplitContainer *CanvasItemEditor::get_bottom_split() { @@ -5191,7 +5131,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { dragged_guide_index = -1; is_hovering_h_guide = false; is_hovering_v_guide = false; - panning = false; pan_pressed = false; ruler_tool_active = false; @@ -5207,8 +5146,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { editor_selection->connect("selection_changed", callable_mp((CanvasItem *)this, &CanvasItem::update)); editor_selection->connect("selection_changed", callable_mp(this, &CanvasItemEditor::_selection_changed)); - editor->get_scene_tree_dock()->connect("node_created", callable_mp(this, &CanvasItemEditor::_node_created)); - editor->get_scene_tree_dock()->connect("add_node_used", callable_mp(this, &CanvasItemEditor::_reset_create_position)); + SceneTreeDock::get_singleton()->connect("node_created", callable_mp(this, &CanvasItemEditor::_node_created)); + SceneTreeDock::get_singleton()->connect("add_node_used", callable_mp(this, &CanvasItemEditor::_reset_create_position)); editor->call_deferred(SNAME("connect"), "play_pressed", Callable(this, "_update_override_camera_button"), make_binds(true)); editor->call_deferred(SNAME("connect"), "stop_pressed", Callable(this, "_update_override_camera_button"), make_binds(false)); @@ -5221,12 +5160,16 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { add_child(bottom_split); bottom_split->set_v_size_flags(Control::SIZE_EXPAND_FILL); - palette_split = memnew(HSplitContainer); - bottom_split->add_child(palette_split); - palette_split->set_v_size_flags(Control::SIZE_EXPAND_FILL); + left_panel_split = memnew(HSplitContainer); + bottom_split->add_child(left_panel_split); + left_panel_split->set_v_size_flags(Control::SIZE_EXPAND_FILL); + + right_panel_split = memnew(HSplitContainer); + left_panel_split->add_child(right_panel_split); + right_panel_split->set_v_size_flags(Control::SIZE_EXPAND_FILL); viewport_scrollable = memnew(Control); - palette_split->add_child(viewport_scrollable); + right_panel_split->add_child(viewport_scrollable); viewport_scrollable->set_mouse_filter(MOUSE_FILTER_PASS); viewport_scrollable->set_clip_contents(true); viewport_scrollable->set_v_size_flags(Control::SIZE_EXPAND_FILL); @@ -5242,6 +5185,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { controls_vb = memnew(VBoxContainer); controls_vb->set_begin(Point2(5, 5)); + panner.instantiate(); + panner->set_callbacks(callable_mp(this, &CanvasItemEditor::_scroll_callback), callable_mp(this, &CanvasItemEditor::_pan_callback), callable_mp(this, &CanvasItemEditor::_zoom_callback)); + viewport = memnew(CanvasItemEditorViewport(p_editor, this)); viewport_scrollable->add_child(viewport); viewport->set_mouse_filter(MOUSE_FILTER_PASS); @@ -5250,6 +5196,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { viewport->set_focus_mode(FOCUS_ALL); viewport->connect("draw", callable_mp(this, &CanvasItemEditor::_draw_viewport)); viewport->connect("gui_input", callable_mp(this, &CanvasItemEditor::_gui_input_viewport)); + viewport->connect("focus_exited", callable_mp(panner.ptr(), &ViewPanner::release_pan_key)); h_scroll = memnew(HScrollBar); viewport->add_child(h_scroll); @@ -5600,13 +5547,12 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { add_node_menu = memnew(PopupMenu); add_child(add_node_menu); - add_node_menu->add_icon_item(editor->get_scene_tree_dock()->get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), TTR("Add Node Here")); - add_node_menu->add_icon_item(editor->get_scene_tree_dock()->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), TTR("Instance Scene Here")); + add_node_menu->add_icon_item(SceneTreeDock::get_singleton()->get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), TTR("Add Node Here")); + add_node_menu->add_icon_item(SceneTreeDock::get_singleton()->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), TTR("Instance Scene Here")); add_node_menu->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_add_node_pressed)); multiply_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/multiply_grid_step", TTR("Multiply grid step by 2"), Key::KP_MULTIPLY); divide_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/divide_grid_step", TTR("Divide grid step by 2"), Key::KP_DIVIDE); - pan_view_shortcut = ED_SHORTCUT("canvas_item_editor/pan_view", TTR("Pan View"), Key::SPACE); skeleton_menu->get_popup()->set_item_checked(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES), true); singleton = this; @@ -6112,7 +6058,7 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte target_node = nullptr; editor = p_node; - editor_data = editor->get_scene_tree_dock()->get_editor_data(); + editor_data = SceneTreeDock::get_singleton()->get_editor_data(); canvas_item_editor = p_canvas_item_editor; preview_node = memnew(Control); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 8bba5130d4..1e8fc0670d 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -42,6 +42,7 @@ #include "scene/main/canvas_item.h" class CanvasItemEditorViewport; +class ViewPanner; class CanvasItemEditorSelectedItem : public Object { GDCLASS(CanvasItemEditorSelectedItem, Object); @@ -276,7 +277,6 @@ private: bool key_pos; bool key_rot; bool key_scale; - bool panning; bool pan_pressed; bool ruler_tool_active; @@ -402,7 +402,13 @@ private: Ref<Shortcut> set_pivot_shortcut; Ref<Shortcut> multiply_grid_step_shortcut; Ref<Shortcut> divide_grid_step_shortcut; - Ref<Shortcut> pan_view_shortcut; + + Ref<ViewPanner> panner; + bool warped_panning = true; + int pan_speed = 20; + void _scroll_callback(Vector2 p_scroll_vec, bool p_alt); + void _pan_callback(Vector2 p_scroll_vec); + void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt); bool _is_node_locked(const Node *p_node); bool _is_node_movable(const Node *p_node, bool p_popup_warning = false); @@ -527,7 +533,8 @@ private: void _update_override_camera_button(bool p_game_running); - HSplitContainer *palette_split; + HSplitContainer *left_panel_split; + HSplitContainer *right_panel_split; VSplitContainer *bottom_split; void _update_context_menu_stylebox(); @@ -571,7 +578,12 @@ public: void add_control_to_menu_panel(Control *p_control); void remove_control_from_menu_panel(Control *p_control); - HSplitContainer *get_palette_split(); + void add_control_to_left_panel(Control *p_control); + void remove_control_from_left_panel(Control *p_control); + + void add_control_to_right_panel(Control *p_control); + void remove_control_from_right_panel(Control *p_control); + VSplitContainer *get_bottom_split(); Control *get_viewport_control() { return viewport; } diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp index 6b93a1872d..06be9d678f 100644 --- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp @@ -110,9 +110,9 @@ void GPUParticles2DEditorPlugin::_menu_callback(int p_idx) { UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Convert to CPUParticles2D")); - ur->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", particles, cpu_particles, true, false); + ur->add_do_method(SceneTreeDock::get_singleton(), "replace_node", particles, cpu_particles, true, false); ur->add_do_reference(cpu_particles); - ur->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", cpu_particles, particles, false, false); + ur->add_undo_method(SceneTreeDock::get_singleton(), "replace_node", cpu_particles, particles, false, false); ur->add_undo_reference(particles); ur->commit_action(); diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp index 0057566603..087b0a26b7 100644 --- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp @@ -269,9 +269,9 @@ void GPUParticles3DEditor::_menu_option(int p_option) { UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Convert to CPUParticles3D")); - ur->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", node, cpu_particles, true, false); + ur->add_do_method(SceneTreeDock::get_singleton(), "replace_node", node, cpu_particles, true, false); ur->add_do_reference(cpu_particles); - ur->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", cpu_particles, node, false, false); + ur->add_undo_method(SceneTreeDock::get_singleton(), "replace_node", cpu_particles, node, false, false); ur->add_undo_reference(node); ur->commit_action(); diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp index d82d0c6ffc..e47381b8a0 100644 --- a/editor/plugins/mesh_library_editor_plugin.cpp +++ b/editor/plugins/mesh_library_editor_plugin.cpp @@ -136,9 +136,11 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library, continue; } - //Transform3D shape_transform = sb->shape_owner_get_transform(E); - - //shape_transform.set_origin(shape_transform.get_origin() - phys_offset); + Transform3D shape_transform; + if (p_apply_xforms) { + shape_transform = mi->get_transform(); + } + shape_transform *= sb->get_transform() * sb->shape_owner_get_transform(E); for (int k = 0; k < sb->shape_owner_get_shape_count(E); k++) { Ref<Shape3D> collision = sb->shape_owner_get_shape(E, k); @@ -147,7 +149,7 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library, } MeshLibrary::ShapeData shape_data; shape_data.shape = collision; - shape_data.local_transform = sb->get_transform() * sb->shape_owner_get_transform(E); + shape_data.local_transform = shape_transform; collisions.push_back(shape_data); } } @@ -226,7 +228,7 @@ void MeshLibraryEditor::_menu_cbk(int p_option) { mesh_library->create_item(mesh_library->get_last_unused_item_id()); } break; case MENU_OPTION_REMOVE_ITEM: { - String p = editor->get_inspector()->get_selected_path(); + String p = InspectorDock::get_inspector_singleton()->get_selected_path(); if (p.begins_with("/MeshLibrary/item") && p.get_slice_count("/") >= 3) { to_erase = p.get_slice("/", 3).to_int(); cd_remove->set_text(vformat(TTR("Remove item %d?"), to_erase)); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index ef9c6a65e7..9165223948 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -2733,7 +2733,7 @@ void Node3DEditorViewport::_notification(int p_what) { _update_freelook(delta); - Node *scene_root = editor->get_scene_tree_dock()->get_editor_data()->get_edited_scene_root(); + Node *scene_root = SceneTreeDock::get_singleton()->get_editor_data()->get_edited_scene_root(); if (previewing_cinema && scene_root != nullptr) { Camera3D *cam = scene_root->get_viewport()->get_camera_3d(); if (cam != nullptr && cam != previewing) { @@ -4284,7 +4284,7 @@ void Node3DEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p_ target_node = root_node; } else { // Create a root node so we can add child nodes to it. - EditorNode::get_singleton()->get_scene_tree_dock()->add_root_node(memnew(Node3D)); + SceneTreeDock::get_singleton()->add_root_node(memnew(Node3D)); target_node = get_tree()->get_edited_scene_root(); } } else { @@ -4311,7 +4311,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito index = p_index; editor = p_editor; - editor_data = editor->get_scene_tree_dock()->get_editor_data(); + editor_data = SceneTreeDock::get_singleton()->get_editor_data(); editor_selection = editor->get_editor_selection(); undo_redo = editor->get_undo_redo(); @@ -6704,7 +6704,7 @@ void Node3DEditor::_add_sun_to_scene(bool p_already_added_environment) { Node *base = get_tree()->get_edited_scene_root(); if (!base) { // Create a root node so we can add child nodes to it. - EditorNode::get_singleton()->get_scene_tree_dock()->add_root_node(memnew(Node3D)); + SceneTreeDock::get_singleton()->add_root_node(memnew(Node3D)); base = get_tree()->get_edited_scene_root(); } ERR_FAIL_COND(!base); @@ -6732,7 +6732,7 @@ void Node3DEditor::_add_environment_to_scene(bool p_already_added_sun) { Node *base = get_tree()->get_edited_scene_root(); if (!base) { // Create a root node so we can add child nodes to it. - EditorNode::get_singleton()->get_scene_tree_dock()->add_root_node(memnew(Node3D)); + SceneTreeDock::get_singleton()->add_root_node(memnew(Node3D)); base = get_tree()->get_edited_scene_root(); } ERR_FAIL_COND(!base); @@ -6790,7 +6790,7 @@ void Node3DEditor::_notification(int p_what) { get_tree()->connect("node_removed", callable_mp(this, &Node3DEditor::_node_removed)); get_tree()->connect("node_added", callable_mp(this, &Node3DEditor::_node_added)); - EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->connect("node_changed", callable_mp(this, &Node3DEditor::_refresh_menu_icons)); + SceneTreeDock::get_singleton()->get_tree_editor()->connect("node_changed", callable_mp(this, &Node3DEditor::_refresh_menu_icons)); editor_selection->connect("selection_changed", callable_mp(this, &Node3DEditor::_selection_changed)); editor->connect("stop_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(false)); @@ -6880,8 +6880,46 @@ VSplitContainer *Node3DEditor::get_shader_split() { return shader_split; } -HSplitContainer *Node3DEditor::get_palette_split() { - return palette_split; +void Node3DEditor::add_control_to_left_panel(Control *p_control) { + left_panel_split->add_child(p_control); + left_panel_split->move_child(p_control, 0); +} + +void Node3DEditor::add_control_to_right_panel(Control *p_control) { + right_panel_split->add_child(p_control); + right_panel_split->move_child(p_control, 1); +} + +void Node3DEditor::remove_control_from_left_panel(Control *p_control) { + left_panel_split->remove_child(p_control); +} + +void Node3DEditor::remove_control_from_right_panel(Control *p_control) { + right_panel_split->remove_child(p_control); +} + +void Node3DEditor::move_control_to_left_panel(Control *p_control) { + ERR_FAIL_NULL(p_control); + if (p_control->get_parent() == left_panel_split) { + return; + } + + ERR_FAIL_COND(p_control->get_parent() != right_panel_split); + right_panel_split->remove_child(p_control); + + add_control_to_left_panel(p_control); +} + +void Node3DEditor::move_control_to_right_panel(Control *p_control) { + ERR_FAIL_NULL(p_control); + if (p_control->get_parent() == right_panel_split) { + return; + } + + ERR_FAIL_COND(p_control->get_parent() != left_panel_split); + left_panel_split->remove_child(p_control); + + add_control_to_right_panel(p_control); } void Node3DEditor::_request_gizmo(Object *p_obj) { @@ -7534,13 +7572,17 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { /* REST OF MENU */ - palette_split = memnew(HSplitContainer); - palette_split->set_v_size_flags(SIZE_EXPAND_FILL); - vbc->add_child(palette_split); + left_panel_split = memnew(HSplitContainer); + left_panel_split->set_v_size_flags(SIZE_EXPAND_FILL); + vbc->add_child(left_panel_split); + + right_panel_split = memnew(HSplitContainer); + right_panel_split->set_v_size_flags(SIZE_EXPAND_FILL); + left_panel_split->add_child(right_panel_split); shader_split = memnew(VSplitContainer); shader_split->set_h_size_flags(SIZE_EXPAND_FILL); - palette_split->add_child(shader_split); + right_panel_split->add_child(shader_split); viewport_base = memnew(Node3DEditorViewportContainer); shader_split->add_child(viewport_base); viewport_base->set_v_size_flags(SIZE_EXPAND_FILL); @@ -8001,7 +8043,6 @@ Node3DEditorPlugin::Node3DEditorPlugin(EditorNode *p_node) { editor->get_main_control()->add_child(spatial_editor); spatial_editor->hide(); - spatial_editor->connect("transform_key_request", Callable(editor->get_inspector_dock(), "_transform_keyed")); } Node3DEditorPlugin::~Node3DEditorPlugin() { diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index da560f4d83..20a782c8a8 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -527,7 +527,8 @@ private: Node3DEditorViewportContainer *viewport_base; Node3DEditorViewport *viewports[VIEWPORTS_COUNT]; VSplitContainer *shader_split; - HSplitContainer *palette_split; + HSplitContainer *left_panel_split; + HSplitContainer *right_panel_split; ///// @@ -801,8 +802,16 @@ public: void add_control_to_menu_panel(Control *p_control); void remove_control_from_menu_panel(Control *p_control); + void add_control_to_left_panel(Control *p_control); + void remove_control_from_left_panel(Control *p_control); + + void add_control_to_right_panel(Control *p_control); + void remove_control_from_right_panel(Control *p_control); + + void move_control_to_left_panel(Control *p_control); + void move_control_to_right_panel(Control *p_control); + VSplitContainer *get_shader_split(); - HSplitContainer *get_palette_split(); Node3D *get_single_selected_node() { return selected; } bool is_current_selected_gizmo(const EditorNode3DGizmo *p_gizmo); diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index c6d1d99c08..7a96e6eced 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -66,7 +66,7 @@ void Polygon2DEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - uv_panner->set_control_scheme((ViewPanner::ControlScheme)EDITOR_GET("interface/editors/sub_editor_panning_scheme").operator int()); + uv_panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/sub_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EditorSettings::get_singleton()->get("editors/panning/simple_panning"))); } break; case NOTIFICATION_READY: { button_uv->set_icon(get_theme_icon(SNAME("Uv"), SNAME("EditorIcons"))); @@ -926,7 +926,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } } -void Polygon2DEditor::_uv_scroll_callback(Vector2 p_scroll_vec) { +void Polygon2DEditor::_uv_scroll_callback(Vector2 p_scroll_vec, bool p_alt) { _uv_pan_callback(-p_scroll_vec * 32); } @@ -935,7 +935,7 @@ void Polygon2DEditor::_uv_pan_callback(Vector2 p_scroll_vec) { uv_vscroll->set_value(uv_vscroll->get_value() - p_scroll_vec.y); } -void Polygon2DEditor::_uv_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin) { +void Polygon2DEditor::_uv_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) { if (p_scroll_vec.y < 0) { uv_zoom->set_value(uv_zoom->get_value() / (1 - (0.1 * Math::abs(p_scroll_vec.y)))); } else { @@ -1280,10 +1280,6 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_edit_mode[2]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select), varray(2)); uv_edit_mode[3]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select), varray(3)); - uv_panner.instantiate(); - uv_panner->set_callbacks(callable_mp(this, &Polygon2DEditor::_uv_scroll_callback), callable_mp(this, &Polygon2DEditor::_uv_pan_callback), callable_mp(this, &Polygon2DEditor::_uv_zoom_callback)); - uv_panner->set_disable_rmb(true); - uv_mode_hb->add_child(memnew(VSeparator)); uv_main_vb->add_child(uv_mode_hb); @@ -1470,8 +1466,13 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : bone_scroll_vb = memnew(VBoxContainer); bone_scroll->add_child(bone_scroll_vb); + uv_panner.instantiate(); + uv_panner->set_callbacks(callable_mp(this, &Polygon2DEditor::_uv_scroll_callback), callable_mp(this, &Polygon2DEditor::_uv_pan_callback), callable_mp(this, &Polygon2DEditor::_uv_zoom_callback)); + uv_edit_draw->connect("draw", callable_mp(this, &Polygon2DEditor::_uv_draw)); uv_edit_draw->connect("gui_input", callable_mp(this, &Polygon2DEditor::_uv_input)); + uv_edit_draw->connect("focus_exited", callable_mp(uv_panner.ptr(), &ViewPanner::release_pan_key)); + uv_edit_draw->set_focus_mode(FOCUS_CLICK); uv_draw_zoom = 1.0; point_drag_index = -1; uv_drag = false; diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h index 959c230d7b..0f10b6b645 100644 --- a/editor/plugins/polygon_2d_editor_plugin.h +++ b/editor/plugins/polygon_2d_editor_plugin.h @@ -81,9 +81,9 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { TextureRect *uv_icon_zoom; Ref<ViewPanner> uv_panner; - void _uv_scroll_callback(Vector2 p_scroll_vec); + void _uv_scroll_callback(Vector2 p_scroll_vec, bool p_alt); void _uv_pan_callback(Vector2 p_scroll_vec); - void _uv_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin); + void _uv_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt); VBoxContainer *bone_scroll_main_vb; ScrollContainer *bone_scroll; diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index f1e5e7612b..2fc4cda861 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -677,6 +677,7 @@ void ScriptEditor::_update_recent_scripts() { recent_scripts->add_separator(); recent_scripts->add_shortcut(ED_SHORTCUT("script_editor/clear_recent", TTR("Clear Recent Files"))); + recent_scripts->set_item_disabled(recent_scripts->get_item_id(recent_scripts->get_item_count() - 1), rc.is_empty()); recent_scripts->set_as_minsize(); } @@ -1421,7 +1422,7 @@ void ScriptEditor::_menu_option(int p_option) { path = path.get_slice("::", 0); // Show the scene instead. } - FileSystemDock *file_system_dock = EditorNode::get_singleton()->get_filesystem_dock(); + FileSystemDock *file_system_dock = FileSystemDock::get_singleton(); file_system_dock->navigate_to_path(path); // Ensure that the FileSystem dock is visible. TabContainer *tab_container = (TabContainer *)file_system_dock->get_parent_control(); @@ -1540,6 +1541,51 @@ void ScriptEditor::_show_save_theme_as_dialog() { file_dialog->set_title(TTR("Save Theme As...")); } +bool ScriptEditor::_has_docs_tab() const { + const int child_count = tab_container->get_child_count(); + for (int i = 0; i < child_count; i++) { + if (Object::cast_to<EditorHelp>(tab_container->get_child(i))) { + return true; + } + } + return false; +} + +bool ScriptEditor::_has_script_tab() const { + const int child_count = tab_container->get_child_count(); + for (int i = 0; i < child_count; i++) { + if (Object::cast_to<ScriptEditorBase>(tab_container->get_child(i))) { + return true; + } + } + return false; +} + +void ScriptEditor::_prepare_file_menu() { + PopupMenu *menu = file_menu->get_popup(); + const bool current_is_doc = _get_current_editor() == nullptr; + + menu->set_item_disabled(menu->get_item_index(FILE_REOPEN_CLOSED), previous_scripts.is_empty()); + + menu->set_item_disabled(menu->get_item_index(FILE_SAVE), current_is_doc); + menu->set_item_disabled(menu->get_item_index(FILE_SAVE_AS), current_is_doc); + menu->set_item_disabled(menu->get_item_index(FILE_SAVE_ALL), !_has_script_tab()); + + menu->set_item_disabled(menu->get_item_index(FILE_TOOL_RELOAD_SOFT), current_is_doc); + menu->set_item_disabled(menu->get_item_index(FILE_COPY_PATH), current_is_doc); + menu->set_item_disabled(menu->get_item_index(SHOW_IN_FILE_SYSTEM), current_is_doc); + + menu->set_item_disabled(menu->get_item_index(WINDOW_PREV), history_pos <= 0); + menu->set_item_disabled(menu->get_item_index(WINDOW_NEXT), history_pos >= history.size() - 1); + + menu->set_item_disabled(menu->get_item_index(FILE_CLOSE), tab_container->get_child_count() < 1); + menu->set_item_disabled(menu->get_item_index(CLOSE_ALL), tab_container->get_child_count() < 1); + menu->set_item_disabled(menu->get_item_index(CLOSE_OTHER_TABS), tab_container->get_child_count() <= 1); + menu->set_item_disabled(menu->get_item_index(CLOSE_DOCS), !_has_docs_tab()); + + menu->set_item_disabled(menu->get_item_index(FILE_RUN), current_is_doc); +} + void ScriptEditor::_tab_changed(int p_which) { ensure_select_current(); } @@ -1551,8 +1597,8 @@ void ScriptEditor::_notification(int p_what) { editor->connect("script_add_function_request", callable_mp(this, &ScriptEditor::_add_callback)); editor->connect("resource_saved", callable_mp(this, &ScriptEditor::_res_saved_callback)); editor->connect("scene_saved", callable_mp(this, &ScriptEditor::_scene_saved_callback)); - editor->get_filesystem_dock()->connect("files_moved", callable_mp(this, &ScriptEditor::_files_moved)); - editor->get_filesystem_dock()->connect("file_removed", callable_mp(this, &ScriptEditor::_file_removed)); + FileSystemDock::get_singleton()->connect("files_moved", callable_mp(this, &ScriptEditor::_files_moved)); + FileSystemDock::get_singleton()->connect("file_removed", callable_mp(this, &ScriptEditor::_file_removed)); script_list->connect("item_selected", callable_mp(this, &ScriptEditor::_script_selected)); members_overview->connect("item_selected", callable_mp(this, &ScriptEditor::_members_overview_selected)); @@ -1595,7 +1641,7 @@ void ScriptEditor::_notification(int p_what) { case NOTIFICATION_READY: { get_tree()->connect("tree_changed", callable_mp(this, &ScriptEditor::_tree_changed)); - editor->get_inspector_dock()->connect("request_help", callable_mp(this, &ScriptEditor::_help_class_open)); + InspectorDock::get_singleton()->connect("request_help", callable_mp(this, &ScriptEditor::_help_class_open)); editor->connect("request_help_search", callable_mp(this, &ScriptEditor::_help_search)); } break; @@ -2122,8 +2168,6 @@ void ScriptEditor::_update_script_names() { _update_members_overview_visibility(); _update_help_overview_visibility(); _update_script_colors(); - - file_menu->get_popup()->set_item_disabled(file_menu->get_popup()->get_item_index(FILE_REOPEN_CLOSED), previous_scripts.is_empty()); } void ScriptEditor::_update_script_connections() { @@ -2347,7 +2391,7 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra // If we delete a script within the filesystem, the original resource path // is lost, so keep it as metadata to figure out the exact tab to delete. se->set_meta("_edit_res_path", p_resource->get_path()); - se->set_tooltip_request_func("_get_debug_tooltip", this); + se->set_tooltip_request_func(callable_mp(this, &ScriptEditor::_get_debug_tooltip)); if (se->get_edit_menu()) { se->get_edit_menu()->hide(); menu_hb->add_child(se->get_edit_menu()); @@ -2794,6 +2838,7 @@ Variant ScriptEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) { if (!preview_icon.is_null()) { TextureRect *tf = memnew(TextureRect); tf->set_texture(preview_icon); + tf->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); drag_preview->add_child(tf); } Label *label = memnew(Label(preview_name)); @@ -3067,6 +3112,12 @@ void ScriptEditor::_make_script_list_context_menu() { context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/window_sort"), WINDOW_SORT); context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/toggle_scripts_panel"), TOGGLE_SCRIPTS_PANEL); + context_menu->set_item_disabled(context_menu->get_item_index(CLOSE_ALL), tab_container->get_child_count() <= 0); + context_menu->set_item_disabled(context_menu->get_item_index(CLOSE_OTHER_TABS), tab_container->get_child_count() <= 1); + context_menu->set_item_disabled(context_menu->get_item_index(WINDOW_MOVE_UP), tab_container->get_current_tab() <= 0); + context_menu->set_item_disabled(context_menu->get_item_index(WINDOW_MOVE_DOWN), tab_container->get_current_tab() >= tab_container->get_child_count() - 1); + context_menu->set_item_disabled(context_menu->get_item_index(WINDOW_SORT), tab_container->get_child_count() <= 1); + context_menu->set_position(get_screen_position() + get_local_mouse_position()); context_menu->reset_size(); context_menu->popup(); @@ -3455,7 +3506,7 @@ void ScriptEditor::register_create_script_editor_function(CreateScriptEditorFunc } void ScriptEditor::_script_changed() { - NodeDock::singleton->update_lists(); + NodeDock::get_singleton()->update_lists(); } void ScriptEditor::_on_find_in_files_requested(String text) { @@ -3547,7 +3598,6 @@ void ScriptEditor::_bind_methods() { ClassDB::bind_method("_goto_script_line2", &ScriptEditor::_goto_script_line2); ClassDB::bind_method("_copy_script_path", &ScriptEditor::_copy_script_path); - ClassDB::bind_method("_get_debug_tooltip", &ScriptEditor::_get_debug_tooltip); ClassDB::bind_method("_update_script_connections", &ScriptEditor::_update_script_connections); ClassDB::bind_method("_help_class_open", &ScriptEditor::_help_class_open); ClassDB::bind_method("_live_auto_reload_running_scripts", &ScriptEditor::_live_auto_reload_running_scripts); @@ -3690,7 +3740,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { ED_SHORTCUT("script_editor/next_script", TTR("Next Script"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::PERIOD); ED_SHORTCUT("script_editor/prev_script", TTR("Previous Script"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::COMMA); set_process_input(true); - set_process_unhandled_input(true); + set_process_unhandled_key_input(true); file_menu = memnew(MenuButton); file_menu->set_text(TTR("File")); @@ -3698,8 +3748,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { file_menu->set_shortcut_context(this); menu_hb->add_child(file_menu); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new", TTR("New Script...")), FILE_NEW); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new_textfile", TTR("New Text File...")), FILE_NEW_TEXTFILE); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new", TTR("New Script..."), KeyModifierMask::CMD | Key::N), FILE_NEW); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new_textfile", TTR("New Text File..."), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::N), FILE_NEW_TEXTFILE); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/open", TTR("Open...")), FILE_OPEN); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reopen_closed_script", TTR("Reopen Closed Script"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::T), FILE_REOPEN_CLOSED); file_menu->get_popup()->add_submenu_item(TTR("Open Recent"), "RecentScripts", FILE_OPEN_RECENT); @@ -3749,6 +3799,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { file_menu->get_popup()->add_separator(); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/toggle_scripts_panel", TTR("Toggle Scripts Panel"), KeyModifierMask::CMD | Key::BACKSLASH), TOGGLE_SCRIPTS_PANEL); file_menu->get_popup()->connect("id_pressed", callable_mp(this, &ScriptEditor::_menu_option)); + file_menu->get_popup()->connect("about_to_popup", callable_mp(this, &ScriptEditor::_prepare_file_menu)); script_search_menu = memnew(MenuButton); script_search_menu->set_text(TTR("Search")); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index ca409e15ca..67a6a9da02 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -165,7 +165,7 @@ public: virtual bool show_members_overview() = 0; - virtual void set_tooltip_request_func(String p_method, Object *p_obj) = 0; + virtual void set_tooltip_request_func(const Callable &p_toolip_callback) = 0; virtual Control *get_edit_menu() = 0; virtual void clear_edit_menu() = 0; virtual void set_find_replace_bar(FindReplaceBar *p_bar) = 0; @@ -315,6 +315,9 @@ class ScriptEditor : public PanelContainer { void _menu_option(int p_option); void _theme_option(int p_option); void _show_save_theme_as_dialog(); + bool _has_docs_tab() const; + bool _has_script_tab() const; + void _prepare_file_menu(); Tree *disk_changed_list; ConfirmationDialog *disk_changed; diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index ab094f4dc6..b765091d2b 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -1375,8 +1375,10 @@ void ScriptTextEditor::clear_breakpoints() { code_editor->get_text_editor()->clear_breakpointed_lines(); } -void ScriptTextEditor::set_tooltip_request_func(String p_method, Object *p_obj) { - code_editor->get_text_editor()->set_tooltip_request_func(p_obj, p_method, this); +void ScriptTextEditor::set_tooltip_request_func(const Callable &p_toolip_callback) { + Variant args[1] = { this }; + const Variant *argp[] = { &args[0] }; + code_editor->get_text_editor()->set_tooltip_request_func(p_toolip_callback.bind(argp, 1)); } void ScriptTextEditor::set_debugger_active(bool p_active) { diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index 6e67444489..bc674ce964 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -233,7 +233,7 @@ public: virtual bool show_members_overview() override; - virtual void set_tooltip_request_func(String p_method, Object *p_obj) override; + virtual void set_tooltip_request_func(const Callable &p_toolip_callback) override; virtual void set_debugger_active(bool p_active) override; diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index e1b27cb045..169ce29438 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -149,6 +149,9 @@ void BoneTransformEditor::set_target(const String &p_prop) { void BoneTransformEditor::_property_keyed(const String &p_path, bool p_advance) { AnimationTrackEditor *te = AnimationPlayerEditor::get_singleton()->get_track_editor(); + if (!te->has_keying()) { + return; + } PackedStringArray split = p_path.split("/"); if (split.size() == 3 && split[0] == "bones") { int bone_idx = split[1].to_int(); diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp index 1eac651ed6..85ff20dd23 100644 --- a/editor/plugins/sprite_2d_editor_plugin.cpp +++ b/editor/plugins/sprite_2d_editor_plugin.cpp @@ -337,9 +337,9 @@ void Sprite2DEditor::_convert_to_mesh_2d_node() { UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Convert to Mesh2D")); - ur->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", node, mesh_instance, true, false); + ur->add_do_method(SceneTreeDock::get_singleton(), "replace_node", node, mesh_instance, true, false); ur->add_do_reference(mesh_instance); - ur->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", mesh_instance, node, false, false); + ur->add_undo_method(SceneTreeDock::get_singleton(), "replace_node", mesh_instance, node, false, false); ur->add_undo_reference(node); ur->commit_action(); } @@ -395,9 +395,9 @@ void Sprite2DEditor::_convert_to_polygon_2d_node() { UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Convert to Polygon2D")); - ur->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", node, polygon_2d_instance, true, false); + ur->add_do_method(SceneTreeDock::get_singleton(), "replace_node", node, polygon_2d_instance, true, false); ur->add_do_reference(polygon_2d_instance); - ur->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", polygon_2d_instance, node, false, false); + ur->add_undo_method(SceneTreeDock::get_singleton(), "replace_node", polygon_2d_instance, node, false, false); ur->add_undo_reference(node); ur->commit_action(); } diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 3350cec912..9013eaf9d8 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -821,19 +821,30 @@ void SpriteFramesEditor::_update_library(bool p_skip_selector) { for (int i = 0; i < frames->get_frame_count(edited_anim); i++) { String name; - Ref<Texture2D> icon; + Ref<Texture> frame = frames->get_frame(edited_anim, i); - if (frames->get_frame(edited_anim, i).is_null()) { + if (frame.is_null()) { name = itos(i) + ": " + TTR("(empty)"); - } else { - name = itos(i) + ": " + frames->get_frame(edited_anim, i)->get_name(); - icon = frames->get_frame(edited_anim, i); + name = itos(i) + ": " + frame->get_name(); } - tree->add_item(name, icon); - if (frames->get_frame(edited_anim, i).is_valid()) { - tree->set_item_tooltip(tree->get_item_count() - 1, frames->get_frame(edited_anim, i)->get_path()); + tree->add_item(name, frame); + if (frame.is_valid()) { + String tooltip = frame->get_path(); + + // Frame is often saved as an AtlasTexture subresource within a scene/resource file, + // thus its path might be not what the user is looking for. So we're also showing + // subsequent source texture paths. + String prefix = String::utf8("┖╴"); + Ref<AtlasTexture> at = frame; + while (at.is_valid() && at->get_atlas().is_valid()) { + tooltip += "\n" + prefix + at->get_atlas()->get_path(); + prefix = " " + prefix; + at = at->get_atlas(); + } + + tree->set_item_tooltip(tree->get_item_count() - 1, tooltip); } if (sel == i) { tree->select(tree->get_item_count() - 1); diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 12d13571f8..940f269803 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -272,8 +272,10 @@ void TextEditor::update_settings() { code_editor->update_editor_settings(); } -void TextEditor::set_tooltip_request_func(String p_method, Object *p_obj) { - code_editor->get_text_editor()->set_tooltip_request_func(p_obj, p_method, this); +void TextEditor::set_tooltip_request_func(const Callable &p_toolip_callback) { + Variant args[1] = { this }; + const Variant *argp[] = { &args[0] }; + code_editor->get_text_editor()->set_tooltip_request_func(p_toolip_callback.bind(argp, 1)); } Control *TextEditor::get_edit_menu() { diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h index d3fb0c0a16..d03385d79e 100644 --- a/editor/plugins/text_editor.h +++ b/editor/plugins/text_editor.h @@ -135,7 +135,7 @@ public: virtual bool show_members_overview() override; virtual bool can_lose_focus_on_node_selection() override { return true; } virtual void set_debugger_active(bool p_active) override; - virtual void set_tooltip_request_func(String p_method, Object *p_obj) override; + virtual void set_tooltip_request_func(const Callable &p_toolip_callback) override; virtual void add_callback(const String &p_function, PackedStringArray p_args) override; void update_toggle_scripts_button() override; diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 900bf4ef57..662c0126ec 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -35,6 +35,7 @@ #include "core/os/keyboard.h" #include "editor/editor_scale.h" #include "scene/gui/check_box.h" +#include "scene/gui/view_panner.h" void draw_margin_line(Control *edit_draw, Vector2 from, Vector2 to) { Vector2 line = (to - from).normalized() * 10; @@ -259,6 +260,10 @@ void TextureRegionEditor::_region_draw() { } void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { + if (panner->gui_input(p_input)) { + return; + } + Transform2D mtx; mtx.elements[2] = -draw_ofs * draw_zoom; mtx.scale_basis(Vector2(draw_zoom, draw_zoom)); @@ -281,7 +286,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { Ref<InputEventMouseButton> mb = p_input; if (mb.is_valid()) { if (mb->get_button_index() == MouseButton::LEFT) { - if (mb->is_pressed()) { + if (mb->is_pressed() && !panner->is_panning()) { if (node_ninepatch || obj_styleBox.is_valid()) { edited_margin = -1; float margins[4] = { 0 }; @@ -400,7 +405,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { } } - } else if (drag) { + } else if (!mb->is_pressed() && drag) { if (edited_margin >= 0) { undo_redo->create_action(TTR("Set Margin")); static Side side[4] = { SIDE_TOP, SIDE_BOTTOM, SIDE_LEFT, SIDE_RIGHT }; @@ -461,21 +466,13 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { drag_index = -1; } } - } else if (mb->get_button_index() == MouseButton::WHEEL_UP && mb->is_pressed()) { - _zoom_on_position(draw_zoom * ((0.95 + (0.05 * mb->get_factor())) / 0.95), mb->get_position()); - } else if (mb->get_button_index() == MouseButton::WHEEL_DOWN && mb->is_pressed()) { - _zoom_on_position(draw_zoom * (1 - (0.05 * mb->get_factor())), mb->get_position()); } } Ref<InputEventMouseMotion> mm = p_input; if (mm.is_valid()) { - if ((mm->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE || Input::get_singleton()->is_key_pressed(Key::SPACE)) { - Vector2 dragged(mm->get_relative().x / draw_zoom, mm->get_relative().y / draw_zoom); - hscroll->set_value(hscroll->get_value() - dragged.x); - vscroll->set_value(vscroll->get_value() - dragged.y); - } else if (drag) { + if (drag) { if (edited_margin >= 0) { float new_margin = 0; @@ -605,6 +602,24 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { } } +void TextureRegionEditor::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) { + _pan_callback(-p_scroll_vec * 32); +} + +void TextureRegionEditor::_pan_callback(Vector2 p_scroll_vec) { + p_scroll_vec /= draw_zoom; + hscroll->set_value(hscroll->get_value() - p_scroll_vec.x); + vscroll->set_value(vscroll->get_value() - p_scroll_vec.y); +} + +void TextureRegionEditor::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) { + if (p_scroll_vec.y < 0) { + _zoom_on_position(draw_zoom * ((0.95 + (0.05 * Math::abs(p_scroll_vec.y))) / 0.95), p_origin); + } else { + _zoom_on_position(draw_zoom * (1 - (0.05 * Math::abs(p_scroll_vec.y))), p_origin); + } +} + void TextureRegionEditor::_scroll_changed(float) { if (updating_scroll) { return; @@ -802,6 +817,10 @@ void TextureRegionEditor::_notification(int p_what) { vscroll->set_anchors_and_offsets_preset(PRESET_RIGHT_WIDE); hscroll->set_anchors_and_offsets_preset(PRESET_BOTTOM_WIDE); + [[fallthrough]]; + } + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/sub_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EditorSettings::get_singleton()->get("editors/panning/simple_panning"))); } break; case NOTIFICATION_VISIBILITY_CHANGED: { if (snap_mode == SNAP_AUTOSLICE && is_visible() && autoslice_is_dirty) { @@ -1058,11 +1077,16 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) { hb_grid->hide(); + panner.instantiate(); + panner->set_callbacks(callable_mp(this, &TextureRegionEditor::_scroll_callback), callable_mp(this, &TextureRegionEditor::_pan_callback), callable_mp(this, &TextureRegionEditor::_zoom_callback)); + edit_draw = memnew(Panel); add_child(edit_draw); edit_draw->set_v_size_flags(SIZE_EXPAND_FILL); edit_draw->connect("draw", callable_mp(this, &TextureRegionEditor::_region_draw)); edit_draw->connect("gui_input", callable_mp(this, &TextureRegionEditor::_region_input)); + edit_draw->connect("focus_exited", callable_mp(panner.ptr(), &ViewPanner::release_pan_key)); + edit_draw->set_focus_mode(FOCUS_CLICK); draw_zoom = 1.0; edit_draw->set_clip_contents(true); diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h index bffc6fd9bf..d78ad3891c 100644 --- a/editor/plugins/texture_region_editor_plugin.h +++ b/editor/plugins/texture_region_editor_plugin.h @@ -40,6 +40,8 @@ #include "scene/resources/style_box.h" #include "scene/resources/texture.h" +class ViewPanner; + class TextureRegionEditor : public VBoxContainer { GDCLASS(TextureRegionEditor, VBoxContainer); @@ -98,6 +100,11 @@ class TextureRegionEditor : public VBoxContainer { Vector2 drag_from; int drag_index; + Ref<ViewPanner> panner; + void _scroll_callback(Vector2 p_scroll_vec, bool p_alt); + void _pan_callback(Vector2 p_scroll_vec); + void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt); + void _set_snap_mode(int p_mode); void _set_snap_off_x(float p_val); void _set_snap_off_y(float p_val); diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 91c17399c2..f95b2b40b5 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -81,8 +81,6 @@ void ThemeItemImportTree::_update_items_tree() { bool is_matching_filter = (filter_text.is_empty() || type_name.findn(filter_text) > -1); bool has_filtered_items = false; - bool any_checked = false; - bool any_checked_with_data = false; for (int i = 0; i < Theme::DATA_TYPE_MAX; i++) { Theme::DataType dt = (Theme::DataType)i; @@ -178,9 +176,6 @@ void ThemeItemImportTree::_update_items_tree() { break; // Can't happen, but silences warning. } - bool data_type_any_checked = false; - bool data_type_any_checked_with_data = false; - filtered_names.sort_custom<StringName::AlphCompare>(); for (const StringName &F : filtered_names) { TreeItem *item_node = import_items_tree->create_item(data_type_node); @@ -194,20 +189,11 @@ void ThemeItemImportTree::_update_items_tree() { item_node->set_editable(IMPORT_ITEM_DATA, true); _restore_selected_item(item_node); - if (item_node->is_checked(IMPORT_ITEM)) { - data_type_any_checked = true; - any_checked = true; - } - if (item_node->is_checked(IMPORT_ITEM_DATA)) { - data_type_any_checked_with_data = true; - any_checked_with_data = true; - } + item_node->propagate_check(IMPORT_ITEM, false); + item_node->propagate_check(IMPORT_ITEM_DATA, false); item_list->push_back(item_node); } - - data_type_node->set_checked(IMPORT_ITEM, data_type_any_checked); - data_type_node->set_checked(IMPORT_ITEM_DATA, data_type_any_checked && data_type_any_checked_with_data); } // Remove the item if it doesn't match the filter in any way. @@ -221,9 +207,6 @@ void ThemeItemImportTree::_update_items_tree() { if (!filter_text.is_empty() && has_filtered_items) { type_node->set_collapsed(false); } - - type_node->set_checked(IMPORT_ITEM, any_checked); - type_node->set_checked(IMPORT_ITEM_DATA, any_checked && any_checked_with_data); } if (color_amount > 0) { @@ -471,23 +454,26 @@ void ThemeItemImportTree::_tree_item_edited() { if (is_checked) { if (edited_column == IMPORT_ITEM_DATA) { edited_item->set_checked(IMPORT_ITEM, true); + edited_item->propagate_check(IMPORT_ITEM); } - - _select_all_subitems(edited_item, (edited_column == IMPORT_ITEM_DATA)); } else { if (edited_column == IMPORT_ITEM) { edited_item->set_checked(IMPORT_ITEM_DATA, false); + edited_item->propagate_check(IMPORT_ITEM_DATA); } - - _deselect_all_subitems(edited_item, (edited_column == IMPORT_ITEM)); } - - _update_parent_items(edited_item); - _store_selected_item(edited_item); - + edited_item->propagate_check(edited_column); updating_tree = false; } +void ThemeItemImportTree::_check_propagated_to_tree_item(Object *p_obj, int p_column) { + TreeItem *item = Object::cast_to<TreeItem>(p_obj); + // Skip "category" tree items by checking for children. + if (item && !item->get_first_child()) { + _store_selected_item(item); + } +} + void ThemeItemImportTree::_select_all_subitems(TreeItem *p_root_item, bool p_select_with_data) { TreeItem *child_item = p_root_item->get_first_child(); while (child_item) { @@ -516,32 +502,6 @@ void ThemeItemImportTree::_deselect_all_subitems(TreeItem *p_root_item, bool p_d } } -void ThemeItemImportTree::_update_parent_items(TreeItem *p_root_item) { - TreeItem *parent_item = p_root_item->get_parent(); - if (!parent_item) { - return; - } - - bool any_checked = false; - bool any_checked_with_data = false; - - TreeItem *child_item = parent_item->get_first_child(); - while (child_item) { - if (child_item->is_checked(IMPORT_ITEM)) { - any_checked = true; - } - if (child_item->is_checked(IMPORT_ITEM_DATA)) { - any_checked_with_data = true; - } - - child_item = child_item->get_next(); - } - - parent_item->set_checked(IMPORT_ITEM, any_checked); - parent_item->set_checked(IMPORT_ITEM_DATA, any_checked && any_checked_with_data); - _update_parent_items(parent_item); -} - void ThemeItemImportTree::_select_all_items_pressed() { if (updating_tree) { return; @@ -629,7 +589,7 @@ void ThemeItemImportTree::_select_all_data_type_pressed(int p_data_type) { } child_item->set_checked(IMPORT_ITEM, true); - _update_parent_items(child_item); + child_item->propagate_check(IMPORT_ITEM, false); _store_selected_item(child_item); } @@ -685,7 +645,8 @@ void ThemeItemImportTree::_select_full_data_type_pressed(int p_data_type) { child_item->set_checked(IMPORT_ITEM, true); child_item->set_checked(IMPORT_ITEM_DATA, true); - _update_parent_items(child_item); + child_item->propagate_check(IMPORT_ITEM, false); + child_item->propagate_check(IMPORT_ITEM_DATA, false); _store_selected_item(child_item); } @@ -741,7 +702,8 @@ void ThemeItemImportTree::_deselect_all_data_type_pressed(int p_data_type) { child_item->set_checked(IMPORT_ITEM, false); child_item->set_checked(IMPORT_ITEM_DATA, false); - _update_parent_items(child_item); + child_item->propagate_check(IMPORT_ITEM, false); + child_item->propagate_check(IMPORT_ITEM_DATA, false); _store_selected_item(child_item); } @@ -937,6 +899,7 @@ ThemeItemImportTree::ThemeItemImportTree() { import_items_tree->set_h_size_flags(Control::SIZE_EXPAND_FILL); import_main_hb->add_child(import_items_tree); import_items_tree->connect("item_edited", callable_mp(this, &ThemeItemImportTree::_tree_item_edited)); + import_items_tree->connect("check_propagated_to_item", callable_mp(this, &ThemeItemImportTree::_check_propagated_to_tree_item)); import_items_tree->set_columns(3); import_items_tree->set_column_titles_visible(true); diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h index 4c6b16a68c..c00ce3ae65 100644 --- a/editor/plugins/theme_editor_plugin.h +++ b/editor/plugins/theme_editor_plugin.h @@ -149,9 +149,9 @@ class ThemeItemImportTree : public VBoxContainer { void _update_total_selected(Theme::DataType p_data_type); void _tree_item_edited(); + void _check_propagated_to_tree_item(Object *p_obj, int p_column); void _select_all_subitems(TreeItem *p_root_item, bool p_select_with_data); void _deselect_all_subitems(TreeItem *p_root_item, bool p_deselect_completely); - void _update_parent_items(TreeItem *p_root_item); void _select_all_items_pressed(); void _select_full_items_pressed(); diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp index 24ede3b85e..3b9bde6b0d 100644 --- a/editor/plugins/tiles/tile_atlas_view.cpp +++ b/editor/plugins/tiles/tile_atlas_view.cpp @@ -48,7 +48,7 @@ void TileAtlasView::gui_input(const Ref<InputEvent> &p_event) { } } -void TileAtlasView::_scroll_callback(Vector2 p_scroll_vec) { +void TileAtlasView::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) { _pan_callback(-p_scroll_vec * 32); } @@ -58,7 +58,7 @@ void TileAtlasView::_pan_callback(Vector2 p_scroll_vec) { _update_zoom_and_panning(true); } -void TileAtlasView::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin) { +void TileAtlasView::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) { zoom_widget->set_zoom_by_increments(-p_scroll_vec.y * 2); emit_signal(SNAME("transform_changed"), zoom_widget->get_zoom(), panning); _update_zoom_and_panning(true); @@ -524,7 +524,7 @@ void TileAtlasView::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: - panner->set_control_scheme((ViewPanner::ControlScheme)EDITOR_GET("interface/editors/sub_editor_panning_scheme").operator int()); + panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/sub_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EditorSettings::get_singleton()->get("editors/panning/simple_panning"))); break; case NOTIFICATION_READY: @@ -540,9 +540,6 @@ void TileAtlasView::_bind_methods() { TileAtlasView::TileAtlasView() { set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST); - panner.instantiate(); - panner->set_callbacks(callable_mp(this, &TileAtlasView::_scroll_callback), callable_mp(this, &TileAtlasView::_pan_callback), callable_mp(this, &TileAtlasView::_zoom_callback)); - Panel *panel = memnew(Panel); panel->set_clip_contents(true); panel->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); @@ -566,10 +563,16 @@ TileAtlasView::TileAtlasView() { button_center_view->set_tooltip(TTR("Center View")); add_child(button_center_view); + panner.instantiate(); + panner->set_callbacks(callable_mp(this, &TileAtlasView::_scroll_callback), callable_mp(this, &TileAtlasView::_pan_callback), callable_mp(this, &TileAtlasView::_zoom_callback)); + panner->set_enable_rmb(true); + center_container = memnew(CenterContainer); center_container->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); center_container->set_anchors_preset(Control::PRESET_CENTER); center_container->connect("gui_input", callable_mp(this, &TileAtlasView::gui_input)); + center_container->connect("focus_exited", callable_mp(panner.ptr(), &ViewPanner::release_pan_key)); + center_container->set_focus_mode(FOCUS_CLICK); panel->add_child(center_container); missing_source_label = memnew(Label); diff --git a/editor/plugins/tiles/tile_atlas_view.h b/editor/plugins/tiles/tile_atlas_view.h index 6a0e0ae820..37ef7d6a2a 100644 --- a/editor/plugins/tiles/tile_atlas_view.h +++ b/editor/plugins/tiles/tile_atlas_view.h @@ -67,9 +67,9 @@ private: virtual void gui_input(const Ref<InputEvent> &p_event) override; Ref<ViewPanner> panner; - void _scroll_callback(Vector2 p_scroll_vec); + void _scroll_callback(Vector2 p_scroll_vec, bool p_alt); void _pan_callback(Vector2 p_scroll_vec); - void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin); + void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt); Map<Vector2, Map<int, Rect2i>> alternative_tiles_rect_cache; void _update_alternative_tiles_rect_cache(); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index f05ff72e5d..2d0ca11b6a 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -42,6 +42,7 @@ #include "scene/animation/animation_player.h" #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" +#include "scene/gui/view_panner.h" #include "scene/main/window.h" #include "scene/resources/visual_shader_nodes.h" #include "scene/resources/visual_shader_particle_nodes.h" @@ -351,6 +352,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { if (!graph_plugin) { return; } + Shader::Mode mode = visual_shader->get_mode(); Control *offset; @@ -707,9 +709,9 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { label->add_theme_style_override("normal", label_style); //more compact hb->add_child(label); - if (vsnode->get_input_port_default_hint(i) != "" && !port_left_used) { + if (vsnode->is_input_port_default(i, mode) && !port_left_used) { Label *hint_label = memnew(Label); - hint_label->set_text("[" + vsnode->get_input_port_default_hint(i) + "]"); + hint_label->set_text(TTR("[default]")); hint_label->add_theme_color_override("font_color", editor->get_theme_color(SNAME("font_readonly_color"), SNAME("TextEdit"))); hint_label->add_theme_style_override("normal", label_style); hb->add_child(hint_label); @@ -840,7 +842,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE)); node->add_child(offset); - String error = vsnode->get_warning(visual_shader->get_mode(), p_type); + String error = vsnode->get_warning(mode, p_type); if (!error.is_empty()) { Label *error_label = memnew(Label); error_label->add_theme_color_override("font_color", editor->get_theme_color(SNAME("error_color"), SNAME("Editor"))); @@ -3222,7 +3224,8 @@ void VisualShaderEditor::_notification(int p_what) { } if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { - graph->set_panning_scheme((GraphEdit::PanningScheme)EDITOR_GET("interface/editors/sub_editor_panning_scheme").operator int()); + graph->get_panner()->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/sub_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EditorSettings::get_singleton()->get("editors/panning/simple_panning"))); + graph->set_warped_panning(bool(EditorSettings::get_singleton()->get("editors/panning/warped_mouse_panning"))); } if (p_what == NOTIFICATION_DRAG_BEGIN) { @@ -4495,7 +4498,6 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("ObjectPosition", "Input", "Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "object_position"), "object_position", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FOG, Shader::MODE_FOG)); add_options.push_back(AddOption("UVW", "Input", "Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "uvw"), "uvw", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FOG, Shader::MODE_FOG)); add_options.push_back(AddOption("Extents", "Input", "Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "extents"), "extents", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FOG, Shader::MODE_FOG)); - add_options.push_back(AddOption("Transform", "Input", "Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "transform"), "transform", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_FOG, Shader::MODE_FOG)); add_options.push_back(AddOption("SDF", "Input", "Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "sdf"), "sdf", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FOG, Shader::MODE_FOG)); add_options.push_back(AddOption("Time", "Input", "Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FOG, Shader::MODE_FOG)); @@ -4967,7 +4969,7 @@ public: } void _open_inspector(RES p_resource) { - EditorNode::get_singleton()->get_inspector()->edit(p_resource.ptr()); + InspectorDock::get_inspector_singleton()->edit(p_resource.ptr()); } bool updating; diff --git a/editor/project_export.cpp b/editor/project_export.cpp index 9bd8c1e227..f39a494df8 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -752,12 +752,10 @@ bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem p_item->set_metadata(0, p_dir->get_path()); bool used = false; - bool checked = true; for (int i = 0; i < p_dir->get_subdir_count(); i++) { TreeItem *subdir = include_files->create_item(p_item); if (_fill_tree(p_dir->get_subdir(i), subdir, current, p_only_scenes)) { used = true; - checked = checked && subdir->is_checked(0); } else { memdelete(subdir); } @@ -782,12 +780,10 @@ bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem file->set_editable(0, true); file->set_checked(0, current->has_export_file(path)); file->set_metadata(0, path); - checked = checked && file->is_checked(0); + file->propagate_check(0); used = true; } - - p_item->set_checked(0, checked); return used; } @@ -806,54 +802,24 @@ void ProjectExportDialog::_tree_changed() { return; } - String path = item->get_metadata(0); - bool added = item->is_checked(0); + item->propagate_check(0); +} - if (path.ends_with("/")) { - _check_dir_recursive(item, added); - } else { +void ProjectExportDialog::_check_propagated_to_item(Object *p_obj, int column) { + Ref<EditorExportPreset> current = get_current_preset(); + if (current.is_null()) { + return; + } + TreeItem *item = Object::cast_to<TreeItem>(p_obj); + String path = item->get_metadata(0); + if (item && !path.ends_with("/")) { + bool added = item->is_checked(0); if (added) { current->add_export_file(path); } else { current->remove_export_file(path); } } - _refresh_parent_checks(item); // Makes parent folder checked if all files/folders are checked. -} - -void ProjectExportDialog::_check_dir_recursive(TreeItem *p_dir, bool p_checked) { - for (TreeItem *child = p_dir->get_first_child(); child; child = child->get_next()) { - String path = child->get_metadata(0); - - child->set_checked(0, p_checked); - if (path.ends_with("/")) { - _check_dir_recursive(child, p_checked); - } else { - if (p_checked) { - get_current_preset()->add_export_file(path); - } else { - get_current_preset()->remove_export_file(path); - } - } - } -} - -void ProjectExportDialog::_refresh_parent_checks(TreeItem *p_item) { - TreeItem *parent = p_item->get_parent(); - if (!parent) { - return; - } - - bool checked = true; - for (TreeItem *child = parent->get_first_child(); child; child = child->get_next()) { - checked = checked && child->is_checked(0); - if (!checked) { - break; - } - } - parent->set_checked(0, checked); - - _refresh_parent_checks(parent); } void ProjectExportDialog::_export_pck_zip() { @@ -1126,6 +1092,7 @@ ProjectExportDialog::ProjectExportDialog() { include_files = memnew(Tree); include_margin->add_child(include_files); include_files->connect("item_edited", callable_mp(this, &ProjectExportDialog::_tree_changed)); + include_files->connect("check_propagated_to_item", callable_mp(this, &ProjectExportDialog::_check_propagated_to_item)); include_filters = memnew(LineEdit); resources_vb->add_margin_child( diff --git a/editor/project_export.h b/editor/project_export.h index af7ec083c4..3d90a0d3ff 100644 --- a/editor/project_export.h +++ b/editor/project_export.h @@ -124,8 +124,7 @@ private: void _fill_resource_tree(); bool _fill_tree(EditorFileSystemDirectory *p_dir, TreeItem *p_item, Ref<EditorExportPreset> ¤t, bool p_only_scenes); void _tree_changed(); - void _check_dir_recursive(TreeItem *p_dir, bool p_checked); - void _refresh_parent_checks(TreeItem *p_item); + void _check_propagated_to_item(Object *p_obj, int column); Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 481ff1a781..9d894afa6f 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -208,19 +208,19 @@ void CustomPropertyEditor::_menu_option(int p_which) { } break; case OBJ_MENU_NEW_SCRIPT: { if (Object::cast_to<Node>(owner)) { - EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(Object::cast_to<Node>(owner), false); + SceneTreeDock::get_singleton()->open_script_dialog(Object::cast_to<Node>(owner), false); } } break; case OBJ_MENU_EXTEND_SCRIPT: { if (Object::cast_to<Node>(owner)) { - EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(Object::cast_to<Node>(owner), true); + SceneTreeDock::get_singleton()->open_script_dialog(Object::cast_to<Node>(owner), true); } } break; case OBJ_MENU_SHOW_IN_FILE_SYSTEM: { RES r = v; - FileSystemDock *file_system_dock = EditorNode::get_singleton()->get_filesystem_dock(); + FileSystemDock *file_system_dock = FileSystemDock::get_singleton(); file_system_dock->navigate_to_path(r->get_path()); // Ensure that the FileSystem dock is visible. TabContainer *tab_container = (TabContainer *)file_system_dock->get_parent_control(); @@ -506,12 +506,16 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } break; case Variant::STRING: { - if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_GLOBAL_FILE) { + if (hint == PROPERTY_HINT_LOCALE_ID) { + List<String> names; + names.push_back(TTR("Locale...")); + names.push_back(TTR("Clear")); + config_action_buttons(names); + } else if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_GLOBAL_FILE) { List<String> names; names.push_back(TTR("File...")); names.push_back(TTR("Clear")); config_action_buttons(names); - } else if (hint == PROPERTY_HINT_DIR || hint == PROPERTY_HINT_GLOBAL_DIR) { List<String> names; names.push_back(TTR("Dir...")); @@ -1034,6 +1038,14 @@ void CustomPropertyEditor::_file_selected(String p_file) { } } +void CustomPropertyEditor::_locale_selected(String p_locale) { + if (type == Variant::STRING && hint == PROPERTY_HINT_LOCALE_ID) { + v = p_locale; + emit_signal(SNAME("variant_changed")); + hide(); + } +} + void CustomPropertyEditor::_type_create_selected(int p_idx) { if (type == Variant::INT || type == Variant::FLOAT) { float newval = 0; @@ -1177,7 +1189,8 @@ void CustomPropertyEditor::_action_pressed(int p_which) { case Variant::STRING: { if (hint == PROPERTY_HINT_MULTILINE_TEXT) { hide(); - + } else if (hint == PROPERTY_HINT_LOCALE_ID) { + locale->popup_locale_dialog(); } else if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_GLOBAL_FILE) { if (p_which == 0) { if (hint == PROPERTY_HINT_FILE) { @@ -1243,7 +1256,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) { if (owner->is_class("Node") && (v.get_type() == Variant::NODE_PATH) && Object::cast_to<Node>(owner)->has_node(v)) { Node *target_node = Object::cast_to<Node>(owner)->get_node(v); EditorNode::get_singleton()->get_editor_selection()->clear(); - EditorNode::get_singleton()->get_scene_tree_dock()->set_selected(target_node); + SceneTreeDock::get_singleton()->set_selected(target_node); } hide(); @@ -1821,6 +1834,12 @@ CustomPropertyEditor::CustomPropertyEditor() { file->connect("file_selected", callable_mp(this, &CustomPropertyEditor::_file_selected)); file->connect("dir_selected", callable_mp(this, &CustomPropertyEditor::_file_selected)); + locale = memnew(EditorLocaleDialog); + value_vbox->add_child(locale); + locale->hide(); + + locale->connect("locale_selected", callable_mp(this, &CustomPropertyEditor::_locale_selected)); + error = memnew(ConfirmationDialog); error->set_title(TTR("Error!")); value_vbox->add_child(error); diff --git a/editor/property_editor.h b/editor/property_editor.h index 9d88aaf26d..298acb3c01 100644 --- a/editor/property_editor.h +++ b/editor/property_editor.h @@ -32,6 +32,7 @@ #define PROPERTY_EDITOR_H #include "editor/editor_file_dialog.h" +#include "editor/editor_locale_dialog.h" #include "editor/scene_tree_editor.h" #include "scene/gui/button.h" #include "scene/gui/check_box.h" @@ -97,6 +98,7 @@ class CustomPropertyEditor : public PopupPanel { PopupMenu *menu; SceneTreeDialog *scene_tree; EditorFileDialog *file; + EditorLocaleDialog *locale; ConfirmationDialog *error; String name; Variant::Type type; @@ -136,6 +138,7 @@ class CustomPropertyEditor : public PopupPanel { void _text_edit_changed(); void _file_selected(String p_file); + void _locale_selected(String p_locale); void _modified(String p_string); real_t _parse_real_expression(String text); diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp index 20845b0e9d..72686e9eb3 100644 --- a/editor/rename_dialog.cpp +++ b/editor/rename_dialog.cpp @@ -284,6 +284,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und vbc->add_child(lbl_preview_title); lbl_preview = memnew(Label); + lbl_preview->set_autowrap_mode(Label::AUTOWRAP_WORD_SMART); vbc->add_child(lbl_preview); // ---- Dialog related diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 9d382e160c..125fcc02dc 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -445,8 +445,11 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { break; } + bool was_empty = false; if (!node_clipboard.is_empty()) { _clear_clipboard(); + } else { + was_empty = true; } clipboard_source_scene = editor->get_edited_scene()->get_scene_file_path(); @@ -464,81 +467,13 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (p_tool == TOOL_CUT) { _delete_confirm(true); } - } break; - case TOOL_PASTE: { - if (node_clipboard.is_empty() || !edited_scene) { - break; - } - - bool has_cycle = false; - if (!edited_scene->get_scene_file_path().is_empty()) { - for (Node *E : node_clipboard) { - if (edited_scene->get_scene_file_path() == E->get_scene_file_path()) { - has_cycle = true; - break; - } - } - } - - if (has_cycle) { - current_option = -1; - accept->set_text(TTR("Can't paste root node into the same scene.")); - accept->popup_centered(); - break; - } - - Node *paste_parent = edited_scene; - List<Node *> selection = editor_selection->get_selected_node_list(); - if (selection.size() > 0) { - paste_parent = selection.back()->get(); - } - - Node *owner = paste_parent->get_owner(); - if (!owner) { - owner = paste_parent; - } - - editor_data->get_undo_redo().create_action(TTR("Paste Node(s)")); - editor_data->get_undo_redo().add_do_method(editor_selection, "clear"); - - Map<RES, RES> resource_remap; - String target_scene = editor->get_edited_scene()->get_scene_file_path(); - if (target_scene != clipboard_source_scene) { - if (!clipboard_resource_remap.has(target_scene)) { - Map<RES, RES> remap; - for (Node *E : node_clipboard) { - _create_remap_for_node(E, remap); - } - clipboard_resource_remap[target_scene] = remap; - } - resource_remap = clipboard_resource_remap[target_scene]; - } - - for (Node *node : node_clipboard) { - Map<const Node *, Node *> duplimap; - - Node *dup = node->duplicate_from_editor(duplimap, resource_remap); - ERR_CONTINUE(!dup); - - editor_data->get_undo_redo().add_do_method(paste_parent, "add_child", dup, true); - - for (KeyValue<const Node *, Node *> &E2 : duplimap) { - Node *d = E2.value; - editor_data->get_undo_redo().add_do_method(d, "set_owner", owner); - } - - editor_data->get_undo_redo().add_do_method(dup, "set_owner", owner); - editor_data->get_undo_redo().add_do_method(editor_selection, "add_node", dup); - editor_data->get_undo_redo().add_undo_method(paste_parent, "remove_child", dup); - editor_data->get_undo_redo().add_do_reference(dup); - - if (node_clipboard.size() == 1) { - editor_data->get_undo_redo().add_do_method(editor, "push_item", dup); - } + if (was_empty) { + _update_create_root_dialog(); } - - editor_data->get_undo_redo().commit_action(); + } break; + case TOOL_PASTE: { + paste_nodes(); } break; case TOOL_REPLACE: { if (!profile_allow_editing) { @@ -1108,7 +1043,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (node) { node->set_scene_inherited_state(Ref<SceneState>()); scene_tree->update_tree(); - EditorNode::get_singleton()->get_inspector()->update_tree(); + InspectorDock::get_inspector_singleton()->update_tree(); } } } break; @@ -1306,6 +1241,12 @@ void SceneTreeDock::_notification(int p_what) { button_custom->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); button_custom->connect("pressed", callable_bind(callable_mp(this, &SceneTreeDock::_tool_selected), TOOL_NEW, false)); + button_clipboard = memnew(Button); + node_shortcuts->add_child(button_clipboard); + button_clipboard->set_text(TTR("Paste From Clipboard")); + button_clipboard->set_icon(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons"))); + button_clipboard->connect("pressed", callable_bind(callable_mp(this, &SceneTreeDock::_tool_selected), TOOL_PASTE, false)); + node_shortcuts->add_spacer(); create_root_dialog->add_child(node_shortcuts); _update_create_root_dialog(); @@ -1330,6 +1271,7 @@ void SceneTreeDock::_notification(int p_what) { button_3d->set_icon(get_theme_icon(SNAME("Node3D"), SNAME("EditorIcons"))); button_ui->set_icon(get_theme_icon(SNAME("Control"), SNAME("EditorIcons"))); button_custom->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); + button_clipboard->set_icon(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons"))); filter->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); filter->set_clear_button_enabled(true); @@ -2125,7 +2067,7 @@ void SceneTreeDock::_delete_confirm(bool p_cut) { // Fixes the EditorHistory from still offering deleted notes EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history(); editor_history->cleanup_history(); - EditorNode::get_singleton()->get_inspector_dock()->call("_prepare_history"); + InspectorDock::get_singleton()->call("_prepare_history"); } void SceneTreeDock::_update_script_button() { @@ -2740,10 +2682,10 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { } if (profile_allow_editing) { - menu->add_shortcut(ED_GET_SHORTCUT("scene_tree/cut_node"), TOOL_CUT); - menu->add_shortcut(ED_GET_SHORTCUT("scene_tree/copy_node"), TOOL_COPY); + menu->add_icon_shortcut(get_theme_icon(SNAME("ActionCut"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/cut_node"), TOOL_CUT); + menu->add_icon_shortcut(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/copy_node"), TOOL_COPY); if (selection.size() == 1 && !node_clipboard.is_empty()) { - menu->add_shortcut(ED_GET_SHORTCUT("scene_tree/paste_node"), TOOL_PASTE); + menu->add_icon_shortcut(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/paste_node"), TOOL_PASTE); } menu->add_separator(); } @@ -2867,15 +2809,9 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { menu->popup(); } -void SceneTreeDock::_open_tree_menu() { - menu->clear(); - - menu->add_check_item(TTR("Auto Expand to Selected"), TOOL_AUTO_EXPAND); - menu->set_item_checked(menu->get_item_idx_from_text(TTR("Auto Expand to Selected")), EditorSettings::get_singleton()->get("docks/scene_tree/auto_expand_to_selected")); - - menu->reset_size(); - menu->set_position(get_screen_position() + get_local_mouse_position()); - menu->popup(); +void SceneTreeDock::_update_tree_menu() { + PopupMenu *tree_menu = button_tree_menu->get_popup(); + tree_menu->set_item_checked(tree_menu->get_item_idx_from_text(TTR("Auto Expand to Selected")), EditorSettings::get_singleton()->get("docks/scene_tree/auto_expand_to_selected")); } void SceneTreeDock::_filter_changed(const String &p_filter) { @@ -3022,6 +2958,108 @@ void SceneTreeDock::open_instance_child_dialog() { _tool_selected(TOOL_INSTANTIATE, true); } +List<Node *> SceneTreeDock::paste_nodes() { + List<Node *> pasted_nodes; + + if (node_clipboard.is_empty()) { + return pasted_nodes; + } + + bool has_cycle = false; + if (edited_scene && !edited_scene->get_scene_file_path().is_empty()) { + for (Node *E : node_clipboard) { + if (edited_scene->get_scene_file_path() == E->get_scene_file_path()) { + has_cycle = true; + break; + } + } + } + + if (has_cycle) { + current_option = -1; + accept->set_text(TTR("Can't paste root node into the same scene.")); + accept->popup_centered(); + return pasted_nodes; + } + + Node *paste_parent = edited_scene; + List<Node *> selection = editor_selection->get_selected_node_list(); + if (selection.size() > 0) { + paste_parent = selection.back()->get(); + } + + Node *owner = nullptr; + if (paste_parent) { + owner = paste_parent->get_owner(); + } + if (!owner) { + owner = paste_parent; + } + + UndoRedo &ur = editor_data->get_undo_redo(); + ur.create_action(TTR("Paste Node(s)")); + ur.add_do_method(editor_selection, "clear"); + + Map<RES, RES> resource_remap; + String target_scene; + if (edited_scene) { + target_scene = edited_scene->get_scene_file_path(); + } + if (target_scene != clipboard_source_scene) { + if (!clipboard_resource_remap.has(target_scene)) { + Map<RES, RES> remap; + for (Node *E : node_clipboard) { + _create_remap_for_node(E, remap); + } + clipboard_resource_remap[target_scene] = remap; + } + resource_remap = clipboard_resource_remap[target_scene]; + } + + for (Node *node : node_clipboard) { + Map<const Node *, Node *> duplimap; + + Node *dup = node->duplicate_from_editor(duplimap, resource_remap); + ERR_CONTINUE(!dup); + + pasted_nodes.push_back(dup); + + if (!paste_parent) { + paste_parent = dup; + owner = dup; + ur.add_do_method(editor, "set_edited_scene", dup); + } else { + ur.add_do_method(paste_parent, "add_child", dup, true); + } + + for (KeyValue<const Node *, Node *> &E2 : duplimap) { + Node *d = E2.value; + if (d != dup) { + ur.add_do_method(d, "set_owner", owner); + } + } + + if (dup != owner) { + ur.add_do_method(dup, "set_owner", owner); + } + ur.add_do_method(editor_selection, "add_node", dup); + + if (dup == paste_parent) { + ur.add_undo_method(editor, "set_edited_scene", (Object *)nullptr); + } else { + ur.add_undo_method(paste_parent, "remove_child", dup); + } + ur.add_do_reference(dup); + + if (node_clipboard.size() == 1) { + ur.add_do_method(editor, "push_item", dup); + } + } + + ur.commit_action(); + return pasted_nodes; +} + void SceneTreeDock::add_remote_tree_editor(Control *p_remote) { ERR_FAIL_COND(remote_tree != nullptr); add_child(p_remote); @@ -3121,6 +3159,7 @@ void SceneTreeDock::_update_create_root_dialog() { beginner_nodes->show(); favorite_nodes->hide(); } + button_clipboard->set_visible(!node_clipboard.is_empty()); } } @@ -3175,7 +3214,7 @@ void SceneTreeDock::_create_remap_for_node(Node *p_node, Map<RES, RES> &r_remap) } Variant v = p_node->get(E.name); - if (v.is_ref()) { + if (v.is_ref_counted()) { RES res = v; if (res.is_valid()) { if (!states_stack_ready) { @@ -3213,7 +3252,7 @@ void SceneTreeDock::_create_remap_for_resource(RES p_resource, Map<RES, RES> &r_ } Variant v = p_resource->get(E.name); - if (v.is_ref()) { + if (v.is_ref_counted()) { RES res = v; if (res.is_valid()) { if (res->is_built_in() && !r_remap.has(res)) { @@ -3325,11 +3364,15 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel filter_hbc->add_child(button_detach_script); button_detach_script->hide(); - button_tree_menu = memnew(Button); + button_tree_menu = memnew(MenuButton); button_tree_menu->set_flat(true); - button_tree_menu->connect("pressed", callable_mp(this, &SceneTreeDock::_open_tree_menu)); + button_tree_menu->connect("about_to_popup", callable_mp(this, &SceneTreeDock::_update_tree_menu)); filter_hbc->add_child(button_tree_menu); + PopupMenu *tree_menu = button_tree_menu->get_popup(); + tree_menu->add_check_item(TTR("Auto Expand to Selected"), TOOL_AUTO_EXPAND); + tree_menu->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(false)); + button_hb = memnew(HBoxContainer); vbc->add_child(button_hb); diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index ffaf34cfdc..d73038ef36 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -117,12 +117,13 @@ class SceneTreeDock : public VBoxContainer { Button *button_instance; Button *button_create_script; Button *button_detach_script; - Button *button_tree_menu; + MenuButton *button_tree_menu; Button *button_2d; Button *button_3d; Button *button_ui; Button *button_custom; + Button *button_clipboard; HBoxContainer *button_hb; Button *edit_local, *edit_remote; @@ -241,7 +242,7 @@ class SceneTreeDock : public VBoxContainer { void _quick_open(); void _tree_rmb(const Vector2 &p_menu_pos); - void _open_tree_menu(); + void _update_tree_menu(); void _filter_changed(const String &p_filter); @@ -263,12 +264,17 @@ class SceneTreeDock : public VBoxContainer { bool profile_allow_editing; bool profile_allow_script_editing; - static SceneTreeDock *singleton; static void _update_configuration_warning(); bool _update_node_path(Node *p_root_node, NodePath &r_node_path, Map<Node *, NodePath> *p_renames) const; bool _check_node_path_recursive(Node *p_root_node, Variant &r_variant, Map<Node *, NodePath> *p_renames) const; +private: + static SceneTreeDock *singleton; + +public: + static SceneTreeDock *get_singleton() { return singleton; } + protected: void _notification(int p_what); static void _bind_methods(); @@ -308,6 +314,8 @@ public: void open_add_child_dialog(); void open_instance_child_dialog(); + List<Node *> paste_nodes(); + ScriptCreateDialog *get_script_create_dialog() { return script_create_dialog; } SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSelection *p_editor_selection, EditorData &p_editor_data); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index dc95b73569..4a36462d65 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -133,8 +133,8 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i set_selected(n); - NodeDock::singleton->get_parent()->call("set_current_tab", NodeDock::singleton->get_index()); - NodeDock::singleton->show_connections(); + NodeDock::get_singleton()->get_parent()->call("set_current_tab", NodeDock::get_singleton()->get_index()); + NodeDock::get_singleton()->show_connections(); } else if (p_id == BUTTON_GROUPS) { editor_selection->clear(); @@ -142,8 +142,8 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i set_selected(n); - NodeDock::singleton->get_parent()->call("set_current_tab", NodeDock::singleton->get_index()); - NodeDock::singleton->show_groups(); + NodeDock::get_singleton()->get_parent()->call("set_current_tab", NodeDock::get_singleton()->get_index()); + NodeDock::get_singleton()->show_groups(); } } diff --git a/misc/dist/html/editor.html b/misc/dist/html/editor.html index 8b077a5725..a681a2a1c3 100644 --- a/misc/dist/html/editor.html +++ b/misc/dist/html/editor.html @@ -9,8 +9,8 @@ <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="application-name" content="Godot" /> <meta name="apple-mobile-web-app-title" content="Godot" /> - <meta name="theme-color" content="#478cbf" /> - <meta name="msapplication-navbutton-color" content="#478cbf" /> + <meta name="theme-color" content="#202531" /> + <meta name="msapplication-navbutton-color" content="#202531" /> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta name="msapplication-starturl" content="/latest" /> <meta property="og:site_name" content="Godot Engine Web Editor" /> diff --git a/misc/dist/html/manifest.json b/misc/dist/html/manifest.json index 0ca27b3742..adc8106e2a 100644 --- a/misc/dist/html/manifest.json +++ b/misc/dist/html/manifest.json @@ -6,7 +6,7 @@ "start_url": "./godot.tools.html", "display": "standalone", "orientation": "landscape", - "theme_color": "#478cbf", + "theme_color": "#202531", "icons": [ { "src": "favicon.png", diff --git a/misc/dist/html/offline.html b/misc/dist/html/offline.html index 000c21b4d3..5cfc3362d9 100644 --- a/misc/dist/html/offline.html +++ b/misc/dist/html/offline.html @@ -4,6 +4,8 @@ <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta name="theme-color" content="#202531" /> + <meta name="msapplication-navbutton-color" content="#202531" /> <title>You are offline</title> <style> html { diff --git a/misc/scripts/clang_format.sh b/misc/scripts/clang_format.sh index b0020da597..0006b82280 100755 --- a/misc/scripts/clang_format.sh +++ b/misc/scripts/clang_format.sh @@ -29,8 +29,6 @@ while IFS= read -rd '' f; do continue 2 elif [[ "$f" == *"glsl" ]]; then continue 2 - elif [[ "$f" == *"theme_data.h" ]]; then - continue 2 elif [[ "$f" == "platform/android/java/lib/src/org/godotengine/godot/input/InputManager"* ]]; then continue 2 fi diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 41b4682c84..4b36bca02a 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -1694,7 +1694,7 @@ CSGBrush *CSGPolygon3D::_build_brush() { } int shape_sides = shape_polygon.size(); Vector<int> shape_faces = Geometry2D::triangulate_polygon(shape_polygon); - ERR_FAIL_COND_V_MSG(shape_faces.size() < 3, brush, "Failed to triangulate CSGPolygon"); + ERR_FAIL_COND_V_MSG(shape_faces.size() < 3, brush, "Failed to triangulate CSGPolygon. Make sure the polygon doesn't have any intersecting edges."); // Get polygon enclosing Rect2. Rect2 shape_rect(shape_polygon[0], Vector2()); diff --git a/modules/csg/doc_classes/CSGMesh3D.xml b/modules/csg/doc_classes/CSGMesh3D.xml index 2810343139..42fcb7bd2b 100644 --- a/modules/csg/doc_classes/CSGMesh3D.xml +++ b/modules/csg/doc_classes/CSGMesh3D.xml @@ -4,7 +4,7 @@ A CSG Mesh shape that uses a mesh resource. </brief_description> <description> - This CSG node allows you to use any mesh resource as a CSG shape, provided it is closed, does not self-intersect, does not contain internal faces and has no edges that connect to more than two faces. + This CSG node allows you to use any mesh resource as a CSG shape, provided it is closed, does not self-intersect, does not contain internal faces and has no edges that connect to more than two faces. See also [CSGPolygon3D] for drawing 2D extruded polygons to be used as CSG nodes. </description> <tutorials> </tutorials> diff --git a/modules/csg/doc_classes/CSGPolygon3D.xml b/modules/csg/doc_classes/CSGPolygon3D.xml index ecbb7962d1..5a49eebc7b 100644 --- a/modules/csg/doc_classes/CSGPolygon3D.xml +++ b/modules/csg/doc_classes/CSGPolygon3D.xml @@ -4,7 +4,7 @@ Extrudes a 2D polygon shape to create a 3D mesh. </brief_description> <description> - An array of 2D points is extruded to quickly and easily create a variety of 3D meshes. + An array of 2D points is extruded to quickly and easily create a variety of 3D meshes. See also [CSGMesh3D] for using 3D meshes as CSG nodes. </description> <tutorials> </tutorials> @@ -46,7 +46,8 @@ When [member mode] is [constant MODE_PATH], this is the distance along the path, in meters, the texture coordinates will tile. When set to 0, texture coordinates will match geometry exactly with no tiling. </member> <member name="polygon" type="PackedVector2Array" setter="set_polygon" getter="get_polygon" default="PackedVector2Array(0, 0, 0, 1, 1, 1, 1, 0)"> - The point array that defines the 2D polygon that is extruded. + The point array that defines the 2D polygon that is extruded. This can be a convex or concave polygon with 3 or more points. The polygon must [i]not[/i] have any intersecting edges. Otherwise, triangulation will fail and no mesh will be generated. + [b]Note:[/b] If only 1 or 2 points are defined in [member polygon], no mesh will be generated. </member> <member name="smooth_faces" type="bool" setter="set_smooth_faces" getter="get_smooth_faces" default="false"> If [code]true[/code], applies smooth shading to the extrusions. diff --git a/modules/etcpak/image_compress_etcpak.cpp b/modules/etcpak/image_compress_etcpak.cpp index c79d449d41..7d5557d197 100644 --- a/modules/etcpak/image_compress_etcpak.cpp +++ b/modules/etcpak/image_compress_etcpak.cpp @@ -132,8 +132,39 @@ void _compress_etcpak(EtcpakType p_compresstype, Image *r_img, float p_lossy_qua // Compress image data and (if required) mipmaps. const bool mipmaps = r_img->has_mipmaps(); - const int width = r_img->get_width(); - const int height = r_img->get_height(); + int width = r_img->get_width(); + int height = r_img->get_height(); + + /* + The first mipmap level of a compressed texture must be a multiple of 4. Quote from D3D11.3 spec: + + BC format surfaces are always multiples of full blocks, each block representing 4x4 pixels. + For mipmaps, the top level map is required to be a multiple of 4 size in all dimensions. + The sizes for the lower level maps are computed as they are for all mipmapped surfaces, + and thus may not be a multiple of 4, for example a top level map of 20 results in a second level + map size of 10. For these cases, there is a differing 'physical' size and a 'virtual' size. + The virtual size is that computed for each mip level without adjustment, which is 10 for the example. + The physical size is the virtual size rounded up to the next multiple of 4, which is 12 for the example, + and this represents the actual memory size. The sampling hardware will apply texture address + processing based on the virtual size (using, for example, border color if specified for accesses + beyond 10), and thus for the example case will not access the 11th and 12th row of the resource. + So for mipmap chains when an axis becomes < 4 in size, only texels 'a','b','e','f' + are used for a 2x2 map, and texel 'a' is used for 1x1. Note that this is similar to, but distinct from, + the surface pitch, which can encompass additional padding beyond the physical surface size. + */ + int next_width = width <= 2 ? width : (width + 3) & ~3; + int next_height = height <= 2 ? height : (height + 3) & ~3; + if (next_width != width || next_height != height) { + r_img->resize(next_width, next_height, Image::INTERPOLATE_LANCZOS); + width = r_img->get_width(); + height = r_img->get_height(); + } + // ERR_FAIL_COND(width % 4 != 0 || height % 4 != 0); // FIXME: No longer guaranteed. + // Multiple-of-4 should be guaranteed by above. + // However, power-of-two 3d textures will create Nx2 and Nx1 mipmap levels, + // which are individually compressed Image objects that violate the above rule. + // Hence, we allow Nx1 and Nx2 images through without forcing to multiple-of-4. + const uint8_t *src_read = r_img->get_data().ptr(); print_verbose(vformat("ETCPAK: Encoding image size %dx%d to format %s.", width, height, Image::get_format_name(target_format))); @@ -144,24 +175,48 @@ void _compress_etcpak(EtcpakType p_compresstype, Image *r_img, float p_lossy_qua uint8_t *dest_write = dest_data.ptrw(); int mip_count = mipmaps ? Image::get_image_required_mipmaps(width, height, target_format) : 0; + Vector<uint32_t> padded_src; for (int i = 0; i < mip_count + 1; i++) { // Get write mip metrics for target image. - int mip_w, mip_h; - int mip_ofs = Image::get_image_mipmap_offset_and_dimensions(width, height, target_format, i, mip_w, mip_h); + int orig_mip_w, orig_mip_h; + int mip_ofs = Image::get_image_mipmap_offset_and_dimensions(width, height, target_format, i, orig_mip_w, orig_mip_h); // Ensure that mip offset is a multiple of 8 (etcpak expects uint64_t pointer). ERR_FAIL_COND(mip_ofs % 8 != 0); uint64_t *dest_mip_write = (uint64_t *)&dest_write[mip_ofs]; // Block size. Align stride to multiple of 4 (RGBA8). - mip_w = (mip_w + 3) & ~3; - mip_h = (mip_h + 3) & ~3; + int mip_w = (orig_mip_w + 3) & ~3; + int mip_h = (orig_mip_h + 3) & ~3; const uint32_t blocks = mip_w * mip_h / 16; // Get mip data from source image for reading. int src_mip_ofs = r_img->get_mipmap_offset(i); const uint32_t *src_mip_read = (const uint32_t *)&src_read[src_mip_ofs]; + // Pad textures to nearest block by smearing. + if (mip_w != orig_mip_w || mip_h != orig_mip_h) { + padded_src.resize(mip_w * mip_h); + uint32_t *ptrw = padded_src.ptrw(); + int x = 0, y = 0; + for (y = 0; y < orig_mip_h; y++) { + for (x = 0; x < orig_mip_w; x++) { + ptrw[mip_w * y + x] = src_mip_read[orig_mip_w * y + x]; + } + // First, smear in x. + for (; x < mip_w; x++) { + ptrw[mip_w * y + x] = ptrw[mip_w * y + x - 1]; + } + } + // Then, smear in y. + for (; y < mip_h; y++) { + for (x = 0; x < mip_w; x++) { + ptrw[mip_w * y + x] = ptrw[mip_w * y + x - mip_w]; + } + } + // Override the src_mip_read pointer to our temporary Vector. + src_mip_read = padded_src.ptr(); + } if (p_compresstype == EtcpakType::ETCPAK_TYPE_ETC1) { CompressEtc1RgbDither(src_mip_read, dest_mip_write, blocks, mip_w); } else if (p_compresstype == EtcpakType::ETCPAK_TYPE_ETC2 || p_compresstype == EtcpakType::ETCPAK_TYPE_ETC2_RA_AS_RG) { diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h index eea898475b..879291c2e0 100644 --- a/modules/gdnative/include/nativescript/godot_nativescript.h +++ b/modules/gdnative/include/nativescript/godot_nativescript.h @@ -79,6 +79,7 @@ typedef enum { GODOT_PROPERTY_HINT_PROPERTY_OF_BASE_TYPE, ///< a property of a base type GODOT_PROPERTY_HINT_PROPERTY_OF_INSTANCE, ///< a property of an instance GODOT_PROPERTY_HINT_PROPERTY_OF_SCRIPT, ///< a property of a script & base + GODOT_PROPERTY_HINT_LOCALE_ID, GODOT_PROPERTY_HINT_MAX, } godot_nativescript_property_hint; diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp index 4ac5a4a60e..6ada7d36f5 100644 --- a/modules/gdscript/gdscript_cache.cpp +++ b/modules/gdscript/gdscript_cache.cpp @@ -122,6 +122,10 @@ Ref<GDScriptParserRef> GDScriptCache::get_parser(const String &p_path, GDScriptP } if (singleton->parser_map.has(p_path)) { ref = Ref<GDScriptParserRef>(singleton->parser_map[p_path]); + if (ref.is_null()) { + r_error = ERR_INVALID_DATA; + return ref; + } } else { if (!FileAccess::exists(p_path)) { r_error = ERR_FILE_NOT_FOUND; @@ -133,7 +137,6 @@ Ref<GDScriptParserRef> GDScriptCache::get_parser(const String &p_path, GDScriptP ref->path = p_path; singleton->parser_map[p_path] = ref.ptr(); } - r_error = ref->raise_status(p_status); return ref; diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index f1877df326..9424de9d22 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -248,7 +248,7 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) { // If the return value is a GDScriptFunctionState reference, // then the function did await again after resuming. - if (ret.is_ref()) { + if (ret.is_ref_counted()) { GDScriptFunctionState *gdfs = Object::cast_to<GDScriptFunctionState>(ret); if (gdfs && gdfs->function == function) { completed = false; diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 5e210074ed..460bd85a86 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -2105,7 +2105,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_precedence(Precedence p_pr ExpressionNode *previous_operand = (this->*prefix_rule)(nullptr, p_can_assign); while (p_precedence <= get_rule(current.type)->precedence) { - if (p_stop_on_assign && current.type == GDScriptTokenizer::Token::EQUAL) { + if (previous_operand == nullptr || (p_stop_on_assign && current.type == GDScriptTokenizer::Token::EQUAL)) { return previous_operand; } // Also switch multiline mode on here for infix operators. @@ -2415,6 +2415,9 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_assignment(ExpressionNode push_error("Assignment is not allowed inside an expression."); return parse_expression(false); // Return the following expression. } + if (p_previous_operand == nullptr) { + return parse_expression(false); // Return the following expression. + } #ifdef DEBUG_ENABLED VariableNode *source_variable = nullptr; diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index e0facaf61d..95122714f9 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -1532,7 +1532,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } } else if (methodstr == "free") { if (err.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) { - if (base->is_ref()) { + if (base->is_ref_counted()) { err_text = "Attempted to free a reference."; OPCODE_BREAK; } else if (base->get_type() == Variant::OBJECT) { @@ -1620,7 +1620,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } } else if (methodstr == "free") { if (err.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) { - if (base->is_ref()) { + if (base->is_ref_counted()) { err_text = "Attempted to free a reference."; OPCODE_BREAK; } else if (base->get_type() == Variant::OBJECT) { diff --git a/modules/gdscript/tests/scripts/parser/errors/dollar-assignment-bug-53696.gd b/modules/gdscript/tests/scripts/parser/errors/dollar-assignment-bug-53696.gd new file mode 100644 index 0000000000..e9690ee93d --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/dollar-assignment-bug-53696.gd @@ -0,0 +1,2 @@ +func test(): + $=$ diff --git a/modules/gdscript/tests/scripts/parser/errors/dollar-assignment-bug-53696.out b/modules/gdscript/tests/scripts/parser/errors/dollar-assignment-bug-53696.out new file mode 100644 index 0000000000..b3dc181a22 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/dollar-assignment-bug-53696.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Expect node path as string or identifier after "$". diff --git a/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out b/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out index 447d7e223c..5b0ea9df43 100644 --- a/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out +++ b/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out @@ -1,2 +1,2 @@ GDTEST_OK -{2:4, a:1, b:2, with spaces:3} +{a:1, b:2, with spaces:3, 2:4} diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml index 885817caf1..9c28421a46 100644 --- a/modules/gridmap/doc_classes/GridMap.xml +++ b/modules/gridmap/doc_classes/GridMap.xml @@ -67,7 +67,7 @@ Returns whether or not the specified layer of the [member collision_mask] is enabled, given a [code]layer_number[/code] between 1 and 32. </description> </method> - <method name="get_meshes"> + <method name="get_meshes" qualifiers="const"> <return type="Array" /> <description> Returns an array of [Transform3D] and [Mesh] references corresponding to the non-empty cells in the grid. The transforms are specified in world space. diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index a861efcbf4..67deedf839 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -35,6 +35,7 @@ #include "scene/3d/light_3d.h" #include "scene/resources/mesh_library.h" #include "scene/resources/physics_material.h" +#include "scene/resources/primitive_meshes.h" #include "scene/resources/surface_tool.h" #include "scene/scene_string_names.h" #include "servers/navigation_server_3d.h" @@ -197,6 +198,24 @@ bool GridMap::get_collision_mask_value(int p_layer_number) const { return get_collision_mask() & (1 << (p_layer_number - 1)); } +Array GridMap::get_collision_shapes() const { + Array shapes; + for (const KeyValue<OctantKey, Octant *> &E : octant_map) { + Octant *g = E.value; + RID body = g->static_body; + Transform3D body_xform = PhysicsServer3D::get_singleton()->body_get_state(body, PhysicsServer3D::BODY_STATE_TRANSFORM); + int nshapes = PhysicsServer3D::get_singleton()->body_get_shape_count(body); + for (int i = 0; i < nshapes; i++) { + RID shape = PhysicsServer3D::get_singleton()->body_get_shape(body, i); + Transform3D xform = PhysicsServer3D::get_singleton()->body_get_shape_transform(body, i); + shapes.push_back(body_xform * xform); + shapes.push_back(shape); + } + } + + return shapes; +} + void GridMap::set_bake_navigation(bool p_bake_navigation) { bake_navigation = p_bake_navigation; _recreate_octant_data(); @@ -930,7 +949,7 @@ Array GridMap::get_used_cells() const { return a; } -Array GridMap::get_meshes() { +Array GridMap::get_meshes() const { if (mesh_library.is_null()) { return Array(); } @@ -938,7 +957,7 @@ Array GridMap::get_meshes() { Vector3 ofs = _get_offset(); Array meshes; - for (KeyValue<IndexKey, Cell> &E : cell_map) { + for (const KeyValue<IndexKey, Cell> &E : cell_map) { int id = E.value.item; if (!mesh_library->has_item(id)) { continue; diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h index 546b530148..6cdc3b178d 100644 --- a/modules/gridmap/grid_map.h +++ b/modules/gridmap/grid_map.h @@ -229,6 +229,8 @@ public: void set_physics_material(Ref<PhysicsMaterial> p_material); Ref<PhysicsMaterial> get_physics_material() const; + Array get_collision_shapes() const; + void set_bake_navigation(bool p_bake_navigation); bool is_baking_navigation(); @@ -265,7 +267,7 @@ public: Array get_used_cells() const; - Array get_meshes(); + Array get_meshes() const; void clear_baked_meshes(); void make_baked_meshes(bool p_gen_lightmap_uv = false, float p_lightmap_uv_texel_size = 0.1); diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 5ef48f8645..320901787d 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -1459,10 +1459,10 @@ void GridMapEditorPlugin::_notification(int p_what) { if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { switch ((int)EditorSettings::get_singleton()->get("editors/grid_map/editor_side")) { case 0: { // Left. - Node3DEditor::get_singleton()->get_palette_split()->move_child(grid_map_editor, 0); + Node3DEditor::get_singleton()->move_control_to_left_panel(grid_map_editor); } break; case 1: { // Right. - Node3DEditor::get_singleton()->get_palette_split()->move_child(grid_map_editor, 1); + Node3DEditor::get_singleton()->move_control_to_right_panel(grid_map_editor); } break; } } @@ -1498,10 +1498,10 @@ GridMapEditorPlugin::GridMapEditorPlugin(EditorNode *p_node) { grid_map_editor = memnew(GridMapEditor(editor)); switch ((int)EditorSettings::get_singleton()->get("editors/grid_map/editor_side")) { case 0: { // Left. - add_control_to_container(CONTAINER_SPATIAL_EDITOR_SIDE_LEFT, grid_map_editor); + Node3DEditor::get_singleton()->add_control_to_left_panel(grid_map_editor); } break; case 1: { // Right. - add_control_to_container(CONTAINER_SPATIAL_EDITOR_SIDE_RIGHT, grid_map_editor); + Node3DEditor::get_singleton()->add_control_to_right_panel(grid_map_editor); } break; } grid_map_editor->hide(); diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp index 59854ad527..49044c4afe 100644 --- a/modules/mobile_vr/mobile_vr_interface.cpp +++ b/modules/mobile_vr/mobile_vr_interface.cpp @@ -181,6 +181,7 @@ void MobileVRInterface::set_position_from_sensors() { orientation = rotate * orientation; tracking_state = XRInterface::XR_NORMAL_TRACKING; + tracking_confidence = XRPose::XR_TRACKING_CONFIDENCE_HIGH; }; ///@TODO improve this, the magnetometer is very fidgety sometimes flipping the axis for no apparent reason (probably a bug on my part) @@ -193,6 +194,7 @@ void MobileVRInterface::set_position_from_sensors() { orientation = Basis(transform_quat); tracking_state = XRInterface::XR_NORMAL_TRACKING; + tracking_confidence = XRPose::XR_TRACKING_CONFIDENCE_HIGH; } else if (has_grav) { // use gravity vector to make sure down is down... // transform gravity into our world space @@ -512,7 +514,7 @@ void MobileVRInterface::process() { if (head.is_valid()) { // Set our head position, note in real space, reference frame and world scale is applied later - head->set_pose("default", head_transform, Vector3(), Vector3()); + head->set_pose("default", head_transform, Vector3(), Vector3(), tracking_confidence); } }; }; diff --git a/modules/mobile_vr/mobile_vr_interface.h b/modules/mobile_vr/mobile_vr_interface.h index ac04763569..47dc33c0c7 100644 --- a/modules/mobile_vr/mobile_vr_interface.h +++ b/modules/mobile_vr/mobile_vr_interface.h @@ -51,6 +51,7 @@ class MobileVRInterface : public XRInterface { private: bool initialized = false; XRInterface::TrackingStatus tracking_state; + XRPose::TrackingConfidence tracking_confidence = XRPose::XR_TRACKING_CONFIDENCE_NONE; // Just set some defaults for these. At some point we need to look at adding a lookup table for common device + headset combos and/or support reading cardboard QR codes double eye_height = 1.85; diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 9d416dcfce..26436e3ec0 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -1168,8 +1168,8 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { #ifdef TOOLS_ENABLED // FIXME: Hack to refresh editor in order to display new properties and signals. See if there is a better alternative. if (Engine::get_singleton()->is_editor_hint()) { - EditorNode::get_singleton()->get_inspector()->update_tree(); - NodeDock::singleton->update_lists(); + InspectorDock::get_inspector_singleton()->update_tree(); + NodeDock::get_singleton()->update_lists(); } #endif } diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs index e9cf7911be..2dbc78ab77 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs @@ -147,7 +147,7 @@ namespace GodotTools.Build Icon = GetThemeIcon("StatusError", "EditorIcons"), ExpandIcon = false, ToggleMode = true, - Pressed = true, + ButtonPressed = true, FocusMode = FocusModeEnum.None }; _errorsBtn.Toggled += ErrorsToggled; @@ -159,7 +159,7 @@ namespace GodotTools.Build Icon = GetThemeIcon("NodeWarning", "EditorIcons"), ExpandIcon = false, ToggleMode = true, - Pressed = true, + ButtonPressed = true, FocusMode = FocusModeEnum.None }; _warningsBtn.Toggled += WarningsToggled; @@ -169,7 +169,7 @@ namespace GodotTools.Build { Text = "Show Output".TTR(), ToggleMode = true, - Pressed = true, + ButtonPressed = true, FocusMode = FocusModeEnum.None }; _viewLogBtn.Toggled += ViewLogToggled; diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index 98c6881166..69960bdbeb 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -428,7 +428,7 @@ namespace GodotTools Shortcut = buildSolutionShortcut, ShortcutInTooltip = true }; - _toolBarBuildButton.PressedSignal += BuildSolutionPressed; + _toolBarBuildButton.Pressed += BuildSolutionPressed; AddControlToContainer(CustomControlContainer.Toolbar, _toolBarBuildButton); if (File.Exists(GodotSharpDirs.ProjectSlnPath) && File.Exists(GodotSharpDirs.ProjectCsProjPath)) diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp index 6cbdb645ca..77fe9cdd19 100644 --- a/modules/navigation/navigation_mesh_generator.cpp +++ b/modules/navigation/navigation_mesh_generator.cpp @@ -265,14 +265,100 @@ void NavigationMeshGenerator::_parse_geometry(Transform3D p_accumulated_transfor } #ifdef MODULE_GRIDMAP_ENABLED - if (Object::cast_to<GridMap>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) { - GridMap *gridmap_instance = Object::cast_to<GridMap>(p_node); - Array meshes = gridmap_instance->get_meshes(); - Transform3D xform = gridmap_instance->get_transform(); - for (int i = 0; i < meshes.size(); i += 2) { - Ref<Mesh> mesh = meshes[i + 1]; - if (mesh.is_valid()) { - _add_mesh(mesh, p_accumulated_transform * xform * (Transform3D)meshes[i], p_vertices, p_indices); + GridMap *gridmap = Object::cast_to<GridMap>(p_node); + + if (gridmap) { + if (p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) { + Array meshes = gridmap->get_meshes(); + Transform3D xform = gridmap->get_transform(); + for (int i = 0; i < meshes.size(); i += 2) { + Ref<Mesh> mesh = meshes[i + 1]; + if (mesh.is_valid()) { + _add_mesh(mesh, p_accumulated_transform * xform * (Transform3D)meshes[i], p_vertices, p_indices); + } + } + } + + if (p_generate_from != NavigationMesh::PARSED_GEOMETRY_MESH_INSTANCES && (gridmap->get_collision_layer() & p_collision_mask)) { + Array shapes = gridmap->get_collision_shapes(); + for (int i = 0; i < shapes.size(); i += 2) { + RID shape = shapes[i + 1]; + PhysicsServer3D::ShapeType type = PhysicsServer3D::get_singleton()->shape_get_type(shape); + Variant data = PhysicsServer3D::get_singleton()->shape_get_data(shape); + Ref<Mesh> mesh; + + switch (type) { + case PhysicsServer3D::SHAPE_SPHERE: { + real_t radius = data; + Ref<SphereMesh> sphere_mesh; + sphere_mesh.instantiate(); + sphere_mesh->set_radius(radius); + sphere_mesh->set_height(radius * 2.0); + mesh = sphere_mesh; + } break; + case PhysicsServer3D::SHAPE_BOX: { + Vector3 extents = data; + Ref<BoxMesh> box_mesh; + box_mesh.instantiate(); + box_mesh->set_size(2.0 * extents); + mesh = box_mesh; + } break; + case PhysicsServer3D::SHAPE_CAPSULE: { + Dictionary dict = data; + real_t radius = dict["radius"]; + real_t height = dict["height"]; + Ref<CapsuleMesh> capsule_mesh; + capsule_mesh.instantiate(); + capsule_mesh->set_radius(radius); + capsule_mesh->set_height(height); + mesh = capsule_mesh; + } break; + case PhysicsServer3D::SHAPE_CYLINDER: { + Dictionary dict = data; + real_t radius = dict["radius"]; + real_t height = dict["height"]; + Ref<CylinderMesh> cylinder_mesh; + cylinder_mesh.instantiate(); + cylinder_mesh->set_height(height); + cylinder_mesh->set_bottom_radius(radius); + cylinder_mesh->set_top_radius(radius); + mesh = cylinder_mesh; + } break; + case PhysicsServer3D::SHAPE_CONVEX_POLYGON: { + PackedVector3Array vertices = data; + Geometry3D::MeshData md; + + Error err = ConvexHullComputer::convex_hull(vertices, md); + + if (err == OK) { + PackedVector3Array faces; + + for (int j = 0; j < md.faces.size(); ++j) { + Geometry3D::MeshData::Face face = md.faces[j]; + + for (int k = 2; k < face.indices.size(); ++k) { + faces.push_back(md.vertices[face.indices[0]]); + faces.push_back(md.vertices[face.indices[k - 1]]); + faces.push_back(md.vertices[face.indices[k]]); + } + } + + _add_faces(faces, shapes[i], p_vertices, p_indices); + } + } break; + case PhysicsServer3D::SHAPE_CONCAVE_POLYGON: { + Dictionary dict = data; + PackedVector3Array faces = Variant(dict["faces"]); + _add_faces(faces, shapes[i], p_vertices, p_indices); + } break; + default: { + WARN_PRINT("Unsupported collision shape type."); + } break; + } + + if (mesh.is_valid()) { + _add_mesh(mesh, shapes[i], p_vertices, p_indices); + } } } } diff --git a/modules/visual_script/editor/visual_script_editor.cpp b/modules/visual_script/editor/visual_script_editor.cpp index ec1a8a6b42..b00b5a2ddd 100644 --- a/modules/visual_script/editor/visual_script_editor.cpp +++ b/modules/visual_script/editor/visual_script_editor.cpp @@ -42,6 +42,7 @@ #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" #include "editor/editor_scale.h" +#include "scene/gui/view_panner.h" #include "scene/main/window.h" #ifdef TOOLS_ENABLED @@ -271,7 +272,7 @@ protected: if (String(p_name) == "export") { script->set_variable_export(var, p_value); - EditorNode::get_singleton()->get_inspector()->update_tree(); + InspectorDock::get_inspector_singleton()->update_tree(); return true; } @@ -1366,7 +1367,7 @@ void VisualScriptEditor::_create_function() { } void VisualScriptEditor::_add_node_dialog() { - _generic_search(script->get_instance_base_type(), graph->get_global_position() + Vector2(55, 80), true); + _generic_search(graph->get_global_position() + Vector2(55, 80), true); } void VisualScriptEditor::_add_func_input() { @@ -1442,7 +1443,7 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt if (p_button == 1) { // Ensure script base exists otherwise use custom base type. ERR_FAIL_COND(script.is_null()); - new_virtual_method_select->select_method_from_base_type(script->get_instance_base_type(), String(), true); + new_virtual_method_select->select_method_from_base_type(script->get_instance_base_type(), true); return; } else if (p_button == 0) { String name = _validate_name("new_function"); @@ -1948,14 +1949,14 @@ void VisualScriptEditor::_on_nodes_duplicate() { } } -void VisualScriptEditor::_generic_search(String p_base_type, Vector2 pos, bool node_centered) { +void VisualScriptEditor::_generic_search(Vector2 pos, bool node_centered) { if (node_centered) { port_action_pos = graph->get_size() / 2.0f; } else { port_action_pos = graph->get_viewport()->get_mouse_position() - graph->get_global_position(); } - new_connect_node_select->select_from_visual_script(p_base_type, false, false); // neither connecting nor reset text + new_connect_node_select->select_from_visual_script(script, false); // do not reset text // Ensure that the dialog fits inside the graph. Size2 bounds = graph->get_global_position() + graph->get_size() - new_connect_node_select->get_size(); @@ -1992,7 +1993,7 @@ void VisualScriptEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { } } if (is_empty_selection && clipboard->nodes.is_empty()) { - _generic_search(script->get_instance_base_type(), mouse_up_position); + _generic_search(); } else { popup_menu->set_item_disabled(int(EDIT_CUT_NODES), is_empty_selection); popup_menu->set_item_disabled(int(EDIT_COPY_NODES), is_empty_selection); @@ -2446,7 +2447,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da drop_position = pos; drop_node = node; drop_path = sn->get_path_to(node); - new_connect_node_select->select_from_instance(node, "", false, node->get_class()); + new_connect_node_select->select_from_instance(node, false); } undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); @@ -2846,7 +2847,7 @@ Control *VisualScriptEditor::get_base_editor() const { return graph; } -void VisualScriptEditor::set_tooltip_request_func(String p_method, Object *p_obj) { +void VisualScriptEditor::set_tooltip_request_func(const Callable &p_toolip_callback) { } Control *VisualScriptEditor::get_edit_menu() { @@ -3234,19 +3235,34 @@ void VisualScriptEditor::_port_action_menu(int p_option) { n->set_base_type("Object"); } String type_string; + String base_script = ""; if (script->get_node(port_action_node)->get_output_value_port_count() > 0) { type_string = script->get_node(port_action_node)->get_output_value_port_info(port_action_output).hint_string; + VisualScriptFunctionCall *vsfc = Object::cast_to<VisualScriptFunctionCall>(*script->get_node(port_action_node)); + if (vsfc) { + base_script = vsfc->get_base_script(); + } else { + VisualScriptPropertyGet *vspg = Object::cast_to<VisualScriptPropertyGet>(*script->get_node(port_action_node)); + if (vspg) { + base_script = vspg->get_base_script(); + } else { + VisualScriptPropertySet *vsps = Object::cast_to<VisualScriptPropertySet>(*script->get_node(port_action_node)); + if (vsps) { + base_script = vsps->get_base_script(); + } + } + } } if (tg.type == Variant::OBJECT) { if (tg.script.is_valid()) { - new_connect_node_select->select_from_script(tg.script, ""); - } else if (!type_string.is_empty()) { - new_connect_node_select->select_from_base_type(type_string); + new_connect_node_select->select_from_script(tg.script); + } else if (type_string != String()) { + new_connect_node_select->select_from_base_type(type_string, base_script); } else { - new_connect_node_select->select_from_base_type(n->get_base_type()); + new_connect_node_select->select_from_base_type(n->get_base_type(), base_script); } } else if (tg.type == Variant::NIL) { - new_connect_node_select->select_from_base_type(""); + new_connect_node_select->select_from_base_type("", base_script); } else { new_connect_node_select->select_from_basic_type(tg.type); } @@ -3309,66 +3325,54 @@ void VisualScriptEditor::connect_data(Ref<VisualScriptNode> vnode_old, Ref<Visua } void VisualScriptEditor::_selected_connect_node(const String &p_text, const String &p_category, const bool p_connecting) { +#ifdef OSX_ENABLED + bool held_ctrl = Input::get_singleton()->is_key_pressed(Key::META); +#else + bool held_ctrl = Input::get_singleton()->is_key_pressed(Key::CTRL); +#endif Vector2 pos = _get_pos_in_graph(port_action_pos); Set<int> vn; + bool port_node_exists = true; if (drop_position != Vector2()) { pos = drop_position; } drop_position = Vector2(); - bool port_node_exists = true; - - // if (func == StringName()) { - // func = default_func; - // port_node_exists = false; - // } - - if (p_category == "visualscript") { - Ref<VisualScriptNode> vnode_new = VisualScriptLanguage::singleton->create_node_from_name(p_text); - Ref<VisualScriptNode> vnode_old; - if (port_node_exists && p_connecting) { - vnode_old = script->get_node(port_action_node); - } - int new_id = script->get_available_id(); + Ref<VisualScriptNode> vnode; + Ref<VisualScriptNode> vnode_old; + if (port_node_exists && p_connecting) { + vnode_old = script->get_node(port_action_node); + } - if (Object::cast_to<VisualScriptOperator>(vnode_new.ptr()) && vnode_old.is_valid()) { - Variant::Type type = vnode_old->get_output_value_port_info(port_action_output).type; - Object::cast_to<VisualScriptOperator>(vnode_new.ptr())->set_typed(type); - } + if (p_category.begins_with("VisualScriptNode")) { + Ref<VisualScriptNode> n = VisualScriptLanguage::singleton->create_node_from_name(p_text); - if (Object::cast_to<VisualScriptTypeCast>(vnode_new.ptr()) && vnode_old.is_valid()) { + if (Object::cast_to<VisualScriptTypeCast>(n.ptr()) && vnode_old.is_valid()) { Variant::Type type = vnode_old->get_output_value_port_info(port_action_output).type; String hint_name = vnode_old->get_output_value_port_info(port_action_output).hint_string; if (type == Variant::OBJECT) { - Object::cast_to<VisualScriptTypeCast>(vnode_new.ptr())->set_base_type(hint_name); + Object::cast_to<VisualScriptTypeCast>(n.ptr())->set_base_type(hint_name); } else if (type == Variant::NIL) { - Object::cast_to<VisualScriptTypeCast>(vnode_new.ptr())->set_base_type(""); + Object::cast_to<VisualScriptTypeCast>(n.ptr())->set_base_type(""); } else { - Object::cast_to<VisualScriptTypeCast>(vnode_new.ptr())->set_base_type(Variant::get_type_name(type)); + Object::cast_to<VisualScriptTypeCast>(n.ptr())->set_base_type(Variant::get_type_name(type)); } } - - undo_redo->create_action(TTR("Add Node")); - undo_redo->add_do_method(script.ptr(), "add_node", new_id, vnode_new, pos); - if (vnode_old.is_valid() && p_connecting) { - connect_seq(vnode_old, vnode_new, new_id); - connect_data(vnode_old, vnode_new, new_id); - } - - undo_redo->add_undo_method(script.ptr(), "remove_node", new_id); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); - undo_redo->commit_action(); - return; + vnode = n; } - Ref<VisualScriptNode> vnode; - Ref<VisualScriptPropertySet> script_prop_set; - - if (p_category == String("method")) { + if (p_category == String("Class") && !p_connecting) { + Ref<VisualScriptFunctionCall> n; + n.instantiate(); + n->set_call_mode(VisualScriptFunctionCall::CALL_MODE_SINGLETON); + n->set_singleton("ClassDB"); + n->set_function("instantiate"); + // Did not find a way to edit the input port value + vnode = n; + } else if (p_category == String("class_method")) { Ref<VisualScriptFunctionCall> n; n.instantiate(); if (!drop_path.is_empty()) { @@ -3386,96 +3390,151 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri } } vnode = n; - } else if (p_category == String("set")) { - Ref<VisualScriptPropertySet> n; - n.instantiate(); - if (!drop_path.is_empty()) { - if (drop_path == ".") { - n->set_call_mode(VisualScriptPropertySet::CALL_MODE_SELF); - } else { - n->set_call_mode(VisualScriptPropertySet::CALL_MODE_NODE_PATH); - n->set_base_path(drop_path); + } else if (p_category == String("class_property")) { + Vector<String> property_path = p_text.split(":"); + if (held_ctrl) { + Ref<VisualScriptPropertySet> n; + n.instantiate(); + n->set_property(property_path[1]); + if (!drop_path.is_empty()) { + if (drop_path == ".") { + n->set_call_mode(VisualScriptPropertySet::CALL_MODE_SELF); + } else { + n->set_call_mode(VisualScriptPropertySet::CALL_MODE_NODE_PATH); + n->set_base_path(drop_path); + } } - } - if (drop_node) { - n->set_base_type(drop_node->get_class()); - if (drop_node->get_script_instance()) { - n->set_base_script(drop_node->get_script_instance()->get_script()->get_path()); + if (drop_node) { + n->set_base_type(drop_node->get_class()); + if (drop_node->get_script_instance()) { + n->set_base_script(drop_node->get_script_instance()->get_script()->get_path()); + } } - } - vnode = n; - script_prop_set = n; - } else if (p_category == String("get")) { - Ref<VisualScriptPropertyGet> n; - n.instantiate(); - n->set_property(p_text); - if (!drop_path.is_empty()) { - if (drop_path == ".") { - n->set_call_mode(VisualScriptPropertyGet::CALL_MODE_SELF); - } else { - n->set_call_mode(VisualScriptPropertyGet::CALL_MODE_NODE_PATH); - n->set_base_path(drop_path); + vnode = n; + } else { + Ref<VisualScriptPropertyGet> n; + n.instantiate(); + n->set_property(property_path[1]); + if (!drop_path.is_empty()) { + if (drop_path == ".") { + n->set_call_mode(VisualScriptPropertyGet::CALL_MODE_SELF); + } else { + n->set_call_mode(VisualScriptPropertyGet::CALL_MODE_NODE_PATH); + n->set_base_path(drop_path); + } } - } - if (drop_node) { - n->set_base_type(drop_node->get_class()); - if (drop_node->get_script_instance()) { - n->set_base_script(drop_node->get_script_instance()->get_script()->get_path()); + if (drop_node) { + n->set_base_type(drop_node->get_class()); + if (drop_node->get_script_instance()) { + n->set_base_script(drop_node->get_script_instance()->get_script()->get_path()); + } } - } - vnode = n; - } - drop_path = String(); - drop_node = nullptr; - - if (p_category == String("action")) { - if (p_text == "VisualScriptCondition") { - Ref<VisualScriptCondition> n; - n.instantiate(); vnode = n; } - if (p_text == "VisualScriptSwitch") { - Ref<VisualScriptSwitch> n; - n.instantiate(); - vnode = n; - } else if (p_text == "VisualScriptSequence") { - Ref<VisualScriptSequence> n; - n.instantiate(); - vnode = n; - } else if (p_text == "VisualScriptIterator") { - Ref<VisualScriptIterator> n; + } else if (p_category == String("class_constant")) { + Vector<String> property_path = p_text.split(":"); + if (ClassDB::class_exists(property_path[0])) { + Ref<VisualScriptClassConstant> n; n.instantiate(); + n->set_base_type(property_path[0]); + n->set_class_constant(property_path[1]); vnode = n; - } else if (p_text == "VisualScriptWhile") { - Ref<VisualScriptWhile> n; - n.instantiate(); - vnode = n; - } else if (p_text == "VisualScriptReturn") { - Ref<VisualScriptReturn> n; + } else { + Ref<VisualScriptBasicTypeConstant> n; n.instantiate(); + if (property_path[0] == "Nil") { + n->set_basic_type(Variant::NIL); + } else if (property_path[0] == "bool") { + n->set_basic_type(Variant::BOOL); + } else if (property_path[0] == "int") { + n->set_basic_type(Variant::INT); + } else if (property_path[0] == "float") { + n->set_basic_type(Variant::FLOAT); + } else if (property_path[0] == "String") { + n->set_basic_type(Variant::STRING); + } else if (property_path[0] == "Vector2") { + n->set_basic_type(Variant::VECTOR2); + } else if (property_path[0] == "Vector2i") { + n->set_basic_type(Variant::VECTOR2I); + } else if (property_path[0] == "Rect2") { + n->set_basic_type(Variant::RECT2); + } else if (property_path[0] == "Rect2i") { + n->set_basic_type(Variant::RECT2I); + } else if (property_path[0] == "Transform2D") { + n->set_basic_type(Variant::TRANSFORM2D); + } else if (property_path[0] == "Vector3") { + n->set_basic_type(Variant::VECTOR3); + } else if (property_path[0] == "Vector3i") { + n->set_basic_type(Variant::VECTOR3I); + } else if (property_path[0] == "Plane") { + n->set_basic_type(Variant::PLANE); + } else if (property_path[0] == "ABB") { + n->set_basic_type(Variant::AABB); + } else if (property_path[0] == "Quaternion") { + n->set_basic_type(Variant::QUATERNION); + } else if (property_path[0] == "Basis") { + n->set_basic_type(Variant::BASIS); + } else if (property_path[0] == "Transform3D") { + n->set_basic_type(Variant::TRANSFORM3D); + } else if (property_path[0] == "Color") { + n->set_basic_type(Variant::COLOR); + } else if (property_path[0] == "RID") { + n->set_basic_type(Variant::RID); + } else if (property_path[0] == "Object") { + n->set_basic_type(Variant::OBJECT); + } else if (property_path[0] == "Callable") { + n->set_basic_type(Variant::CALLABLE); + } else if (property_path[0] == "Signal") { + n->set_basic_type(Variant::SIGNAL); + } else if (property_path[0] == "StringName") { + n->set_basic_type(Variant::STRING_NAME); + } else if (property_path[0] == "NodePath") { + n->set_basic_type(Variant::NODE_PATH); + } else if (property_path[0] == "Dictionary") { + n->set_basic_type(Variant::DICTIONARY); + } else if (property_path[0] == "Array") { + n->set_basic_type(Variant::ARRAY); + } else if (property_path[0] == "PackedByteArray") { + n->set_basic_type(Variant::PACKED_BYTE_ARRAY); + } else if (property_path[0] == "PackedInt32Array") { + n->set_basic_type(Variant::PACKED_INT32_ARRAY); + } else if (property_path[0] == "PackedInt64Array") { + n->set_basic_type(Variant::PACKED_INT64_ARRAY); + } else if (property_path[0] == "PackedFloat32Array") { + n->set_basic_type(Variant::PACKED_FLOAT32_ARRAY); + } else if (property_path[0] == "PackedStringArray") { + n->set_basic_type(Variant::PACKED_STRING_ARRAY); + } else if (property_path[0] == "PackedVector2Array") { + n->set_basic_type(Variant::PACKED_VECTOR2_ARRAY); + } else if (property_path[0] == "PackedVector3Array") { + n->set_basic_type(Variant::PACKED_VECTOR3_ARRAY); + } else if (property_path[0] == "PackedColorArray") { + n->set_basic_type(Variant::PACKED_COLOR_ARRAY); + } + n->set_basic_type_constant(property_path[1]); vnode = n; } - } - int new_id = script->get_available_id(); - undo_redo->create_action(TTR("Add Node")); - undo_redo->add_do_method(script.ptr(), "add_node", new_id, vnode, pos); - undo_redo->add_undo_method(script.ptr(), "remove_node", new_id); - undo_redo->add_do_method(this, "_update_graph", new_id); - undo_redo->add_undo_method(this, "_update_graph", new_id); - undo_redo->commit_action(); + } else if (p_category == String("class_signal")) { + Vector<String> property_path = p_text.split(":"); + ERR_FAIL_COND(!(script->has_custom_signal(property_path[1]) || ClassDB::has_signal(script->get_instance_base_type(), property_path[1]))); - if (script_prop_set.is_valid()) { - script_prop_set->set_property(p_text); + Ref<VisualScriptEmitSignal> n; + n.instantiate(); + n->set_signal(property_path[1]); + vnode = n; + } + if (vnode == nullptr) { + print_error("Category not handled: " + p_category.quote()); } - port_action_new_node = new_id; - - Ref<VisualScriptNode> vsn = script->get_node(port_action_new_node); + if (Object::cast_to<VisualScriptFunctionCall>(vnode.ptr()) && p_category != "Class") { + Vector<String> property_path = p_text.split(":"); + String class_of_method = property_path[0]; + String method_name = property_path[1]; - if (Object::cast_to<VisualScriptFunctionCall>(vsn.ptr())) { - Ref<VisualScriptFunctionCall> vsfc = vsn; - vsfc->set_function(p_text); + Ref<VisualScriptFunctionCall> vsfc = vnode; + vsfc->set_function(method_name); if (port_node_exists && p_connecting) { VisualScriptNode::TypeGuess tg = _guess_output_type(port_action_node, port_action_output, vn); @@ -3492,7 +3551,7 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri if (!base_type.is_empty() && hint == PROPERTY_HINT_TYPE_STRING) { vsfc->set_base_type(base_type); } - if (p_text == "call" || p_text == "call_deferred") { + if (method_name == "call" || method_name == "call_deferred") { vsfc->set_function(String("")); } } @@ -3510,8 +3569,8 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri } if (port_node_exists && p_connecting) { - if (Object::cast_to<VisualScriptPropertySet>(vsn.ptr())) { - Ref<VisualScriptPropertySet> vsp = vsn; + if (Object::cast_to<VisualScriptPropertySet>(vnode.ptr())) { + Ref<VisualScriptPropertySet> vsp = vnode; VisualScriptNode::TypeGuess tg = _guess_output_type(port_action_node, port_action_output, vn); if (tg.type == Variant::OBJECT) { @@ -3540,8 +3599,8 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri } } - if (Object::cast_to<VisualScriptPropertyGet>(vsn.ptr())) { - Ref<VisualScriptPropertyGet> vsp = vsn; + if (Object::cast_to<VisualScriptPropertyGet>(vnode.ptr())) { + Ref<VisualScriptPropertyGet> vsp = vnode; VisualScriptNode::TypeGuess tg = _guess_output_type(port_action_node, port_action_output, vn); if (tg.type == Variant::OBJECT) { @@ -3569,13 +3628,85 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri } } } + if (vnode == nullptr) { + print_error("Not able to create node from category: \"" + p_category + "\" and text \"" + p_text + "\" Not created"); + return; + } + + int new_id = script->get_available_id(); + undo_redo->create_action(TTR("Add Node")); + undo_redo->add_do_method(script.ptr(), "add_node", new_id, vnode, pos); + undo_redo->add_undo_method(script.ptr(), "remove_node", new_id); + undo_redo->add_do_method(this, "_update_graph", new_id); + undo_redo->add_undo_method(this, "_update_graph", new_id); + undo_redo->commit_action(); + + port_action_new_node = new_id; + + String base_script = ""; + String base_type = ""; if (port_node_exists) { - Ref<VisualScriptNode> vnode_old = script->get_node(port_action_node); + if (vnode_old.is_valid()) { + if (Object::cast_to<VisualScriptTypeCast>(vnode_old.ptr())) { + base_type = Object::cast_to<VisualScriptTypeCast>(vnode_old.ptr())->get_base_type(); + base_script = Object::cast_to<VisualScriptTypeCast>(vnode_old.ptr())->get_base_script(); + } else if (Object::cast_to<VisualScriptFunctionCall>(vnode_old.ptr())) { + base_type = Object::cast_to<VisualScriptFunctionCall>(vnode_old.ptr())->get_base_type(); + base_script = Object::cast_to<VisualScriptFunctionCall>(vnode_old.ptr())->get_base_script(); + } else if (Object::cast_to<VisualScriptPropertySet>(vnode_old.ptr())) { + base_type = Object::cast_to<VisualScriptPropertySet>(vnode_old.ptr())->get_base_type(); + base_script = Object::cast_to<VisualScriptPropertySet>(vnode_old.ptr())->get_base_script(); + } else if (Object::cast_to<VisualScriptPropertyGet>(vnode_old.ptr())) { + base_type = Object::cast_to<VisualScriptPropertyGet>(vnode_old.ptr())->get_base_type(); + base_script = Object::cast_to<VisualScriptPropertyGet>(vnode_old.ptr())->get_base_script(); + } + } + + Vector<String> property_path = p_text.split(":"); + if (ClassDB::is_parent_class(script->get_instance_base_type(), property_path[0]) || script->get_path().ends_with(property_path[0].unquote())) { + if (!p_connecting) { + base_type = script->get_instance_base_type(); + base_script = script->get_path(); + } + } else { + base_type = property_path[0]; + base_script = ""; + } + + if (drop_node) { + Ref<Script> script = drop_node->get_script(); + if (script != nullptr) { + base_script = script->get_path(); + } + } + if (vnode_old.is_valid() && p_connecting) { + if (base_type == "") { + base_type = property_path[0]; + } else if (ClassDB::is_parent_class(property_path[0], base_type)) { + base_type = property_path[0]; + } connect_seq(vnode_old, vnode, port_action_new_node); connect_data(vnode_old, vnode, port_action_new_node); } } + if (Object::cast_to<VisualScriptTypeCast>(vnode.ptr())) { + Object::cast_to<VisualScriptTypeCast>(vnode.ptr())->set_base_type(base_type); + Object::cast_to<VisualScriptTypeCast>(vnode.ptr())->set_base_script(base_script); + } else if (Object::cast_to<VisualScriptFunctionCall>(vnode.ptr())) { + Object::cast_to<VisualScriptFunctionCall>(vnode.ptr())->set_base_type(base_type); + Object::cast_to<VisualScriptFunctionCall>(vnode.ptr())->set_base_script(base_script); + } else if (Object::cast_to<VisualScriptPropertySet>(vnode.ptr())) { + Object::cast_to<VisualScriptPropertySet>(vnode.ptr())->set_base_type(base_type); + Object::cast_to<VisualScriptPropertySet>(vnode.ptr())->set_base_script(base_script); + } else if (Object::cast_to<VisualScriptPropertyGet>(vnode.ptr())) { + Object::cast_to<VisualScriptPropertyGet>(vnode.ptr())->set_base_type(base_type); + Object::cast_to<VisualScriptPropertyGet>(vnode.ptr())->set_base_script(base_script); + } + + drop_path = String(); + drop_node = nullptr; + _update_graph(port_action_new_node); } @@ -3625,7 +3756,7 @@ void VisualScriptEditor::connect_seq(Ref<VisualScriptNode> vnode_old, Ref<Visual } void VisualScriptEditor::_selected_new_virtual_method(const String &p_text, const String &p_category, const bool p_connecting) { - String name = p_text; + String name = p_text.substr(p_text.find_char(':') + 1); if (script->has_function(name)) { EditorNode::get_singleton()->show_warning(vformat(TTR("Script already has function '%s'"), name)); return; @@ -3782,7 +3913,8 @@ void VisualScriptEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - graph->set_panning_scheme((GraphEdit::PanningScheme)EDITOR_GET("interface/editors/sub_editor_panning_scheme").operator int()); + graph->get_panner()->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/sub_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EditorSettings::get_singleton()->get("editors/panning/simple_panning"))); + graph->set_warped_panning(bool(EditorSettings::get_singleton()->get("editors/panning/warped_mouse_panning"))); } break; case NOTIFICATION_READY: { @@ -3901,7 +4033,7 @@ void VisualScriptEditor::_comment_node_resized(const Vector2 &p_new_size, int p_ void VisualScriptEditor::_menu_option(int p_what) { switch (p_what) { case EDIT_ADD_NODE: { - _generic_search(script->get_instance_base_type(), mouse_up_position); + _generic_search(); } break; case EDIT_DELETE_NODES: { _on_nodes_delete(); @@ -3931,7 +4063,7 @@ void VisualScriptEditor::_menu_option(int p_what) { } break; case EDIT_FIND_NODE_TYPE: { - _generic_search(script->get_instance_base_type()); + _generic_search(); } break; case EDIT_COPY_NODES: { _on_nodes_copy(); diff --git a/modules/visual_script/editor/visual_script_editor.h b/modules/visual_script/editor/visual_script_editor.h index 90e4fb9d56..f1b01aa6dc 100644 --- a/modules/visual_script/editor/visual_script_editor.h +++ b/modules/visual_script/editor/visual_script_editor.h @@ -85,55 +85,55 @@ class VisualScriptEditor : public ScriptEditorBase { MEMBER_SIGNAL }; - VBoxContainer *members_section; - MenuButton *edit_menu; + VBoxContainer *members_section = nullptr; + MenuButton *edit_menu = nullptr; Ref<VisualScript> script; - Button *base_type_select; + Button *base_type_select = nullptr; - LineEdit *func_name_box; - ScrollContainer *func_input_scroll; - VBoxContainer *func_input_vbox; - ConfirmationDialog *function_create_dialog; + LineEdit *func_name_box = nullptr; + ScrollContainer *func_input_scroll = nullptr; + VBoxContainer *func_input_vbox = nullptr; + ConfirmationDialog *function_create_dialog = nullptr; - GraphEdit *graph; - HBoxContainer *status_bar; - Button *toggle_scripts_button; + GraphEdit *graph = nullptr; + HBoxContainer *status_bar = nullptr; + Button *toggle_scripts_button = nullptr; - VisualScriptEditorSignalEdit *signal_editor; + VisualScriptEditorSignalEdit *signal_editor = nullptr; - AcceptDialog *edit_signal_dialog; - EditorInspector *edit_signal_edit; + AcceptDialog *edit_signal_dialog = nullptr; + EditorInspector *edit_signal_edit = nullptr; - VisualScriptPropertySelector *method_select; - VisualScriptPropertySelector *new_connect_node_select; - VisualScriptPropertySelector *new_virtual_method_select; + VisualScriptPropertySelector *method_select = nullptr; + VisualScriptPropertySelector *new_connect_node_select = nullptr; + VisualScriptPropertySelector *new_virtual_method_select = nullptr; - VisualScriptEditorVariableEdit *variable_editor; + VisualScriptEditorVariableEdit *variable_editor = nullptr; - AcceptDialog *edit_variable_dialog; - EditorInspector *edit_variable_edit; + AcceptDialog *edit_variable_dialog = nullptr; + EditorInspector *edit_variable_edit = nullptr; - CustomPropertyEditor *default_value_edit; + CustomPropertyEditor *default_value_edit = nullptr; - UndoRedo *undo_redo; + UndoRedo *undo_redo = nullptr; - Tree *members; - AcceptDialog *function_name_edit; - LineEdit *function_name_box; + Tree *members = nullptr; + AcceptDialog *function_name_edit = nullptr; + LineEdit *function_name_box = nullptr; - Label *hint_text; - Timer *hint_text_timer; + Label *hint_text = nullptr; + Timer *hint_text_timer = nullptr; - Label *select_func_text; + Label *select_func_text = nullptr; bool updating_graph = false; void _show_hint(const String &p_hint); void _hide_timer(); - CreateDialog *select_base_type; + CreateDialog *select_base_type = nullptr; struct VirtualInMenu { String name; @@ -241,7 +241,7 @@ class VisualScriptEditor : public ScriptEditorBase { bool node_has_sequence_connections(int p_id); - void _generic_search(String p_base_type = "", Vector2 pos = Vector2(), bool node_centered = false); + void _generic_search(Vector2 pos = Vector2(), bool node_centered = false); virtual void input(const Ref<InputEvent> &p_event) override; void _graph_gui_input(const Ref<InputEvent> &p_event); @@ -328,7 +328,7 @@ public: virtual void update_settings() override; virtual bool show_members_overview() override; virtual void set_debugger_active(bool p_active) override; - virtual void set_tooltip_request_func(String p_method, Object *p_obj) override; + virtual void set_tooltip_request_func(const Callable &p_toolip_callback) override; virtual Control *get_edit_menu() override; virtual void clear_edit_menu() override; virtual void set_find_replace_bar(FindReplaceBar *p_bar) override { p_bar->hide(); }; // Not needed here. diff --git a/modules/visual_script/editor/visual_script_property_selector.cpp b/modules/visual_script/editor/visual_script_property_selector.cpp index c88d10dabd..1059d126bc 100644 --- a/modules/visual_script/editor/visual_script_property_selector.cpp +++ b/modules/visual_script/editor/visual_script_property_selector.cpp @@ -37,13 +37,28 @@ #include "../visual_script_nodes.h" #include "core/os/keyboard.h" #include "editor/doc_tools.h" +#include "editor/editor_feature_profile.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "scene/main/node.h" #include "scene/main/window.h" -void VisualScriptPropertySelector::_text_changed(const String &p_newtext) { - _update_search(); +void VisualScriptPropertySelector::_update_icons() { + search_box->set_right_icon(results_tree->get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); + search_box->set_clear_button_enabled(true); + search_box->add_theme_icon_override("right_icon", results_tree->get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); + + search_visual_script_nodes->set_icon(results_tree->get_theme_icon(SNAME("VisualScript"), SNAME("EditorIcons"))); + search_classes->set_icon(results_tree->get_theme_icon(SNAME("Object"), SNAME("EditorIcons"))); + search_methods->set_icon(results_tree->get_theme_icon(SNAME("MemberMethod"), SNAME("EditorIcons"))); + search_operators->set_icon(results_tree->get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); + search_signals->set_icon(results_tree->get_theme_icon(SNAME("MemberSignal"), SNAME("EditorIcons"))); + search_constants->set_icon(results_tree->get_theme_icon(SNAME("MemberConstant"), SNAME("EditorIcons"))); + search_properties->set_icon(results_tree->get_theme_icon(SNAME("MemberProperty"), SNAME("EditorIcons"))); + search_theme_items->set_icon(results_tree->get_theme_icon(SNAME("MemberTheme"), SNAME("EditorIcons"))); + + case_sensitive_button->set_icon(results_tree->get_theme_icon(SNAME("MatchCase"), SNAME("EditorIcons"))); + hierarchy_button->set_icon(results_tree->get_theme_icon(SNAME("ClassList"), SNAME("EditorIcons"))); } void VisualScriptPropertySelector::_sbox_input(const Ref<InputEvent> &p_ie) { @@ -55,24 +70,8 @@ void VisualScriptPropertySelector::_sbox_input(const Ref<InputEvent> &p_ie) { case Key::DOWN: case Key::PAGEUP: case Key::PAGEDOWN: { - search_options->gui_input(k); + results_tree->gui_input(k); search_box->accept_event(); - - TreeItem *root = search_options->get_root(); - if (!root->get_first_child()) { - break; - } - - TreeItem *current = search_options->get_selected(); - - TreeItem *item = search_options->get_next_selected(root); - while (item) { - item->deselect(0); - item = search_options->get_next_selected(item); - } - - current->select(0); - } break; default: break; @@ -80,654 +79,1191 @@ void VisualScriptPropertySelector::_sbox_input(const Ref<InputEvent> &p_ie) { } } -void VisualScriptPropertySelector::_update_search() { - set_title(TTR("Search VisualScript")); - - search_options->clear(); - help_bit->set_text(""); - - TreeItem *root = search_options->create_item(); - bool found = false; - StringName base = base_type; - List<StringName> base_list; - while (base) { - base_list.push_back(base); - base = ClassDB::get_parent_class_nocheck(base); - } - - for (const StringName &E : base_list) { - List<MethodInfo> methods; - List<PropertyInfo> props; - TreeItem *category = nullptr; - Ref<Texture2D> type_icons[Variant::VARIANT_MAX] = { - vbc->get_theme_icon(SNAME("Variant"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("bool"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("int"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("float"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("String"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("Vector2"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("Vector2i"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("Rect2"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("Rect2i"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("Vector3i"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("Transform2D"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("Plane"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("Quaternion"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("AABB"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("Basis"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("Transform3D"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("Color"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("StringName"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("NodePath"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("RID"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("MiniObject"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("Callable"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("Signal"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("Dictionary"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("Array"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("PackedByteArray"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("PackedInt32Array"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("PackedInt64Array"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("PackedFloat32Array"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("PackedFloat64Array"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("PackedStringArray"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("PackedVector2Array"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("PackedVector3Array"), SNAME("EditorIcons")), - vbc->get_theme_icon(SNAME("PackedColorArray"), SNAME("EditorIcons")) - }; - { - String b = String(E); - category = search_options->create_item(root); - if (category) { - category->set_text(0, b.replace_first("*", "")); - category->set_selectable(0, false); - Ref<Texture2D> icon; - String rep = b.replace("*", ""); - icon = EditorNode::get_singleton()->get_class_icon(rep); - category->set_icon(0, icon); - } - } - if (properties || seq_connect) { - if (instance) { - instance->get_property_list(&props, true); - } else { - Object *obj = ObjectDB::get_instance(script); - if (Object::cast_to<Script>(obj)) { - Object::cast_to<Script>(obj)->get_script_property_list(&props); - } else { - ClassDB::get_property_list(E, &props, true); - } - } - for (const PropertyInfo &F : props) { - if (!(F.usage & PROPERTY_USAGE_EDITOR) && !(F.usage & PROPERTY_USAGE_SCRIPT_VARIABLE)) { - continue; - } +void VisualScriptPropertySelector::_update_results_i(int p_int) { + _update_results(); +} - if (type_filter.size() && type_filter.find(F.type) == -1) { - continue; - } +void VisualScriptPropertySelector::_update_results_s(String p_string) { + _update_results(); +} - // capitalize() also converts underscore to space, we'll match again both possible styles - String get_text_raw = String(vformat(TTR("Get %s"), F.name)); - String get_text = get_text_raw.capitalize(); - String set_text_raw = String(vformat(TTR("Set %s"), F.name)); - String set_text = set_text_raw.capitalize(); - String input = search_box->get_text().capitalize(); - - if (input.is_empty() || get_text_raw.findn(input) != -1 || get_text.findn(input) != -1) { - TreeItem *item = search_options->create_item(category ? category : root); - item->set_text(0, get_text); - item->set_metadata(0, F.name); - item->set_icon(0, type_icons[F.type]); - item->set_metadata(1, "get"); - item->set_collapsed(true); - item->set_selectable(0, true); - item->set_selectable(1, false); - item->set_selectable(2, false); - item->set_metadata(2, connecting); - } +void VisualScriptPropertySelector::_update_results() { + _update_icons(); + search_runner = Ref<SearchRunner>(memnew(SearchRunner(this, results_tree))); + set_process(true); +} + +void VisualScriptPropertySelector::_confirmed() { + TreeItem *ti = results_tree->get_selected(); + if (!ti) { + return; + } + emit_signal(SNAME("selected"), ti->get_metadata(0), ti->get_metadata(1), connecting); + set_visible(false); +} - if (input.is_empty() || set_text_raw.findn(input) != -1 || set_text.findn(input) != -1) { - TreeItem *item = search_options->create_item(category ? category : root); - item->set_text(0, set_text); - item->set_metadata(0, F.name); - item->set_icon(0, type_icons[F.type]); - item->set_metadata(1, "set"); - item->set_selectable(0, true); - item->set_selectable(1, false); - item->set_selectable(2, false); - item->set_metadata(2, connecting); +void VisualScriptPropertySelector::_item_selected() { + if (results_tree->get_selected()->has_meta("description")) { + help_bit->set_text(results_tree->get_selected()->get_meta("description")); + } else { + help_bit->set_text("No description available"); + } +} + +void VisualScriptPropertySelector::_hide_requested() { + _cancel_pressed(); // From AcceptDialog. +} + +void VisualScriptPropertySelector::_notification(int p_what) { + switch (p_what) { + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + _update_icons(); + } break; + case NOTIFICATION_ENTER_TREE: { + connect("confirmed", callable_mp(this, &VisualScriptPropertySelector::_confirmed)); + } break; + case NOTIFICATION_PROCESS: { + // Update background search. + if (search_runner.is_valid()) { + if (search_runner->work()) { + // Search done. + get_ok_button()->set_disabled(!results_tree->get_selected()); + + search_runner = Ref<SearchRunner>(); + set_process(false); } - } - } - { - if (type != Variant::NIL) { - Variant v; - Callable::CallError ce; - Variant::construct(type, v, nullptr, 0, ce); - v.get_method_list(&methods); } else { - Object *obj = ObjectDB::get_instance(script); - if (Object::cast_to<Script>(obj)) { - Object::cast_to<Script>(obj)->get_script_method_list(&methods); - } - - ClassDB::get_method_list(E, &methods, true, true); - } - } - for (List<MethodInfo>::Element *M = methods.front(); M; M = M->next()) { - String name = M->get().name.get_slice(":", 0); - if (name.begins_with("_") && !(M->get().flags & METHOD_FLAG_VIRTUAL)) { - continue; + // if one is valid + set_process(false); } + } break; + } +} - if (virtuals_only && !(M->get().flags & METHOD_FLAG_VIRTUAL)) { - continue; - } +void VisualScriptPropertySelector::select_method_from_base_type(const String &p_base, const bool p_virtuals_only, const bool p_connecting, bool clear_text) { + set_title(TTR("Select method from base type")); + base_type = p_base; + base_script = ""; + type = Variant::NIL; + connecting = p_connecting; - if (!virtuals_only && (M->get().flags & METHOD_FLAG_VIRTUAL)) { - continue; - } + if (clear_text) { + if (p_virtuals_only) { + search_box->set_text("._"); // show all _methods + search_box->set_caret_column(2); + } else { + search_box->set_text("."); // show all methods + search_box->set_caret_column(1); + } + } - MethodInfo mi = M->get(); - String desc_arguments; - if (mi.arguments.size() > 0) { - desc_arguments = "("; - for (int i = 0; i < mi.arguments.size(); i++) { - if (i > 0) { - desc_arguments += ", "; - } - if (mi.arguments[i].type == Variant::NIL) { - desc_arguments += "var"; - } else if (mi.arguments[i].name.find(":") != -1) { - desc_arguments += mi.arguments[i].name.get_slice(":", 1); - mi.arguments[i].name = mi.arguments[i].name.get_slice(":", 0); - } else { - desc_arguments += Variant::get_type_name(mi.arguments[i].type); - } - } - desc_arguments += ")"; - } - String desc_raw = mi.name + desc_arguments; - String desc = desc_raw.capitalize().replace("( ", "("); + search_visual_script_nodes->set_pressed(false); + search_classes->set_pressed(false); + search_methods->set_pressed(true); + search_operators->set_pressed(false); + search_signals->set_pressed(false); + search_constants->set_pressed(false); + search_properties->set_pressed(false); + search_theme_items->set_pressed(false); - if (!search_box->get_text().is_empty() && - name.findn(search_box->get_text()) == -1 && - desc.findn(search_box->get_text()) == -1 && - desc_raw.findn(search_box->get_text()) == -1) { - continue; - } + scope_combo->select(2); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" - TreeItem *item = search_options->create_item(category ? category : root); - item->set_text(0, desc); - item->set_icon(0, vbc->get_theme_icon(SNAME("MemberMethod"), SNAME("EditorIcons"))); - item->set_metadata(0, name); - item->set_selectable(0, true); + results_tree->clear(); + show_window(.5f); + search_box->grab_focus(); - item->set_metadata(1, "method"); - item->set_collapsed(true); - item->set_selectable(1, false); + _update_results(); +} - item->set_selectable(2, false); - item->set_metadata(2, connecting); - } +void VisualScriptPropertySelector::select_from_base_type(const String &p_base, const String &p_base_script, bool p_virtuals_only, const bool p_connecting, bool clear_text) { + set_title(TTR("Select from base type")); + base_type = p_base; + base_script = p_base_script.lstrip("res://").quote(); // filepath to EditorHelp::get_doc_data().name + type = Variant::NIL; + connecting = p_connecting; - if (category && category->get_first_child() == nullptr) { - memdelete(category); //old category was unused + if (clear_text) { + if (p_virtuals_only) { + search_box->set_text("_"); + } else { + search_box->set_text(" "); } } - if (properties) { - if (!seq_connect && !visual_script_generic) { - get_visual_node_names("flow_control/type_cast", Set<String>(), found, root, search_box); - get_visual_node_names("functions/built_in/print", Set<String>(), found, root, search_box); - get_visual_node_names("functions/by_type/" + Variant::get_type_name(type), Set<String>(), found, root, search_box); - get_visual_node_names("functions/deconstruct/" + Variant::get_type_name(type), Set<String>(), found, root, search_box); - get_visual_node_names("operators/compare/", Set<String>(), found, root, search_box); - if (type == Variant::INT) { - get_visual_node_names("operators/bitwise/", Set<String>(), found, root, search_box); - } - if (type == Variant::BOOL) { - get_visual_node_names("operators/logic/", Set<String>(), found, root, search_box); - } - if (type == Variant::BOOL || type == Variant::INT || type == Variant::FLOAT || type == Variant::VECTOR2 || type == Variant::VECTOR3) { - get_visual_node_names("operators/math/", Set<String>(), found, root, search_box); - } - } + search_box->select_all(); + + search_visual_script_nodes->set_pressed(false); + search_classes->set_pressed(false); + search_methods->set_pressed(true); + search_operators->set_pressed(false); + search_signals->set_pressed(true); + search_constants->set_pressed(false); + search_properties->set_pressed(true); + search_theme_items->set_pressed(false); + + // When class is Input only show inheritors + scope_combo->select(0); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" + + results_tree->clear(); + show_window(.5f); + search_box->grab_focus(); + _update_results(); +} + +void VisualScriptPropertySelector::select_from_script(const Ref<Script> &p_script, const bool p_connecting, bool clear_text) { + set_title(TTR("Select from script")); + ERR_FAIL_COND(p_script.is_null()); + + base_type = p_script->get_instance_base_type(); + base_script = p_script->get_path().lstrip("res://").quote(); // filepath to EditorHelp::get_doc_data().name + type = Variant::NIL; + script = p_script->get_instance_id(); + connecting = p_connecting; + + if (clear_text) { + search_box->set_text(""); } + search_box->select_all(); + + search_visual_script_nodes->set_pressed(false); + search_classes->set_pressed(true); + search_methods->set_pressed(true); + search_operators->set_pressed(true); + search_signals->set_pressed(true); + search_constants->set_pressed(true); + search_properties->set_pressed(true); + search_theme_items->set_pressed(false); + + scope_combo->select(2); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" + + results_tree->clear(); + show_window(.5f); + search_box->grab_focus(); + _update_results(); +} - if (seq_connect && !visual_script_generic) { - String text = search_box->get_text(); - create_visualscript_item(String("VisualScriptCondition"), root, text, String("Condition")); - create_visualscript_item(String("VisualScriptSwitch"), root, text, String("Switch")); - create_visualscript_item(String("VisualScriptSequence"), root, text, String("Sequence")); - create_visualscript_item(String("VisualScriptIterator"), root, text, String("Iterator")); - create_visualscript_item(String("VisualScriptWhile"), root, text, String("While")); - create_visualscript_item(String("VisualScriptReturn"), root, text, String("Return")); - get_visual_node_names("flow_control/type_cast", Set<String>(), found, root, search_box); - get_visual_node_names("functions/built_in/print", Set<String>(), found, root, search_box); +void VisualScriptPropertySelector::select_from_basic_type(Variant::Type p_type, const bool p_connecting, bool clear_text) { + set_title(TTR("Select from basic type")); + ERR_FAIL_COND(p_type == Variant::NIL); + base_type = Variant::get_type_name(p_type); + base_script = ""; + type = p_type; + connecting = p_connecting; + + if (clear_text) { + search_box->set_text(" "); + } + search_box->select_all(); + + search_visual_script_nodes->set_pressed(false); + search_classes->set_pressed(false); + search_methods->set_pressed(true); + search_operators->set_pressed(true); + search_signals->set_pressed(false); + search_constants->set_pressed(true); + search_properties->set_pressed(true); + search_theme_items->set_pressed(false); + + scope_combo->select(2); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" //id5 "Search All" + + results_tree->clear(); + show_window(.5f); + search_box->grab_focus(); + + _update_results(); +} + +void VisualScriptPropertySelector::select_from_action(const String &p_type, const bool p_connecting, bool clear_text) { + set_title(TTR("Select from action")); + base_type = p_type; + base_script = ""; + type = Variant::NIL; + connecting = p_connecting; + + if (clear_text) { + search_box->set_text(""); } + search_box->select_all(); + + search_visual_script_nodes->set_pressed(true); + search_classes->set_pressed(false); + search_methods->set_pressed(false); + search_operators->set_pressed(false); + search_signals->set_pressed(false); + search_constants->set_pressed(false); + search_properties->set_pressed(false); + search_theme_items->set_pressed(false); + + scope_combo->select(0); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" //id5 "Search All" + + results_tree->clear(); + show_window(.5f); + search_box->grab_focus(); + _update_results(); +} + +void VisualScriptPropertySelector::select_from_instance(Object *p_instance, const bool p_connecting, bool clear_text) { + set_title(TTR("Select from instance")); + base_type = p_instance->get_class(); - if ((properties || seq_connect) && visual_script_generic) { - get_visual_node_names("", Set<String>(), found, root, search_box); + const Ref<Script> &p_script = p_instance->get_script(); + if (p_script == nullptr) { + base_script = ""; + } else { + base_script = p_script->get_path().lstrip("res://").quote(); // filepath to EditorHelp::get_doc_data().name } - TreeItem *selected_item = search_options->search_item_text(search_box->get_text()); - if (!found && selected_item != nullptr) { - selected_item->select(0); - found = true; + type = Variant::NIL; + connecting = p_connecting; + + if (clear_text) { + search_box->set_text(" "); } + search_box->select_all(); + + search_visual_script_nodes->set_pressed(false); + search_classes->set_pressed(false); + search_methods->set_pressed(true); + search_operators->set_pressed(false); + search_signals->set_pressed(true); + search_constants->set_pressed(true); + search_properties->set_pressed(true); + search_theme_items->set_pressed(false); - get_ok_button()->set_disabled(root->get_first_child() == nullptr); + scope_combo->select(2); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" //id5 "Search All" + + results_tree->clear(); + show_window(.5f); + search_box->grab_focus(); + _update_results(); } -void VisualScriptPropertySelector::create_visualscript_item(const String &name, TreeItem *const root, const String &search_input, const String &text) { - if (search_input.is_empty() || text.findn(search_input) != -1) { - TreeItem *item = search_options->create_item(root); - item->set_text(0, text); - item->set_icon(0, vbc->get_theme_icon(SNAME("VisualScript"), SNAME("EditorIcons"))); - item->set_metadata(0, name); - item->set_metadata(1, "action"); - item->set_selectable(0, true); - item->set_collapsed(true); - item->set_selectable(1, false); - item->set_selectable(2, false); - item->set_metadata(2, connecting); +void VisualScriptPropertySelector::select_from_visual_script(const Ref<Script> &p_script, bool clear_text) { + set_title(TTR("Select from visual script")); + base_type = p_script->get_instance_base_type(); + if (p_script == nullptr) { + base_script = ""; + } else { + base_script = p_script->get_path().lstrip("res://").quote(); // filepath to EditorHelp::get_doc_data().name + } + type = Variant::NIL; + connecting = false; + + if (clear_text) { + search_box->set_text(" "); } + search_box->select_all(); + + search_visual_script_nodes->set_pressed(true); + search_classes->set_pressed(false); + search_methods->set_pressed(true); + search_operators->set_pressed(false); + search_signals->set_pressed(true); + search_constants->set_pressed(true); + search_properties->set_pressed(true); + search_theme_items->set_pressed(false); + + scope_combo->select(2); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" //id5 "Search All" + + results_tree->clear(); + show_window(.5f); + search_box->grab_focus(); + _update_results(); +} + +void VisualScriptPropertySelector::show_window(float p_screen_ratio) { + popup_centered_ratio(p_screen_ratio); } -void VisualScriptPropertySelector::get_visual_node_names(const String &root_filter, const Set<String> &p_modifiers, bool &found, TreeItem *const root, LineEdit *const search_box) { - Map<String, TreeItem *> path_cache; +void VisualScriptPropertySelector::_bind_methods() { + ADD_SIGNAL(MethodInfo("selected", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::STRING, "category"), PropertyInfo(Variant::BOOL, "connecting"))); +} - List<String> fnodes; - VisualScriptLanguage::singleton->get_registered_node_names(&fnodes); +VisualScriptPropertySelector::VisualScriptPropertySelector() { + virtuals_only = false; - for (const String &E : fnodes) { - if (!E.begins_with(root_filter)) { - continue; - } - Vector<String> path = E.split("/"); - - // check if the name has the filter - bool in_filter = false; - Vector<String> tx_filters = search_box->get_text().split(" "); - for (int i = 0; i < tx_filters.size(); i++) { - if (tx_filters[i].is_empty()) { - in_filter = true; - } else { - in_filter = false; - } - if (E.findn(tx_filters[i]) != -1) { - in_filter = true; - break; - } - } - if (!in_filter) { - continue; - } + vbox = memnew(VBoxContainer); + add_child(vbox); + + HBoxContainer *hbox = memnew(HBoxContainer); + hbox->set_alignment(hbox->ALIGNMENT_CENTER); + vbox->add_child(hbox); + + case_sensitive_button = memnew(Button); + case_sensitive_button->set_flat(true); + case_sensitive_button->set_tooltip(TTR("Case Sensitive")); + case_sensitive_button->connect("pressed", callable_mp(this, &VisualScriptPropertySelector::_update_results)); + case_sensitive_button->set_toggle_mode(true); + case_sensitive_button->set_focus_mode(Control::FOCUS_NONE); + hbox->add_child(case_sensitive_button); + + hierarchy_button = memnew(Button); + hierarchy_button->set_flat(true); + hierarchy_button->set_tooltip(TTR("Show Hierarchy")); + hierarchy_button->connect("pressed", callable_mp(this, &VisualScriptPropertySelector::_update_results)); + hierarchy_button->set_toggle_mode(true); + hierarchy_button->set_pressed(true); + hierarchy_button->set_focus_mode(Control::FOCUS_NONE); + hbox->add_child(hierarchy_button); + + hbox->add_child(memnew(VSeparator)); + + search_visual_script_nodes = memnew(Button); + search_visual_script_nodes->set_flat(true); + search_visual_script_nodes->set_tooltip(TTR("Search Visual Script Nodes")); + search_visual_script_nodes->connect("pressed", callable_mp(this, &VisualScriptPropertySelector::_update_results)); + search_visual_script_nodes->set_toggle_mode(true); + search_visual_script_nodes->set_pressed(true); + search_visual_script_nodes->set_focus_mode(Control::FOCUS_NONE); + hbox->add_child(search_visual_script_nodes); + + search_classes = memnew(Button); + search_classes->set_flat(true); + search_classes->set_tooltip(TTR("Search Classes")); + search_classes->connect("pressed", callable_mp(this, &VisualScriptPropertySelector::_update_results)); + search_classes->set_toggle_mode(true); + search_classes->set_pressed(true); + search_classes->set_focus_mode(Control::FOCUS_NONE); + hbox->add_child(search_classes); + + search_operators = memnew(Button); + search_operators->set_flat(true); + search_operators->set_tooltip(TTR("Search Operators")); + search_operators->connect("pressed", callable_mp(this, &VisualScriptPropertySelector::_update_results)); + search_operators->set_toggle_mode(true); + search_operators->set_pressed(true); + search_operators->set_focus_mode(Control::FOCUS_NONE); + hbox->add_child(search_operators); + + hbox->add_child(memnew(VSeparator)); + + search_methods = memnew(Button); + search_methods->set_flat(true); + search_methods->set_tooltip(TTR("Search Methods")); + search_methods->connect("pressed", callable_mp(this, &VisualScriptPropertySelector::_update_results)); + search_methods->set_toggle_mode(true); + search_methods->set_pressed(true); + search_methods->set_focus_mode(Control::FOCUS_NONE); + hbox->add_child(search_methods); + + search_signals = memnew(Button); + search_signals->set_flat(true); + search_signals->set_tooltip(TTR("Search Signals")); + search_signals->connect("pressed", callable_mp(this, &VisualScriptPropertySelector::_update_results)); + search_signals->set_toggle_mode(true); + search_signals->set_pressed(true); + search_signals->set_focus_mode(Control::FOCUS_NONE); + hbox->add_child(search_signals); + + search_constants = memnew(Button); + search_constants->set_flat(true); + search_constants->set_tooltip(TTR("Search Constants")); + search_constants->connect("pressed", callable_mp(this, &VisualScriptPropertySelector::_update_results)); + search_constants->set_toggle_mode(true); + search_constants->set_pressed(true); + search_constants->set_focus_mode(Control::FOCUS_NONE); + hbox->add_child(search_constants); + + search_properties = memnew(Button); + search_properties->set_flat(true); + search_properties->set_tooltip(TTR("Search Properties")); + search_properties->connect("pressed", callable_mp(this, &VisualScriptPropertySelector::_update_results)); + search_properties->set_toggle_mode(true); + search_properties->set_pressed(true); + search_properties->set_focus_mode(Control::FOCUS_NONE); + hbox->add_child(search_properties); + + search_theme_items = memnew(Button); + search_theme_items->set_flat(true); + search_theme_items->set_tooltip(TTR("Search Theme Items")); + search_theme_items->connect("pressed", callable_mp(this, &VisualScriptPropertySelector::_update_results)); + search_theme_items->set_toggle_mode(true); + search_theme_items->set_pressed(true); + search_theme_items->set_focus_mode(Control::FOCUS_NONE); + hbox->add_child(search_theme_items); + + scope_combo = memnew(OptionButton); + scope_combo->set_custom_minimum_size(Size2(200, 0) * EDSCALE); + scope_combo->set_tooltip(TTR("Select the search limits")); + scope_combo->set_stretch_ratio(0); // Fixed width. + scope_combo->add_item(TTR("Search Related"), SCOPE_RELATED); + scope_combo->add_separator(); + scope_combo->add_item(TTR("Search Base"), SCOPE_BASE); + scope_combo->add_item(TTR("Search Inheriters"), SCOPE_INHERITERS); + scope_combo->add_item(TTR("Search Unrelated"), SCOPE_UNRELATED); + scope_combo->add_item(TTR("Search All"), SCOPE_ALL); + scope_combo->connect("item_selected", callable_mp(this, &VisualScriptPropertySelector::_update_results_i)); + hbox->add_child(scope_combo); - bool in_modifier = p_modifiers.is_empty(); - for (Set<String>::Element *F = p_modifiers.front(); F && in_modifier; F = F->next()) { - if (E.findn(F->get()) != -1) { - in_modifier = true; - } - } - if (!in_modifier) { - continue; - } + search_box = memnew(LineEdit); + search_box->set_tooltip(TTR("Enter \" \" to show all filterd options\nEnter \".\" to show all filterd methods, operators and constructors\nUse CTRL_KEY to drop property setters")); + search_box->set_custom_minimum_size(Size2(200, 0) * EDSCALE); + search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); + search_box->connect("text_changed", callable_mp(this, &VisualScriptPropertySelector::_update_results_s)); + search_box->connect("gui_input", callable_mp(this, &VisualScriptPropertySelector::_sbox_input)); + register_text_enter(search_box); + vbox->add_child(search_box); + + results_tree = memnew(Tree); + results_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); + results_tree->set_hide_root(true); + results_tree->set_hide_folding(false); + results_tree->set_columns(2); + results_tree->set_column_title(0, TTR("Name")); + results_tree->set_column_clip_content(0, true); + results_tree->set_column_title(1, TTR("Member Type")); + results_tree->set_column_expand(1, false); + results_tree->set_column_custom_minimum_width(1, 150 * EDSCALE); + results_tree->set_column_clip_content(1, true); + results_tree->set_custom_minimum_size(Size2(0, 100) * EDSCALE); + results_tree->set_select_mode(Tree::SELECT_ROW); + results_tree->connect("item_activated", callable_mp(this, &VisualScriptPropertySelector::_confirmed)); + results_tree->connect("item_selected", callable_mp(this, &VisualScriptPropertySelector::_item_selected)); + vbox->add_child(results_tree); - TreeItem *item = search_options->create_item(root); - Ref<VisualScriptNode> vnode = VisualScriptLanguage::singleton->create_node_from_name(E); - Ref<VisualScriptOperator> vnode_operator = vnode; - String type_name; - if (vnode_operator.is_valid()) { - String type; - if (path.size() >= 2) { - type = path[1]; - } - type_name = type.capitalize() + " "; + help_bit = memnew(EditorHelpBit); + vbox->add_child(help_bit); + help_bit->connect("request_hide", callable_mp(this, &VisualScriptPropertySelector::_hide_requested)); + get_ok_button()->set_text(TTR("Open")); + get_ok_button()->set_disabled(true); + set_hide_on_ok(false); +} + +bool VisualScriptPropertySelector::SearchRunner::_is_class_disabled_by_feature_profile(const StringName &p_class) { + Ref<EditorFeatureProfile> profile = EditorFeatureProfileManager::get_singleton()->get_current_profile(); + if (profile.is_null()) { + return false; + } + + StringName class_name = p_class; + while (class_name != StringName()) { + if (!ClassDB::class_exists(class_name)) { + return false; } - Ref<VisualScriptFunctionCall> vnode_function_call = vnode; - if (vnode_function_call.is_valid()) { - String basic_type = Variant::get_type_name(vnode_function_call->get_basic_type()); - type_name = basic_type.capitalize() + " "; + + if (profile->is_class_disabled(class_name)) { + return true; } - Ref<VisualScriptConstructor> vnode_constructor = vnode; - if (vnode_constructor.is_valid()) { - type_name = "Construct "; + class_name = ClassDB::get_parent_class(class_name); + } + + return false; +} + +bool VisualScriptPropertySelector::SearchRunner::_is_class_disabled_by_scope(const StringName &p_class) { + bool is_base_script = false; + if (p_class == selector_ui->base_script) { + is_base_script = true; + } + bool is_base = false; + if (selector_ui->base_type == p_class) { + is_base = true; + } + bool is_parent = false; + if ((ClassDB::is_parent_class(selector_ui->base_type, p_class)) && !is_base) { + is_parent = true; + } + + bool is_inheriter = false; + List<StringName> inheriters; + ClassDB::get_inheriters_from_class(selector_ui->base_type, &inheriters); + if (inheriters.find(p_class)) { + is_inheriter = true; + } + + if (scope_flags & SCOPE_BASE) { + if (is_base_script || is_base || is_parent) { + return false; } - Ref<VisualScriptDeconstruct> vnode_deconstruct = vnode; - if (vnode_deconstruct.is_valid()) { - type_name = "Deconstruct "; + } + if (scope_flags & SCOPE_INHERITERS) { + if (is_base_script || is_base || is_inheriter) { + return false; } - Vector<String> desc = path[path.size() - 1].replace("(", " ").replace(")", " ").replace(",", " ").split(" "); - for (int i = 0; i < desc.size(); i++) { - desc.write[i] = desc[i].capitalize(); - if (desc[i].ends_with(",")) { - desc.write[i] = desc[i].replace(",", ", "); - } + } + // if (scope_flags & SCOPE_RELATED) { + // /* code */ + // } + if (scope_flags & SCOPE_UNRELATED) { + if (!is_base_script && !is_base && !is_inheriter) { + return false; } - - item->set_text(0, type_name + String("").join(desc)); - item->set_icon(0, vbc->get_theme_icon(SNAME("VisualScript"), SNAME("EditorIcons"))); - item->set_selectable(0, true); - item->set_metadata(0, E); - item->set_selectable(0, true); - item->set_metadata(1, "visualscript"); - item->set_selectable(1, false); - item->set_selectable(2, false); - item->set_metadata(2, connecting); } + return true; } -void VisualScriptPropertySelector::_confirmed() { - TreeItem *ti = search_options->get_selected(); - if (!ti) { - return; +bool VisualScriptPropertySelector::SearchRunner::_slice() { + bool phase_done = false; + switch (phase) { + case PHASE_INIT: + phase_done = _phase_init(); + break; + case PHASE_MATCH_CLASSES_INIT: + phase_done = _phase_match_classes_init(); + break; + case PHASE_NODE_CLASSES_INIT: + phase_done = _phase_node_classes_init(); + break; + case PHASE_NODE_CLASSES_BUILD: + phase_done = _phase_node_classes_build(); + break; + case PHASE_MATCH_CLASSES: + phase_done = _phase_match_classes(); + break; + case PHASE_CLASS_ITEMS_INIT: + phase_done = _phase_class_items_init(); + break; + case PHASE_CLASS_ITEMS: + phase_done = _phase_class_items(); + break; + case PHASE_MEMBER_ITEMS_INIT: + phase_done = _phase_member_items_init(); + break; + case PHASE_MEMBER_ITEMS: + phase_done = _phase_member_items(); + break; + case PHASE_SELECT_MATCH: + phase_done = _phase_select_match(); + break; + case PHASE_MAX: + return true; + default: + WARN_PRINT("Invalid or unhandled phase in EditorHelpSearch::Runner, aborting search."); + return true; + }; + + if (phase_done) { + phase++; } - emit_signal(SNAME("selected"), ti->get_metadata(0), ti->get_metadata(1), ti->get_metadata(2)); - set_visible(false); + return false; } -void VisualScriptPropertySelector::_item_selected() { - help_bit->set_text(""); - - TreeItem *item = search_options->get_selected(); - if (!item) { - return; +bool VisualScriptPropertySelector::SearchRunner::_phase_init() { + search_flags = 0; // selector_ui->filter_combo->get_selected_id(); + if (selector_ui->search_visual_script_nodes->is_pressed()) { + search_flags |= SEARCH_VISUAL_SCRIPT_NODES; } - String name = item->get_metadata(0); - - String class_type; - if (type != Variant::NIL) { - class_type = Variant::get_type_name(type); - - } else { - class_type = base_type; + if (selector_ui->search_classes->is_pressed()) { + search_flags |= SEARCH_CLASSES; } + // if (selector_ui->search_constructors->is_pressed()) { + search_flags |= SEARCH_CONSTRUCTORS; + // } + if (selector_ui->search_methods->is_pressed()) { + search_flags |= SEARCH_METHODS; + } + if (selector_ui->search_operators->is_pressed()) { + search_flags |= SEARCH_OPERATORS; + } + if (selector_ui->search_signals->is_pressed()) { + search_flags |= SEARCH_SIGNALS; + } + if (selector_ui->search_constants->is_pressed()) { + search_flags |= SEARCH_CONSTANTS; + } + if (selector_ui->search_properties->is_pressed()) { + search_flags |= SEARCH_PROPERTIES; + } + if (selector_ui->search_theme_items->is_pressed()) { + search_flags |= SEARCH_THEME_ITEMS; + } + if (selector_ui->case_sensitive_button->is_pressed()) { + search_flags |= SEARCH_CASE_SENSITIVE; + } + if (selector_ui->hierarchy_button->is_pressed()) { + search_flags |= SEARCH_SHOW_HIERARCHY; + } + scope_flags = selector_ui->scope_combo->get_selected_id(); - DocTools *dd = EditorHelp::get_doc_data(); - String text; - - String at_class = class_type; + return true; +} - while (!at_class.is_empty()) { - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(at_class); - if (E) { - for (int i = 0; i < E->get().properties.size(); i++) { - if (E->get().properties[i].name == name) { - text = DTR(E->get().properties[i].description); +bool VisualScriptPropertySelector::SearchRunner::_phase_match_classes_init() { + combined_docs = EditorHelp::get_doc_data()->class_list; + matches.clear(); + matched_item = nullptr; + match_highest_score = 0; + + if ( + (selector_ui->base_script.unquote() != "") && + (selector_ui->base_script.unquote() != ".") && + !combined_docs.has(selector_ui->base_script)) { + String file_path = "res://" + selector_ui->base_script.unquote(); // EditorHelp::get_doc_data().name to filepath + Ref<Script> script; + script = ResourceLoader::load(file_path); + if (!script.is_null()) { + DocData::ClassDoc class_doc = DocData::ClassDoc(); + + class_doc.name = selector_ui->base_script; + + class_doc.inherits = script->get_instance_base_type(); + class_doc.brief_description = ".vs files not suported by EditorHelp::get_doc_data()"; + class_doc.description = ""; + + Object *obj = ObjectDB::get_instance(script->get_instance_id()); + if (Object::cast_to<Script>(obj)) { + List<MethodInfo> methods; + Object::cast_to<Script>(obj)->get_script_method_list(&methods); + for (List<MethodInfo>::Element *M = methods.front(); M; M = M->next()) { + class_doc.methods.push_back(_get_method_doc(M->get())); } - } - } - at_class = ClassDB::get_parent_class_nocheck(at_class); - } - at_class = class_type; + List<MethodInfo> signals; + Object::cast_to<Script>(obj)->get_script_signal_list(&signals); + for (List<MethodInfo>::Element *S = signals.front(); S; S = S->next()) { + class_doc.signals.push_back(_get_method_doc(S->get())); + } - while (!at_class.is_empty()) { - Map<String, DocData::ClassDoc>::Element *C = dd->class_list.find(at_class); - if (C) { - for (int i = 0; i < C->get().methods.size(); i++) { - if (C->get().methods[i].name == name) { - text = DTR(C->get().methods[i].description); + List<PropertyInfo> propertys; + Object::cast_to<Script>(obj)->get_script_property_list(&propertys); + for (List<PropertyInfo>::Element *P = propertys.front(); P; P = P->next()) { + DocData::PropertyDoc pd = DocData::PropertyDoc(); + pd.name = P->get().name; + pd.type = Variant::get_type_name(P->get().type); + class_doc.properties.push_back(pd); } } + combined_docs.insert(class_doc.name, class_doc); } + } + iterator_doc = combined_docs.front(); + return true; +} + +bool VisualScriptPropertySelector::SearchRunner::_phase_node_classes_init() { + VisualScriptLanguage::singleton->get_registered_node_names(&vs_nodes); + _add_class_doc("functions", "", ""); + _add_class_doc("operators", "", ""); + return true; +} - at_class = ClassDB::get_parent_class_nocheck(at_class); +bool VisualScriptPropertySelector::SearchRunner::_phase_node_classes_build() { + if (vs_nodes.is_empty()) { + return true; } - Vector<String> functions = name.rsplit("/", false); - at_class = functions.size() > 3 ? functions[functions.size() - 2] : class_type; - Map<String, DocData::ClassDoc>::Element *T = dd->class_list.find(at_class); - if (T) { - for (int i = 0; i < T->get().methods.size(); i++) { - if (T->get().methods[i].name == functions[functions.size() - 1]) { - text = DTR(T->get().methods[i].description); + String registerd_node_name = vs_nodes[0]; + vs_nodes.pop_front(); + + Vector<String> path = registerd_node_name.split("/"); + if (path[0] == "constants") { + _add_class_doc(registerd_node_name, "", "constants"); + } else if (path[0] == "custom") { + _add_class_doc(registerd_node_name, "", "custom"); + } else if (path[0] == "data") { + _add_class_doc(registerd_node_name, "", "data"); + } else if (path[0] == "flow_control") { + _add_class_doc(registerd_node_name, "", "flow_control"); + } else if (path[0] == "functions") { + if (path[1] == "built_in") { + _add_class_doc(registerd_node_name, "functions", "built_in"); + } else if (path[1] == "by_type") { + if (search_flags & SEARCH_CLASSES) { + _add_class_doc(registerd_node_name, path[2], "by_type_class"); } + } else if (path[1] == "constructors") { + if (search_flags & SEARCH_CLASSES) { + _add_class_doc(registerd_node_name, path[2].substr(0, path[2].find_char('(')), "constructors_class"); + } + } else if (path[1] == "deconstruct") { + _add_class_doc(registerd_node_name, "", "deconstruct"); + } else if (path[1] == "wait") { + _add_class_doc(registerd_node_name, "functions", "yield"); + } else { + _add_class_doc(registerd_node_name, "functions", ""); + } + } else if (path[0] == "index") { + _add_class_doc(registerd_node_name, "", "index"); + } else if (path[0] == "operators") { + if (path[1] == "bitwise") { + _add_class_doc(registerd_node_name, "operators", "bitwise"); + } else if (path[1] == "compare") { + _add_class_doc(registerd_node_name, "operators", "compare"); + } else if (path[1] == "logic") { + _add_class_doc(registerd_node_name, "operators", "logic"); + } else if (path[1] == "math") { + _add_class_doc(registerd_node_name, "operators", "math"); + } else { + _add_class_doc(registerd_node_name, "operators", ""); } } + return false; +} - List<String> *names = memnew(List<String>); - VisualScriptLanguage::singleton->get_registered_node_names(names); - if (names->find(name) != nullptr) { - Ref<VisualScriptOperator> operator_node = VisualScriptLanguage::singleton->create_node_from_name(name); - if (operator_node.is_valid()) { - Map<String, DocData::ClassDoc>::Element *F = dd->class_list.find(operator_node->get_class_name()); - if (F) { - text = Variant::get_operator_name(operator_node->get_operator()); +bool VisualScriptPropertySelector::SearchRunner::_phase_match_classes() { + DocData::ClassDoc &class_doc = iterator_doc->value(); + if ( + (!_is_class_disabled_by_feature_profile(class_doc.name) && !_is_class_disabled_by_scope(class_doc.name)) || + _match_visual_script(class_doc)) { + if (class_doc.inherits == "VisualScriptCustomNode") { + class_doc.script_path = "res://" + class_doc.name.unquote(); + Ref<Script> script = ResourceLoader::load(class_doc.script_path); + Ref<VisualScriptCustomNode> vsn; + vsn.instantiate(); + vsn->set_script(script); + class_doc.name = vsn->get_caption(); + if (combined_docs.has(vsn->get_category())) { + class_doc.inherits = vsn->get_category(); + } else if (combined_docs.has("VisualScriptNode/" + vsn->get_category())) { + class_doc.inherits = "VisualScriptNode/" + vsn->get_category(); + } else if (combined_docs.has("VisualScriptCustomNode/" + vsn->get_category())) { + class_doc.inherits = "VisualScriptCustomNode/" + vsn->get_category(); + } else { + class_doc.inherits = ""; } + class_doc.category = "VisualScriptCustomNode/" + vsn->get_category(); + class_doc.brief_description = ""; + class_doc.constructors.clear(); + class_doc.methods.clear(); + class_doc.operators.clear(); + class_doc.signals.clear(); + class_doc.constants.clear(); + class_doc.enums.clear(); + class_doc.properties.clear(); + class_doc.theme_properties.clear(); } - Ref<VisualScriptTypeCast> typecast_node = VisualScriptLanguage::singleton->create_node_from_name(name); - if (typecast_node.is_valid()) { - Map<String, DocData::ClassDoc>::Element *F = dd->class_list.find(typecast_node->get_class_name()); - if (F) { - text = DTR(F->get().description); + + matches[class_doc.name] = ClassMatch(); + ClassMatch &match = matches[class_doc.name]; + + match.category = class_doc.category; + match.doc = &class_doc; + // Match class name. + if (search_flags & SEARCH_CLASSES || _match_visual_script(class_doc)) { + if (term == "") { + match.name = !_match_is_hidden(class_doc); + } else { + match.name = _match_string(term, class_doc.name); } + // match.name = term == "" || _match_string(term, class_doc.name); } - Ref<VisualScriptBuiltinFunc> builtin_node = VisualScriptLanguage::singleton->create_node_from_name(name); - if (builtin_node.is_valid()) { - Map<String, DocData::ClassDoc>::Element *F = dd->class_list.find(builtin_node->get_class_name()); - if (F) { - for (int i = 0; i < F->get().constants.size(); i++) { - if (F->get().constants[i].value.to_int() == int(builtin_node->get_func())) { - text = DTR(F->get().constants[i].description); + // Match members if the term is long enough. + if (term.length() >= 0) { + if (search_flags & SEARCH_CONSTRUCTORS) { + for (int i = 0; i < class_doc.constructors.size(); i++) { + String method_name = (search_flags & SEARCH_CASE_SENSITIVE) ? class_doc.constructors[i].name : class_doc.constructors[i].name.to_lower(); + if (method_name.find(term) > -1 || + term == " " || + (term.begins_with(".") && method_name.begins_with(term.substr(1))) || + (term.ends_with("(") && method_name.ends_with(term.left(term.length() - 1).strip_edges())) || + (term.begins_with(".") && term.ends_with("(") && method_name == term.substr(1, term.length() - 2).strip_edges())) { + match.constructors.push_back(const_cast<DocData::MethodDoc *>(&class_doc.constructors[i])); + } + } + } + if (search_flags & SEARCH_METHODS) { + for (int i = 0; i < class_doc.methods.size(); i++) { + String method_name = (search_flags & SEARCH_CASE_SENSITIVE) ? class_doc.methods[i].name : class_doc.methods[i].name.to_lower(); + if (method_name.find(term) > -1 || + term == " " || + (term.begins_with(".") && method_name.begins_with(term.substr(1))) || + (term.ends_with("(") && method_name.ends_with(term.left(term.length() - 1).strip_edges())) || + (term.begins_with(".") && term.ends_with("(") && method_name == term.substr(1, term.length() - 2).strip_edges())) { + match.methods.push_back(const_cast<DocData::MethodDoc *>(&class_doc.methods[i])); + } + } + } + if (search_flags & SEARCH_OPERATORS) { + for (int i = 0; i < class_doc.operators.size(); i++) { + String method_name = (search_flags & SEARCH_CASE_SENSITIVE) ? class_doc.operators[i].name : class_doc.operators[i].name.to_lower(); + if (method_name.find(term) > -1 || + term == " " || + (term.begins_with(".") && method_name.begins_with(term.substr(1))) || + (term.ends_with("(") && method_name.ends_with(term.left(term.length() - 1).strip_edges())) || + (term.begins_with(".") && term.ends_with("(") && method_name == term.substr(1, term.length() - 2).strip_edges())) { + match.operators.push_back(const_cast<DocData::MethodDoc *>(&class_doc.operators[i])); + } + } + } + if (search_flags & SEARCH_SIGNALS) { + for (int i = 0; i < class_doc.signals.size(); i++) { + if (_match_string(term, class_doc.signals[i].name) || + term == " ") { + match.signals.push_back(const_cast<DocData::MethodDoc *>(&class_doc.signals[i])); + } + } + } + if (search_flags & SEARCH_CONSTANTS) { + for (int i = 0; i < class_doc.constants.size(); i++) { + if (_match_string(term, class_doc.constants[i].name) || + term == " ") { + match.constants.push_back(const_cast<DocData::ConstantDoc *>(&class_doc.constants[i])); + } + } + } + if (search_flags & SEARCH_PROPERTIES) { + for (int i = 0; i < class_doc.properties.size(); i++) { + if (_match_string(term, class_doc.properties[i].name) || + term == " " || + _match_string(term, class_doc.properties[i].getter) || + _match_string(term, class_doc.properties[i].setter)) { + match.properties.push_back(const_cast<DocData::PropertyDoc *>(&class_doc.properties[i])); + } + } + } + if (search_flags & SEARCH_THEME_ITEMS) { + for (int i = 0; i < class_doc.theme_properties.size(); i++) { + if (_match_string(term, class_doc.theme_properties[i].name) || + term == " ") { + match.theme_properties.push_back(const_cast<DocData::ThemeItemDoc *>(&class_doc.theme_properties[i])); } } } } } - memdelete(names); + iterator_doc = iterator_doc->next(); + return !iterator_doc; +} - if (text.is_empty()) { - return; - } +bool VisualScriptPropertySelector::SearchRunner::_phase_class_items_init() { + results_tree->clear(); + iterator_match = matches.front(); - help_bit->set_text(text); -} + root_item = results_tree->create_item(); + class_items.clear(); -void VisualScriptPropertySelector::_hide_requested() { - _cancel_pressed(); // From AcceptDialog. + return true; } -void VisualScriptPropertySelector::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE) { - connect("confirmed", callable_mp(this, &VisualScriptPropertySelector::_confirmed)); +bool VisualScriptPropertySelector::SearchRunner::_phase_class_items() { + if (!iterator_match) { + return true; } -} -void VisualScriptPropertySelector::select_method_from_base_type(const String &p_base, const String &p_current, const bool p_virtuals_only, const bool p_connecting, bool clear_text) { - base_type = p_base; - selected = p_current; - type = Variant::NIL; - properties = false; - instance = nullptr; - virtuals_only = p_virtuals_only; + ClassMatch &match = iterator_match->value(); - show_window(.5f); - if (clear_text) { - search_box->set_text(""); + if (search_flags & SEARCH_SHOW_HIERARCHY) { + if (match.required()) { + _create_class_hierarchy(match); + } } else { - search_box->select_all(); + if (match.name) { + _create_class_item(root_item, match.doc, true); + } } - search_box->grab_focus(); - connecting = p_connecting; - _update_search(); + iterator_match = iterator_match->next(); + return !iterator_match; } -void VisualScriptPropertySelector::set_type_filter(const Vector<Variant::Type> &p_type_filter) { - type_filter = p_type_filter; +bool VisualScriptPropertySelector::SearchRunner::_phase_member_items_init() { + iterator_match = matches.front(); + + return true; } -void VisualScriptPropertySelector::select_from_base_type(const String &p_base, const String &p_current, bool p_virtuals_only, bool p_seq_connect, const bool p_connecting, bool clear_text) { - base_type = p_base; - selected = p_current; - type = Variant::NIL; - properties = true; - visual_script_generic = false; - instance = nullptr; - virtuals_only = p_virtuals_only; +bool VisualScriptPropertySelector::SearchRunner::_phase_member_items() { + if (!iterator_match) { + return true; + } - show_window(.5f); - if (clear_text) { - search_box->set_text(""); + ClassMatch &match = iterator_match->value(); + + TreeItem *parent = (search_flags & SEARCH_SHOW_HIERARCHY) ? class_items[match.doc->name] : root_item; + bool constructor_created = false; + for (int i = 0; i < match.methods.size(); i++) { + String text = match.methods[i]->name; + if (!constructor_created) { + if (match.doc->name == match.methods[i]->name) { + text += " " + TTR("(constructors)"); + constructor_created = true; + } + } else { + if (match.doc->name == match.methods[i]->name) { + continue; + } + } + _create_method_item(parent, match.doc, text, match.methods[i]); + } + for (int i = 0; i < match.signals.size(); i++) { + _create_signal_item(parent, match.doc, match.signals[i]); + } + for (int i = 0; i < match.constants.size(); i++) { + _create_constant_item(parent, match.doc, match.constants[i]); + } + for (int i = 0; i < match.properties.size(); i++) { + _create_property_item(parent, match.doc, match.properties[i]); + } + for (int i = 0; i < match.theme_properties.size(); i++) { + _create_theme_property_item(parent, match.doc, match.theme_properties[i]); + } + + iterator_match = iterator_match->next(); + return !iterator_match; +} + +bool VisualScriptPropertySelector::SearchRunner::_phase_select_match() { + if (matched_item) { + matched_item->select(0); + } + return true; +} + +bool VisualScriptPropertySelector::SearchRunner::_match_string(const String &p_term, const String &p_string) const { + if (search_flags & SEARCH_CASE_SENSITIVE) { + return p_string.find(p_term) > -1; } else { - search_box->select_all(); + return p_string.findn(p_term) > -1; + } +} + +bool VisualScriptPropertySelector::SearchRunner::_match_visual_script(DocData::ClassDoc &class_doc) { + if (class_doc.category.ends_with("_class")) { + if (class_doc.category.begins_with("VisualScript") && search_flags & SEARCH_CLASSES) { + if (matches.has(class_doc.inherits)) { + return true; + } + } + return false; + } + if (class_doc.category.begins_with("VisualScript") && search_flags & SEARCH_VISUAL_SCRIPT_NODES) { + return true; + } + if (class_doc.name.begins_with("operators") && search_flags & SEARCH_OPERATORS) { + return true; + } + if (class_doc.category.begins_with("VisualScriptNode/deconstruct")) { + if (class_doc.name.find(selector_ui->base_type, 0) > -1) { + return true; + } } - search_box->grab_focus(); - seq_connect = p_seq_connect; - connecting = p_connecting; - _update_search(); + return false; } -void VisualScriptPropertySelector::select_from_script(const Ref<Script> &p_script, const String &p_current, const bool p_connecting, bool clear_text) { - ERR_FAIL_COND(p_script.is_null()); +bool VisualScriptPropertySelector::SearchRunner::_match_is_hidden(DocData::ClassDoc &class_doc) { + if (class_doc.category.begins_with("VisualScript")) { + if (class_doc.name.begins_with("flow_control")) { + return false; + } else if (class_doc.name.begins_with("operators")) { + return !(search_flags & SEARCH_OPERATORS); + } else if (class_doc.name.begins_with("functions/built_in/print")) { + return false; + } + return true; + } + return false; +} - base_type = p_script->get_instance_base_type(); - selected = p_current; - type = Variant::NIL; - script = p_script->get_instance_id(); - properties = true; - visual_script_generic = false; - instance = nullptr; - virtuals_only = false; +void VisualScriptPropertySelector::SearchRunner::_match_item(TreeItem *p_item, const String &p_text) { + float inverse_length = 1.f / float(p_text.length()); - show_window(.5f); - if (clear_text) { - search_box->set_text(""); - } else { - search_box->select_all(); + // Favor types where search term is a substring close to the start of the type. + float w = 0.5f; + int pos = p_text.findn(term); + float score = (pos > -1) ? 1.0f - w * MIN(1, 3 * pos * inverse_length) : MAX(0.f, .9f - w); + + // Favor shorter items: they resemble the search term more. + w = 0.1f; + score *= (1 - w) + w * (term.length() * inverse_length); + + if (match_highest_score == 0 || score > match_highest_score) { + matched_item = p_item; + match_highest_score = score; } - search_box->grab_focus(); - seq_connect = false; - connecting = p_connecting; +} - _update_search(); +void VisualScriptPropertySelector::SearchRunner::_add_class_doc(String class_name, String inherits, String category) { + DocData::ClassDoc class_doc = DocData::ClassDoc(); + class_doc.name = class_name; + class_doc.inherits = inherits; + class_doc.category = "VisualScriptNode/" + category; + class_doc.brief_description = category; + combined_docs.insert(class_doc.name, class_doc); } -void VisualScriptPropertySelector::select_from_basic_type(Variant::Type p_type, const String &p_current, const bool p_connecting, bool clear_text) { - ERR_FAIL_COND(p_type == Variant::NIL); - base_type = ""; - selected = p_current; - type = p_type; - properties = true; - visual_script_generic = false; - instance = nullptr; - virtuals_only = false; +DocData::MethodDoc VisualScriptPropertySelector::SearchRunner::_get_method_doc(MethodInfo method_info) { + DocData::MethodDoc method_doc = DocData::MethodDoc(); + method_doc.name = method_info.name; + method_doc.return_type = Variant::get_type_name(method_info.return_val.type); + method_doc.description = "No description available"; + for (List<PropertyInfo>::Element *P = method_info.arguments.front(); P; P = P->next()) { + DocData::ArgumentDoc argument_doc = DocData::ArgumentDoc(); + argument_doc.name = P->get().name; + argument_doc.type = Variant::get_type_name(P->get().type); + method_doc.arguments.push_back(argument_doc); + } + return method_doc; +} - show_window(.5f); - if (clear_text) { - search_box->set_text(""); - } else { - search_box->select_all(); +TreeItem *VisualScriptPropertySelector::SearchRunner::_create_class_hierarchy(const ClassMatch &p_match) { + if (class_items.has(p_match.doc->name)) { + return class_items[p_match.doc->name]; + } + + // Ensure parent nodes are created first. + TreeItem *parent = root_item; + if (p_match.doc->inherits != "") { + if (class_items.has(p_match.doc->inherits)) { + parent = class_items[p_match.doc->inherits]; + } else if (matches.has(p_match.doc->inherits)) { + ClassMatch &base_match = matches[p_match.doc->inherits]; + parent = _create_class_hierarchy(base_match); + } } - search_box->grab_focus(); - seq_connect = false; - connecting = p_connecting; - _update_search(); + TreeItem *class_item = _create_class_item(parent, p_match.doc, !p_match.name); + class_items[p_match.doc->name] = class_item; + return class_item; } -void VisualScriptPropertySelector::select_from_action(const String &p_type, const String &p_current, const bool p_connecting, bool clear_text) { - base_type = p_type; - selected = p_current; - type = Variant::NIL; - properties = false; - visual_script_generic = false; - instance = nullptr; - virtuals_only = false; +TreeItem *VisualScriptPropertySelector::SearchRunner::_create_class_item(TreeItem *p_parent, const DocData::ClassDoc *p_doc, bool p_gray) { + Ref<Texture2D> icon = empty_icon; + String text_0 = p_doc->name; + String text_1 = "Class"; + + String what = "Class"; + String details = p_doc->name; + if (p_doc->category.begins_with("VisualScriptCustomNode/")) { + Vector<String> path = p_doc->name.split("/"); + icon = ui_service->get_theme_icon("VisualScript", "EditorIcons"); + text_0 = path[path.size() - 1]; + text_1 = "VisualScriptCustomNode"; + what = "VisualScriptCustomNode"; + details = "CustomNode"; + } else if (p_doc->category.begins_with("VisualScriptNode/")) { + Vector<String> path = p_doc->name.split("/"); + icon = ui_service->get_theme_icon("VisualScript", "EditorIcons"); + text_0 = path[path.size() - 1]; + if (p_doc->category.begins_with("VisualScriptNode/deconstruct")) { + text_0 = "deconstruct " + text_0; + } + text_1 = "VisualScriptNode"; + what = "VisualScriptNode"; + details = p_doc->name; + + if (path.size() == 1) { + if (path[0] == "functions" || path[0] == "operators") { + text_1 = "VisualScript"; + p_gray = true; + what = "no_result"; + details = ""; + } + } - show_window(.5f); - if (clear_text) { - search_box->set_text(""); } else { - search_box->select_all(); + if (p_doc->name.is_quoted()) { + text_0 = p_doc->name.unquote().get_file(); + if (ui_service->has_theme_icon(p_doc->inherits, "EditorIcons")) { + icon = ui_service->get_theme_icon(p_doc->inherits, "EditorIcons"); + } + } else if (ui_service->has_theme_icon(p_doc->name, "EditorIcons")) { + icon = ui_service->get_theme_icon(p_doc->name, "EditorIcons"); + } else if (ClassDB::class_exists(p_doc->name) && ClassDB::is_parent_class(p_doc->name, "Object")) { + icon = ui_service->get_theme_icon(SNAME("Object"), SNAME("EditorIcons")); + } } - search_box->grab_focus(); - seq_connect = true; - connecting = p_connecting; + String tooltip = p_doc->brief_description.strip_edges(); + + TreeItem *item = results_tree->create_item(p_parent); + item->set_icon(0, icon); + item->set_text(0, text_0); + item->set_text(1, TTR(text_1)); + item->set_tooltip(0, tooltip); + item->set_tooltip(1, tooltip); + item->set_metadata(0, details); + item->set_metadata(1, what); + if (p_gray) { + item->set_custom_color(0, disabled_color); + item->set_custom_color(1, disabled_color); + } + + _match_item(item, p_doc->name); - _update_search(); + return item; } -void VisualScriptPropertySelector::select_from_instance(Object *p_instance, const String &p_current, const bool p_connecting, const String &p_basetype, bool clear_text) { - base_type = p_basetype; - selected = p_current; - type = Variant::NIL; - properties = true; - visual_script_generic = false; - instance = p_instance; - virtuals_only = false; +TreeItem *VisualScriptPropertySelector::SearchRunner::_create_method_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const String &p_text, const DocData::MethodDoc *p_doc) { + String tooltip = p_doc->return_type + " " + p_class_doc->name + "." + p_doc->name + "("; + for (int i = 0; i < p_doc->arguments.size(); i++) { + const DocData::ArgumentDoc &arg = p_doc->arguments[i]; + tooltip += arg.type + " " + arg.name; + if (arg.default_value != "") { + tooltip += " = " + arg.default_value; + } + if (i < p_doc->arguments.size() - 1) { + tooltip += ", "; + } + } + tooltip += ")"; + return _create_member_item(p_parent, p_class_doc->name, "MemberMethod", p_doc->name, p_text, TTRC("Method"), "method", tooltip, p_doc->description); +} - show_window(.5f); - if (clear_text) { - search_box->set_text(""); - } else { - search_box->select_all(); +TreeItem *VisualScriptPropertySelector::SearchRunner::_create_signal_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::MethodDoc *p_doc) { + String tooltip = p_doc->return_type + " " + p_class_doc->name + "." + p_doc->name + "("; + for (int i = 0; i < p_doc->arguments.size(); i++) { + const DocData::ArgumentDoc &arg = p_doc->arguments[i]; + tooltip += arg.type + " " + arg.name; + if (arg.default_value != "") { + tooltip += " = " + arg.default_value; + } + if (i < p_doc->arguments.size() - 1) { + tooltip += ", "; + } } - search_box->grab_focus(); - seq_connect = false; - connecting = p_connecting; + tooltip += ")"; + return _create_member_item(p_parent, p_class_doc->name, "MemberSignal", p_doc->name, p_doc->name, TTRC("Signal"), "signal", tooltip, p_doc->description); +} - _update_search(); +TreeItem *VisualScriptPropertySelector::SearchRunner::_create_constant_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::ConstantDoc *p_doc) { + String tooltip = p_class_doc->name + "." + p_doc->name; + return _create_member_item(p_parent, p_class_doc->name, "MemberConstant", p_doc->name, p_doc->name, TTRC("Constant"), "constant", tooltip, p_doc->description); } -void VisualScriptPropertySelector::select_from_visual_script(const String &p_base, const bool p_connecting, bool clear_text) { - base_type = p_base; - selected = ""; - type = Variant::NIL; - properties = true; - visual_script_generic = true; - instance = nullptr; - virtuals_only = false; - show_window(.5f); - if (clear_text) { - search_box->set_text(""); +TreeItem *VisualScriptPropertySelector::SearchRunner::_create_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::PropertyDoc *p_doc) { + String tooltip = p_doc->type + " " + p_class_doc->name + "." + p_doc->name; + tooltip += "\n " + p_class_doc->name + "." + p_doc->setter + "(value) setter"; + tooltip += "\n " + p_class_doc->name + "." + p_doc->getter + "() getter"; + return _create_member_item(p_parent, p_class_doc->name, "MemberProperty", p_doc->name, p_doc->name, TTRC("Property"), "property", tooltip, p_doc->description); +} + +TreeItem *VisualScriptPropertySelector::SearchRunner::_create_theme_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::ThemeItemDoc *p_doc) { + String tooltip = p_doc->type + " " + p_class_doc->name + "." + p_doc->name; + return _create_member_item(p_parent, p_class_doc->name, "MemberTheme", p_doc->name, p_doc->name, TTRC("Theme Property"), "theme_item", tooltip, p_doc->description); +} + +TreeItem *VisualScriptPropertySelector::SearchRunner::_create_member_item(TreeItem *p_parent, const String &p_class_name, const String &p_icon, const String &p_name, const String &p_text, const String &p_type, const String &p_metatype, const String &p_tooltip, const String &p_description) { + Ref<Texture2D> icon; + String text; + if (search_flags & SEARCH_SHOW_HIERARCHY) { + icon = ui_service->get_theme_icon(p_icon, SNAME("EditorIcons")); + text = p_text; } else { - search_box->select_all(); + icon = ui_service->get_theme_icon(p_icon, SNAME("EditorIcons")); + text = p_class_name + "." + p_text; } - search_box->grab_focus(); - connecting = p_connecting; - _update_search(); -} + TreeItem *item = results_tree->create_item(p_parent); + item->set_icon(0, icon); + item->set_text(0, text); + item->set_text(1, TTRGET(p_type)); + item->set_tooltip(0, p_tooltip); + item->set_tooltip(1, p_tooltip); + item->set_metadata(0, p_class_name + ":" + p_name); + item->set_metadata(1, "class_" + p_metatype); + item->set_meta("description", p_description); -void VisualScriptPropertySelector::show_window(float p_screen_ratio) { - popup_centered_ratio(p_screen_ratio); + _match_item(item, p_name); + + return item; } -void VisualScriptPropertySelector::_bind_methods() { - ADD_SIGNAL(MethodInfo("selected", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::STRING, "category"), PropertyInfo(Variant::BOOL, "connecting"))); +bool VisualScriptPropertySelector::SearchRunner::work(uint64_t slot) { + // Return true when the search has been completed, otherwise false. + const uint64_t until = OS::get_singleton()->get_ticks_usec() + slot; + while (!_slice()) { + if (OS::get_singleton()->get_ticks_usec() > until) { + return false; + } + } + return true; } -VisualScriptPropertySelector::VisualScriptPropertySelector() { - vbc = memnew(VBoxContainer); - add_child(vbc); - //set_child_rect(vbc); - search_box = memnew(LineEdit); - vbc->add_margin_child(TTR("Search:"), search_box); - search_box->connect("text_changed", callable_mp(this, &VisualScriptPropertySelector::_text_changed)); - search_box->connect("gui_input", callable_mp(this, &VisualScriptPropertySelector::_sbox_input)); - search_options = memnew(Tree); - vbc->add_margin_child(TTR("Matches:"), search_options, true); - get_ok_button()->set_text(TTR("Open")); - get_ok_button()->set_disabled(true); - register_text_enter(search_box); - set_hide_on_ok(false); - search_options->connect("item_activated", callable_mp(this, &VisualScriptPropertySelector::_confirmed)); - search_options->connect("cell_selected", callable_mp(this, &VisualScriptPropertySelector::_item_selected)); - search_options->set_hide_root(true); - search_options->set_hide_folding(true); - virtuals_only = false; - seq_connect = false; - help_bit = memnew(EditorHelpBit); - vbc->add_margin_child(TTR("Description:"), help_bit); - help_bit->connect("request_hide", callable_mp(this, &VisualScriptPropertySelector::_hide_requested)); - search_options->set_columns(3); - search_options->set_column_expand(1, false); - search_options->set_column_expand(2, false); +VisualScriptPropertySelector::SearchRunner::SearchRunner(VisualScriptPropertySelector *p_selector_ui, Tree *p_results_tree) : + selector_ui(p_selector_ui), + ui_service(p_selector_ui->vbox), + results_tree(p_results_tree), + term(p_selector_ui->search_box->get_text()), + empty_icon(ui_service->get_theme_icon(SNAME("ArrowRight"), SNAME("EditorIcons"))), + disabled_color(ui_service->get_theme_color(SNAME("disabled_font_color"), SNAME("Editor"))) { } diff --git a/modules/visual_script/editor/visual_script_property_selector.h b/modules/visual_script/editor/visual_script_property_selector.h index 9e065548a0..3970c4473e 100644 --- a/modules/visual_script/editor/visual_script_property_selector.h +++ b/modules/visual_script/editor/visual_script_property_selector.h @@ -31,6 +31,7 @@ #ifndef VISUALSCRIPT_PROPERTYSELECTOR_H #define VISUALSCRIPT_PROPERTYSELECTOR_H +#include "../visual_script.h" #include "editor/editor_help.h" #include "editor/property_editor.h" #include "scene/gui/rich_text_label.h" @@ -38,15 +39,56 @@ class VisualScriptPropertySelector : public ConfirmationDialog { GDCLASS(VisualScriptPropertySelector, ConfirmationDialog); + enum SearchFlags { + SEARCH_CLASSES = 1 << 0, + SEARCH_CONSTRUCTORS = 1 << 1, + SEARCH_METHODS = 1 << 2, + SEARCH_OPERATORS = 1 << 3, + SEARCH_SIGNALS = 1 << 4, + SEARCH_CONSTANTS = 1 << 5, + SEARCH_PROPERTIES = 1 << 6, + SEARCH_THEME_ITEMS = 1 << 7, + SEARCH_VISUAL_SCRIPT_NODES = 1 << 8, + SEARCH_ALL = SEARCH_CLASSES | SEARCH_CONSTRUCTORS | SEARCH_METHODS | SEARCH_OPERATORS | SEARCH_SIGNALS | SEARCH_CONSTANTS | SEARCH_PROPERTIES | SEARCH_THEME_ITEMS, + SEARCH_CASE_SENSITIVE = 1 << 29, + SEARCH_SHOW_HIERARCHY = 1 << 30, + }; + + enum ScopeFlags { + SCOPE_BASE = 1 << 0, + SCOPE_INHERITERS = 1 << 1, + SCOPE_UNRELATED = 1 << 2, + SCOPE_RELATED = SCOPE_BASE | SCOPE_INHERITERS, + SCOPE_ALL = SCOPE_BASE | SCOPE_INHERITERS | SCOPE_UNRELATED + }; + LineEdit *search_box; - Tree *search_options; - void _text_changed(const String &p_newtext); - void _sbox_input(const Ref<InputEvent> &p_ie); - void _update_search(); + Button *case_sensitive_button; + Button *hierarchy_button; + + Button *search_visual_script_nodes; + Button *search_classes; + Button *search_operators; + + Button *search_methods; + Button *search_signals; + Button *search_constants; + Button *search_properties; + Button *search_theme_items; - void create_visualscript_item(const String &name, TreeItem *const root, const String &search_input, const String &text); - void get_visual_node_names(const String &root_filter, const Set<String> &p_modifiers, bool &found, TreeItem *const root, LineEdit *const search_box); + OptionButton *scope_combo; + Tree *results_tree; + + class SearchRunner; + Ref<SearchRunner> search_runner; + + void _update_icons(); + + void _sbox_input(const Ref<InputEvent> &p_ie); + void _update_results_i(int p_int); + void _update_results_s(String p_string); + void _update_results(); void _confirmed(); void _item_selected(); @@ -60,32 +102,118 @@ class VisualScriptPropertySelector : public ConfirmationDialog { String selected; Variant::Type type; String base_type; + String base_script; ObjectID script; Object *instance; bool virtuals_only; - bool seq_connect; - VBoxContainer *vbc; - - Vector<Variant::Type> type_filter; + VBoxContainer *vbox; protected: void _notification(int p_what); static void _bind_methods(); public: - void select_method_from_base_type(const String &p_base, const String &p_current = "", const bool p_virtuals_only = false, const bool p_connecting = true, bool clear_text = true); - void select_from_base_type(const String &p_base, const String &p_current = "", bool p_virtuals_only = false, bool p_seq_connect = false, const bool p_connecting = true, bool clear_text = true); - void select_from_script(const Ref<Script> &p_script, const String &p_current = "", const bool p_connecting = true, bool clear_text = true); - void select_from_basic_type(Variant::Type p_type, const String &p_current = "", const bool p_connecting = true, bool clear_text = true); - void select_from_action(const String &p_type, const String &p_current = "", const bool p_connecting = true, bool clear_text = true); - void select_from_instance(Object *p_instance, const String &p_current = "", const bool p_connecting = true, const String &p_basetype = "", bool clear_text = true); - void select_from_visual_script(const String &p_base, const bool p_connecting = true, bool clear_text = true); + void select_method_from_base_type(const String &p_base, const bool p_virtuals_only = false, const bool p_connecting = true, bool clear_text = true); + void select_from_base_type(const String &p_base, const String &p_base_script = "", bool p_virtuals_only = false, const bool p_connecting = true, bool clear_text = true); + void select_from_script(const Ref<Script> &p_script, const bool p_connecting = true, bool clear_text = true); + void select_from_basic_type(Variant::Type p_type, const bool p_connecting = true, bool clear_text = true); + void select_from_action(const String &p_type, const bool p_connecting = true, bool clear_text = true); + void select_from_instance(Object *p_instance, const bool p_connecting = true, bool clear_text = true); + void select_from_visual_script(const Ref<Script> &p_script, bool clear_text = true); void show_window(float p_screen_ratio); - void set_type_filter(const Vector<Variant::Type> &p_type_filter); - VisualScriptPropertySelector(); }; +class VisualScriptPropertySelector::SearchRunner : public RefCounted { + enum Phase { + PHASE_INIT, + PHASE_MATCH_CLASSES_INIT, + PHASE_NODE_CLASSES_INIT, + PHASE_NODE_CLASSES_BUILD, + PHASE_MATCH_CLASSES, + PHASE_CLASS_ITEMS_INIT, + PHASE_CLASS_ITEMS, + PHASE_MEMBER_ITEMS_INIT, + PHASE_MEMBER_ITEMS, + PHASE_SELECT_MATCH, + PHASE_MAX + }; + int phase = 0; + + struct ClassMatch { + DocData::ClassDoc *doc; + bool name = false; + String category = ""; + Vector<DocData::MethodDoc *> constructors; + Vector<DocData::MethodDoc *> methods; + Vector<DocData::MethodDoc *> operators; + Vector<DocData::MethodDoc *> signals; + Vector<DocData::ConstantDoc *> constants; + Vector<DocData::PropertyDoc *> properties; + Vector<DocData::ThemeItemDoc *> theme_properties; + + bool required() { + return name || methods.size() || signals.size() || constants.size() || properties.size() || theme_properties.size(); + } + }; + + VisualScriptPropertySelector *selector_ui; + Control *ui_service; + Tree *results_tree; + String term; + int search_flags; + int scope_flags; + + Ref<Texture2D> empty_icon; + Color disabled_color; + + Map<String, DocData::ClassDoc>::Element *iterator_doc = nullptr; + Map<String, ClassMatch> matches; + Map<String, ClassMatch>::Element *iterator_match = nullptr; + TreeItem *root_item = nullptr; + Map<String, TreeItem *> class_items; + TreeItem *matched_item = nullptr; + float match_highest_score = 0; + + Map<String, DocData::ClassDoc> combined_docs; + List<String> vs_nodes; + + bool _is_class_disabled_by_feature_profile(const StringName &p_class); + bool _is_class_disabled_by_scope(const StringName &p_class); + + bool _slice(); + bool _phase_init(); + bool _phase_match_classes_init(); + bool _phase_node_classes_init(); + bool _phase_node_classes_build(); + bool _phase_match_classes(); + bool _phase_class_items_init(); + bool _phase_class_items(); + bool _phase_member_items_init(); + bool _phase_member_items(); + bool _phase_select_match(); + + bool _match_string(const String &p_term, const String &p_string) const; + bool _match_visual_script(DocData::ClassDoc &class_doc); + bool _match_is_hidden(DocData::ClassDoc &class_doc); + void _match_item(TreeItem *p_item, const String &p_text); + void _add_class_doc(String class_name, String inherits, String category); + DocData::MethodDoc _get_method_doc(MethodInfo method_info); + TreeItem *_create_class_hierarchy(const ClassMatch &p_match); + TreeItem *_create_class_item(TreeItem *p_parent, const DocData::ClassDoc *p_doc, bool p_gray); + TreeItem *_create_method_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const String &p_text, const DocData::MethodDoc *p_doc); + TreeItem *_create_signal_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::MethodDoc *p_doc); + TreeItem *_create_constant_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::ConstantDoc *p_doc); + TreeItem *_create_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::PropertyDoc *p_doc); + TreeItem *_create_theme_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::ThemeItemDoc *p_doc); + TreeItem *_create_member_item(TreeItem *p_parent, const String &p_class_name, const String &p_icon, const String &p_name, const String &p_text, const String &p_type, const String &p_metatype, const String &p_tooltip, const String &p_description); + +public: + bool work(uint64_t slot = 100000); + + SearchRunner(VisualScriptPropertySelector *p_selector_ui, Tree *p_results_tree); +}; + #endif // VISUALSCRIPT_PROPERTYSELECTOR_H diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp index 99e75f9289..fd55796a66 100644 --- a/modules/visual_script/visual_script_builtin_funcs.cpp +++ b/modules/visual_script/visual_script_builtin_funcs.cpp @@ -964,7 +964,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in return; } - if (p_inputs[0]->is_ref()) { + if (p_inputs[0]->is_ref_counted()) { REF r = *p_inputs[0]; if (!r.is_valid()) { return; diff --git a/modules/webrtc/doc_classes/WebRTCPeerConnection.xml b/modules/webrtc/doc_classes/WebRTCPeerConnection.xml index 618fe14137..2f2c2c379d 100644 --- a/modules/webrtc/doc_classes/WebRTCPeerConnection.xml +++ b/modules/webrtc/doc_classes/WebRTCPeerConnection.xml @@ -33,8 +33,7 @@ <method name="create_data_channel"> <return type="WebRTCDataChannel" /> <argument index="0" name="label" type="String" /> - <argument index="1" name="options" type="Dictionary" default="{ -}" /> + <argument index="1" name="options" type="Dictionary" default="{}" /> <description> Returns a new [WebRTCDataChannel] (or [code]null[/code] on failure) with given [code]label[/code] and optionally configured via the [code]options[/code] dictionary. This method can only be called when the connection is in state [constant STATE_NEW]. There are two ways to create a working data channel: either call [method create_data_channel] on only one of the peer and listen to [signal data_channel_received] on the other, or call [method create_data_channel] on both peers, with the same values, and the [code]negotiated[/code] option set to [code]true[/code]. @@ -70,8 +69,7 @@ </method> <method name="initialize"> <return type="int" enum="Error" /> - <argument index="0" name="configuration" type="Dictionary" default="{ -}" /> + <argument index="0" name="configuration" type="Dictionary" default="{}" /> <description> Re-initialize this peer connection, closing any previously active connection, and going back to state [constant STATE_NEW]. A dictionary of [code]options[/code] can be passed to configure the peer connection. Valid [code]options[/code] are: diff --git a/modules/webrtc/register_types.cpp b/modules/webrtc/register_types.cpp index 54d4f57eef..e6a8dcc31a 100644 --- a/modules/webrtc/register_types.cpp +++ b/modules/webrtc/register_types.cpp @@ -38,11 +38,11 @@ #include "webrtc_peer_connection_extension.h" void register_webrtc_types() { -#define _SET_HINT(NAME, _VAL_, _MAX_) \ - GLOBAL_DEF(NAME, _VAL_); \ +#define SET_HINT(NAME, _VAL_, _MAX_) \ + GLOBAL_DEF(NAME, _VAL_); \ ProjectSettings::get_singleton()->set_custom_property_info(NAME, PropertyInfo(Variant::INT, NAME, PROPERTY_HINT_RANGE, "2," #_MAX_ ",1,or_greater")); - _SET_HINT(WRTC_IN_BUF, 64, 4096); + SET_HINT(WRTC_IN_BUF, 64, 4096); ClassDB::register_custom_instance_class<WebRTCPeerConnection>(); GDREGISTER_CLASS(WebRTCPeerConnectionExtension); @@ -51,6 +51,8 @@ void register_webrtc_types() { GDREGISTER_CLASS(WebRTCDataChannelExtension); GDREGISTER_CLASS(WebRTCMultiplayerPeer); + +#undef SET_HINT } void unregister_webrtc_types() {} diff --git a/modules/websocket/wsl_client.cpp b/modules/websocket/wsl_client.cpp index bccbf88417..be1c75c354 100644 --- a/modules/websocket/wsl_client.cpp +++ b/modules/websocket/wsl_client.cpp @@ -124,17 +124,17 @@ bool WSLClient::_verify_headers(String &r_protocol) { } } -#define _WSL_CHECK(NAME, VALUE) \ +#define WSL_CHECK(NAME, VALUE) \ ERR_FAIL_COND_V_MSG(!headers.has(NAME) || headers[NAME].to_lower() != VALUE, false, \ "Missing or invalid header '" + String(NAME) + "'. Expected value '" + VALUE + "'."); -#define _WSL_CHECK_NC(NAME, VALUE) \ +#define WSL_CHECK_NC(NAME, VALUE) \ ERR_FAIL_COND_V_MSG(!headers.has(NAME) || headers[NAME] != VALUE, false, \ "Missing or invalid header '" + String(NAME) + "'. Expected value '" + VALUE + "'."); - _WSL_CHECK("connection", "upgrade"); - _WSL_CHECK("upgrade", "websocket"); - _WSL_CHECK_NC("sec-websocket-accept", WSLPeer::compute_key_response(_key)); -#undef _WSL_CHECK_NC -#undef _WSL_CHECK + WSL_CHECK("connection", "upgrade"); + WSL_CHECK("upgrade", "websocket"); + WSL_CHECK_NC("sec-websocket-accept", WSLPeer::compute_key_response(_key)); +#undef WSL_CHECK_NC +#undef WSL_CHECK if (_protocols.size() == 0) { // We didn't request a custom protocol ERR_FAIL_COND_V(headers.has("sec-websocket-protocol"), false); diff --git a/modules/websocket/wsl_server.cpp b/modules/websocket/wsl_server.cpp index 31175c5779..eadd7ef7ac 100644 --- a/modules/websocket/wsl_server.cpp +++ b/modules/websocket/wsl_server.cpp @@ -58,17 +58,17 @@ bool WSLServer::PendingPeer::_parse_request(const Vector<String> p_protocols, St headers[name] = value; } } -#define _WSL_CHECK(NAME, VALUE) \ +#define WSL_CHECK(NAME, VALUE) \ ERR_FAIL_COND_V_MSG(!headers.has(NAME) || headers[NAME].to_lower() != VALUE, false, \ "Missing or invalid header '" + String(NAME) + "'. Expected value '" + VALUE + "'."); -#define _WSL_CHECK_EX(NAME) \ +#define WSL_CHECK_EX(NAME) \ ERR_FAIL_COND_V_MSG(!headers.has(NAME), false, "Missing header '" + String(NAME) + "'."); - _WSL_CHECK("upgrade", "websocket"); - _WSL_CHECK("sec-websocket-version", "13"); - _WSL_CHECK_EX("sec-websocket-key"); - _WSL_CHECK_EX("connection"); -#undef _WSL_CHECK_EX -#undef _WSL_CHECK + WSL_CHECK("upgrade", "websocket"); + WSL_CHECK("sec-websocket-version", "13"); + WSL_CHECK_EX("sec-websocket-key"); + WSL_CHECK_EX("connection"); +#undef WSL_CHECK_EX +#undef WSL_CHECK key = headers["sec-websocket-key"]; if (headers.has("sec-websocket-protocol")) { Vector<String> protos = headers["sec-websocket-protocol"].split(","); diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index 941cf9fd53..15f61db27c 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -95,6 +95,17 @@ String DisplayServerAndroid::clipboard_get() const { } } +bool DisplayServerAndroid::clipboard_has() const { + GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java(); + ERR_FAIL_COND_V(!godot_java, false); + + if (godot_java->has_has_clipboard()) { + return godot_java->has_clipboard(); + } else { + return DisplayServer::clipboard_has(); + } +} + void DisplayServerAndroid::screen_set_keep_on(bool p_enable) { GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java(); ERR_FAIL_COND(!godot_java); diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h index 8538b6e660..6aadc7e1a9 100644 --- a/platform/android/display_server_android.h +++ b/platform/android/display_server_android.h @@ -93,6 +93,7 @@ public: virtual void clipboard_set(const String &p_text) override; virtual String clipboard_get() const override; + virtual bool clipboard_has() const override; virtual void screen_set_keep_on(bool p_enable) override; virtual bool screen_is_kept_on() const override; diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java index 3fbbd8fbcc..78848c109a 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java @@ -660,10 +660,14 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC } } + public boolean hasClipboard() { + return mClipboard.hasPrimaryClip(); + } + public String getClipboard() { String copiedText = ""; - if (mClipboard.getPrimaryClip() != null) { + if (mClipboard.hasPrimaryClip()) { ClipData.Item item = mClipboard.getPrimaryClip().getItemAt(0); copiedText = item.getText().toString(); } diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp index 115264d7ee..5beec6b611 100644 --- a/platform/android/java_godot_wrapper.cpp +++ b/platform/android/java_godot_wrapper.cpp @@ -66,6 +66,7 @@ GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_ _get_GLES_version_code = p_env->GetMethodID(godot_class, "getGLESVersionCode", "()I"); _get_clipboard = p_env->GetMethodID(godot_class, "getClipboard", "()Ljava/lang/String;"); _set_clipboard = p_env->GetMethodID(godot_class, "setClipboard", "(Ljava/lang/String;)V"); + _has_clipboard = p_env->GetMethodID(godot_class, "hasClipboard", "()Z"); _request_permission = p_env->GetMethodID(godot_class, "requestPermission", "(Ljava/lang/String;)Z"); _request_permissions = p_env->GetMethodID(godot_class, "requestPermissions", "()Z"); _get_granted_permissions = p_env->GetMethodID(godot_class, "getGrantedPermissions", "()[Ljava/lang/String;"); @@ -248,6 +249,21 @@ void GodotJavaWrapper::set_clipboard(const String &p_text) { } } +bool GodotJavaWrapper::has_has_clipboard() { + return _has_clipboard != 0; +} + +bool GodotJavaWrapper::has_clipboard() { + if (_has_clipboard) { + JNIEnv *env = get_jni_env(); + ERR_FAIL_COND_V(env == nullptr, false); + + return env->CallBooleanMethod(godot_instance, _has_clipboard); + } else { + return false; + } +} + bool GodotJavaWrapper::request_permission(const String &p_name) { if (_request_permission) { JNIEnv *env = get_jni_env(); diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h index 4d058ac426..42ae91480f 100644 --- a/platform/android/java_godot_wrapper.h +++ b/platform/android/java_godot_wrapper.h @@ -58,6 +58,7 @@ private: jmethodID _get_GLES_version_code = 0; jmethodID _get_clipboard = 0; jmethodID _set_clipboard = 0; + jmethodID _has_clipboard = 0; jmethodID _request_permission = 0; jmethodID _request_permissions = 0; jmethodID _get_granted_permissions = 0; @@ -92,6 +93,8 @@ public: String get_clipboard(); bool has_set_clipboard(); void set_clipboard(const String &p_text); + bool has_has_clipboard(); + bool has_clipboard(); bool request_permission(const String &p_name); bool request_permissions(); Vector<String> get_granted_permissions() const; diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index b57f3b3f16..b6be44fbb2 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -89,10 +89,10 @@ def configure(env): if env["tools"]: if not env["threads_enabled"]: - print("Threads must be enabled to build the editor. Please add the 'threads_enabled=yes' option") - sys.exit(255) + print('Note: Forcing "threads_enabled=yes" as it is required for the web editor.') + env["threads_enabled"] = "yes" if env["initial_memory"] < 64: - print("Editor build requires at least 64MiB of initial memory. Forcing it.") + print('Note: Forcing "initial_memory=64" as it is required for the web editor.') env["initial_memory"] = 64 env.Append(CCFLAGS=["-frtti"]) elif env["builtin_icu"]: diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp index e7564a599c..2842fc2f5e 100644 --- a/platform/javascript/display_server_javascript.cpp +++ b/platform/javascript/display_server_javascript.cpp @@ -137,7 +137,6 @@ int DisplayServerJavaScript::mouse_button_callback(int p_pressed, int p_button, DisplayServerJavaScript *ds = get_singleton(); Point2 pos(p_x, p_y); - Input::get_singleton()->set_mouse_position(pos); Ref<InputEventMouseButton> ev; ev.instantiate(); ev->set_position(pos); @@ -219,7 +218,6 @@ void DisplayServerJavaScript::mouse_move_callback(double p_x, double p_y, double } Point2 pos(p_x, p_y); - Input::get_singleton()->set_mouse_position(pos); Ref<InputEventMouseMotion> ev; ev.instantiate(); dom2godot_mod(ev, p_modifiers); @@ -229,7 +227,6 @@ void DisplayServerJavaScript::mouse_move_callback(double p_x, double p_y, double ev->set_global_position(pos); ev->set_relative(Vector2(p_rel_x, p_rel_y)); - Input::get_singleton()->set_mouse_position(ev->get_position()); ev->set_velocity(Input::get_singleton()->get_last_mouse_velocity()); Input::get_singleton()->parse_input_event(ev); diff --git a/platform/javascript/http_client_javascript.cpp b/platform/javascript/http_client_javascript.cpp index 57416ebe48..45aa68ce7c 100644 --- a/platform/javascript/http_client_javascript.cpp +++ b/platform/javascript/http_client_javascript.cpp @@ -143,7 +143,7 @@ Error HTTPClientJavaScript::get_response_headers(List<String> *r_response) { return OK; } -int HTTPClientJavaScript::get_response_body_length() const { +int64_t HTTPClientJavaScript::get_response_body_length() const { return godot_js_fetch_body_length_get(js_id); } diff --git a/platform/javascript/http_client_javascript.h b/platform/javascript/http_client_javascript.h index d8f23fe694..096aa6a153 100644 --- a/platform/javascript/http_client_javascript.h +++ b/platform/javascript/http_client_javascript.h @@ -95,7 +95,7 @@ public: bool is_response_chunked() const override; int get_response_code() const override; Error get_response_headers(List<String> *r_response) override; - int get_response_body_length() const override; + int64_t get_response_body_length() const override; PackedByteArray read_response_body_chunk() override; void set_blocking_mode(bool p_enable) override; bool is_blocking_mode_enabled() const override; diff --git a/platform/javascript/package-lock.json b/platform/javascript/package-lock.json index 1bc11c7ccf..35f864f01a 100644 --- a/platform/javascript/package-lock.json +++ b/platform/javascript/package-lock.json @@ -1,8 +1,3009 @@ { "name": "godot", "version": "1.0.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "godot", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "eslint": "^7.28.0", + "eslint-config-airbnb-base": "^14.2.1", + "eslint-plugin-import": "^2.23.4", + "jsdoc": "^3.6.7", + "serve": "^13.0.2" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", + "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.5.tgz", + "integrity": "sha512-TM8C+xtH/9n1qzX+JNHi7AN2zHMTiPUtspO0ZdHflW8KaskkALhMmuMHb4bCmNdv9VAPzJX3/bXqkVLnAvsPfg==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz", + "integrity": "sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "node_modules/@zeit/schemas": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.6.0.tgz", + "integrity": "sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/arg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arg/-/arg-2.0.0.tgz", + "integrity": "sha512-XxNTUzKnz1ctK3ZIcI2XUPlD96wbHP2nGqkPKpvk/HNRlPveYrXIVSTk9m3LcqOgDPg3B1nMvdV/K8wZd7PG4w==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-includes": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", + "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", + "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/chalk/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/chalk/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clipboardy": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", + "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", + "dev": true, + "dependencies": { + "arch": "^2.1.1", + "execa": "^1.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz", + "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.14", + "debug": "2.6.9", + "on-headers": "~1.0.1", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz", + "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", + "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.3", + "is-string": "^1.0.6", + "object-inspect": "^1.10.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.28.0.tgz", + "integrity": "sha512-UMfH0VSjP0G4p3EWirscJEQ/cHqnT/iuH6oNZOB94nBjWbMnhGEPxsZm1eyIW0C/9jLI0Fow4W5DXLjEI7mn1g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-airbnb-base": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz", + "integrity": "sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA==", + "dev": true, + "dependencies": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.2" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "eslint": "^5.16.0 || ^6.8.0 || ^7.2.0", + "eslint-plugin-import": "^2.22.1" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "dev": true, + "dependencies": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/eslint-module-utils": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz", + "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "pkg-dir": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.23.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz", + "integrity": "sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.3", + "array.prototype.flat": "^1.2.4", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.4", + "eslint-module-utils": "^2.6.1", + "find-up": "^2.0.0", + "has": "^1.0.3", + "is-core-module": "^2.4.0", + "minimatch": "^3.0.4", + "object.values": "^1.1.3", + "pkg-up": "^2.0.0", + "read-pkg-up": "^3.0.0", + "resolve": "^1.20.0", + "tsconfig-paths": "^3.9.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/execa/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/execa/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/execa/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/execa/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=", + "dev": true, + "dependencies": { + "punycode": "^1.3.2" + } + }, + "node_modules/fast-url-parser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz", + "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", + "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", + "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", + "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-string": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", + "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js2xmlparser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.1.tgz", + "integrity": "sha512-KrPTolcw6RocpYjdC7pL7v62e55q7qOMHvLX1UCLc5AAS8qeJ6nukarEJAF2KL2PZxlbGueEbINqZR2bDe/gUw==", + "dev": true, + "dependencies": { + "xmlcreate": "^2.0.3" + } + }, + "node_modules/jsdoc": { + "version": "3.6.7", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.7.tgz", + "integrity": "sha512-sxKt7h0vzCd+3Y81Ey2qinupL6DpRSZJclS04ugHDNmRUXGzqicMJ6iwayhSA0S0DwwX30c5ozyUthr1QKF6uw==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.9.4", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.1", + "klaw": "^3.0.0", + "markdown-it": "^10.0.0", + "markdown-it-anchor": "^5.2.7", + "marked": "^2.0.3", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "taffydb": "2.6.2", + "underscore": "~1.13.1" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=8.15.0" + } + }, + "node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/markdown-it": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", + "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "entities": "~2.0.0", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it-anchor": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", + "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", + "dev": true, + "peerDependencies": { + "markdown-it": "*" + } + }, + "node_modules/marked": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/marked/-/marked-2.0.7.tgz", + "integrity": "sha512-BJXxkuIfJchcXOJWTT2DOL+yFWifFv2yGYOUzvXg8Qz610QKw+sHCvTMYwA+qWGhlA2uivBezChZ/pBy1tWdkQ==", + "dev": true, + "bin": { + "marked": "bin/marked" + }, + "engines": { + "node": ">= 8.16.2" + } + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "node_modules/mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "dev": true, + "dependencies": { + "mime-db": "1.51.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/object-inspect": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", + "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.4.tgz", + "integrity": "sha512-h4LWKWE+wKQGhtMjZEBud7uLGhqyLwj8fpHOarZhD2uY3C9cRtk57VQ89ke3moByLXMedqs3XCHzyb4AmA2DjA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz", + "integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "dependencies": { + "find-up": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", + "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", + "dev": true, + "dependencies": { + "find-up": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "dependencies": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dev": true, + "dependencies": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "dependencies": { + "rc": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requizzle": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", + "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serve": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/serve/-/serve-13.0.2.tgz", + "integrity": "sha512-71R6fKvNgKrqARAag6lYJNnxDzpH7DCNrMuvPY5PLVaC2PDhJsGTj/34o4o4tPWhTuLgEXqvgnAWbATQ9zGZTQ==", + "dev": true, + "dependencies": { + "@zeit/schemas": "2.6.0", + "ajv": "6.12.6", + "arg": "2.0.0", + "boxen": "5.1.2", + "chalk": "2.4.1", + "clipboardy": "2.3.0", + "compression": "1.7.3", + "serve-handler": "6.1.3", + "update-check": "1.5.2" + }, + "bin": { + "serve": "bin/serve.js" + } + }, + "node_modules/serve-handler": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz", + "integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==", + "dev": true, + "dependencies": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.0.4", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" + } + }, + "node_modules/serve-handler/node_modules/mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-handler/node_modules/mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "dependencies": { + "mime-db": "~1.33.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve/node_modules/chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/serve/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", + "dev": true + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", + "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", + "dev": true + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/table": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", + "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.0.tgz", + "integrity": "sha512-cnUG4NSBiM4YFBxgZIj/In3/6KX+rQ2l2YPRVcvAMQGWEPKuXoPIhxzwqh31jA3IPbI4qEOp/5ILI4ynioXsGQ==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", + "dev": true + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "node_modules/unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/underscore": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", + "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==", + "dev": true + }, + "node_modules/update-check": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.2.tgz", + "integrity": "sha512-1TrmYLuLj/5ZovwUS7fFd1jMH3NnFDN1y1A8dboedIDt7zs/zJMo6TwwlhYKkSeEwzleeiSBV5/3c9ufAQWDaQ==", + "dev": true, + "dependencies": { + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/xmlcreate": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz", + "integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + }, "dependencies": { "@babel/code-frame": { "version": "7.12.11", @@ -78,6 +3079,22 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@zeit/schemas": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.6.0.tgz", + "integrity": "sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg==", + "dev": true + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, "acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -88,7 +3105,8 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true + "dev": true, + "requires": {} }, "ajv": { "version": "6.12.6", @@ -102,6 +3120,15 @@ "uri-js": "^4.2.2" } }, + "ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "requires": { + "string-width": "^4.1.0" + } + }, "ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -123,6 +3150,18 @@ "color-convert": "^1.9.0" } }, + "arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true + }, + "arg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arg/-/arg-2.0.0.tgz", + "integrity": "sha512-XxNTUzKnz1ctK3ZIcI2XUPlD96wbHP2nGqkPKpvk/HNRlPveYrXIVSTk9m3LcqOgDPg3B1nMvdV/K8wZd7PG4w==", + "dev": true + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -174,6 +3213,22 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, + "boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -184,6 +3239,12 @@ "concat-map": "0.0.1" } }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -200,6 +3261,12 @@ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, "catharsis": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", @@ -260,6 +3327,23 @@ } } }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true + }, + "clipboardy": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", + "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", + "dev": true, + "requires": { + "arch": "^2.1.1", + "execa": "^1.0.0", + "is-wsl": "^2.1.1" + } + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -275,6 +3359,47 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz", + "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.14", + "debug": "2.6.9", + "on-headers": "~1.0.1", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -287,6 +3412,12 @@ "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", "dev": true }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "dev": true + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -307,6 +3438,12 @@ "ms": "2.1.2" } }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -337,6 +3474,15 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, "enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", @@ -661,6 +3807,72 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -679,6 +3891,23 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=", + "dev": true, + "requires": { + "punycode": "^1.3.2" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -742,6 +3971,15 @@ "has-symbols": "^1.0.1" } }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "glob": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", @@ -851,6 +4089,12 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -893,6 +4137,12 @@ "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", "dev": true }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -936,6 +4186,12 @@ "has-symbols": "^1.0.2" } }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, "is-string": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", @@ -951,6 +4207,15 @@ "has-symbols": "^1.0.2" } }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1139,7 +4404,8 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", - "dev": true + "dev": true, + "requires": {} }, "marked": { "version": "2.0.7", @@ -1153,6 +4419,21 @@ "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", "dev": true }, + "mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "dev": true + }, + "mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "dev": true, + "requires": { + "mime-db": "1.51.0" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -1186,6 +4467,18 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -1206,6 +4499,23 @@ } } }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + }, + "dependencies": { + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + } + } + }, "object-inspect": { "version": "1.10.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", @@ -1252,6 +4562,12 @@ "es-abstract": "^1.18.2" } }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1275,6 +4591,12 @@ "word-wrap": "^1.2.3" } }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -1330,6 +4652,12 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -1342,6 +4670,12 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", + "dev": true + }, "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", @@ -1387,12 +4721,48 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + } + } + }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -1420,6 +4790,25 @@ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, + "registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dev": true, + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "requires": { + "rc": "^1.0.1" + } + }, "require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -1460,6 +4849,12 @@ "glob": "^7.1.3" } }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", @@ -1469,6 +4864,75 @@ "lru-cache": "^6.0.0" } }, + "serve": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/serve/-/serve-13.0.2.tgz", + "integrity": "sha512-71R6fKvNgKrqARAag6lYJNnxDzpH7DCNrMuvPY5PLVaC2PDhJsGTj/34o4o4tPWhTuLgEXqvgnAWbATQ9zGZTQ==", + "dev": true, + "requires": { + "@zeit/schemas": "2.6.0", + "ajv": "6.12.6", + "arg": "2.0.0", + "boxen": "5.1.2", + "chalk": "2.4.1", + "clipboardy": "2.3.0", + "compression": "1.7.3", + "serve-handler": "6.1.3", + "update-check": "1.5.2" + }, + "dependencies": { + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + } + } + }, + "serve-handler": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz", + "integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.0.4", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" + }, + "dependencies": { + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "~1.33.0" + } + } + } + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -1484,6 +4948,12 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "signal-exit": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", + "dev": true + }, "slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", @@ -1605,6 +5075,12 @@ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -1717,6 +5193,16 @@ "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==", "dev": true }, + "update-check": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.2.tgz", + "integrity": "sha512-1TrmYLuLj/5ZovwUS7fFd1jMH3NnFDN1y1A8dboedIDt7zs/zJMo6TwwlhYKkSeEwzleeiSBV5/3c9ufAQWDaQ==", + "dev": true, + "requires": { + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0" + } + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -1742,6 +5228,12 @@ "spdx-expression-parse": "^3.0.0" } }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -1764,12 +5256,58 @@ "is-symbol": "^1.0.3" } }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "requires": { + "string-width": "^4.0.0" + } + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/platform/javascript/package.json b/platform/javascript/package.json index 9dafae30c5..2ff1544837 100644 --- a/platform/javascript/package.json +++ b/platform/javascript/package.json @@ -2,9 +2,8 @@ "name": "godot", "private": true, "version": "1.0.0", - "description": "Linting setup for Godot's HTML5 platform code", + "description": "Development and linting setup for Godot's HTML5 platform code", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", "docs": "jsdoc --template js/jsdoc2rst/ js/engine/engine.js js/engine/config.js --destination ''", "lint": "npm run lint:engine && npm run lint:libs && npm run lint:modules && npm run lint:tools", "lint:engine": "eslint \"js/engine/*.js\" --no-eslintrc -c .eslintrc.engine.js", @@ -15,7 +14,8 @@ "format:engine": "npm run lint:engine -- --fix", "format:libs": "npm run lint:libs -- --fix", "format:modules": "npm run lint:modules -- --fix", - "format:tools": "npm run lint:tools -- --fix" + "format:tools": "npm run lint:tools -- --fix", + "serve": "serve" }, "author": "Godot Engine contributors", "license": "MIT", @@ -23,6 +23,7 @@ "eslint": "^7.28.0", "eslint-config-airbnb-base": "^14.2.1", "eslint-plugin-import": "^2.23.4", - "jsdoc": "^3.6.7" + "jsdoc": "^3.6.7", + "serve": "^13.0.2" } } diff --git a/platform/javascript/serve.json b/platform/javascript/serve.json new file mode 100644 index 0000000000..f2ef24751f --- /dev/null +++ b/platform/javascript/serve.json @@ -0,0 +1,21 @@ +{ + "public": "../../bin", + "headers": [{ + "source": "**/*", + "headers": [ + { + "key": "Cross-Origin-Embedder-Policy", + "value": "require-corp" + }, { + "key": "Cross-Origin-Opener-Policy", + "value": "same-origin" + }, { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, { + "key": "Cache-Control", + "value": "no-store, max-age=0" + } + ] + }] +} diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index c4f7a3a646..0ce627ca4f 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -64,7 +64,6 @@ // EWMH #define _NET_WM_STATE_REMOVE 0L // remove/unset property #define _NET_WM_STATE_ADD 1L // add/set property -#define _NET_WM_STATE_TOGGLE 2L // toggle property #include <dlfcn.h> #include <fcntl.h> @@ -365,21 +364,6 @@ void DisplayServerX11::mouse_warp_to_position(const Point2i &p_to) { } Point2i DisplayServerX11::mouse_get_position() const { - int root_x, root_y; - int win_x, win_y; - unsigned int mask_return; - Window window_returned; - - Bool result = XQueryPointer(x11_display, RootWindow(x11_display, DefaultScreen(x11_display)), &window_returned, - &window_returned, &root_x, &root_y, &win_x, &win_y, - &mask_return); - if (result == True) { - return Point2i(root_x, root_y); - } - return Point2i(); -} - -Point2i DisplayServerX11::mouse_get_absolute_position() const { int number_of_screens = XScreenCount(x11_display); for (int i = 0; i < number_of_screens; i++) { Window root, child; @@ -3647,7 +3631,6 @@ void DisplayServerX11::process_events() { mm->set_button_mask((MouseButton)mouse_get_button_state()); mm->set_position(pos); mm->set_global_position(pos); - Input::get_singleton()->set_mouse_position(pos); mm->set_velocity(Input::get_singleton()->get_last_mouse_velocity()); mm->set_relative(rel); diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index 1dcedabb1a..8929f528d6 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -289,7 +289,6 @@ public: virtual void mouse_warp_to_position(const Point2i &p_to) override; virtual Point2i mouse_get_position() const override; - virtual Point2i mouse_get_absolute_position() const override; virtual MouseButton mouse_get_button_state() const override; virtual void clipboard_set(const String &p_text) override; diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h index afc2754b0e..d609a84e50 100644 --- a/platform/osx/display_server_osx.h +++ b/platform/osx/display_server_osx.h @@ -98,6 +98,8 @@ public: NSTimeInterval last_warp = 0; bool ignore_warp = false; + float display_max_scale = 1.f; + Vector<KeyEvent> key_event_buffer; int key_event_pos; @@ -214,7 +216,6 @@ public: virtual void mouse_warp_to_position(const Point2i &p_to) override; virtual Point2i mouse_get_position() const override; - virtual Point2i mouse_get_absolute_position() const override; virtual MouseButton mouse_get_button_state() const override; virtual void clipboard_set(const String &p_text) override; diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm index 52cabfd821..1340aad9b2 100644 --- a/platform/osx/display_server_osx.mm +++ b/platform/osx/display_server_osx.mm @@ -158,12 +158,7 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) { } if (wd.transient_parent != DisplayServerOSX::INVALID_WINDOW_ID) { - DisplayServerOSX::WindowData &pwd = DS_OSX->windows[wd.transient_parent]; - [pwd.window_object makeKeyAndOrderFront:nil]; // Move focus back to parent. DS_OSX->window_set_transient(window_id, DisplayServerOSX::INVALID_WINDOW_ID); - } else if ((window_id != DisplayServerOSX::MAIN_WINDOW_ID) && (DS_OSX->windows.size() == 1)) { - DisplayServerOSX::WindowData &pwd = DS_OSX->windows[DisplayServerOSX::MAIN_WINDOW_ID]; - [pwd.window_object makeKeyAndOrderFront:nil]; // Move focus back to main window if there is no parent or other windows left. } #if defined(GLES3_ENABLED) @@ -321,7 +316,7 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) { CGPoint lMouseWarpPos = { pointOnScreen.x, CGDisplayBounds(CGMainDisplayID()).size.height - pointOnScreen.y }; CGWarpMouseCursorPosition(lMouseWarpPos); } else { - _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]); + _ALLOW_DISCARD_ _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]); Input::get_singleton()->set_mouse_position(wd.mouse_pos); } @@ -792,7 +787,6 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, M mm->set_relative(relativeMotion); _get_key_modifier_state([event modifierFlags], mm); - Input::get_singleton()->set_mouse_position(wd.mouse_pos); Input::get_singleton()->parse_input_event(mm); } @@ -1396,7 +1390,7 @@ inline void sendPanEvent(DisplayServer::WindowID window_id, double dx, double dy double deltaX, deltaY; - _get_mouse_pos(wd, [event locationInWindow]); + _ALLOW_DISCARD_ _get_mouse_pos(wd, [event locationInWindow]); deltaX = [event scrollingDeltaX]; deltaY = [event scrollingDeltaY]; @@ -2001,10 +1995,6 @@ void DisplayServerOSX::mouse_warp_to_position(const Point2i &p_to) { } Point2i DisplayServerOSX::mouse_get_position() const { - return last_mouse_pos; -} - -Point2i DisplayServerOSX::mouse_get_absolute_position() const { _THREAD_SAFE_METHOD_ const NSPoint mouse_pos = [NSEvent mouseLocation]; @@ -2071,10 +2061,8 @@ int DisplayServerOSX::get_screen_count() const { // to convert between OS X native screen coordinates and the ones expected by Godot static bool displays_arrangement_dirty = true; -static bool displays_scale_dirty = true; static void displays_arrangement_changed(CGDirectDisplayID display_id, CGDisplayChangeSummaryFlags flags, void *user_info) { displays_arrangement_dirty = true; - displays_scale_dirty = true; } Point2i DisplayServerOSX::_get_screens_origin() const { @@ -2185,15 +2173,8 @@ float DisplayServerOSX::screen_get_scale(int p_screen) const { float DisplayServerOSX::screen_get_max_scale() const { _THREAD_SAFE_METHOD_ - static float scale = 1.f; - if (displays_scale_dirty) { - int screen_count = get_screen_count(); - for (int i = 0; i < screen_count; i++) { - scale = fmax(scale, screen_get_scale(i)); - } - displays_scale_dirty = false; - } - return scale; + // Note: Do not update max display scale on screen configuration change, existing editor windows can't be rescaled on the fly. + return display_max_scale; } Rect2i DisplayServerOSX::screen_get_usable_rect(int p_screen) const { @@ -2380,8 +2361,24 @@ int DisplayServerOSX::window_get_current_screen(WindowID p_window) const { void DisplayServerOSX::window_set_current_screen(int p_screen, WindowID p_window) { _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + bool was_fullscreen = false; + if (wd.fullscreen) { + // Temporary exit fullscreen mode to move window. + [wd.window_object toggleFullScreen:nil]; + was_fullscreen = true; + } + Point2i wpos = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window)); window_set_position(wpos + screen_get_position(p_screen), p_window); + + if (was_fullscreen) { + // Re-enter fullscreen mode. + [wd.window_object toggleFullScreen:nil]; + } } void DisplayServerOSX::window_set_transient(WindowID p_window, WindowID p_parent) { @@ -2404,7 +2401,7 @@ void DisplayServerOSX::window_set_transient(WindowID p_window, WindowID p_parent wd_window.transient_parent = INVALID_WINDOW_ID; wd_parent.transient_children.erase(p_window); - [wd_parent.window_object removeChildWindow:wd_window.window_object]; + [wd_window.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; } else { ERR_FAIL_COND(!windows.has(p_parent)); ERR_FAIL_COND_MSG(wd_window.transient_parent != INVALID_WINDOW_ID, "Window already has a transient parent"); @@ -2413,7 +2410,7 @@ void DisplayServerOSX::window_set_transient(WindowID p_window, WindowID p_parent wd_window.transient_parent = p_parent; wd_parent.transient_children.insert(p_window); - [wd_parent.window_object addChildWindow:wd_window.window_object ordered:NSWindowAbove]; + [wd_window.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary]; } } @@ -2423,7 +2420,9 @@ Point2i DisplayServerOSX::window_get_position(WindowID p_window) const { ERR_FAIL_COND_V(!windows.has(p_window), Point2i()); const WindowData &wd = windows[p_window]; - NSRect nsrect = [wd.window_object frame]; + // Use content rect position (without titlebar / window border). + const NSRect contentRect = [wd.window_view frame]; + const NSRect nsrect = [wd.window_object convertRectToScreen:contentRect]; Point2i pos; // Return the position of the top-left corner, for OS X the y starts at the bottom @@ -2451,10 +2450,19 @@ void DisplayServerOSX::window_set_position(const Point2i &p_position, WindowID p position += _get_screens_origin(); position /= screen_get_max_scale(); - [wd.window_object setFrameTopLeftPoint:NSMakePoint(position.x, position.y)]; + // Remove titlebar / window border size. + const NSRect contentRect = [wd.window_view frame]; + const NSRect windowRect = [wd.window_object frame]; + const NSRect nsrect = [wd.window_object convertRectToScreen:contentRect]; + Point2i offset; + offset.x = (nsrect.origin.x - windowRect.origin.x); + offset.y = (nsrect.origin.y + nsrect.size.height); + offset.y -= (windowRect.origin.y + windowRect.size.height); + + [wd.window_object setFrameTopLeftPoint:NSMakePoint(position.x - offset.x, position.y - offset.y)]; _update_window(wd); - _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]); + _ALLOW_DISCARD_ _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]); } void DisplayServerOSX::window_set_max_size(const Size2i p_size, WindowID p_window) { @@ -3699,7 +3707,11 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode keyboard_layout_dirty = true; displays_arrangement_dirty = true; - displays_scale_dirty = true; + + int screen_count = get_screen_count(); + for (int i = 0; i < screen_count; i++) { + display_max_scale = fmax(display_max_scale, screen_get_scale(i)); + } // Register to be notified on keyboard layout changes CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), diff --git a/platform/osx/export/export_plugin.cpp b/platform/osx/export/export_plugin.cpp index 0a213fd19b..4d1f72f5c9 100644 --- a/platform/osx/export/export_plugin.cpp +++ b/platform/osx/export/export_plugin.cpp @@ -47,6 +47,23 @@ void EditorExportPlatformOSX::get_preset_features(const Ref<EditorExportPreset> r_features->push_back("64"); } +bool EditorExportPlatformOSX::get_export_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { + // These options are not supported by built-in codesign, used on non macOS host. + if (!OS::get_singleton()->has_feature("macos")) { + if (p_option == "codesign/identity" || p_option == "codesign/timestamp" || p_option == "codesign/hardened_runtime" || p_option == "codesign/custom_options" || p_option.begins_with("notarization/")) { + return false; + } + } + + // These entitlements are required to run managed code, and are always enabled in Mono builds. + if (Engine::get_singleton()->has_singleton("GodotSharp")) { + if (p_option == "codesign/entitlements/allow_jit_code_execution" || p_option == "codesign/entitlements/allow_unsigned_executable_memory" || p_option == "codesign/entitlements/allow_dyld_environment_variables") { + return false; + } + } + return true; +} + void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options) { r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); @@ -74,20 +91,15 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/removable_volumes_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use removable volumes"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), true)); -#ifdef OSX_ENABLED r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_PLACEHOLDER_TEXT, "Type: Name (ID)"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/timestamp"), true)); -#endif r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/replace_existing_signature"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/hardened_runtime"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/entitlements/custom_file", PROPERTY_HINT_GLOBAL_FILE, "*.plist"), "")); - if (!Engine::get_singleton()->has_singleton("GodotSharp")) { - // These entitlements are required to run managed code, and are always enabled in Mono builds. - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_jit_code_execution"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_unsigned_executable_memory"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_dyld_environment_variables"), false)); - } + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_jit_code_execution"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_unsigned_executable_memory"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_dyld_environment_variables"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/disable_library_validation"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/audio_input"), false)); @@ -110,14 +122,12 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_movies", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0)); r_options->push_back(ExportOption(PropertyInfo(Variant::ARRAY, "codesign/entitlements/app_sandbox/helper_executables", PROPERTY_HINT_ARRAY_TYPE, itos(Variant::STRING) + "/" + itos(PROPERTY_HINT_GLOBAL_FILE) + ":"), Array())); -#ifdef OSX_ENABLED r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray())); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "notarization/enable"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_id_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Apple ID email"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_id_password", PROPERTY_HINT_PLACEHOLDER_TEXT, "Enable two-factor authentication and provide app-specific password"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_team_id", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide team ID if your Apple ID belongs to multiple teams"), "")); -#endif r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/s3tc"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false)); @@ -443,12 +453,15 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese if ((!FileAccess::exists("/usr/bin/codesign") && !FileAccess::exists("/bin/codesign")) || force_builtin_codesign) { print_verbose("using built-in codesign..."); #ifdef MODULE_REGEX_ENABLED + +#ifdef OSX_ENABLED if (p_preset->get("codesign/timestamp")) { WARN_PRINT("Timestamping is not compatible with ad-hoc signature, and was disabled!"); } if (p_preset->get("codesign/hardened_runtime")) { WARN_PRINT("Hardened Runtime is not compatible with ad-hoc signature, and was disabled!"); } +#endif String error_msg; Error err = CodeSign::codesign(false, p_preset->get("codesign/replace_existing_signature"), p_path, p_ent_path, error_msg); @@ -1170,6 +1183,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p } } +#ifdef OSX_ENABLED bool noto_enabled = p_preset->get("notarization/enable"); if (err == OK && noto_enabled) { if (export_format == "app") { @@ -1181,6 +1195,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p err = _notarize(p_preset, p_path); } } +#endif // Clean up temporary entitlements files. DirAccess::remove_file_or_error(hlp_ent_path); @@ -1355,17 +1370,17 @@ bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset } bool sign_enabled = p_preset->get("codesign/enable"); + +#ifdef OSX_ENABLED bool noto_enabled = p_preset->get("notarization/enable"); bool ad_hoc = ((p_preset->get("codesign/identity") == "") || (p_preset->get("codesign/identity") == "-")); -#ifdef OSX_ENABLED if (!ad_hoc && (bool)EditorSettings::get_singleton()->get("export/macos/force_builtin_codesign")) { err += TTR("Warning: Built-in \"codesign\" is selected in the Editor Settings. Code signing is limited to ad-hoc signature only.") + "\n"; } if (!ad_hoc && !FileAccess::exists("/usr/bin/codesign") && !FileAccess::exists("/bin/codesign")) { err += TTR("Warning: Xcode command line tools are not installed, using built-in \"codesign\". Code signing is limited to ad-hoc signature only.") + "\n"; } -#endif if (noto_enabled) { if (ad_hoc) { @@ -1393,11 +1408,7 @@ bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset valid = false; } } else { -#ifdef OSX_ENABLED err += TTR("Warning: Notarization is disabled. Exported project will be blocked by Gatekeeper, if it's downloaded from an unknown source.") + "\n"; -#else - err += TTR("Warning: Notarization is not supported on this OS. Exported project will be blocked by Gatekeeper, if it's downloaded from an unknown source.") + "\n"; -#endif if (!sign_enabled) { err += TTR("Code signing is disabled. Exported project will not run on Macs with enabled Gatekeeper and Apple Silicon powered Macs.") + "\n"; } else { @@ -1409,6 +1420,12 @@ bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset } } } +#else + err += TTR("Warning: Notarization is not supported on this OS. Exported project will be blocked by Gatekeeper, if it's downloaded from an unknown source.") + "\n"; + if (!sign_enabled) { + err += TTR("Code signing is disabled. Exported project will not run on Macs with enabled Gatekeeper and Apple Silicon powered Macs.") + "\n"; + } +#endif if (sign_enabled) { if ((bool)p_preset->get("codesign/entitlements/audio_input") && ((String)p_preset->get("privacy/microphone_usage_description")).is_empty()) { diff --git a/platform/osx/export/export_plugin.h b/platform/osx/export/export_plugin.h index 85fc72437c..0c2ac90206 100644 --- a/platform/osx/export/export_plugin.h +++ b/platform/osx/export/export_plugin.h @@ -101,6 +101,7 @@ class EditorExportPlatformOSX : public EditorExportPlatform { protected: virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override; virtual void get_export_options(List<ExportOption> *r_options) override; + virtual bool get_export_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; public: virtual String get_name() const override { return "macOS"; } diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 1271e64945..c9e2251b35 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -674,8 +674,20 @@ void DisplayServerWindows::window_set_current_screen(int p_screen, WindowID p_wi ERR_FAIL_COND(!windows.has(p_window)); ERR_FAIL_INDEX(p_screen, get_screen_count()); - Vector2 ofs = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window)); - window_set_position(ofs + screen_get_position(p_screen), p_window); + const WindowData &wd = windows[p_window]; + if (wd.fullscreen) { + int cs = window_get_current_screen(p_window); + if (cs == p_screen) { + return; + } + Point2 pos = screen_get_position(p_screen); + Size2 size = screen_get_size(p_screen); + + MoveWindow(wd.hWnd, pos.x, pos.y, size.width, size.height, TRUE); + } else { + Vector2 ofs = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window)); + window_set_position(ofs + screen_get_position(p_screen), p_window); + } } Point2i DisplayServerWindows::window_get_position(WindowID p_window) const { @@ -2060,7 +2072,6 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mm->set_position(c); mm->set_global_position(c); - Input::get_singleton()->set_mouse_position(c); mm->set_velocity(Vector2(0, 0)); if (raw->data.mouse.usFlags == MOUSE_MOVE_RELATIVE) { @@ -2165,7 +2176,6 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA SetCursorPos(pos.x, pos.y); } - Input::get_singleton()->set_mouse_position(mm->get_position()); mm->set_velocity(Input::get_singleton()->get_last_mouse_velocity()); if (old_invalid) { @@ -2307,7 +2317,6 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA SetCursorPos(pos.x, pos.y); } - Input::get_singleton()->set_mouse_position(mm->get_position()); mm->set_velocity(Input::get_singleton()->get_last_mouse_velocity()); if (old_invalid) { @@ -2408,7 +2417,6 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA SetCursorPos(pos.x, pos.y); } - Input::get_singleton()->set_mouse_position(mm->get_position()); mm->set_velocity(Input::get_singleton()->get_last_mouse_velocity()); if (old_invalid) { diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp index 02b2d026b5..68762db3a9 100644 --- a/platform/windows/export/export_plugin.cpp +++ b/platform/windows/export/export_plugin.cpp @@ -54,13 +54,19 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> return err; } +bool EditorExportPlatformWindows::get_export_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { + // This option is not supported by "osslsigncode", used on non-Windows host. + if (!OS::get_singleton()->has_feature("windows") && p_option == "codesign/identity_type") { + return false; + } + return true; +} + void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_options) { EditorExportPlatformPC::get_export_options(r_options); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), false)); -#ifdef WINDOWS_ENABLED r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/identity_type", PROPERTY_HINT_ENUM, "Select automatically,Use PKCS12 file (specify *.PFX/*.P12 file),Use certificate store (specify SHA1 hash)"), 0)); -#endif r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_GLOBAL_FILE, "*.pfx,*.p12"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/password"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/timestamp"), true)); diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h index 4ec9342cdf..351333aa42 100644 --- a/platform/windows/export/export_plugin.h +++ b/platform/windows/export/export_plugin.h @@ -43,9 +43,10 @@ class EditorExportPlatformWindows : public EditorExportPlatformPC { Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path); public: - virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0); - virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path); - virtual void get_export_options(List<ExportOption> *r_options); + virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override; + virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) override; + virtual void get_export_options(List<ExportOption> *r_options) override; + virtual bool get_export_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; }; #endif diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 9331340e1b..9d26543243 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -413,7 +413,7 @@ void Node2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_relative_transform_to_parent", "parent"), &Node2D::get_relative_transform_to_parent); ADD_GROUP("Transform", ""); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_RANGE, "-99999,99999,0,or_lesser,or_greater,noslider,suffix:px"), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_lesser,or_greater,noslider,suffix:px"), "set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians"), "set_rotation", "get_rotation"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "skew", PROPERTY_HINT_RANGE, "-89.9,89.9,0.1,radians"), "set_skew", "get_skew"); diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index b2cc8164b6..01fa109384 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -1162,7 +1162,7 @@ bool CharacterBody2D::move_and_slide() { if (motion_mode == MOTION_MODE_GROUNDED) { _move_and_slide_grounded(delta, was_on_floor); } else { - _move_and_slide_free(delta); + _move_and_slide_floating(delta); } // Compute real velocity. @@ -1350,7 +1350,7 @@ void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo } } -void CharacterBody2D::_move_and_slide_free(double p_delta) { +void CharacterBody2D::_move_and_slide_floating(double p_delta) { Vector2 motion = motion_velocity * p_delta; platform_rid = RID(); @@ -1376,7 +1376,7 @@ void CharacterBody2D::_move_and_slide_free(double p_delta) { break; } - if (free_mode_min_slide_angle != 0 && result.get_angle(-motion_velocity.normalized()) < free_mode_min_slide_angle + FLOOR_ANGLE_THRESHOLD) { + if (wall_min_slide_angle != 0 && result.get_angle(-motion_velocity.normalized()) < wall_min_slide_angle + FLOOR_ANGLE_THRESHOLD) { motion = Vector2(); } else if (first_slide) { Vector2 motion_slide_norm = result.remainder.slide(result.collision_normal).normalized(); @@ -1668,12 +1668,12 @@ void CharacterBody2D::set_floor_snap_length(real_t p_floor_snap_length) { floor_snap_length = p_floor_snap_length; } -real_t CharacterBody2D::get_free_mode_min_slide_angle() const { - return free_mode_min_slide_angle; +real_t CharacterBody2D::get_wall_min_slide_angle() const { + return wall_min_slide_angle; } -void CharacterBody2D::set_free_mode_min_slide_angle(real_t p_radians) { - free_mode_min_slide_angle = p_radians; +void CharacterBody2D::set_wall_min_slide_angle(real_t p_radians) { + wall_min_slide_angle = p_radians; } const Vector2 &CharacterBody2D::get_up_direction() const { @@ -1681,7 +1681,7 @@ const Vector2 &CharacterBody2D::get_up_direction() const { } void CharacterBody2D::set_up_direction(const Vector2 &p_up_direction) { - ERR_FAIL_COND_MSG(p_up_direction == Vector2(), "up_direction can't be equal to Vector2.ZERO, consider using Free motion mode instead."); + ERR_FAIL_COND_MSG(p_up_direction == Vector2(), "up_direction can't be equal to Vector2.ZERO, consider using Floating motion mode instead."); up_direction = p_up_direction.normalized(); } @@ -1728,8 +1728,8 @@ void CharacterBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_floor_max_angle", "radians"), &CharacterBody2D::set_floor_max_angle); ClassDB::bind_method(D_METHOD("get_floor_snap_length"), &CharacterBody2D::get_floor_snap_length); ClassDB::bind_method(D_METHOD("set_floor_snap_length", "floor_snap_length"), &CharacterBody2D::set_floor_snap_length); - ClassDB::bind_method(D_METHOD("get_free_mode_min_slide_angle"), &CharacterBody2D::get_free_mode_min_slide_angle); - ClassDB::bind_method(D_METHOD("set_free_mode_min_slide_angle", "radians"), &CharacterBody2D::set_free_mode_min_slide_angle); + ClassDB::bind_method(D_METHOD("get_wall_min_slide_angle"), &CharacterBody2D::get_wall_min_slide_angle); + ClassDB::bind_method(D_METHOD("set_wall_min_slide_angle", "radians"), &CharacterBody2D::set_wall_min_slide_angle); ClassDB::bind_method(D_METHOD("get_up_direction"), &CharacterBody2D::get_up_direction); ClassDB::bind_method(D_METHOD("set_up_direction", "up_direction"), &CharacterBody2D::set_up_direction); ClassDB::bind_method(D_METHOD("set_motion_mode", "mode"), &CharacterBody2D::set_motion_mode); @@ -1754,14 +1754,12 @@ void CharacterBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &CharacterBody2D::_get_slide_collision); ClassDB::bind_method(D_METHOD("get_last_slide_collision"), &CharacterBody2D::_get_last_slide_collision); - ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Free", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Floating", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "up_direction"), "set_up_direction", "get_up_direction"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion_velocity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_motion_velocity", "get_motion_velocity"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_ceiling"), "set_slide_on_ceiling_enabled", "is_slide_on_ceiling_enabled"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_slides", "get_max_slides"); - - ADD_GROUP("Free Mode", "free_mode_"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "free_mode_min_slide_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians", PROPERTY_USAGE_DEFAULT), "set_free_mode_min_slide_angle", "get_free_mode_min_slide_angle"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wall_min_slide_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians", PROPERTY_USAGE_DEFAULT), "set_wall_min_slide_angle", "get_wall_min_slide_angle"); ADD_GROUP("Floor", "floor_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_stop_on_slope"), "set_floor_stop_on_slope_enabled", "is_floor_stop_on_slope_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_constant_speed"), "set_floor_constant_speed_enabled", "is_floor_constant_speed_enabled"); @@ -1775,7 +1773,7 @@ void CharacterBody2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin"); BIND_ENUM_CONSTANT(MOTION_MODE_GROUNDED); - BIND_ENUM_CONSTANT(MOTION_MODE_FREE); + BIND_ENUM_CONSTANT(MOTION_MODE_FLOATING); BIND_ENUM_CONSTANT(PLATFORM_VEL_ON_LEAVE_ALWAYS); BIND_ENUM_CONSTANT(PLATFORM_VEL_ON_LEAVE_UPWARD_ONLY); @@ -1783,12 +1781,12 @@ void CharacterBody2D::_bind_methods() { } void CharacterBody2D::_validate_property(PropertyInfo &property) const { - if (motion_mode == MOTION_MODE_FREE) { + if (motion_mode == MOTION_MODE_FLOATING) { if (property.name.begins_with("floor_") || property.name == "up_direction" || property.name == "slide_on_ceiling") { property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } else { - if (property.name == "free_mode_min_slide_angle") { + if (property.name == "wall_min_slide_angle") { property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 649d67d759..f1cc100a58 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -328,7 +328,7 @@ class CharacterBody2D : public PhysicsBody2D { public: enum MotionMode { MOTION_MODE_GROUNDED, - MOTION_MODE_FREE, + MOTION_MODE_FLOATING, }; enum MovingPlatformApplyVelocityOnLeave { PLATFORM_VEL_ON_LEAVE_ALWAYS, @@ -374,7 +374,7 @@ private: int platform_layer = 0; real_t floor_max_angle = Math::deg2rad((real_t)45.0); real_t floor_snap_length = 1; - real_t free_mode_min_slide_angle = Math::deg2rad((real_t)15.0); + real_t wall_min_slide_angle = Math::deg2rad((real_t)15.0); Vector2 up_direction = Vector2(0.0, -1.0); uint32_t moving_platform_floor_layers = UINT32_MAX; uint32_t moving_platform_wall_layers = 0; @@ -420,8 +420,8 @@ private: real_t get_floor_snap_length(); void set_floor_snap_length(real_t p_floor_snap_length); - real_t get_free_mode_min_slide_angle() const; - void set_free_mode_min_slide_angle(real_t p_radians); + real_t get_wall_min_slide_angle() const; + void set_wall_min_slide_angle(real_t p_radians); uint32_t get_moving_platform_floor_layers() const; void set_moving_platform_floor_layers(const uint32_t p_exclude_layer); @@ -435,7 +435,7 @@ private: void set_moving_platform_apply_velocity_on_leave(MovingPlatformApplyVelocityOnLeave p_on_leave_velocity); MovingPlatformApplyVelocityOnLeave get_moving_platform_apply_velocity_on_leave() const; - void _move_and_slide_free(double p_delta); + void _move_and_slide_floating(double p_delta); void _move_and_slide_grounded(double p_delta, bool p_was_on_floor); Ref<KinematicCollision2D> _get_slide_collision(int p_bounce); diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 62dc4d1c15..25c83b0c8f 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -1809,7 +1809,7 @@ void TileMap::_scenes_update_dirty_quadrants(SelfList<TileMapQuadrant>::List &r_ // Clear the scenes. for (const KeyValue<Vector2i, String> &E : q.scenes) { - Node *node = get_node(E.value); + Node *node = get_node_or_null(E.value); if (node) { node->queue_delete(); } @@ -1857,7 +1857,7 @@ void TileMap::_scenes_update_dirty_quadrants(SelfList<TileMapQuadrant>::List &r_ void TileMap::_scenes_cleanup_quadrant(TileMapQuadrant *p_quadrant) { // Clear the scenes. for (const KeyValue<Vector2i, String> &E : p_quadrant->scenes) { - Node *node = get_node(E.value); + Node *node = get_node_or_null(E.value); if (node) { node->queue_delete(); } @@ -2725,7 +2725,7 @@ void TileMap::_get_property_list(List<PropertyInfo> *p_list) const { } Vector2 TileMap::map_to_world(const Vector2i &p_pos) const { - // SHOULD RETURN THE CENTER OF THE TILE + // SHOULD RETURN THE CENTER OF THE CELL ERR_FAIL_COND_V(!tile_set.is_valid(), Vector2()); Vector2 ret = p_pos; diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index 0a0507207a..d88bb815bc 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -247,7 +247,7 @@ void Light3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_angular_distance", PROPERTY_HINT_RANGE, "0,90,0.01"), "set_param", "get_param", PARAM_SIZE); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SPECULAR); - ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disabled,Dynamic,Static"), "set_bake_mode", "get_bake_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disabled,Static (VoxelGI/SDFGI/LightmapGI),Dynamic (VoxelGI/SDFGI only)"), "set_bake_mode", "get_bake_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "light_cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); ADD_GROUP("Shadow", "shadow_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow", "has_shadow"); @@ -284,8 +284,8 @@ void Light3D::_bind_methods() { BIND_ENUM_CONSTANT(PARAM_MAX); BIND_ENUM_CONSTANT(BAKE_DISABLED); - BIND_ENUM_CONSTANT(BAKE_DYNAMIC); BIND_ENUM_CONSTANT(BAKE_STATIC); + BIND_ENUM_CONSTANT(BAKE_DYNAMIC); } Light3D::Light3D(RenderingServer::LightType p_type) { diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h index 93dc8155bb..d5d2aee43d 100644 --- a/scene/3d/light_3d.h +++ b/scene/3d/light_3d.h @@ -63,8 +63,8 @@ public: enum BakeMode { BAKE_DISABLED, + BAKE_STATIC, BAKE_DYNAMIC, - BAKE_STATIC }; private: diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index 715c421632..825742da35 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -217,7 +217,7 @@ LightmapGIData::~LightmapGIData() { void LightmapGI::_find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound> &meshes, Vector<LightsFound> &lights, Vector<Vector3> &probes) { MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node); - if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_BAKED && mi->is_visible_in_tree()) { + if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_STATIC && mi->is_visible_in_tree()) { Ref<Mesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { bool all_have_uv2_and_normal = true; diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index a992d2aaf2..515d2cfdc7 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -990,7 +990,7 @@ void Node3D::_bind_methods() { ADD_GROUP("Transform", ""); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_transform", "get_transform"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "global_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_transform", "get_global_transform"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position", PROPERTY_HINT_RANGE, "-99999,99999,0,or_greater,or_lesser,noslider,suffix:m", PROPERTY_USAGE_EDITOR), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_greater,or_lesser,noslider,suffix:m", PROPERTY_USAGE_EDITOR), "set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians", PROPERTY_USAGE_EDITOR), "set_rotation", "get_rotation"); ADD_PROPERTY(PropertyInfo(Variant::QUATERNION, "quaternion", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_quaternion", "get_quaternion"); ADD_PROPERTY(PropertyInfo(Variant::BASIS, "basis", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_basis", "get_basis"); diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index b3192a5bb5..1a707024c5 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -1233,7 +1233,7 @@ bool CharacterBody3D::move_and_slide() { if (motion_mode == MOTION_MODE_GROUNDED) { _move_and_slide_grounded(delta, was_on_floor); } else { - _move_and_slide_free(delta); + _move_and_slide_floating(delta); } // Compute real velocity. @@ -1512,7 +1512,7 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo } } -void CharacterBody3D::_move_and_slide_free(double p_delta) { +void CharacterBody3D::_move_and_slide_floating(double p_delta) { Vector3 motion = motion_velocity * p_delta; platform_rid = RID(); @@ -1929,7 +1929,7 @@ const Vector3 &CharacterBody3D::get_up_direction() const { } void CharacterBody3D::set_up_direction(const Vector3 &p_up_direction) { - ERR_FAIL_COND_MSG(p_up_direction == Vector3(), "up_direction can't be equal to Vector3.ZERO, consider using Free motion mode instead."); + ERR_FAIL_COND_MSG(p_up_direction == Vector3(), "up_direction can't be equal to Vector3.ZERO, consider using Floating motion mode instead."); up_direction = p_up_direction.normalized(); } @@ -2000,12 +2000,11 @@ void CharacterBody3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &CharacterBody3D::_get_slide_collision); ClassDB::bind_method(D_METHOD("get_last_slide_collision"), &CharacterBody3D::_get_last_slide_collision); - ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Free", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Floating", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_direction"), "set_up_direction", "get_up_direction"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_ceiling"), "set_slide_on_ceiling_enabled", "is_slide_on_ceiling_enabled"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "motion_velocity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_motion_velocity", "get_motion_velocity"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_slides", "get_max_slides"); - ADD_GROUP("Free Mode", "free_mode_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wall_min_slide_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians", PROPERTY_USAGE_DEFAULT), "set_wall_min_slide_angle", "get_wall_min_slide_angle"); ADD_GROUP("Floor", "floor_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_stop_on_slope"), "set_floor_stop_on_slope_enabled", "is_floor_stop_on_slope_enabled"); @@ -2020,7 +2019,7 @@ void CharacterBody3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin"); BIND_ENUM_CONSTANT(MOTION_MODE_GROUNDED); - BIND_ENUM_CONSTANT(MOTION_MODE_FREE); + BIND_ENUM_CONSTANT(MOTION_MODE_FLOATING); BIND_ENUM_CONSTANT(PLATFORM_VEL_ON_LEAVE_ALWAYS); BIND_ENUM_CONSTANT(PLATFORM_VEL_ON_LEAVE_UPWARD_ONLY); @@ -2028,7 +2027,7 @@ void CharacterBody3D::_bind_methods() { } void CharacterBody3D::_validate_property(PropertyInfo &property) const { - if (motion_mode == MOTION_MODE_FREE) { + if (motion_mode == MOTION_MODE_FLOATING) { if (property.name.begins_with("floor_") || property.name == "up_direction" || property.name == "slide_on_ceiling") { property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index e37b841117..65a763b21e 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -345,7 +345,7 @@ class CharacterBody3D : public PhysicsBody3D { public: enum MotionMode { MOTION_MODE_GROUNDED, - MOTION_MODE_FREE, + MOTION_MODE_FLOATING, }; enum MovingPlatformApplyVelocityOnLeave { PLATFORM_VEL_ON_LEAVE_ALWAYS, @@ -468,7 +468,7 @@ private: void set_moving_platform_apply_velocity_on_leave(MovingPlatformApplyVelocityOnLeave p_on_leave_velocity); MovingPlatformApplyVelocityOnLeave get_moving_platform_apply_velocity_on_leave() const; - void _move_and_slide_free(double p_delta); + void _move_and_slide_floating(double p_delta); void _move_and_slide_grounded(double p_delta, bool p_was_on_floor); Ref<KinematicCollision3D> _get_slide_collision(int p_bounce); diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp index 0db2fe9fc6..005bb5a737 100644 --- a/scene/3d/visual_instance_3d.cpp +++ b/scene/3d/visual_instance_3d.cpp @@ -247,7 +247,7 @@ bool GeometryInstance3D::_set(const StringName &p_name, const Variant &p_value) } #ifndef DISABLE_DEPRECATED if (p_name == SceneStringNames::get_singleton()->use_in_baked_light && bool(p_value)) { - set_gi_mode(GI_MODE_BAKED); + set_gi_mode(GI_MODE_STATIC); return true; } @@ -358,7 +358,7 @@ void GeometryInstance3D::set_gi_mode(GIMode p_mode) { RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false); RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_DYNAMIC_GI, false); } break; - case GI_MODE_BAKED: { + case GI_MODE_STATIC: { RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_BAKED_LIGHT, true); RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_DYNAMIC_GI, false); @@ -462,7 +462,7 @@ void GeometryInstance3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_bias", PROPERTY_HINT_RANGE, "0.001,128,0.001"), "set_lod_bias", "get_lod_bias"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_occlusion_culling"), "set_ignore_occlusion_culling", "is_ignoring_occlusion_culling"); ADD_GROUP("Global Illumination", "gi_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_mode", PROPERTY_HINT_ENUM, "Disabled,Baked,Dynamic"), "set_gi_mode", "get_gi_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_mode", PROPERTY_HINT_ENUM, "Disabled,Static (VoxelGI/SDFGI/LightmapGI),Dynamic (VoxelGI only)"), "set_gi_mode", "get_gi_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_lightmap_scale", PROPERTY_HINT_ENUM, String::utf8("1×,2×,4×,8×")), "set_lightmap_scale", "get_lightmap_scale"); ADD_GROUP("Visibility Range", "visibility_range_"); @@ -479,7 +479,7 @@ void GeometryInstance3D::_bind_methods() { BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY); BIND_ENUM_CONSTANT(GI_MODE_DISABLED); - BIND_ENUM_CONSTANT(GI_MODE_BAKED); + BIND_ENUM_CONSTANT(GI_MODE_STATIC); BIND_ENUM_CONSTANT(GI_MODE_DYNAMIC); BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_1X); diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h index dd0eb25001..be964e5080 100644 --- a/scene/3d/visual_instance_3d.h +++ b/scene/3d/visual_instance_3d.h @@ -89,7 +89,7 @@ public: enum GIMode { GI_MODE_DISABLED, - GI_MODE_BAKED, + GI_MODE_STATIC, GI_MODE_DYNAMIC }; diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp index 35ac1792e9..bfe3c80a4f 100644 --- a/scene/3d/voxel_gi.cpp +++ b/scene/3d/voxel_gi.cpp @@ -282,7 +282,7 @@ Vector3 VoxelGI::get_extents() const { void VoxelGI::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) { MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node); - if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_BAKED && mi->is_visible_in_tree()) { + if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_STATIC && mi->is_visible_in_tree()) { Ref<Mesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { AABB aabb = mesh->get_aabb(); diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index eee7663b09..bcb2b0c50e 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -444,7 +444,7 @@ void BaseButton::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "toggle_mode"), "set_toggle_mode", "is_toggle_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_in_tooltip"), "set_shortcut_in_tooltip", "is_shortcut_in_tooltip_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "button_pressed"), "set_pressed", "is_pressed"); ADD_PROPERTY(PropertyInfo(Variant::INT, "action_mode", PROPERTY_HINT_ENUM, "Button Press,Button Release"), "set_action_mode", "get_action_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "button_mask", PROPERTY_HINT_FLAGS, "Mouse Left, Mouse Right, Mouse Middle"), "set_button_mask", "get_button_mask"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_pressed_outside"), "set_keep_pressed_outside", "is_keep_pressed_outside"); diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index 046b9c18c7..552dd28513 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -569,7 +569,7 @@ void Button::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text"); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_button_icon", "get_button_icon"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "get_clip_text"); diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 040075150b..8924c37c50 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -937,8 +937,10 @@ void CodeEdit::_new_line(bool p_split_current_line, bool p_above) { return; } - const int cc = get_caret_column(); + /* When not splitting the line, we need to factor in indentation from the end of the current line. */ + const int cc = p_split_current_line ? get_caret_column() : get_line(get_caret_line()).length(); const int cl = get_caret_line(); + const String line = get_line(cl); String ins = "\n"; @@ -1012,6 +1014,8 @@ void CodeEdit::_new_line(bool p_split_current_line, bool p_above) { bool first_line = false; if (!p_split_current_line) { + deselect(); + if (p_above) { if (cl > 0) { set_caret_line(cl - 1, false); @@ -1793,7 +1797,7 @@ void CodeEdit::request_code_completion(bool p_force) { } if (p_force) { - emit_signal(SNAME("request_code_completion")); + emit_signal(SNAME("code_completion_requested")); return; } @@ -1801,9 +1805,9 @@ void CodeEdit::request_code_completion(bool p_force) { int ofs = CLAMP(get_caret_column(), 0, line.length()); if (ofs > 0 && (is_in_string(get_caret_line(), ofs) != -1 || _is_char(line[ofs - 1]) || code_completion_prefixes.has(line[ofs - 1]))) { - emit_signal(SNAME("request_code_completion")); + emit_signal(SNAME("code_completion_requested")); } else if (ofs > 1 && line[ofs - 1] == ' ' && code_completion_prefixes.has(line[ofs - 2])) { - emit_signal(SNAME("request_code_completion")); + emit_signal(SNAME("code_completion_requested")); } } @@ -2085,8 +2089,6 @@ void CodeEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("get_auto_brace_completion_close_key", "open_key"), &CodeEdit::get_auto_brace_completion_close_key); /* Main Gutter */ - ClassDB::bind_method(D_METHOD("_main_gutter_draw_callback"), &CodeEdit::_main_gutter_draw_callback); - ClassDB::bind_method(D_METHOD("set_draw_breakpoints_gutter", "enable"), &CodeEdit::set_draw_breakpoints_gutter); ClassDB::bind_method(D_METHOD("is_drawing_breakpoints_gutter"), &CodeEdit::is_drawing_breakpoints_gutter); @@ -2115,16 +2117,12 @@ void CodeEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("get_executing_lines"), &CodeEdit::get_executing_lines); /* Line numbers */ - ClassDB::bind_method(D_METHOD("_line_number_draw_callback"), &CodeEdit::_line_number_draw_callback); - ClassDB::bind_method(D_METHOD("set_draw_line_numbers", "enable"), &CodeEdit::set_draw_line_numbers); ClassDB::bind_method(D_METHOD("is_draw_line_numbers_enabled"), &CodeEdit::is_draw_line_numbers_enabled); ClassDB::bind_method(D_METHOD("set_line_numbers_zero_padded", "enable"), &CodeEdit::set_line_numbers_zero_padded); ClassDB::bind_method(D_METHOD("is_line_numbers_zero_padded"), &CodeEdit::is_line_numbers_zero_padded); /* Fold Gutter */ - ClassDB::bind_method(D_METHOD("_fold_gutter_draw_callback"), &CodeEdit::_fold_gutter_draw_callback); - ClassDB::bind_method(D_METHOD("set_draw_fold_gutter", "enable"), &CodeEdit::set_draw_fold_gutter); ClassDB::bind_method(D_METHOD("is_drawing_fold_gutter"), &CodeEdit::is_drawing_fold_gutter); @@ -2267,7 +2265,7 @@ void CodeEdit::_bind_methods() { ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo(Variant::INT, "line"))); /* Code Completion */ - ADD_SIGNAL(MethodInfo("request_code_completion")); + ADD_SIGNAL(MethodInfo("code_completion_requested")); /* Symbol lookup */ ADD_SIGNAL(MethodInfo("symbol_lookup", PropertyInfo(Variant::STRING, "symbol"), PropertyInfo(Variant::INT, "line"), PropertyInfo(Variant::INT, "column"))); @@ -3084,7 +3082,7 @@ CodeEdit::CodeEdit() { set_gutter_draw(gutter_idx, false); set_gutter_overwritable(gutter_idx, true); set_gutter_type(gutter_idx, GUTTER_TYPE_CUSTOM); - set_gutter_custom_draw(gutter_idx, this, "_main_gutter_draw_callback"); + set_gutter_custom_draw(gutter_idx, callable_mp(this, &CodeEdit::_main_gutter_draw_callback)); gutter_idx++; /* Line numbers */ @@ -3092,7 +3090,7 @@ CodeEdit::CodeEdit() { set_gutter_name(gutter_idx, "line_numbers"); set_gutter_draw(gutter_idx, false); set_gutter_type(gutter_idx, GUTTER_TYPE_CUSTOM); - set_gutter_custom_draw(gutter_idx, this, "_line_number_draw_callback"); + set_gutter_custom_draw(gutter_idx, callable_mp(this, &CodeEdit::_line_number_draw_callback)); gutter_idx++; /* Fold Gutter */ @@ -3100,7 +3098,7 @@ CodeEdit::CodeEdit() { set_gutter_name(gutter_idx, "fold_gutter"); set_gutter_draw(gutter_idx, false); set_gutter_type(gutter_idx, GUTTER_TYPE_CUSTOM); - set_gutter_custom_draw(gutter_idx, this, "_fold_gutter_draw_callback"); + set_gutter_custom_draw(gutter_idx, callable_mp(this, &CodeEdit::_fold_gutter_draw_callback)); gutter_idx++; connect("lines_edited_from", callable_mp(this, &CodeEdit::_lines_edited_from)); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 11d7946866..562ea8a8f7 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -240,7 +240,7 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) { return false; } - if (p_value.get_type() == Variant::NIL) { + if (p_value.get_type() == Variant::NIL || (p_value.get_type() == Variant::OBJECT && (Object *)p_value == nullptr)) { if (name.begins_with("theme_override_icons/") || name.begins_with("custom_icons/")) { String dname = name.get_slicec('/', 1); if (data.icon_override.has(dname)) { @@ -733,8 +733,10 @@ void Control::_notification(int p_notification) { } break; case NOTIFICATION_TRANSLATION_CHANGED: case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: { - data.is_rtl_dirty = true; - _size_changed(); + if (is_inside_tree()) { + data.is_rtl_dirty = true; + _size_changed(); + } } break; } } diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 44ef641cb8..e5bd6f4882 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -110,6 +110,9 @@ void FileDialog::_notification(int p_what) { show_hidden->set_icon(vbox->get_theme_icon(SNAME("toggle_hidden"), SNAME("FileDialog"))); _theme_changed(); } + if (p_what == NOTIFICATION_TRANSLATION_CHANGED) { + update_filters(); + } } void FileDialog::unhandled_input(const Ref<InputEvent> &p_event) { @@ -638,7 +641,7 @@ void FileDialog::update_filters() { all_filters += ", ..."; } - filter->add_item(String(TTRC("All Recognized")) + " (" + all_filters + ")"); + filter->add_item(RTR("All Recognized") + " (" + all_filters + ")"); } for (int i = 0; i < filters.size(); i++) { String flt = filters[i].get_slice(";", 0).strip_edges(); @@ -650,7 +653,7 @@ void FileDialog::update_filters() { } } - filter->add_item(TTRC("All Files (*)")); + filter->add_item(RTR("All Files") + " (*)"); } void FileDialog::clear_filters() { diff --git a/scene/gui/flow_container.cpp b/scene/gui/flow_container.cpp new file mode 100644 index 0000000000..d1ac60b325 --- /dev/null +++ b/scene/gui/flow_container.cpp @@ -0,0 +1,252 @@ +/*************************************************************************/ +/* flow_container.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "scene/gui/container.h" + +#include "flow_container.h" + +struct _LineData { + int child_count = 0; + int min_line_height = 0; + int min_line_length = 0; + int stretch_avail = 0; + float stretch_ratio_total = 0; +}; + +void FlowContainer::_resort() { + int separation_horizontal = get_theme_constant(SNAME("hseparation")); + int separation_vertical = get_theme_constant(SNAME("vseparation")); + + bool rtl = is_layout_rtl(); + + Map<Control *, Size2i> children_minsize_cache; + + Vector<_LineData> lines_data; + + Vector2i ofs; + int line_height = 0; + int line_length = 0; + float line_stretch_ratio_total = 0; + int current_container_size = vertical ? get_rect().size.y : get_rect().size.x; + int children_in_current_line = 0; + + // First pass for line wrapping and minimum size calculation. + for (int i = 0; i < get_child_count(); i++) { + Control *child = Object::cast_to<Control>(get_child(i)); + if (!child || !child->is_visible_in_tree()) { + continue; + } + if (child->is_set_as_top_level()) { + continue; + } + + Size2i child_msc = child->get_combined_minimum_size(); + + if (vertical) { /* VERTICAL */ + if (children_in_current_line > 0) { + ofs.y += separation_vertical; + } + if (ofs.y + child_msc.y > current_container_size) { + line_length = ofs.y - separation_vertical; + lines_data.push_back(_LineData{ children_in_current_line, line_height, line_length, current_container_size - line_length, line_stretch_ratio_total }); + + // Move in new column (vertical line). + ofs.x += line_height + separation_horizontal; + ofs.y = 0; + line_height = 0; + line_stretch_ratio_total = 0; + children_in_current_line = 0; + } + + line_height = MAX(line_height, child_msc.x); + if (child->get_v_size_flags() & SIZE_EXPAND) { + line_stretch_ratio_total += child->get_stretch_ratio(); + } + ofs.y += child_msc.y; + + } else { /* HORIZONTAL */ + if (children_in_current_line > 0) { + ofs.x += separation_horizontal; + } + if (ofs.x + child_msc.x > current_container_size) { + line_length = ofs.x - separation_horizontal; + lines_data.push_back(_LineData{ children_in_current_line, line_height, line_length, current_container_size - line_length, line_stretch_ratio_total }); + + // Move in new line. + ofs.y += line_height + separation_vertical; + ofs.x = 0; + line_height = 0; + line_stretch_ratio_total = 0; + children_in_current_line = 0; + } + + line_height = MAX(line_height, child_msc.y); + if (child->get_h_size_flags() & SIZE_EXPAND) { + line_stretch_ratio_total += child->get_stretch_ratio(); + } + ofs.x += child_msc.x; + } + + children_minsize_cache[child] = child_msc; + children_in_current_line++; + } + line_length = vertical ? (ofs.y) : (ofs.x); + lines_data.push_back(_LineData{ children_in_current_line, line_height, line_length, current_container_size - line_length, line_stretch_ratio_total }); + + // Second pass for in-line expansion and alignment. + + int current_line_idx = 0; + int child_idx_in_line = 0; + + ofs.x = 0; + ofs.y = 0; + + for (int i = 0; i < get_child_count(); i++) { + Control *child = Object::cast_to<Control>(get_child(i)); + if (!child || !child->is_visible_in_tree()) { + continue; + } + if (child->is_set_as_top_level()) { + continue; + } + Size2i child_size = children_minsize_cache[child]; + + _LineData line_data = lines_data[current_line_idx]; + if (child_idx_in_line >= lines_data[current_line_idx].child_count) { + current_line_idx++; + child_idx_in_line = 0; + if (vertical) { + ofs.x += line_data.min_line_height + separation_horizontal; + ofs.y = 0; + } else { + ofs.x = 0; + ofs.y += line_data.min_line_height + separation_vertical; + } + line_data = lines_data[current_line_idx]; + } + + if (vertical) { /* VERTICAL */ + if (child->get_h_size_flags() & (SIZE_FILL | SIZE_SHRINK_CENTER | SIZE_SHRINK_END)) { + child_size.width = line_data.min_line_height; + } + + if (child->get_v_size_flags() & SIZE_EXPAND) { + int stretch = line_data.stretch_avail * child->get_stretch_ratio() / line_data.stretch_ratio_total; + child_size.height += stretch; + } + + } else { /* HORIZONTAL */ + if (child->get_v_size_flags() & (SIZE_FILL | SIZE_SHRINK_CENTER | SIZE_SHRINK_END)) { + child_size.height = line_data.min_line_height; + } + + if (child->get_h_size_flags() & SIZE_EXPAND) { + int stretch = line_data.stretch_avail * child->get_stretch_ratio() / line_data.stretch_ratio_total; + child_size.width += stretch; + } + } + + Rect2 child_rect = Rect2(ofs, child_size); + if (rtl) { + child_rect.position.x = get_rect().size.x - child_rect.position.x - child_rect.size.width; + } + + fit_child_in_rect(child, child_rect); + + if (vertical) { /* VERTICAL */ + ofs.y += child_size.height + separation_vertical; + } else { /* HORIZONTAL */ + ofs.x += child_size.width + separation_horizontal; + } + + child_idx_in_line++; + } + cached_size = (vertical ? ofs.x : ofs.y) + line_height; + cached_line_count = lines_data.size(); +} + +Size2 FlowContainer::get_minimum_size() const { + Size2i minimum; + + for (int i = 0; i < get_child_count(); i++) { + Control *c = Object::cast_to<Control>(get_child(i)); + if (!c) { + continue; + } + if (c->is_set_as_top_level()) { + continue; + } + + if (!c->is_visible()) { + continue; + } + + Size2i size = c->get_combined_minimum_size(); + + if (vertical) { /* VERTICAL */ + minimum.height = MAX(minimum.height, size.height); + minimum.width = cached_size; + + } else { /* HORIZONTAL */ + minimum.width = MAX(minimum.width, size.width); + minimum.height = cached_size; + } + } + + return minimum; +} + +void FlowContainer::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_SORT_CHILDREN: { + _resort(); + update_minimum_size(); + } break; + case NOTIFICATION_THEME_CHANGED: { + update_minimum_size(); + } break; + case NOTIFICATION_TRANSLATION_CHANGED: + case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: { + queue_sort(); + } break; + } +} + +int FlowContainer::get_line_count() const { + return cached_line_count; +} + +FlowContainer::FlowContainer(bool p_vertical) { + vertical = p_vertical; +} + +void FlowContainer::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_line_count"), &FlowContainer::get_line_count); +} diff --git a/scene/gui/flow_container.h b/scene/gui/flow_container.h new file mode 100644 index 0000000000..e3ed423ae1 --- /dev/null +++ b/scene/gui/flow_container.h @@ -0,0 +1,76 @@ +/*************************************************************************/ +/* flow_container.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef FLOW_CONTAINER_H +#define FLOW_CONTAINER_H + +class Container; + +class FlowContainer : public Container { + GDCLASS(FlowContainer, Container); + +private: + int cached_size = 0; + int cached_line_count = 0; + + bool vertical = false; + + void _resort(); + +protected: + void _notification(int p_what); + + static void _bind_methods(); + +public: + int get_line_count() const; + + virtual Size2 get_minimum_size() const override; + + FlowContainer(bool p_vertical = false); +}; + +class HFlowContainer : public FlowContainer { + GDCLASS(HFlowContainer, FlowContainer); + +public: + HFlowContainer() : + FlowContainer(false) {} +}; + +class VFlowContainer : public FlowContainer { + GDCLASS(VFlowContainer, FlowContainer); + +public: + VFlowContainer() : + FlowContainer(true) {} +}; + +#endif // FLOW_CONTAINER_H diff --git a/scene/gui/gradient_edit.h b/scene/gui/gradient_edit.h index 407f61f7c1..67531d4f4a 100644 --- a/scene/gui/gradient_edit.h +++ b/scene/gui/gradient_edit.h @@ -33,7 +33,6 @@ #include "scene/gui/color_picker.h" #include "scene/gui/popup.h" -#include "scene/resources/default_theme/theme_data.h" #include "scene/resources/gradient.h" class GradientEdit : public Control { diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 79b73f7cc3..2be76473b0 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -1070,7 +1070,9 @@ void GraphEdit::set_selected(Node *p_child) { void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { ERR_FAIL_COND(p_ev.is_null()); - panner->gui_input(p_ev); + if (panner->gui_input(p_ev, warped_panning ? get_global_rect() : Rect2())) { + return; + } Ref<InputEventMouseMotion> mm = p_ev; @@ -1272,7 +1274,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { if (_filter_input(b->get_position())) { return; } - if (Input::get_singleton()->is_key_pressed(Key::SPACE)) { + if (panner->is_panning()) { return; } @@ -1354,7 +1356,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { } } -void GraphEdit::_scroll_callback(Vector2 p_scroll_vec) { +void GraphEdit::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) { if (p_scroll_vec.x != 0) { h_scroll->set_value(h_scroll->get_value() + (h_scroll->get_page() * Math::abs(p_scroll_vec.x) / 8) * SIGN(p_scroll_vec.x)); } else { @@ -1367,7 +1369,7 @@ void GraphEdit::_pan_callback(Vector2 p_scroll_vec) { v_scroll->set_value(v_scroll->get_value() - p_scroll_vec.y); } -void GraphEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin) { +void GraphEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) { set_zoom_custom(p_scroll_vec.y < 0 ? zoom * zoom_step : zoom / zoom_step, p_origin); } @@ -1678,6 +1680,14 @@ HBoxContainer *GraphEdit::get_zoom_hbox() { return zoom_hb; } +Ref<ViewPanner> GraphEdit::get_panner() { + return panner; +} + +void GraphEdit::set_warped_panning(bool p_warped) { + warped_panning = p_warped; +} + int GraphEdit::_set_operations(SET_OPERATIONS p_operation, Set<StringName> &r_u, const Set<StringName> &r_v) { switch (p_operation) { case GraphEdit::IS_EQUAL: { @@ -2305,7 +2315,6 @@ GraphEdit::GraphEdit() { panner.instantiate(); panner->set_callbacks(callable_mp(this, &GraphEdit::_scroll_callback), callable_mp(this, &GraphEdit::_pan_callback), callable_mp(this, &GraphEdit::_zoom_callback)); - panner->set_disable_rmb(true); top_layer = memnew(GraphEditFilter(this)); add_child(top_layer, false, INTERNAL_MODE_BACK); @@ -2313,6 +2322,7 @@ GraphEdit::GraphEdit() { top_layer->set_anchors_and_offsets_preset(Control::PRESET_WIDE); top_layer->connect("draw", callable_mp(this, &GraphEdit::_top_layer_draw)); top_layer->connect("gui_input", callable_mp(this, &GraphEdit::_top_layer_input)); + top_layer->connect("focus_exited", callable_mp(panner.ptr(), &ViewPanner::release_pan_key)); connections_layer = memnew(Control); add_child(connections_layer, false, INTERNAL_MODE_FRONT); diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index 4e998d30a7..da973b46f0 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -130,9 +130,10 @@ private: float port_grab_distance_vertical; Ref<ViewPanner> panner; - void _scroll_callback(Vector2 p_scroll_vec); + bool warped_panning = true; + void _scroll_callback(Vector2 p_scroll_vec, bool p_alt); void _pan_callback(Vector2 p_scroll_vec); - void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin); + void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt); bool connecting = false; String connecting_from; @@ -348,6 +349,8 @@ public: bool is_connection_lines_antialiased() const; HBoxContainer *get_zoom_hbox(); + Ref<ViewPanner> get_panner(); + void set_warped_panning(bool p_warped); void arrange_nodes(); diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index d6569e3de4..30f6cf4a14 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -1022,7 +1022,7 @@ void GraphNode::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title"); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position_offset"), "set_position_offset", "get_position_offset"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_close"), "set_show_close_button", "is_close_button_visible"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resizable"), "set_resizable", "is_resizable"); diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index a3878fe7ed..fab420d593 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -916,7 +916,7 @@ void Label::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text"); ADD_GROUP("Locale", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language"); ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment"); ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_alignment", PROPERTY_HINT_ENUM, "Top,Center,Bottom,Fill"), "set_vertical_alignment", "get_vertical_alignment"); ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode"); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index f7d6850a88..88953fa7db 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -2344,7 +2344,7 @@ void LineEdit::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "right_icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_right_icon", "get_right_icon"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat"); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_control_chars"), "set_draw_control_chars", "get_draw_control_chars"); ADD_GROUP("Structured Text", "structured_text_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override"); diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp index 67ffa2c7ed..0ff05faf85 100644 --- a/scene/gui/link_button.cpp +++ b/scene/gui/link_button.cpp @@ -308,7 +308,7 @@ void LinkButton::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text"); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language"); ADD_PROPERTY(PropertyInfo(Variant::INT, "underline", PROPERTY_HINT_ENUM, "Always,On Hover,Never"), "set_underline_mode", "get_underline_mode"); ADD_GROUP("Structured Text", "structured_text_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override"); diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index d7139d0140..c9fddc3e17 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -1403,12 +1403,12 @@ void PopupMenu::activate_item(int p_item) { need_hide = false; } - emit_signal(SNAME("id_pressed"), id); - emit_signal(SNAME("index_pressed"), p_item); - if (need_hide) { hide(); } + + emit_signal(SNAME("id_pressed"), id); + emit_signal(SNAME("index_pressed"), p_item); } void PopupMenu::remove_item(int p_idx) { diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 863555120d..e9d346f943 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -254,7 +254,12 @@ void RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font> for (int i = 0; i < col_count; i++) { remaining_width -= table->columns[i].min_width; if (table->columns[i].max_width > table->columns[i].min_width) { + // If the column can grow, allow it to grow. table->columns.write[i].expand = true; + } else { + // Otherwise make it shrink as much as possible, so that other columns can grow if needs be. + // We keep the max width as is to spread the remaining space between the columns later. + table->columns.write[i].min_width = 0; } if (table->columns[i].expand) { total_ratio += table->columns[i].expand_ratio; @@ -264,7 +269,7 @@ void RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font> // Assign actual widths. for (int i = 0; i < col_count; i++) { table->columns.write[i].width = table->columns[i].min_width; - if (table->columns[i].expand && total_ratio > 0) { + if (table->columns[i].expand && total_ratio > 0 && remaining_width > 0) { table->columns.write[i].width += table->columns[i].expand_ratio * remaining_width / total_ratio; } table->total_width += table->columns[i].width + hseparation; @@ -325,13 +330,16 @@ void RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font> table->columns.write[column].width = MAX(table->columns.write[column].width, ceil(frame->lines[i].text_buf->get_size().x)); if (i > 0) { - frame->lines.write[i].offset.y = frame->lines[i - 1].offset.y + frame->lines[i - 1].text_buf->get_size().y; + frame->lines.write[i].offset.y = frame->lines[i - 1].offset.y + frame->lines[i - 1].text_buf->get_size().y + frame->lines[i - 1].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); } else { frame->lines.write[i].offset.y = 0; } frame->lines.write[i].offset += offset; - float h = frame->lines[i].text_buf->get_size().y; + float h = frame->lines[i].text_buf->get_size().y + (frame->lines[i].text_buf->get_line_count() - 1) * get_theme_constant(SNAME("line_separation")); + if (i > 0) { + h += get_theme_constant(SNAME("line_separation")); + } if (frame->min_size_over.y > 0) { h = MAX(h, frame->min_size_over.y); } @@ -362,7 +370,7 @@ void RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font> } if (p_line > 0) { - l.offset.y = p_frame->lines[p_line - 1].offset.y + p_frame->lines[p_line - 1].text_buf->get_size().y + get_theme_constant(SNAME("line_separation")); + l.offset.y = p_frame->lines[p_line - 1].offset.y + p_frame->lines[p_line - 1].text_buf->get_size().y + p_frame->lines[p_line - 1].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); } else { l.offset.y = 0; } @@ -499,7 +507,12 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> for (int i = 0; i < col_count; i++) { remaining_width -= table->columns[i].min_width; if (table->columns[i].max_width > table->columns[i].min_width) { + // If the column can grow, allow it to grow. table->columns.write[i].expand = true; + } else { + // Otherwise make it shrink as much as possible, so that other columns can grow if needs be. + // We keep the max width as is to spread the remaining space between the columns later. + table->columns.write[i].min_width = 0; } if (table->columns[i].expand) { total_ratio += table->columns[i].expand_ratio; @@ -509,7 +522,7 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> // Assign actual widths. for (int i = 0; i < col_count; i++) { table->columns.write[i].width = table->columns[i].min_width; - if (table->columns[i].expand && total_ratio > 0) { + if (table->columns[i].expand && total_ratio > 0 && remaining_width > 0) { table->columns.write[i].width += table->columns[i].expand_ratio * remaining_width / total_ratio; } table->total_width += table->columns[i].width + hseparation; @@ -570,13 +583,16 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> table->columns.write[column].width = MAX(table->columns.write[column].width, ceil(frame->lines[i].text_buf->get_size().x)); if (i > 0) { - frame->lines.write[i].offset.y = frame->lines[i - 1].offset.y + frame->lines[i - 1].text_buf->get_size().y; + frame->lines.write[i].offset.y = frame->lines[i - 1].offset.y + frame->lines[i - 1].text_buf->get_size().y + frame->lines[i - 1].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); } else { frame->lines.write[i].offset.y = 0; } frame->lines.write[i].offset += offset; - float h = frame->lines[i].text_buf->get_size().y; + float h = frame->lines[i].text_buf->get_size().y + (frame->lines[i].text_buf->get_line_count() - 1) * get_theme_constant(SNAME("line_separation")); + if (i > 0) { + h += get_theme_constant(SNAME("line_separation")); + } if (frame->min_size_over.y > 0) { h = MAX(h, frame->min_size_over.y); } @@ -615,18 +631,19 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> *r_char_offset = l.char_offset + l.char_count; if (p_line > 0) { - l.offset.y = p_frame->lines[p_line - 1].offset.y + p_frame->lines[p_line - 1].text_buf->get_size().y + get_theme_constant(SNAME("line_separation")); + l.offset.y = p_frame->lines[p_line - 1].offset.y + p_frame->lines[p_line - 1].text_buf->get_size().y + p_frame->lines[p_line - 1].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); } else { l.offset.y = 0; } } int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Color &p_base_color, int p_outline_size, const Color &p_outline_color, const Color &p_font_shadow_color, int p_shadow_outline_size, const Point2 &p_shadow_ofs, int &r_processed_glyphs) { - Vector2 off; - ERR_FAIL_COND_V(p_frame == nullptr, 0); ERR_FAIL_COND_V(p_line < 0 || p_line >= p_frame->lines.size(), 0); + Vector2 off; + int line_spacing = get_theme_constant(SNAME("line_separation")); + Line &l = p_frame->lines.write[p_line]; Item *it_from = l.from; @@ -712,6 +729,10 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o Size2 ctrl_size = get_size(); // Draw text. for (int line = 0; line < l.text_buf->get_line_count(); line++) { + if (line > 0) { + off.y += line_spacing; + } + RID rid = l.text_buf->get_line_rid(line); if (p_ofs.y + off.y >= ctrl_size.height) { break; @@ -1177,7 +1198,7 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item //TODO, change to binary search ? while (from_line < main->lines.size()) { - if (main->lines[from_line].offset.y + main->lines[from_line].text_buf->get_size().y >= vofs) { + if (main->lines[from_line].offset.y + main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")) >= vofs) { break; } from_line++; @@ -1190,7 +1211,7 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item Point2 ofs = text_rect.get_position() + Vector2(0, main->lines[from_line].offset.y - vofs); while (ofs.y < size.height && from_line < main->lines.size()) { _find_click_in_line(p_frame, from_line, ofs, text_rect.size.x, p_click, r_click_frame, r_click_line, r_click_item, r_click_char); - ofs.y += main->lines[from_line].text_buf->get_size().y + get_theme_constant(SNAME("line_separation")); + ofs.y += main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); if (((r_click_item != nullptr) && ((*r_click_item) != nullptr)) || ((r_click_frame != nullptr) && ((*r_click_frame) != nullptr))) { if (r_outside != nullptr) { *r_outside = false; @@ -1309,7 +1330,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V if (rect.has_point(p_click) && !table_hit) { char_pos = TS->shaped_text_hit_test_position(rid, p_click.x - rect.position.x); } - off.y += TS->shaped_text_get_descent(rid) + l.text_buf->get_spacing_bottom(); + off.y += TS->shaped_text_get_descent(rid) + l.text_buf->get_spacing_bottom() + get_theme_constant(SNAME("line_separation")); } if (char_pos >= 0) { @@ -1473,7 +1494,7 @@ void RichTextLabel::_notification(int p_what) { //TODO, change to binary search ? while (from_line < main->lines.size()) { - if (main->lines[from_line].offset.y + main->lines[from_line].text_buf->get_size().y >= vofs) { + if (main->lines[from_line].offset.y + main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")) >= vofs) { break; } from_line++; @@ -1499,7 +1520,7 @@ void RichTextLabel::_notification(int p_what) { while (ofs.y < size.height && from_line < main->lines.size()) { visible_paragraph_count++; visible_line_count += _draw_line(main, from_line, ofs, text_rect.size.x, base_color, outline_size, outline_color, font_shadow_color, shadow_outline_size, shadow_ofs, processed_glyphs); - ofs.y += main->lines[from_line].text_buf->get_size().y + get_theme_constant(SNAME("line_separation")); + ofs.y += main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); from_line++; } } break; @@ -2176,10 +2197,6 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) { } // Resize lines without reshaping. - Size2 size = get_size(); - if (fixed_width != -1) { - size.width = fixed_width; - } Rect2 text_rect = _get_text_rect(); Ref<Font> base_font = get_theme_font(SNAME("normal_font")); @@ -2191,7 +2208,7 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) { int total_height = 0; if (p_frame->lines.size()) { - total_height = p_frame->lines[p_frame->lines.size() - 1].offset.y + p_frame->lines[p_frame->lines.size() - 1].text_buf->get_size().y; + total_height = p_frame->lines[p_frame->lines.size() - 1].offset.y + p_frame->lines[p_frame->lines.size() - 1].text_buf->get_size().y * p_frame->lines[p_frame->lines.size() - 1].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); } p_frame->first_resized_line = p_frame->lines.size(); @@ -2200,7 +2217,7 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) { vscroll->set_max(total_height); vscroll->set_page(text_rect.size.height); if (scroll_follow && scroll_following) { - vscroll->set_value(total_height - size.height); + vscroll->set_value(total_height); } updating_scroll = false; @@ -2211,10 +2228,6 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) { } // Shape invalid lines. - Size2 size = get_size(); - if (fixed_width != -1) { - size.width = fixed_width; - } Rect2 text_rect = _get_text_rect(); Ref<Font> base_font = get_theme_font(SNAME("normal_font")); @@ -2227,7 +2240,7 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) { int total_height = 0; if (p_frame->lines.size()) { - total_height = p_frame->lines[p_frame->lines.size() - 1].offset.y + p_frame->lines[p_frame->lines.size() - 1].text_buf->get_size().y; + total_height = p_frame->lines[p_frame->lines.size() - 1].offset.y + p_frame->lines[p_frame->lines.size() - 1].text_buf->get_size().y + p_frame->lines[p_frame->lines.size() - 1].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); } p_frame->first_invalid_line = p_frame->lines.size(); @@ -2237,7 +2250,7 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) { vscroll->set_max(total_height); vscroll->set_page(text_rect.size.height); if (scroll_follow && scroll_following) { - vscroll->set_value(total_height - size.height); + vscroll->set_value(total_height); } updating_scroll = false; @@ -4053,7 +4066,7 @@ void RichTextLabel::install_effect(const Variant effect) { int RichTextLabel::get_content_height() const { int total_height = 0; if (main->lines.size()) { - total_height = main->lines[main->lines.size() - 1].offset.y + main->lines[main->lines.size() - 1].text_buf->get_size().y; + total_height = main->lines[main->lines.size() - 1].offset.y + main->lines[main->lines.size() - 1].text_buf->get_size().y * main->lines[main->lines.size() - 1].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); } return total_height; } @@ -4207,7 +4220,7 @@ void RichTextLabel::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "custom_effects", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "RichTextEffect"), (PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE)), "set_effects", "get_effects"); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language"); ADD_GROUP("Structured Text", "structured_text_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override"); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 2b10ead8f6..fe1aaab557 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -128,6 +128,10 @@ void TextEdit::Text::set_width(float p_width) { width = p_width; } +float TextEdit::Text::get_width() const { + return width; +} + int TextEdit::Text::get_line_wrap_amount(int p_line) const { ERR_FAIL_INDEX_V(p_line, text.size(), 0); @@ -646,6 +650,8 @@ void TextEdit::_notification(int p_what) { } } + bool draw_placeholder = text[0].length() == 0; + // Get the highlighted words. String highlighted_text = get_selected_text(); @@ -656,7 +662,7 @@ void TextEdit::_notification(int p_what) { int first_visible_line = get_first_visible_line() - 1; int draw_amount = visible_rows + (smooth_scroll_enabled ? 1 : 0); - draw_amount += get_line_wrap_count(first_visible_line + 1); + draw_amount += draw_placeholder ? placeholder_wraped_rows.size() - 1 : get_line_wrap_count(first_visible_line + 1); // Draw minimap. if (draw_minimap) { @@ -841,7 +847,7 @@ void TextEdit::_notification(int p_what) { // Draw main text. caret.visible = false; line_drawing_cache.clear(); - int row_height = get_line_height(); + int row_height = draw_placeholder ? placeholder_line_height + line_spacing : get_line_height(); int line = first_visible_line; for (int i = 0; i < draw_amount; i++) { line++; @@ -867,11 +873,14 @@ void TextEdit::_notification(int p_what) { // Ensure we at least use the font color. Color current_color = !editable ? font_readonly_color : font_color; + if (draw_placeholder) { + current_color.a *= placeholder_alpha; + } - const Ref<TextParagraph> ldata = text.get_line_data(line); + const Ref<TextParagraph> ldata = draw_placeholder ? placeholder_data_buf : text.get_line_data(line); - Vector<String> wrap_rows = get_line_wrapped_text(line); - int line_wrap_amount = get_line_wrap_count(line); + Vector<String> wrap_rows = draw_placeholder ? placeholder_wraped_rows : get_line_wrapped_text(line); + int line_wrap_amount = draw_placeholder ? placeholder_wraped_rows.size() - 1 : get_line_wrap_count(line); for (int line_wrap_index = 0; line_wrap_index <= line_wrap_amount; line_wrap_index++) { if (line_wrap_index != 0) { @@ -1008,15 +1017,17 @@ void TextEdit::_notification(int p_what) { icon->draw_rect(ci, gutter_rect, false, get_line_gutter_item_color(line, g)); } break; case GUTTER_TYPE_CUSTOM: { - if (gutter.custom_draw_obj.is_valid()) { - Object *cdo = ObjectDB::get_instance(gutter.custom_draw_obj); - if (cdo) { - Rect2i gutter_rect = Rect2i(Point2i(gutter_offset, ofs_y), Size2i(gutter.width, row_height)); - if (rtl) { - gutter_rect.position.x = size.width - gutter_rect.position.x - gutter_rect.size.x; - } - cdo->call(gutter.custom_draw_callback, line, g, Rect2(gutter_rect)); + if (gutter.custom_draw_callback.is_valid()) { + Rect2i gutter_rect = Rect2i(Point2i(gutter_offset, ofs_y), Size2i(gutter.width, row_height)); + if (rtl) { + gutter_rect.position.x = size.width - gutter_rect.position.x - gutter_rect.size.x; } + + Variant args[3] = { line, g, Rect2(gutter_rect) }; + const Variant *argp[] = { &args[0], &args[1], &args[2] }; + Callable::CallError ce; + Variant ret; + gutter.custom_draw_callback.call(argp, 3, ret, ce); } } break; } @@ -1383,7 +1394,9 @@ void TextEdit::_notification(int p_what) { } } - line_drawing_cache[line] = cache_entry; + if (draw_placeholder) { + line_drawing_cache[line] = cache_entry; + } } if (has_focus()) { @@ -2045,6 +2058,7 @@ void TextEdit::_new_line(bool p_split_current_line, bool p_above) { bool first_line = false; if (!p_split_current_line) { + deselect(); if (p_above) { if (caret.line > 0) { set_caret_line(caret.line - 1, false); @@ -2430,6 +2444,47 @@ void TextEdit::_move_caret_document_end(bool p_select) { } } +void TextEdit::_update_placeholder() { + if (font.is_null() || font_size <= 0) { + return; // Not in tree? + } + + // Placeholder is generally smaller then text docuemnts, and updates less so this should be fast enough for now. + placeholder_data_buf->clear(); + placeholder_data_buf->set_width(text.get_width()); + placeholder_data_buf->set_direction((TextServer::Direction)text_direction); + placeholder_data_buf->set_preserve_control(draw_control_chars); + placeholder_data_buf->add_string(placeholder_text, font, font_size, opentype_features, language); + + placeholder_bidi_override = structured_text_parser(st_parser, st_args, placeholder_text); + if (placeholder_bidi_override.is_empty()) { + TS->shaped_text_set_bidi_override(placeholder_data_buf->get_rid(), placeholder_bidi_override); + } + + if (get_tab_size() > 0) { + Vector<float> tabs; + tabs.push_back(font->get_char_size(' ', 0, font_size).width * get_tab_size()); + placeholder_data_buf->tab_align(tabs); + } + + // Update height. + const int wrap_amount = placeholder_data_buf->get_line_count() - 1; + placeholder_line_height = font->get_height(font_size); + for (int i = 0; i <= wrap_amount; i++) { + placeholder_line_height = MAX(placeholder_line_height, placeholder_data_buf->get_line_size(i).y); + } + + // Update width. + placeholder_max_width = placeholder_data_buf->get_size().x; + + // Update wrapped rows. + placeholder_wraped_rows.clear(); + for (int i = 0; i <= wrap_amount; i++) { + Vector2i line_range = placeholder_data_buf->get_line_range(i); + placeholder_wraped_rows.push_back(placeholder_text.substr(line_range.x, line_range.y - line_range.x)); + } +} + void TextEdit::_update_caches() { /* Internal API for CodeEdit. */ brace_mismatch_color = get_theme_color(SNAME("brace_mismatch_color"), SNAME("CodeEdit")); @@ -2483,6 +2538,7 @@ void TextEdit::_update_caches() { text.set_font(font); text.set_font_size(font_size); text.invalidate_all(); + _update_placeholder(); /* Syntax highlighting. */ if (syntax_highlighter.is_valid()) { @@ -2598,8 +2654,7 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const { } String TextEdit::get_tooltip(const Point2 &p_pos) const { - Object *tooltip_obj = ObjectDB::get_instance(tooltip_obj_id); - if (!tooltip_obj) { + if (!tooltip_callback.is_valid()) { return Control::get_tooltip(p_pos); } Point2i pos = get_line_column_at_pos(p_pos); @@ -2612,19 +2667,20 @@ String TextEdit::get_tooltip(const Point2 &p_pos) const { } int beg, end; if (select_word(s, col, beg, end)) { - String tt = tooltip_obj->call(tooltip_func, s.substr(beg, end - beg), tooltip_ud); - - return tt; + Variant args[1] = { s.substr(beg, end - beg) }; + const Variant *argp[] = { &args[0] }; + Callable::CallError ce; + Variant ret; + tooltip_callback.call(argp, 1, ret, ce); + ERR_FAIL_COND_V_MSG(ce.error != Callable::CallError::CALL_OK, "", "Failed to call custom tooltip."); + return ret; } return Control::get_tooltip(p_pos); } -void TextEdit::set_tooltip_request_func(Object *p_obj, const StringName &p_function, const Variant &p_udata) { - ERR_FAIL_NULL(p_obj); - tooltip_obj_id = p_obj->get_instance_id(); - tooltip_func = p_function; - tooltip_ud = p_udata; +void TextEdit::set_tooltip_request_func(const Callable &p_tooltip_callback) { + tooltip_callback = p_tooltip_callback; } /* Text */ @@ -2662,6 +2718,7 @@ void TextEdit::set_text_direction(Control::TextDirection p_text_direction) { } text.set_direction_and_language(dir, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale()); text.invalidate_all(); + _update_placeholder(); if (menu_dir) { menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_INHERITED), text_direction == TEXT_DIRECTION_INHERITED); @@ -2683,6 +2740,7 @@ void TextEdit::set_opentype_feature(const String &p_name, int p_value) { opentype_features[tag] = p_value; text.set_font_features(opentype_features); text.invalidate_all(); + _update_placeholder(); update(); } } @@ -2699,6 +2757,7 @@ void TextEdit::clear_opentype_features() { opentype_features.clear(); text.set_font_features(opentype_features); text.invalidate_all(); + _update_placeholder(); update(); } @@ -2713,6 +2772,7 @@ void TextEdit::set_language(const String &p_language) { } text.set_direction_and_language(dir, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale()); text.invalidate_all(); + _update_placeholder(); update(); } } @@ -2754,6 +2814,7 @@ void TextEdit::set_tab_size(const int p_size) { } text.set_tab_size(p_size); text.invalidate_all_lines(); + _update_placeholder(); update(); } @@ -2876,6 +2937,25 @@ int TextEdit::get_line_count() const { return text.size(); } +void TextEdit::set_placeholder(const String &p_text) { + placeholder_text = p_text; + _update_placeholder(); + update(); +} + +String TextEdit::get_placeholder() const { + return placeholder_text; +} + +void TextEdit::set_placeholder_alpha(float p_alpha) { + placeholder_alpha = p_alpha; + update(); +} + +float TextEdit::get_placeholder_alpha() const { + return placeholder_alpha; +} + void TextEdit::set_line(int p_line, const String &p_new_text) { if (p_line < 0 || p_line >= text.size()) { return; @@ -4658,12 +4738,10 @@ void TextEdit::merge_gutters(int p_from_line, int p_to_line) { update(); } -void TextEdit::set_gutter_custom_draw(int p_gutter, Object *p_object, const StringName &p_callback) { +void TextEdit::set_gutter_custom_draw(int p_gutter, const Callable &p_draw_callback) { ERR_FAIL_INDEX(p_gutter, gutters.size()); - ERR_FAIL_NULL(p_object); - gutters.write[p_gutter].custom_draw_obj = p_object->get_instance_id(); - gutters.write[p_gutter].custom_draw_callback = p_callback; + gutters.write[p_gutter].custom_draw_callback = p_draw_callback; update(); } @@ -4783,6 +4861,7 @@ void TextEdit::set_draw_control_chars(bool p_enabled) { } text.set_draw_control_chars(draw_control_chars); text.invalidate_all(); + _update_placeholder(); update(); } } @@ -4862,6 +4941,12 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("get_text"), &TextEdit::get_text); ClassDB::bind_method(D_METHOD("get_line_count"), &TextEdit::get_line_count); + ClassDB::bind_method(D_METHOD("set_placeholder", "text"), &TextEdit::set_placeholder); + ClassDB::bind_method(D_METHOD("get_placeholder"), &TextEdit::get_placeholder); + + ClassDB::bind_method(D_METHOD("set_placeholder_alpha", "alpha"), &TextEdit::set_placeholder_alpha); + ClassDB::bind_method(D_METHOD("get_placeholder_alpha"), &TextEdit::get_placeholder_alpha); + ClassDB::bind_method(D_METHOD("set_line", "line", "new_text"), &TextEdit::set_line); ClassDB::bind_method(D_METHOD("get_line", "line"), &TextEdit::get_line); @@ -4953,7 +5038,7 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("search", "text", "flags", "from_line", "from_colum"), &TextEdit::search); /* Tooltip */ - ClassDB::bind_method(D_METHOD("set_tooltip_request_func", "object", "callback", "data"), &TextEdit::set_tooltip_request_func); + ClassDB::bind_method(D_METHOD("set_tooltip_request_func", "callback"), &TextEdit::set_tooltip_request_func); /* Mouse */ ClassDB::bind_method(D_METHOD("get_local_mouse_pos"), &TextEdit::get_local_mouse_pos); @@ -5125,7 +5210,7 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("set_gutter_overwritable", "gutter", "overwritable"), &TextEdit::set_gutter_overwritable); ClassDB::bind_method(D_METHOD("is_gutter_overwritable", "gutter"), &TextEdit::is_gutter_overwritable); ClassDB::bind_method(D_METHOD("merge_gutters", "from_line", "to_line"), &TextEdit::merge_gutters); - ClassDB::bind_method(D_METHOD("set_gutter_custom_draw", "column", "object", "callback"), &TextEdit::set_gutter_custom_draw); + ClassDB::bind_method(D_METHOD("set_gutter_custom_draw", "column", "draw_callback"), &TextEdit::set_gutter_custom_draw); ClassDB::bind_method(D_METHOD("get_total_gutter_width"), &TextEdit::get_total_gutter_width); // Line gutters. @@ -5170,8 +5255,10 @@ void TextEdit::_bind_methods() { /* Inspector */ ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "placeholder_text", PROPERTY_HINT_MULTILINE_TEXT), "set_placeholder", "get_placeholder"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "placeholder_alpha", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_placeholder_alpha", "get_placeholder_alpha"); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled"); @@ -5245,6 +5332,7 @@ bool TextEdit::_set(const StringName &p_name, const Variant &p_value) { opentype_features.erase(tag); text.set_font_features(opentype_features); text.invalidate_all(); + _update_placeholder(); update(); } } else { @@ -5252,6 +5340,7 @@ bool TextEdit::_set(const StringName &p_name, const Variant &p_value) { opentype_features[tag] = value; text.set_font_features(opentype_features); text.invalidate_all(); + _update_placeholder(); update(); } } @@ -5903,6 +5992,7 @@ void TextEdit::_update_wrap_at_column(bool p_force) { text.set_width(-1); } text.invalidate_all_lines(); + _update_placeholder(); } _update_caret_wrap_offset(); @@ -5930,14 +6020,16 @@ void TextEdit::_update_scrollbars() { h_scroll->set_begin(Point2(0, size.height - hmin.height)); h_scroll->set_end(Point2(size.width - vmin.width, size.height)); + bool draw_placeholder = text[0].length() == 0; + int visible_rows = get_visible_line_count(); - int total_rows = get_total_visible_line_count(); + int total_rows = draw_placeholder ? placeholder_wraped_rows.size() - 1 : get_total_visible_line_count(); if (scroll_past_end_of_file_enabled) { total_rows += visible_rows - 1; } int visible_width = size.width - style_normal->get_minimum_size().width; - int total_width = text.get_max_width() + vmin.x + gutters_width + gutter_padding; + int total_width = (draw_placeholder ? placeholder_max_width : text.get_max_width()) + vmin.x + gutters_width + gutter_padding; if (draw_minimap) { total_width += minimap_width; @@ -6009,20 +6101,22 @@ void TextEdit::_scroll_moved(double p_to_val) { } if (v_scroll->is_visible_in_tree()) { // Set line ofs and wrap ofs. + bool draw_placeholder = text[0].length() == 0; + int v_scroll_i = floor(get_v_scroll()); int sc = 0; int n_line; for (n_line = 0; n_line < text.size(); n_line++) { if (!_is_line_hidden(n_line)) { sc++; - sc += get_line_wrap_count(n_line); + sc += draw_placeholder ? placeholder_wraped_rows.size() - 1 : get_line_wrap_count(n_line); if (sc > v_scroll_i) { break; } } } n_line = MIN(n_line, text.size() - 1); - int line_wrap_amount = get_line_wrap_count(n_line); + int line_wrap_amount = (text[0].length() == 0) ? placeholder_wraped_rows.size() - 1 : get_line_wrap_count(n_line); int wi = line_wrap_amount - (sc - v_scroll_i - 1); wi = CLAMP(wi, 0, line_wrap_amount); @@ -6450,6 +6544,8 @@ void TextEdit::_base_remove_text(int p_from_line, int p_from_column, int p_to_li } TextEdit::TextEdit() { + placeholder_data_buf.instantiate(); + clear(); set_focus_mode(FOCUS_ALL); _update_caches(); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 57b48b5f52..fdaa928598 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -120,8 +120,7 @@ private: bool clickable = false; bool overwritable = false; - ObjectID custom_draw_obj = ObjectID(); - StringName custom_draw_callback; + Callable custom_draw_callback; }; class Text { @@ -190,6 +189,7 @@ private: int get_max_width() const; void set_width(float p_width); + float get_width() const; int get_line_wrap_amount(int p_line) const; Vector<Vector2i> get_line_wrap_ranges(int p_line) const; @@ -250,6 +250,19 @@ private: String ime_text = ""; Point2 ime_selection; + // Placeholder + float placeholder_alpha = 0.6; + + String placeholder_text = ""; + Array placeholder_bidi_override; + Ref<TextParagraph> placeholder_data_buf; + int placeholder_line_height = -1; + int placeholder_max_width = -1; + + Vector<String> placeholder_wraped_rows; + + void _update_placeholder(); + /* Initialise to opposite first, so we get past the early-out in set_editable. */ bool editable = false; @@ -332,9 +345,7 @@ private: int _get_column_pos_of_word(const String &p_key, const String &p_search, uint32_t p_search_flags, int p_from_column) const; /* Tooltip. */ - ObjectID tooltip_obj_id; - StringName tooltip_func; - Variant tooltip_ud; + Callable tooltip_callback; /* Mouse */ struct LineDrawingCache { @@ -620,7 +631,7 @@ public: virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const override; virtual void drop_data(const Point2 &p_point, const Variant &p_data) override; virtual String get_tooltip(const Point2 &p_pos) const override; - void set_tooltip_request_func(Object *p_obj, const StringName &p_function, const Variant &p_udata); + void set_tooltip_request_func(const Callable &p_tooltip_callback); /* Text */ // Text properties. @@ -670,6 +681,12 @@ public: String get_text() const; int get_line_count() const; + void set_placeholder(const String &p_text); + String get_placeholder() const; + + void set_placeholder_alpha(float p_alpha); + float get_placeholder_alpha() const; + void set_line(int p_line, const String &p_new_text); String get_line(int p_line) const; @@ -884,7 +901,7 @@ public: void merge_gutters(int p_from_line, int p_to_line); - void set_gutter_custom_draw(int p_gutter, Object *p_object, const StringName &p_callback); + void set_gutter_custom_draw(int p_gutter, const Callable &p_draw_callback); // Line gutters. void set_line_gutter_metadata(int p_line, int p_gutter, const Variant &p_metadata); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index e46de43f1e..e75d147134 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -198,6 +198,65 @@ bool TreeItem::is_indeterminate(int p_column) const { return cells[p_column].indeterminate; } +void TreeItem::propagate_check(int p_column, bool p_emit_signal) { + bool ch = cells[p_column].checked; + + if (p_emit_signal) { + tree->emit_signal("check_propagated_to_item", this, p_column); + } + _propagate_check_through_children(p_column, ch, p_emit_signal); + _propagate_check_through_parents(p_column, p_emit_signal); +} + +void TreeItem::_propagate_check_through_children(int p_column, bool p_checked, bool p_emit_signal) { + TreeItem *current = get_first_child(); + while (current) { + current->set_checked(p_column, p_checked); + if (p_emit_signal) { + current->tree->emit_signal("check_propagated_to_item", current, p_column); + } + current->_propagate_check_through_children(p_column, p_checked, p_emit_signal); + current = current->get_next(); + } +} + +void TreeItem::_propagate_check_through_parents(int p_column, bool p_emit_signal) { + TreeItem *current = get_parent(); + if (!current) { + return; + } + + bool all_unchecked_and_not_indeterminate = true; + bool any_unchecked_or_indeterminate = false; + + TreeItem *child_item = current->get_first_child(); + while (child_item) { + if (!child_item->is_checked(p_column)) { + any_unchecked_or_indeterminate = true; + if (child_item->is_indeterminate(p_column)) { + all_unchecked_and_not_indeterminate = false; + break; + } + } else { + all_unchecked_and_not_indeterminate = false; + } + child_item = child_item->get_next(); + } + + if (all_unchecked_and_not_indeterminate) { + current->set_checked(p_column, false); + } else if (any_unchecked_or_indeterminate) { + current->set_indeterminate(p_column, true); + } else { + current->set_checked(p_column, true); + } + + if (p_emit_signal) { + current->tree->emit_signal("check_propagated_to_item", current, p_column); + } + current->_propagate_check_through_parents(p_column, p_emit_signal); +} + void TreeItem::set_text(int p_column, String p_text) { ERR_FAIL_INDEX(p_column, cells.size()); cells.write[p_column].text = p_text; @@ -1141,6 +1200,8 @@ void TreeItem::_bind_methods() { ClassDB::bind_method(D_METHOD("is_checked", "column"), &TreeItem::is_checked); ClassDB::bind_method(D_METHOD("is_indeterminate", "column"), &TreeItem::is_indeterminate); + ClassDB::bind_method(D_METHOD("propagate_check", "column", "emit_signal"), &TreeItem::propagate_check, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("set_text", "column", "text"), &TreeItem::set_text); ClassDB::bind_method(D_METHOD("get_text", "column"), &TreeItem::get_text); @@ -4847,6 +4908,7 @@ void Tree::_bind_methods() { ADD_SIGNAL(MethodInfo("item_custom_button_pressed")); ADD_SIGNAL(MethodInfo("item_double_clicked")); ADD_SIGNAL(MethodInfo("item_collapsed", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"))); + ADD_SIGNAL(MethodInfo("check_propagated_to_item", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"), PropertyInfo(Variant::INT, "column"))); //ADD_SIGNAL( MethodInfo("item_double_clicked" ) ); ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"), PropertyInfo(Variant::INT, "column"), PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("custom_popup_edited", PropertyInfo(Variant::BOOL, "arrow_clicked"))); diff --git a/scene/gui/tree.h b/scene/gui/tree.h index c60c87564e..33170cad35 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -212,6 +212,14 @@ public: bool is_checked(int p_column) const; bool is_indeterminate(int p_column) const; + void propagate_check(int p_column, bool p_emit_signal = true); + +private: + // Check helpers. + void _propagate_check_through_children(int p_column, bool p_checked, bool p_emit_signal); + void _propagate_check_through_parents(int p_column, bool p_emit_signal); + +public: void set_text(int p_column, String p_text); String get_text(int p_column) const; diff --git a/scene/gui/view_panner.cpp b/scene/gui/view_panner.cpp index ba5e8d4a17..7476887877 100644 --- a/scene/gui/view_panner.cpp +++ b/scene/gui/view_panner.cpp @@ -31,22 +31,18 @@ #include "view_panner.h" #include "core/input/input.h" +#include "core/input/shortcut.h" #include "core/os/keyboard.h" bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - // Alt modifier is unused, so ignore such events. - if (mb->is_alt_pressed()) { - return false; - } - Vector2i scroll_vec = Vector2((mb->get_button_index() == MouseButton::WHEEL_RIGHT) - (mb->get_button_index() == MouseButton::WHEEL_LEFT), (mb->get_button_index() == MouseButton::WHEEL_DOWN) - (mb->get_button_index() == MouseButton::WHEEL_UP)); if (scroll_vec != Vector2()) { if (control_scheme == SCROLL_PANS) { if (mb->is_ctrl_pressed()) { scroll_vec.y *= mb->get_factor(); - callback_helper(zoom_callback, scroll_vec, mb->get_position()); + callback_helper(zoom_callback, varray(scroll_vec, mb->get_position(), mb->is_alt_pressed())); return true; } else { Vector2 panning; @@ -57,7 +53,7 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect) panning.y += mb->get_factor() * scroll_vec.y; panning.x += mb->get_factor() * scroll_vec.x; } - callback_helper(scroll_callback, panning); + callback_helper(scroll_callback, varray(panning, mb->is_alt_pressed())); return true; } } else { @@ -70,23 +66,28 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect) panning.y += mb->get_factor() * scroll_vec.y; panning.x += mb->get_factor() * scroll_vec.x; } - callback_helper(scroll_callback, panning); + callback_helper(scroll_callback, varray(panning, mb->is_alt_pressed())); return true; } else if (!mb->is_shift_pressed()) { scroll_vec.y *= mb->get_factor(); - callback_helper(zoom_callback, scroll_vec, mb->get_position()); + callback_helper(zoom_callback, varray(scroll_vec, mb->get_position(), mb->is_alt_pressed())); return true; } } } - if (mb->get_button_index() == MouseButton::MIDDLE || (mb->get_button_index() == MouseButton::RIGHT && !disable_rmb) || (mb->get_button_index() == MouseButton::LEFT && (Input::get_singleton()->is_key_pressed(Key::SPACE) || (is_dragging && !mb->is_pressed())))) { + // Alt is not used for button presses, so ignore it. + if (mb->is_alt_pressed()) { + return false; + } + + if (mb->get_button_index() == MouseButton::MIDDLE || (enable_rmb && mb->get_button_index() == MouseButton::RIGHT) || (!simple_panning_enabled && mb->get_button_index() == MouseButton::LEFT && is_panning())) { if (mb->is_pressed()) { is_dragging = true; } else { is_dragging = false; } - return true; + return mb->get_button_index() != MouseButton::LEFT || mb->is_pressed(); // Don't consume LMB release events (it fixes some selection problems). } } @@ -94,9 +95,20 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect) if (mm.is_valid()) { if (is_dragging) { if (p_canvas_rect != Rect2()) { - callback_helper(pan_callback, Input::get_singleton()->warp_mouse_motion(mm, p_canvas_rect)); + callback_helper(pan_callback, varray(Input::get_singleton()->warp_mouse_motion(mm, p_canvas_rect))); } else { - callback_helper(pan_callback, mm->get_relative()); + callback_helper(pan_callback, varray(mm->get_relative())); + } + return true; + } + } + + Ref<InputEventKey> k = p_event; + if (k.is_valid()) { + if (pan_view_shortcut.is_valid() && pan_view_shortcut->matches_event(k)) { + pan_key_pressed = k->is_pressed(); + if (simple_panning_enabled || (Input::get_singleton()->get_mouse_button_mask() & MouseButton::LEFT) != MouseButton::NONE) { + is_dragging = pan_key_pressed; } return true; } @@ -105,26 +117,20 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect) return false; } -void ViewPanner::callback_helper(Callable p_callback, Vector2 p_arg1, Vector2 p_arg2) { - if (p_callback == zoom_callback) { - const Variant **argptr = (const Variant **)alloca(sizeof(Variant *) * 2); - Variant var1 = p_arg1; - argptr[0] = &var1; - Variant var2 = p_arg2; - argptr[1] = &var2; - - Variant result; - Callable::CallError ce; - p_callback.call(argptr, 2, result, ce); - } else { - const Variant **argptr = (const Variant **)alloca(sizeof(Variant *)); - Variant var = p_arg1; - argptr[0] = &var; - - Variant result; - Callable::CallError ce; - p_callback.call(argptr, 1, result, ce); +void ViewPanner::release_pan_key() { + pan_key_pressed = false; + is_dragging = false; +} + +void ViewPanner::callback_helper(Callable p_callback, Vector<Variant> p_args) { + const Variant **argptr = (const Variant **)alloca(sizeof(Variant *) * p_args.size()); + for (int i = 0; i < p_args.size(); i++) { + argptr[i] = &p_args[i]; } + + Variant result; + Callable::CallError ce; + p_callback.call(argptr, p_args.size(), result, ce); } void ViewPanner::set_callbacks(Callable p_scroll_callback, Callable p_pan_callback, Callable p_zoom_callback) { @@ -137,6 +143,33 @@ void ViewPanner::set_control_scheme(ControlScheme p_scheme) { control_scheme = p_scheme; } -void ViewPanner::set_disable_rmb(bool p_disable) { - disable_rmb = p_disable; +void ViewPanner::set_enable_rmb(bool p_enable) { + enable_rmb = p_enable; +} + +void ViewPanner::set_pan_shortcut(Ref<Shortcut> p_shortcut) { + pan_view_shortcut = p_shortcut; + pan_key_pressed = false; +} + +void ViewPanner::set_simple_panning_enabled(bool p_enabled) { + simple_panning_enabled = p_enabled; +} + +void ViewPanner::setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning) { + set_control_scheme(p_scheme); + set_pan_shortcut(p_shortcut); + set_simple_panning_enabled(p_simple_panning); +} + +bool ViewPanner::is_panning() const { + return is_dragging || pan_key_pressed; +} + +ViewPanner::ViewPanner() { + Array inputs; + inputs.append(InputEventKey::create_reference(Key::SPACE)); + + pan_view_shortcut.instantiate(); + pan_view_shortcut->set_events(inputs); } diff --git a/scene/gui/view_panner.h b/scene/gui/view_panner.h index 0a92cb3dfd..8423c2a1c0 100644 --- a/scene/gui/view_panner.h +++ b/scene/gui/view_panner.h @@ -34,6 +34,7 @@ #include "core/object/ref_counted.h" class InputEvent; +class Shortcut; class ViewPanner : public RefCounted { GDCLASS(ViewPanner, RefCounted); @@ -46,23 +47,34 @@ public: private: bool is_dragging = false; - bool disable_rmb = false; + bool pan_key_pressed = false; + bool enable_rmb = false; + bool simple_panning_enabled = false; + + Ref<Shortcut> pan_view_shortcut; Callable scroll_callback; Callable pan_callback; Callable zoom_callback; - void callback_helper(Callable p_callback, Vector2 p_arg1, Vector2 p_arg2 = Vector2()); + void callback_helper(Callable p_callback, Vector<Variant> p_args); ControlScheme control_scheme = SCROLL_ZOOMS; public: void set_callbacks(Callable p_scroll_callback, Callable p_pan_callback, Callable p_zoom_callback); void set_control_scheme(ControlScheme p_scheme); - void set_disable_rmb(bool p_disable); + void set_enable_rmb(bool p_enable); + void set_pan_shortcut(Ref<Shortcut> p_shortcut); + void set_simple_panning_enabled(bool p_enabled); + + void setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning); - bool is_panning() const { return is_dragging; } + bool is_panning() const; bool gui_input(const Ref<InputEvent> &p_ev, Rect2 p_canvas_rect = Rect2()); + void release_pan_key(); + + ViewPanner(); }; #endif // VIEW_PANNER_H diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 59d933fa1d..a0916c6291 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -1017,8 +1017,8 @@ void CanvasItem::set_notify_transform(bool p_enable) { notify_transform = p_enable; if (notify_transform && is_inside_tree()) { - //this ensures that invalid globals get resolved, so notifications can be received - get_global_transform(); + // This ensures that invalid globals get resolved, so notifications can be received. + _ALLOW_DISCARD_ get_global_transform(); } } diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 34cc4aceb8..65d210983e 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -442,30 +442,25 @@ void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArra is_compressed = false; } - const PackedByteArray *data = nullptr; - if (accept_gzip && is_compressed && p_data.size() > 0) { // Decompress request body - PackedByteArray *decompressed = memnew(PackedByteArray); - int result = Compression::decompress_dynamic(decompressed, body_size_limit, p_data.ptr(), p_data.size(), mode); + PackedByteArray decompressed; + int result = Compression::decompress_dynamic(&decompressed, body_size_limit, p_data.ptr(), p_data.size(), mode); if (result == OK) { - data = decompressed; + emit_signal(SNAME("request_completed"), p_status, p_code, p_headers, decompressed); + return; } else if (result == -5) { WARN_PRINT("Decompressed size of HTTP response body exceeded body_size_limit"); p_status = RESULT_BODY_SIZE_LIMIT_EXCEEDED; // Just return the raw data if we failed to decompress it - data = &p_data; } else { WARN_PRINT("Failed to decompress HTTP response body"); p_status = RESULT_BODY_DECOMPRESS_FAILED; // Just return the raw data if we failed to decompress it - data = &p_data; } - } else { - data = &p_data; } - emit_signal(SNAME("request_completed"), p_status, p_code, p_headers, *data); + emit_signal(SNAME("request_completed"), p_status, p_code, p_headers, p_data); } void HTTPRequest::_notification(int p_what) { diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 9d96c71113..a2415442f8 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1316,12 +1316,14 @@ Node *Node::get_node_or_null(const NodePath &p_path) const { Node *Node::get_node(const NodePath &p_path) const { Node *node = get_node_or_null(p_path); - if (p_path.is_absolute()) { - ERR_FAIL_COND_V_MSG(!node, nullptr, - vformat(R"(Node not found: "%s" (absolute path attempted from "%s").)", p_path, get_path())); - } else { - ERR_FAIL_COND_V_MSG(!node, nullptr, - vformat(R"(Node not found: "%s" (relative to "%s").)", p_path, get_path())); + if (unlikely(!node)) { + if (p_path.is_absolute()) { + ERR_FAIL_V_MSG(nullptr, + vformat(R"(Node not found: "%s" (absolute path attempted from "%s").)", p_path, get_path())); + } else { + ERR_FAIL_V_MSG(nullptr, + vformat(R"(Node not found: "%s" (relative to "%s").)", p_path, get_path())); + } } return node; @@ -2186,7 +2188,7 @@ void Node::remap_node_resources(Node *p_node, const Map<RES, RES> &p_resource_re } Variant v = p_node->get(E.name); - if (v.is_ref()) { + if (v.is_ref_counted()) { RES res = v; if (res.is_valid()) { if (p_resource_remap.has(res)) { @@ -2212,7 +2214,7 @@ void Node::remap_nested_resources(RES p_resource, const Map<RES, RES> &p_resourc } Variant v = p_resource->get(E.name); - if (v.is_ref()) { + if (v.is_ref_counted()) { RES res = v; if (res.is_valid()) { if (p_resource_remap.has(res)) { diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index cafa4a43fd..0c92dcae11 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -1328,6 +1328,8 @@ SceneTree::SceneTree() { root = memnew(Window); root->set_process_mode(Node::PROCESS_MODE_PAUSABLE); root->set_name("root"); + root->set_title(ProjectSettings::get_singleton()->get("application/config/name")); + #ifndef _3D_DISABLED if (!root->get_world_3d().is_valid()) { root->set_world_3d(Ref<World3D>(memnew(World3D))); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 2cdafefba7..1244e0c028 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -523,6 +523,13 @@ void Viewport::_process_picking() { _drop_physics_mouseover(true); +#ifndef _3D_DISABLED + Vector2 last_pos(1e20, 1e20); + CollisionObject3D *last_object = nullptr; + ObjectID last_id; + PhysicsDirectSpaceState3D::RayResult result; +#endif // _3D_DISABLED + PhysicsDirectSpaceState2D *ss2d = PhysicsServer2D::get_singleton()->space_get_direct_state(find_world_2d()->get_space()); if (physics_has_last_mousepos) { @@ -690,10 +697,6 @@ void Viewport::_process_picking() { } #ifndef _3D_DISABLED - Vector2 last_pos(1e20, 1e20); - CollisionObject3D *last_object = nullptr; - ObjectID last_id; - PhysicsDirectSpaceState3D::RayResult result; bool captured = false; if (physics_object_capture.is_valid()) { @@ -790,7 +793,7 @@ void Viewport::update_canvas_items() { } void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override, const Rect2i &p_to_screen_rect, const Transform2D &p_stretch_transform, bool p_allocated) { - if (size == p_size && size_allocated == p_allocated && stretch_transform == p_stretch_transform && p_size_2d_override == size_2d_override && to_screen_rect != p_to_screen_rect) { + if (size == p_size && size_allocated == p_allocated && stretch_transform == p_stretch_transform && p_size_2d_override == size_2d_override && to_screen_rect == p_to_screen_rect) { return; } @@ -1090,7 +1093,7 @@ Transform2D Viewport::_get_input_pre_xform() const { if (to_screen_rect.size.x != 0 && to_screen_rect.size.y != 0) { pre_xf.elements[2] = -to_screen_rect.position; - pre_xf.scale(size / to_screen_rect.size); + pre_xf.scale(Vector2(size) / to_screen_rect.size); } return pre_xf; diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 43de4187d4..fbc0bc5301 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -41,7 +41,16 @@ void Window::set_title(const String &p_title) { if (embedder) { embedder->_sub_window_update(this); } else if (window_id != DisplayServer::INVALID_WINDOW_ID) { - DisplayServer::get_singleton()->window_set_title(atr(p_title), window_id); + String tr_title = atr(p_title); +#ifdef DEBUG_ENABLED + if (window_id == DisplayServer::MAIN_WINDOW_ID) { + // Append a suffix to the window title to denote that the project is running + // from a debug build (including the editor). Since this results in lower performance, + // this should be clearly presented to the user. + tr_title = vformat("%s (DEBUG)", tr_title); + } +#endif + DisplayServer::get_singleton()->window_set_title(tr_title, window_id); } } @@ -234,7 +243,16 @@ void Window::_make_window() { DisplayServer::get_singleton()->window_set_current_screen(current_screen, window_id); DisplayServer::get_singleton()->window_set_max_size(max_size, window_id); DisplayServer::get_singleton()->window_set_min_size(min_size, window_id); - DisplayServer::get_singleton()->window_set_title(atr(title), window_id); + String tr_title = atr(title); +#ifdef DEBUG_ENABLED + if (window_id == DisplayServer::MAIN_WINDOW_ID) { + // Append a suffix to the window title to denote that the project is running + // from a debug build (including the editor). Since this results in lower performance, + // this should be clearly presented to the user. + tr_title = vformat("%s (DEBUG)", tr_title); + } +#endif + DisplayServer::get_singleton()->window_set_title(tr_title, window_id); DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id); _update_window_size(); @@ -281,6 +299,11 @@ void Window::_clear_window() { DisplayServer::get_singleton()->delete_sub_window(window_id); window_id = DisplayServer::INVALID_WINDOW_ID; + // If closing window was focused and has a parent, return focus. + if (focused && transient_parent) { + transient_parent->grab_focus(); + } + _update_viewport_size(); RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_DISABLED); } @@ -768,7 +791,16 @@ void Window::_notification(int p_what) { if (embedder) { embedder->_sub_window_update(this); } else if (window_id != DisplayServer::INVALID_WINDOW_ID) { - DisplayServer::get_singleton()->window_set_title(atr(title), window_id); + String tr_title = atr(title); +#ifdef DEBUG_ENABLED + if (window_id == DisplayServer::MAIN_WINDOW_ID) { + // Append a suffix to the window title to denote that the project is running + // from a debug build (including the editor). Since this results in lower performance, + // this should be clearly presented to the user. + tr_title = vformat("%s (DEBUG)", tr_title); + } +#endif + DisplayServer::get_singleton()->window_set_title(tr_title, window_id); } child_controls_changed(); @@ -1574,6 +1606,7 @@ void Window::_bind_methods() { ADD_SIGNAL(MethodInfo("go_back_requested")); ADD_SIGNAL(MethodInfo("visibility_changed")); ADD_SIGNAL(MethodInfo("about_to_popup")); + ADD_SIGNAL(MethodInfo("theme_changed")); BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index e6b73b7780..69b06c1803 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -91,6 +91,7 @@ #include "scene/gui/control.h" #include "scene/gui/dialogs.h" #include "scene/gui/file_dialog.h" +#include "scene/gui/flow_container.h" #include "scene/gui/graph_edit.h" #include "scene/gui/graph_node.h" #include "scene/gui/grid_container.h" @@ -353,6 +354,9 @@ void register_scene_types() { GDREGISTER_CLASS(CenterContainer); GDREGISTER_CLASS(ScrollContainer); GDREGISTER_CLASS(PanelContainer); + GDREGISTER_VIRTUAL_CLASS(FlowContainer); + GDREGISTER_CLASS(HFlowContainer); + GDREGISTER_CLASS(VFlowContainer); OS::get_singleton()->yield(); // may take time to init @@ -390,6 +394,7 @@ void register_scene_types() { GDREGISTER_VIRTUAL_CLASS(SplitContainer); GDREGISTER_CLASS(HSplitContainer); GDREGISTER_CLASS(VSplitContainer); + GDREGISTER_CLASS(GraphNode); GDREGISTER_CLASS(GraphEdit); @@ -1046,8 +1051,9 @@ void register_scene_types() { } void initialize_theme() { - bool default_theme_hidpi = GLOBAL_DEF("gui/theme/use_hidpi", false); - ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/use_hidpi", PropertyInfo(Variant::BOOL, "gui/theme/use_hidpi", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + // Allow creating the default theme at a different scale to suit higher/lower base resolutions. + float default_theme_scale = GLOBAL_DEF("gui/theme/default_theme_scale", 1.0); + ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_theme_scale", PropertyInfo(Variant::FLOAT, "gui/theme/default_theme_scale", PROPERTY_HINT_RANGE, "0.5,8,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); String theme_path = GLOBAL_DEF_RST("gui/theme/custom", ""); ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom", PropertyInfo(Variant::STRING, "gui/theme/custom", PROPERTY_HINT_FILE, "*.tres,*.res,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); String font_path = GLOBAL_DEF_RST("gui/theme/custom_font", ""); @@ -1063,7 +1069,7 @@ void initialize_theme() { // Always make the default theme to avoid invalid default font/icon/style in the given theme. if (RenderingServer::get_singleton()) { - make_default_theme(default_theme_hidpi, font); + make_default_theme(default_theme_scale, font); } if (!theme_path.is_empty()) { diff --git a/scene/resources/capsule_shape_2d.cpp b/scene/resources/capsule_shape_2d.cpp index cb8a189116..4d2698d27d 100644 --- a/scene/resources/capsule_shape_2d.cpp +++ b/scene/resources/capsule_shape_2d.cpp @@ -84,13 +84,11 @@ real_t CapsuleShape2D::get_height() const { void CapsuleShape2D::draw(const RID &p_to_rid, const Color &p_color) { Vector<Vector2> points = _get_points(); - Vector<Color> col; - col.push_back(p_color); + Vector<Color> col = { p_color }; RenderingServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); if (is_collision_outline_enabled()) { + points.push_back(points[0]); RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col); - // Draw the last segment as it's not drawn by `canvas_item_add_polyline()`. - RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color); } } diff --git a/scene/resources/circle_shape_2d.cpp b/scene/resources/circle_shape_2d.cpp index 68ee1be9f9..9c16ac2eed 100644 --- a/scene/resources/circle_shape_2d.cpp +++ b/scene/resources/circle_shape_2d.cpp @@ -71,18 +71,19 @@ real_t CircleShape2D::get_enclosing_radius() const { void CircleShape2D::draw(const RID &p_to_rid, const Color &p_color) { Vector<Vector2> points; + points.resize(24); + const real_t turn_step = Math_TAU / 24.0; for (int i = 0; i < 24; i++) { - points.push_back(Vector2(Math::cos(i * turn_step), Math::sin(i * turn_step)) * get_radius()); + points.write[i] = Vector2(Math::cos(i * turn_step), Math::sin(i * turn_step)) * get_radius(); } - Vector<Color> col; - col.push_back(p_color); + Vector<Color> col = { p_color }; RenderingServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); + if (is_collision_outline_enabled()) { + points.push_back(points[0]); RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col); - // Draw the last segment as it's not drawn by `canvas_item_add_polyline()`. - RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color); } } diff --git a/scene/resources/default_theme/SCsub b/scene/resources/default_theme/SCsub index 3667ab7c14..f27bd9144e 100644 --- a/scene/resources/default_theme/SCsub +++ b/scene/resources/default_theme/SCsub @@ -4,6 +4,7 @@ Import("env") from platform_methods import run_in_subprocess import default_theme_builders +import default_theme_icons_builders env.add_source_files(env.scene_sources, "*.cpp") @@ -13,3 +14,19 @@ env.CommandNoCache( "#thirdparty/fonts/OpenSans_SemiBold.ttf", run_in_subprocess(default_theme_builders.make_fonts_header), ) + +env["BUILDERS"]["MakeDefaultThemeIconsBuilder"] = Builder( + action=env.Run( + default_theme_icons_builders.make_default_theme_icons_action, "Generating default project theme icons header." + ), + suffix=".h", + src_suffix=".svg", +) + +# Default theme icons +icon_sources = Glob("*.svg") + +env.Alias( + "default_theme_icons", + [env.MakeDefaultThemeIconsBuilder("#scene/resources/default_theme/default_theme_icons.gen.h", icon_sources)], +) diff --git a/scene/resources/default_theme/add.svg b/scene/resources/default_theme/add.svg new file mode 100644 index 0000000000..6884a07aa0 --- /dev/null +++ b/scene/resources/default_theme/add.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v6h-6v2h6v6h2v-6h6v-2h-6v-6z" fill="#b2b2b2" fill-rule="nonzero"/></svg> diff --git a/scene/resources/default_theme/arrow_down.png b/scene/resources/default_theme/arrow_down.png Binary files differdeleted file mode 100644 index bfb87a4761..0000000000 --- a/scene/resources/default_theme/arrow_down.png +++ /dev/null diff --git a/scene/resources/default_theme/arrow_down.svg b/scene/resources/default_theme/arrow_down.svg new file mode 100644 index 0000000000..16cc00fa8f --- /dev/null +++ b/scene/resources/default_theme/arrow_down.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m5 7 3 3 3-3" fill="none" stroke="#b2b2b2" stroke-opacity=".45" stroke-width="2"/></svg> diff --git a/scene/resources/default_theme/arrow_left.png b/scene/resources/default_theme/arrow_left.png Binary files differdeleted file mode 100644 index 4163059dd3..0000000000 --- a/scene/resources/default_theme/arrow_left.png +++ /dev/null diff --git a/scene/resources/default_theme/arrow_left.svg b/scene/resources/default_theme/arrow_left.svg new file mode 100644 index 0000000000..7dbf01e186 --- /dev/null +++ b/scene/resources/default_theme/arrow_left.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m9 11-3-3 3-3" fill="none" stroke="#b2b2b2" stroke-opacity=".45" stroke-width="2"/></svg> diff --git a/scene/resources/default_theme/arrow_right.png b/scene/resources/default_theme/arrow_right.png Binary files differdeleted file mode 100644 index 1e4c8e5529..0000000000 --- a/scene/resources/default_theme/arrow_right.png +++ /dev/null diff --git a/scene/resources/default_theme/arrow_right.svg b/scene/resources/default_theme/arrow_right.svg new file mode 100644 index 0000000000..b031f12ec0 --- /dev/null +++ b/scene/resources/default_theme/arrow_right.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m6 11 3-3-3-3" fill="none" stroke="#b2b2b2" stroke-opacity=".45" stroke-width="2"/></svg> diff --git a/scene/resources/default_theme/bar_arrow.png b/scene/resources/default_theme/bar_arrow.png Binary files differdeleted file mode 100644 index 7cf146b8da..0000000000 --- a/scene/resources/default_theme/bar_arrow.png +++ /dev/null diff --git a/scene/resources/default_theme/bookmark.png b/scene/resources/default_theme/bookmark.png Binary files differdeleted file mode 100644 index 9718cf53b6..0000000000 --- a/scene/resources/default_theme/bookmark.png +++ /dev/null diff --git a/scene/resources/default_theme/bookmark.svg b/scene/resources/default_theme/bookmark.svg new file mode 100644 index 0000000000..0b50c2b034 --- /dev/null +++ b/scene/resources/default_theme/bookmark.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#fefffe" fill-opacity=".85"><path d="m14.505 1.476h-12.995v13.049l6.491-5.185 6.504 5.185z"/><path d="m15.018 1.476c0-.25-.23-.452-.514-.452h-12.994c-.284 0-.513.202-.513.452v13.049c0 .178.119.34.306.413.185.071.402.041.552-.079l6.146-4.909 6.158 4.909c.151.12.367.15.553.079.187-.073.306-.235.306-.413zm-.514 0h-12.994v13.049l6.491-5.185 6.503 5.185z"/></g></svg> diff --git a/scene/resources/default_theme/breakpoint.svg b/scene/resources/default_theme/breakpoint.svg new file mode 100644 index 0000000000..9b18b276d8 --- /dev/null +++ b/scene/resources/default_theme/breakpoint.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m15 8c0 3.84-3.16 7-7 7s-7-3.16-7-7 3.16-7 7-7 7 3.16 7 7" fill="#ff5d5d" fill-opacity=".5" fill-rule="nonzero"/></svg> diff --git a/scene/resources/default_theme/button_disabled.png b/scene/resources/default_theme/button_disabled.png Binary files differdeleted file mode 100644 index 708748dfe9..0000000000 --- a/scene/resources/default_theme/button_disabled.png +++ /dev/null diff --git a/scene/resources/default_theme/button_focus.png b/scene/resources/default_theme/button_focus.png Binary files differdeleted file mode 100644 index 70e16b953b..0000000000 --- a/scene/resources/default_theme/button_focus.png +++ /dev/null diff --git a/scene/resources/default_theme/button_hover.png b/scene/resources/default_theme/button_hover.png Binary files differdeleted file mode 100644 index ff2258281e..0000000000 --- a/scene/resources/default_theme/button_hover.png +++ /dev/null diff --git a/scene/resources/default_theme/button_normal.png b/scene/resources/default_theme/button_normal.png Binary files differdeleted file mode 100644 index c189b61b89..0000000000 --- a/scene/resources/default_theme/button_normal.png +++ /dev/null diff --git a/scene/resources/default_theme/button_pressed.png b/scene/resources/default_theme/button_pressed.png Binary files differdeleted file mode 100644 index 19a7e237aa..0000000000 --- a/scene/resources/default_theme/button_pressed.png +++ /dev/null diff --git a/scene/resources/default_theme/checked.png b/scene/resources/default_theme/checked.png Binary files differdeleted file mode 100644 index bde031b6a2..0000000000 --- a/scene/resources/default_theme/checked.png +++ /dev/null diff --git a/scene/resources/default_theme/checked.svg b/scene/resources/default_theme/checked.svg new file mode 100644 index 0000000000..6c3bc8f210 --- /dev/null +++ b/scene/resources/default_theme/checked.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.3333333 1c-1.2887 0-2.3333333 1.0446683-2.3333333 2.3333333v9.3333337c0 1.2887 1.0446683 2.333333 2.3333333 2.333333h9.3333337c1.2887 0 2.333333-1.044668 2.333333-2.333333v-9.3333337c0-1.2887-1.044668-2.3333333-2.333333-2.3333333z" fill="#fff" fill-opacity=".75" stroke-width="1.16667"/><path d="m11.500773 3.7343508-5.6117507 5.6117502-1.7045017-1.6814543-1.4992276 1.4992276 3.2037293 3.1806817 7.1109777-7.1109775z" fill="#1a1a1a" stroke-width="1.06023"/></svg> diff --git a/scene/resources/default_theme/checked_disabled.png b/scene/resources/default_theme/checked_disabled.png Binary files differdeleted file mode 100644 index 70549e2edc..0000000000 --- a/scene/resources/default_theme/checked_disabled.png +++ /dev/null diff --git a/scene/resources/default_theme/checked_disabled.svg b/scene/resources/default_theme/checked_disabled.svg new file mode 100644 index 0000000000..109c4dc129 --- /dev/null +++ b/scene/resources/default_theme/checked_disabled.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.3333333 1c-1.2887 0-2.3333333 1.0446683-2.3333333 2.3333333v9.3333337c0 1.2887 1.0446683 2.333333 2.3333333 2.333333h9.3333337c1.2887 0 2.333333-1.044668 2.333333-2.333333v-9.3333337c0-1.2887-1.044668-2.3333333-2.333333-2.3333333z" fill="#fff" fill-opacity=".37" stroke-width="1.16667"/><path d="m11.500773 3.7343508-5.6117507 5.6117502-1.7045017-1.6814543-1.4992276 1.4992276 3.2037293 3.1806817 7.1109777-7.1109775z" fill="#1a1a1a" fill-opacity=".5" stroke-width="1.06023"/></svg> diff --git a/scene/resources/default_theme/checker_bg.png b/scene/resources/default_theme/checker_bg.png Binary files differdeleted file mode 100644 index 3eff2f0e08..0000000000 --- a/scene/resources/default_theme/checker_bg.png +++ /dev/null diff --git a/scene/resources/default_theme/close.png b/scene/resources/default_theme/close.png Binary files differdeleted file mode 100644 index 4d4ac4a551..0000000000 --- a/scene/resources/default_theme/close.png +++ /dev/null diff --git a/scene/resources/default_theme/close.svg b/scene/resources/default_theme/close.svg new file mode 100644 index 0000000000..c26cca06c3 --- /dev/null +++ b/scene/resources/default_theme/close.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 3 2-2 5 5 5-5 2 2-5 5 5 5-2 2-5.3020979-5-4.6979021 5-2-2 5-5z" fill="#fff" fill-opacity=".75"/></svg> diff --git a/scene/resources/default_theme/close_hl.png b/scene/resources/default_theme/close_hl.png Binary files differdeleted file mode 100644 index 4d4ac4a551..0000000000 --- a/scene/resources/default_theme/close_hl.png +++ /dev/null diff --git a/scene/resources/default_theme/close_hl.svg b/scene/resources/default_theme/close_hl.svg new file mode 100644 index 0000000000..ec44ba6d24 --- /dev/null +++ b/scene/resources/default_theme/close_hl.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 3 2-2 5 5 5-5 2 2-5 5 5 5-2 2-5.3020979-5-4.6979021 5-2-2 5-5z" fill="#fff"/></svg> diff --git a/scene/resources/default_theme/color_picker_bar_arrow.svg b/scene/resources/default_theme/color_picker_bar_arrow.svg new file mode 100644 index 0000000000..5043da0761 --- /dev/null +++ b/scene/resources/default_theme/color_picker_bar_arrow.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 20" xmlns="http://www.w3.org/2000/svg"><path d="m3.564 15.218h8.872l-4.436-4.436z" fill="#b2b2b2" fill-rule="nonzero" stroke="#b2b2b2"/></svg> diff --git a/scene/resources/default_theme/color_picker_cursor.svg b/scene/resources/default_theme/color_picker_cursor.svg new file mode 100644 index 0000000000..88ee3f55ce --- /dev/null +++ b/scene/resources/default_theme/color_picker_cursor.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2a6 6 0 0 0 -6 6 6 6 0 0 0 6 6 6 6 0 0 0 6-6 6 6 0 0 0 -6-6zm0 1a5 5 0 0 1 5 5 5 5 0 0 1 -5 5 5 5 0 0 1 -5-5 5 5 0 0 1 5-5z" fill="#fff"/><path d="m8 3a5 5 0 0 0 -5 5 5 5 0 0 0 5 5 5 5 0 0 0 5-5 5 5 0 0 0 -5-5zm-.0605469 1a4 4 0 0 1 .0605469 0 4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 3.9394531-4z"/></svg> diff --git a/scene/resources/default_theme/color_picker_hue.png b/scene/resources/default_theme/color_picker_hue.png Binary files differdeleted file mode 100644 index 7b46f03cb4..0000000000 --- a/scene/resources/default_theme/color_picker_hue.png +++ /dev/null diff --git a/scene/resources/default_theme/color_picker_hue.svg b/scene/resources/default_theme/color_picker_hue.svg new file mode 100644 index 0000000000..ff75d5eb9e --- /dev/null +++ b/scene/resources/default_theme/color_picker_hue.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 1 256" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(0 256 -256 0 0 0)" gradientUnits="userSpaceOnUse" x1="0" x2="1" y1="0" y2="0"><stop offset="0" stop-color="#f00"/><stop offset=".04" stop-color="#ff4000"/><stop offset=".08" stop-color="#ff8000"/><stop offset=".17" stop-color="#ff0"/><stop offset=".25" stop-color="#80ff00"/><stop offset=".33" stop-color="#0f0"/><stop offset=".42" stop-color="#00ff80"/><stop offset=".5" stop-color="#0ff"/><stop offset=".58" stop-color="#0080ff"/><stop offset=".63" stop-color="#0040ff"/><stop offset=".67" stop-color="#00f"/><stop offset=".75" stop-color="#8000ff"/><stop offset=".83" stop-color="#f0f"/><stop offset=".92" stop-color="#ff0080"/><stop offset="1" stop-color="#f00"/></linearGradient><path d="m0 0h1v256h-1z" fill="url(#a)"/></svg> diff --git a/scene/resources/default_theme/color_picker_overbright.svg b/scene/resources/default_theme/color_picker_overbright.svg new file mode 100644 index 0000000000..f618980d51 --- /dev/null +++ b/scene/resources/default_theme/color_picker_overbright.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m.5.5v10l10-10z" fill="#fff" stroke="#000"/><path d="m0 12 12-12h-1.714286l-10.285714 10.285714z" fill="#000003" stroke-width="2"/></svg> diff --git a/scene/resources/default_theme/color_picker_pipette.svg b/scene/resources/default_theme/color_picker_pipette.svg new file mode 100644 index 0000000000..5213a6e1bc --- /dev/null +++ b/scene/resources/default_theme/color_picker_pipette.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-1.108 0-2 .892-2 2v2h-1v2h1v5c.001.712.383 1.372 1 1.729v1.271h2v-1.27c.618-.356.999-1.017 1-1.73v-5h1v-2h-1v-2c0-1.108-.892-2-2-2zm-1 6h2v5c0 .549-.451 1-1 1s-1-.451-1-1z" fill="#b2b2b2" fill-rule="nonzero"/></svg> diff --git a/scene/resources/default_theme/color_picker_sample.png b/scene/resources/default_theme/color_picker_sample.png Binary files differdeleted file mode 100644 index e6ec28d307..0000000000 --- a/scene/resources/default_theme/color_picker_sample.png +++ /dev/null diff --git a/scene/resources/default_theme/color_picker_sample.svg b/scene/resources/default_theme/color_picker_sample.svg new file mode 100644 index 0000000000..140ac20a99 --- /dev/null +++ b/scene/resources/default_theme/color_picker_sample.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 256 20" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero"><path d="m0 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m5 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m80 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m85 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m159.978 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m164.978 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m39.991 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m44.991 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m119.99 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m124.99 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m199.968 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m204.968 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m9.98 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m14.98 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m89.98 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m94.98 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m169.957 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m174.957 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m49.97 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m54.97 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m129.97 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m134.97 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m209.948 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m214.948 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m19.995 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m24.995 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m99.995 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m104.995 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m179.973 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m184.973 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m59.986 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m64.986 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m139.986 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m144.986 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m219.964 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m224.964 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m30.011 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m35.011 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m110.011 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m115.011 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m189.989 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m194.989 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m70.001 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m75.001 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m150.001 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m155.001 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m229.979 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m234.979 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m240.017 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m245.017 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m249.996 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m254.996 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m249.996 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m254.996 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m240.017 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m245.017 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m0 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m5 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m80 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m85 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m159.978 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m164.978 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m39.991 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m44.991 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m119.99 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m124.99 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m199.968 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m204.968 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m9.98 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m14.98 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m89.98 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m94.98 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m169.957 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m174.957 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m49.97 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m54.97 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m129.97 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m134.97 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m209.948 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m214.948 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m19.995 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m24.995 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m99.995 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m104.995 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m179.973 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m184.973 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m59.986 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m64.986 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m139.986 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m144.986 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m219.964 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m224.964 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m30.011 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m35.011 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m110.011 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m115.011 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m189.989 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m194.989 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m70.001 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m75.001 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m150.001 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m155.001 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m229.979 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m234.979 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/></g></svg> diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 61cd834867..12ea1683c8 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -32,49 +32,22 @@ #include "core/os/os.h" #include "default_font.gen.h" +#include "default_theme_icons.gen.h" #include "scene/resources/font.h" #include "scene/resources/theme.h" #include "servers/text_server.h" -#include "theme_data.h" -typedef Map<const void *, Ref<ImageTexture>> TexCacheMap; +#include "modules/modules_enabled.gen.h" // For svg. +#ifdef MODULE_SVG_ENABLED +#include "modules/svg/image_loader_svg.h" +#endif -static TexCacheMap *tex_cache; static float scale = 1.0; -template <class T> -static Ref<StyleBoxTexture> make_stylebox(T p_src, float p_left, float p_top, float p_right, float p_bottom, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1, bool p_draw_center = true) { - Ref<ImageTexture> texture; +static const int default_margin = 4; +static const int default_corner_radius = 3; - if (tex_cache->has(p_src)) { - texture = (*tex_cache)[p_src]; - } else { - texture = Ref<ImageTexture>(memnew(ImageTexture)); - Ref<Image> img = memnew(Image(p_src)); - const Size2 orig_size = img->get_size(); - img->convert(Image::FORMAT_RGBA8); - img->resize(orig_size.x * scale, orig_size.y * scale); - - texture->create_from_image(img); - (*tex_cache)[p_src] = texture; - } - - Ref<StyleBoxTexture> style(memnew(StyleBoxTexture)); - style->set_texture(texture); - style->set_margin_size(SIDE_LEFT, p_left * scale); - style->set_margin_size(SIDE_RIGHT, p_right * scale); - style->set_margin_size(SIDE_BOTTOM, p_bottom * scale); - style->set_margin_size(SIDE_TOP, p_top * scale); - style->set_default_margin(SIDE_LEFT, p_margin_left * scale); - style->set_default_margin(SIDE_RIGHT, p_margin_right * scale); - style->set_default_margin(SIDE_BOTTOM, p_margin_bottom * scale); - style->set_default_margin(SIDE_TOP, p_margin_top * scale); - style->set_draw_center(p_draw_center); - - return style; -} - -static Ref<StyleBoxFlat> make_flat_stylebox(Color p_color, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) { +static Ref<StyleBoxFlat> make_flat_stylebox(Color p_color, float p_margin_left = default_margin, float p_margin_top = default_margin, float p_margin_right = default_margin, float p_margin_bottom = default_margin, int p_corner_radius = default_corner_radius, bool p_draw_center = true, int p_border_width = 0) { Ref<StyleBoxFlat> style(memnew(StyleBoxFlat)); style->set_bg_color(p_color); style->set_default_margin(SIDE_LEFT, p_margin_left * scale); @@ -82,10 +55,18 @@ static Ref<StyleBoxFlat> make_flat_stylebox(Color p_color, float p_margin_left = style->set_default_margin(SIDE_BOTTOM, p_margin_bottom * scale); style->set_default_margin(SIDE_TOP, p_margin_top * scale); + style->set_corner_radius_all(p_corner_radius); + style->set_anti_aliased(true); + // Adjust level of detail based on the corners' effective sizes. + style->set_corner_detail(MIN(Math::ceil(1.5 * p_corner_radius), 6) * scale); + + style->set_draw_center(p_draw_center); + style->set_border_width_all(p_border_width); + return style; } -static Ref<StyleBoxTexture> sb_expand(Ref<StyleBoxTexture> p_sbox, float p_left, float p_top, float p_right, float p_bottom) { +static Ref<StyleBoxFlat> sb_expand(Ref<StyleBoxFlat> p_sbox, float p_left, float p_top, float p_right, float p_bottom) { p_sbox->set_expand_margin_size(SIDE_LEFT, p_left * scale); p_sbox->set_expand_margin_size(SIDE_TOP, p_top * scale); p_sbox->set_expand_margin_size(SIDE_RIGHT, p_right * scale); @@ -93,36 +74,22 @@ static Ref<StyleBoxTexture> sb_expand(Ref<StyleBoxTexture> p_sbox, float p_left, return p_sbox; } -template <class T> -static Ref<Texture2D> make_icon(T p_src) { - Ref<ImageTexture> texture(memnew(ImageTexture)); - Ref<Image> img = memnew(Image(p_src)); - const Size2 orig_size = img->get_size(); - img->convert(Image::FORMAT_RGBA8); - img->resize(orig_size.x * scale, orig_size.y * scale); - texture->create_from_image(img); - - return texture; -} - -static Ref<Texture2D> flip_icon(Ref<Texture2D> p_texture, bool p_flip_y = false, bool p_flip_x = false) { - if (!p_flip_y && !p_flip_x) { - return p_texture; - } - - Ref<ImageTexture> texture(memnew(ImageTexture)); - Ref<Image> img = p_texture->get_image(); - img = img->duplicate(); - - if (p_flip_y) { - img->flip_y(); - } - if (p_flip_x) { - img->flip_x(); - } - - texture->create_from_image(img); - return texture; +// See also `editor_generate_icon()` in `editor/editor_themes.cpp`. +static Ref<ImageTexture> generate_icon(int p_index) { + Ref<ImageTexture> icon = memnew(ImageTexture); + Ref<Image> img = memnew(Image); + +#ifdef MODULE_SVG_ENABLED + // Upsample icon generation only if the scale isn't an integer multiplier. + // Generating upsampled icons is slower, and the benefit is hardly visible + // with integer scales. + const bool upsample = !Math::is_equal_approx(Math::round(scale), scale); + ImageLoaderSVG img_loader; + img_loader.create_image_from_string(img, default_theme_icons_sources[p_index], scale, upsample, false); +#endif + icon->create_from_image(img); + + return icon; } static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) { @@ -136,48 +103,59 @@ static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margi return style; } -void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &large_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale) { +void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale) { scale = p_scale; - tex_cache = memnew(TexCacheMap); - - // Font Colors - - Color control_font_color = Color(0.88, 0.88, 0.88); - Color control_font_lower_color = Color(0.63, 0.63, 0.63); - Color control_font_low_color = Color(0.69, 0.69, 0.69); - Color control_font_hover_color = Color(0.94, 0.94, 0.94); - Color control_font_focus_color = Color(0.94, 0.94, 0.94); - Color control_font_disabled_color = Color(0.9, 0.9, 0.9, 0.2); - Color control_font_pressed_color = Color(1, 1, 1); - - Color control_selection_color = Color(0.49, 0.49, 0.49); + // Font colors + const Color control_font_color = Color(0.875, 0.875, 0.875); + const Color control_font_low_color = Color(0.7, 0.7, 0.7); + const Color control_font_lower_color = Color(0.65, 0.65, 0.65); + const Color control_font_hover_color = Color(0.95, 0.95, 0.95); + const Color control_font_focus_color = Color(0.95, 0.95, 0.95); + const Color control_font_disabled_color = control_font_color * Color(1, 1, 1, 0.5); + const Color control_font_pressed_color = Color(1, 1, 1); + const Color control_selection_color = Color(0.5, 0.5, 0.5); + + // StyleBox colors + const Color style_normal_color = Color(0.1, 0.1, 0.1, 0.6); + const Color style_hover_color = Color(0.225, 0.225, 0.225, 0.6); + const Color style_pressed_color = Color(0, 0, 0, 0.6); + const Color style_disabled_color = Color(0.1, 0.1, 0.1, 0.3); + const Color style_focus_color = Color(1, 1, 1, 0.75); + const Color style_popup_color = Color(0.25, 0.25, 0.25, 1); + const Color style_popup_border_color = Color(0.175, 0.175, 0.175, 1); + const Color style_popup_hover_color = Color(0.4, 0.4, 0.4, 1); + const Color style_selected_color = Color(1, 1, 1, 0.3); + // Don't use a color too bright to keep the percentage readable. + const Color style_progress_color = Color(1, 1, 1, 0.4); + const Color style_separator_color = Color(0.5, 0.5, 0.5); + + // Convert the generated icon sources to a dictionary for easier access. + // Unlike the editor icons, there is no central repository of icons in the Theme resource itself to keep it tidy. + Dictionary icons; + for (int i = 0; i < default_theme_icons_count; i++) { + icons[default_theme_icons_names[i]] = generate_icon(i); + } // Panel - - theme->set_stylebox("panel", "Panel", make_stylebox(panel_bg_png, 0, 0, 0, 0)); - theme->set_stylebox("panel_fg", "Panel", make_stylebox(panel_bg_png, 0, 0, 0, 0)); - - // Focus - - Ref<StyleBoxTexture> focus = make_stylebox(focus_png, 5, 5, 5, 5); - for (int i = 0; i < 4; i++) { - focus->set_expand_margin_size(Side(i), 1 * scale); - } + theme->set_stylebox("panel", "Panel", make_flat_stylebox(style_normal_color, 0, 0, 0, 0)); + theme->set_stylebox("panel_fg", "Panel", make_flat_stylebox(style_normal_color, 0, 0, 0, 0)); // Button - Ref<StyleBox> sb_button_normal = sb_expand(make_stylebox(button_normal_png, 4, 4, 4, 4, 6, 3, 6, 3), 2, 2, 2, 2); - Ref<StyleBox> sb_button_pressed = sb_expand(make_stylebox(button_pressed_png, 4, 4, 4, 4, 6, 3, 6, 3), 2, 2, 2, 2); - Ref<StyleBox> sb_button_hover = sb_expand(make_stylebox(button_hover_png, 4, 4, 4, 4, 6, 2, 6, 2), 2, 2, 2, 2); - Ref<StyleBox> sb_button_disabled = sb_expand(make_stylebox(button_disabled_png, 4, 4, 4, 4, 6, 2, 6, 2), 2, 2, 2, 2); - Ref<StyleBox> sb_button_focus = sb_expand(make_stylebox(button_focus_png, 4, 4, 4, 4, 6, 2, 6, 2), 2, 2, 2, 2); + const Ref<StyleBoxFlat> button_normal = make_flat_stylebox(style_normal_color); + const Ref<StyleBoxFlat> button_hover = make_flat_stylebox(style_hover_color); + const Ref<StyleBoxFlat> button_pressed = make_flat_stylebox(style_pressed_color); + const Ref<StyleBoxFlat> button_disabled = make_flat_stylebox(style_disabled_color); + Ref<StyleBoxFlat> focus = make_flat_stylebox(style_focus_color, default_margin, default_margin, default_margin, default_margin, default_corner_radius, false, 2); + // Make the focus outline appear to be flush with the buttons it's focusing. + focus->set_expand_margin_size_all(2 * scale); - theme->set_stylebox("normal", "Button", sb_button_normal); - theme->set_stylebox("pressed", "Button", sb_button_pressed); - theme->set_stylebox("hover", "Button", sb_button_hover); - theme->set_stylebox("disabled", "Button", sb_button_disabled); - theme->set_stylebox("focus", "Button", sb_button_focus); + theme->set_stylebox("normal", "Button", button_normal); + theme->set_stylebox("hover", "Button", button_hover); + theme->set_stylebox("pressed", "Button", button_pressed); + theme->set_stylebox("disabled", "Button", button_disabled); + theme->set_stylebox("focus", "Button", focus); theme->set_font("font", "Button", Ref<Font>()); theme->set_font_size("font_size", "Button", -1); @@ -217,31 +195,29 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("underline_spacing", "LinkButton", 2 * scale); // OptionButton + theme->set_stylebox("focus", "OptionButton", focus); - Ref<StyleBox> sb_optbutton_focus = sb_expand(make_stylebox(button_focus_png, 4, 4, 4, 4, 6, 2, 6, 2), 2, 2, 2, 2); - theme->set_stylebox("focus", "OptionButton", sb_optbutton_focus); - - Ref<StyleBox> sb_optbutton_normal = sb_expand(make_stylebox(option_button_normal_png, 4, 4, 21, 4, 6, 3, 9, 3), 2, 2, 2, 2); - Ref<StyleBox> sb_optbutton_pressed = sb_expand(make_stylebox(option_button_pressed_png, 4, 4, 21, 4, 6, 3, 9, 3), 2, 2, 2, 2); - Ref<StyleBox> sb_optbutton_hover = sb_expand(make_stylebox(option_button_hover_png, 4, 4, 21, 4, 6, 2, 9, 2), 2, 2, 2, 2); - Ref<StyleBox> sb_optbutton_disabled = sb_expand(make_stylebox(option_button_disabled_png, 4, 4, 21, 4, 6, 2, 9, 2), 2, 2, 2, 2); + Ref<StyleBox> sb_optbutton_normal = make_flat_stylebox(style_normal_color, 2 * default_margin, default_margin, 21, default_margin); + Ref<StyleBox> sb_optbutton_hover = make_flat_stylebox(style_hover_color, 2 * default_margin, default_margin, 21, default_margin); + Ref<StyleBox> sb_optbutton_pressed = make_flat_stylebox(style_pressed_color, 2 * default_margin, default_margin, 21, default_margin); + Ref<StyleBox> sb_optbutton_disabled = make_flat_stylebox(style_disabled_color, 2 * default_margin, default_margin, 21, default_margin); theme->set_stylebox("normal", "OptionButton", sb_optbutton_normal); - theme->set_stylebox("pressed", "OptionButton", sb_optbutton_pressed); theme->set_stylebox("hover", "OptionButton", sb_optbutton_hover); + theme->set_stylebox("pressed", "OptionButton", sb_optbutton_pressed); theme->set_stylebox("disabled", "OptionButton", sb_optbutton_disabled); - Ref<StyleBox> sb_optbutton_normal_mirrored = sb_expand(make_stylebox(option_button_normal_mirrored_png, 21, 4, 4, 4, 9, 3, 6, 3), 2, 2, 2, 2); - Ref<StyleBox> sb_optbutton_pressed_mirrored = sb_expand(make_stylebox(option_button_pressed_mirrored_png, 21, 4, 4, 4, 9, 3, 6, 3), 2, 2, 2, 2); - Ref<StyleBox> sb_optbutton_hover_mirrored = sb_expand(make_stylebox(option_button_hover_mirrored_png, 21, 4, 4, 4, 9, 2, 6, 2), 2, 2, 2, 2); - Ref<StyleBox> sb_optbutton_disabled_mirrored = sb_expand(make_stylebox(option_button_disabled_mirrored_png, 21, 4, 4, 4, 9, 2, 6, 2), 2, 2, 2, 2); + Ref<StyleBox> sb_optbutton_normal_mirrored = make_flat_stylebox(style_normal_color, 21, default_margin, 2 * default_margin, default_margin); + Ref<StyleBox> sb_optbutton_hover_mirrored = make_flat_stylebox(style_hover_color, 21, default_margin, 2 * default_margin, default_margin); + Ref<StyleBox> sb_optbutton_pressed_mirrored = make_flat_stylebox(style_pressed_color, 21, default_margin, 2 * default_margin, default_margin); + Ref<StyleBox> sb_optbutton_disabled_mirrored = make_flat_stylebox(style_disabled_color, 21, default_margin, 2 * default_margin, default_margin); theme->set_stylebox("normal_mirrored", "OptionButton", sb_optbutton_normal_mirrored); - theme->set_stylebox("pressed_mirrored", "OptionButton", sb_optbutton_pressed_mirrored); theme->set_stylebox("hover_mirrored", "OptionButton", sb_optbutton_hover_mirrored); + theme->set_stylebox("pressed_mirrored", "OptionButton", sb_optbutton_pressed_mirrored); theme->set_stylebox("disabled_mirrored", "OptionButton", sb_optbutton_disabled_mirrored); - theme->set_icon("arrow", "OptionButton", make_icon(option_arrow_png)); + theme->set_icon("arrow", "OptionButton", icons["option_button_arrow"]); theme->set_font("font", "OptionButton", Ref<Font>()); theme->set_font_size("font_size", "OptionButton", -1); @@ -254,16 +230,16 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_color("font_outline_color", "OptionButton", Color(1, 1, 1)); theme->set_constant("hseparation", "OptionButton", 2 * scale); - theme->set_constant("arrow_margin", "OptionButton", 2 * scale); + theme->set_constant("arrow_margin", "OptionButton", 4 * scale); theme->set_constant("outline_size", "OptionButton", 0); // MenuButton - theme->set_stylebox("normal", "MenuButton", sb_button_normal); - theme->set_stylebox("pressed", "MenuButton", sb_button_pressed); - theme->set_stylebox("hover", "MenuButton", sb_button_hover); - theme->set_stylebox("disabled", "MenuButton", sb_button_disabled); - theme->set_stylebox("focus", "MenuButton", sb_button_focus); + theme->set_stylebox("normal", "MenuButton", button_normal); + theme->set_stylebox("pressed", "MenuButton", button_pressed); + theme->set_stylebox("hover", "MenuButton", button_hover); + theme->set_stylebox("disabled", "MenuButton", button_disabled); + theme->set_stylebox("focus", "MenuButton", focus); theme->set_font("font", "MenuButton", Ref<Font>()); theme->set_font_size("font_size", "MenuButton", -1); @@ -298,14 +274,14 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("hover_pressed", "CheckBox", cbx_empty); theme->set_stylebox("focus", "CheckBox", cbx_focus); - theme->set_icon("checked", "CheckBox", make_icon(checked_png)); - theme->set_icon("checked_disabled", "CheckBox", make_icon(checked_disabled_png)); - theme->set_icon("unchecked", "CheckBox", make_icon(unchecked_png)); - theme->set_icon("unchecked_disabled", "CheckBox", make_icon(unchecked_disabled_png)); - theme->set_icon("radio_checked", "CheckBox", make_icon(radio_checked_png)); - theme->set_icon("radio_checked_disabled", "CheckBox", make_icon(radio_checked_disabled_png)); - theme->set_icon("radio_unchecked", "CheckBox", make_icon(radio_unchecked_png)); - theme->set_icon("radio_unchecked_disabled", "CheckBox", make_icon(radio_unchecked_disabled_png)); + theme->set_icon("checked", "CheckBox", icons["checked"]); + theme->set_icon("checked_disabled", "CheckBox", icons["checked"]); + theme->set_icon("unchecked", "CheckBox", icons["unchecked"]); + theme->set_icon("unchecked_disabled", "CheckBox", icons["unchecked"]); + theme->set_icon("radio_checked", "CheckBox", icons["radio_checked"]); + theme->set_icon("radio_checked_disabled", "CheckBox", icons["radio_checked"]); + theme->set_icon("radio_unchecked", "CheckBox", icons["radio_unchecked"]); + theme->set_icon("radio_unchecked_disabled", "CheckBox", icons["radio_unchecked"]); theme->set_font("font", "CheckBox", Ref<Font>()); theme->set_font_size("font_size", "CheckBox", -1); @@ -337,15 +313,15 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("hover_pressed", "CheckButton", cb_empty); theme->set_stylebox("focus", "CheckButton", focus); - theme->set_icon("on", "CheckButton", make_icon(toggle_on_png)); - theme->set_icon("on_disabled", "CheckButton", make_icon(toggle_on_disabled_png)); - theme->set_icon("off", "CheckButton", make_icon(toggle_off_png)); - theme->set_icon("off_disabled", "CheckButton", make_icon(toggle_off_disabled_png)); + theme->set_icon("on", "CheckButton", icons["toggle_on"]); + theme->set_icon("on_disabled", "CheckButton", icons["toggle_on_disabled"]); + theme->set_icon("off", "CheckButton", icons["toggle_off"]); + theme->set_icon("off_disabled", "CheckButton", icons["toggle_off_disabled"]); - theme->set_icon("on_mirrored", "CheckButton", make_icon(toggle_on_mirrored_png)); - theme->set_icon("on_disabled_mirrored", "CheckButton", make_icon(toggle_on_disabled_mirrored_png)); - theme->set_icon("off_mirrored", "CheckButton", make_icon(toggle_off_mirrored_png)); - theme->set_icon("off_disabled_mirrored", "CheckButton", make_icon(toggle_off_disabled_mirrored_png)); + theme->set_icon("on_mirrored", "CheckButton", icons["toggle_on_mirrored"]); + theme->set_icon("on_disabled_mirrored", "CheckButton", icons["toggle_on_disabled_mirrored"]); + theme->set_icon("off_mirrored", "CheckButton", icons["toggle_off_mirrored"]); + theme->set_icon("off_disabled_mirrored", "CheckButton", icons["toggle_off_disabled_mirrored"]); theme->set_font("font", "CheckButton", Ref<Font>()); theme->set_font_size("font_size", "CheckButton", -1); @@ -389,16 +365,26 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // LineEdit - theme->set_stylebox("normal", "LineEdit", make_stylebox(line_edit_png, 5, 5, 5, 5)); + Ref<StyleBoxFlat> style_line_edit = make_flat_stylebox(style_normal_color); + // Add a line at the bottom to make LineEdits distinguishable from Buttons. + style_line_edit->set_border_width(SIDE_BOTTOM, 2); + style_line_edit->set_border_color(style_pressed_color); + theme->set_stylebox("normal", "LineEdit", style_line_edit); + theme->set_stylebox("focus", "LineEdit", focus); - theme->set_stylebox("read_only", "LineEdit", make_stylebox(line_edit_disabled_png, 6, 6, 6, 6)); + + Ref<StyleBoxFlat> style_line_edit_read_only = make_flat_stylebox(style_disabled_color); + // Add a line at the bottom to make LineEdits distinguishable from Buttons. + style_line_edit_read_only->set_border_width(SIDE_BOTTOM, 2); + style_line_edit_read_only->set_border_color(style_pressed_color * Color(1, 1, 1, 0.5)); + theme->set_stylebox("read_only", "LineEdit", style_line_edit_read_only); theme->set_font("font", "LineEdit", Ref<Font>()); theme->set_font_size("font_size", "LineEdit", -1); theme->set_color("font_color", "LineEdit", control_font_color); - theme->set_color("font_selected_color", "LineEdit", Color(0, 0, 0)); - theme->set_color("font_uneditable_color", "LineEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f)); + theme->set_color("font_selected_color", "LineEdit", control_font_pressed_color); + theme->set_color("font_uneditable_color", "LineEdit", control_font_disabled_color); theme->set_color("font_outline_color", "LineEdit", Color(1, 1, 1)); theme->set_color("caret_color", "LineEdit", control_font_hover_color); theme->set_color("selection_color", "LineEdit", control_selection_color); @@ -409,12 +395,12 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("outline_size", "LineEdit", 0); theme->set_constant("caret_width", "LineEdit", 1); - theme->set_icon("clear", "LineEdit", make_icon(line_edit_clear_png)); + theme->set_icon("clear", "LineEdit", icons["line_edit_clear"]); // ProgressBar - theme->set_stylebox("bg", "ProgressBar", make_stylebox(progress_bar_png, 4, 4, 4, 4, 0, 0, 0, 0)); - theme->set_stylebox("fg", "ProgressBar", make_stylebox(progress_fill_png, 6, 6, 6, 6, 2, 1, 2, 1)); + theme->set_stylebox("bg", "ProgressBar", make_flat_stylebox(style_disabled_color, 2, 2, 2, 2, 6)); + theme->set_stylebox("fg", "ProgressBar", make_flat_stylebox(style_progress_color, 2, 2, 2, 2, 6)); theme->set_font("font", "ProgressBar", Ref<Font>()); theme->set_font_size("font_size", "ProgressBar", -1); @@ -427,26 +413,26 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // TextEdit - theme->set_stylebox("normal", "TextEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3, 0, 0, 0, 0)); + theme->set_stylebox("normal", "TextEdit", style_line_edit); theme->set_stylebox("focus", "TextEdit", focus); - theme->set_stylebox("read_only", "TextEdit", make_stylebox(tree_bg_disabled_png, 4, 4, 4, 4, 0, 0, 0, 0)); + theme->set_stylebox("read_only", "TextEdit", style_line_edit_read_only); - theme->set_icon("tab", "TextEdit", make_icon(tab_png)); - theme->set_icon("space", "TextEdit", make_icon(space_png)); + theme->set_icon("tab", "TextEdit", icons["text_edit_tab"]); + theme->set_icon("space", "TextEdit", icons["text_edit_space"]); theme->set_font("font", "TextEdit", Ref<Font>()); theme->set_font_size("font_size", "TextEdit", -1); theme->set_color("background_color", "TextEdit", Color(0, 0, 0, 0)); theme->set_color("font_color", "TextEdit", control_font_color); - theme->set_color("font_selected_color", "TextEdit", Color(0, 0, 0)); - theme->set_color("font_readonly_color", "TextEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f)); + theme->set_color("font_selected_color", "TextEdit", control_font_pressed_color); + theme->set_color("font_readonly_color", "TextEdit", control_font_disabled_color); theme->set_color("font_outline_color", "TextEdit", Color(1, 1, 1)); theme->set_color("selection_color", "TextEdit", control_selection_color); theme->set_color("current_line_color", "TextEdit", Color(0.25, 0.25, 0.26, 0.8)); theme->set_color("caret_color", "TextEdit", control_font_color); theme->set_color("caret_background_color", "TextEdit", Color(0, 0, 0)); - theme->set_color("word_highlighted_color", "TextEdit", Color(0.8, 0.9, 0.9, 0.15)); + theme->set_color("word_highlighted_color", "TextEdit", Color(0.5, 0.5, 0.5, 0.25)); theme->set_color("search_result_color", "TextEdit", Color(0.3, 0.3, 0.3)); theme->set_color("search_result_border_color", "TextEdit", Color(0.3, 0.3, 0.3, 0.4)); @@ -456,19 +442,19 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // CodeEdit - theme->set_stylebox("normal", "CodeEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3, 0, 0, 0, 0)); + theme->set_stylebox("normal", "CodeEdit", style_line_edit); theme->set_stylebox("focus", "CodeEdit", focus); - theme->set_stylebox("read_only", "CodeEdit", make_stylebox(tree_bg_disabled_png, 4, 4, 4, 4, 0, 0, 0, 0)); - theme->set_stylebox("completion", "CodeEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3, 0, 0, 0, 0)); - - theme->set_icon("tab", "CodeEdit", make_icon(tab_png)); - theme->set_icon("space", "CodeEdit", make_icon(space_png)); - theme->set_icon("breakpoint", "CodeEdit", make_icon(graph_port_png)); - theme->set_icon("bookmark", "CodeEdit", make_icon(bookmark_png)); - theme->set_icon("executing_line", "CodeEdit", make_icon(arrow_right_png)); - theme->set_icon("can_fold", "CodeEdit", make_icon(arrow_down_png)); - theme->set_icon("folded", "CodeEdit", make_icon(arrow_right_png)); - theme->set_icon("folded_eol_icon", "CodeEdit", make_icon(ellipsis_png)); + theme->set_stylebox("read_only", "CodeEdit", style_line_edit_read_only); + theme->set_stylebox("completion", "CodeEdit", make_flat_stylebox(style_normal_color, 0, 0, 0, 0)); + + theme->set_icon("tab", "CodeEdit", icons["text_edit_tab"]); + theme->set_icon("space", "CodeEdit", icons["text_edit_space"]); + theme->set_icon("breakpoint", "CodeEdit", icons["breakpoint"]); + theme->set_icon("bookmark", "CodeEdit", icons["bookmark"]); + theme->set_icon("executing_line", "CodeEdit", icons["arrow_right"]); + theme->set_icon("can_fold", "CodeEdit", icons["arrow_down"]); + theme->set_icon("folded", "CodeEdit", icons["arrow_right"]); + theme->set_icon("folded_eol_icon", "CodeEdit", icons["text_edit_ellipsis"]); theme->set_font("font", "CodeEdit", Ref<Font>()); theme->set_font_size("font_size", "CodeEdit", -1); @@ -506,13 +492,18 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Texture2D> empty_icon = memnew(ImageTexture); + const Ref<StyleBoxFlat> style_scrollbar = make_flat_stylebox(style_normal_color, 4, 4, 4, 4, 10); + Ref<StyleBoxFlat> style_scrollbar_grabber = make_flat_stylebox(style_progress_color, 4, 4, 4, 4, 10); + Ref<StyleBoxFlat> style_scrollbar_grabber_highlight = make_flat_stylebox(style_focus_color, 4, 4, 4, 4, 10); + Ref<StyleBoxFlat> style_scrollbar_grabber_pressed = make_flat_stylebox(style_focus_color * Color(0.75, 0.75, 0.75), 4, 4, 4, 4, 10); + // HScrollBar - theme->set_stylebox("scroll", "HScrollBar", make_stylebox(scroll_bg_png, 5, 5, 5, 5, 0, 0, 0, 0)); - theme->set_stylebox("scroll_focus", "HScrollBar", make_stylebox(scroll_bg_png, 5, 5, 5, 5, 0, 0, 0, 0)); - theme->set_stylebox("grabber", "HScrollBar", make_stylebox(scroll_grabber_png, 5, 5, 5, 5, 2, 2, 2, 2)); - theme->set_stylebox("grabber_highlight", "HScrollBar", make_stylebox(scroll_grabber_hl_png, 5, 5, 5, 5, 2, 2, 2, 2)); - theme->set_stylebox("grabber_pressed", "HScrollBar", make_stylebox(scroll_grabber_pressed_png, 5, 5, 5, 5, 2, 2, 2, 2)); + theme->set_stylebox("scroll", "HScrollBar", style_scrollbar); + theme->set_stylebox("scroll_focus", "HScrollBar", focus); + theme->set_stylebox("grabber", "HScrollBar", style_scrollbar_grabber); + theme->set_stylebox("grabber_highlight", "HScrollBar", style_scrollbar_grabber_highlight); + theme->set_stylebox("grabber_pressed", "HScrollBar", style_scrollbar_grabber_pressed); theme->set_icon("increment", "HScrollBar", empty_icon); theme->set_icon("increment_highlight", "HScrollBar", empty_icon); @@ -523,11 +514,11 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // VScrollBar - theme->set_stylebox("scroll", "VScrollBar", make_stylebox(scroll_bg_png, 5, 5, 5, 5, 0, 0, 0, 0)); - theme->set_stylebox("scroll_focus", "VScrollBar", make_stylebox(scroll_bg_png, 5, 5, 5, 5, 0, 0, 0, 0)); - theme->set_stylebox("grabber", "VScrollBar", make_stylebox(scroll_grabber_png, 5, 5, 5, 5, 2, 2, 2, 2)); - theme->set_stylebox("grabber_highlight", "VScrollBar", make_stylebox(scroll_grabber_hl_png, 5, 5, 5, 5, 2, 2, 2, 2)); - theme->set_stylebox("grabber_pressed", "VScrollBar", make_stylebox(scroll_grabber_pressed_png, 5, 5, 5, 5, 2, 2, 2, 2)); + theme->set_stylebox("scroll", "VScrollBar", style_scrollbar); + theme->set_stylebox("scroll_focus", "VScrollBar", focus); + theme->set_stylebox("grabber", "VScrollBar", style_scrollbar_grabber); + theme->set_stylebox("grabber_highlight", "VScrollBar", style_scrollbar_grabber_highlight); + theme->set_stylebox("grabber_pressed", "VScrollBar", style_scrollbar_grabber_pressed); theme->set_icon("increment", "VScrollBar", empty_icon); theme->set_icon("increment_highlight", "VScrollBar", empty_icon); @@ -536,31 +527,35 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_icon("decrement_highlight", "VScrollBar", empty_icon); theme->set_icon("decrement_pressed", "VScrollBar", empty_icon); + const Ref<StyleBoxFlat> style_slider = make_flat_stylebox(style_normal_color, 4, 4, 4, 4, 4); + const Ref<StyleBoxFlat> style_slider_grabber = make_flat_stylebox(style_progress_color, 4, 4, 4, 4, 4); + const Ref<StyleBoxFlat> style_slider_grabber_highlight = make_flat_stylebox(style_focus_color, 4, 4, 4, 4, 4); + // HSlider - theme->set_stylebox("slider", "HSlider", make_stylebox(hslider_bg_png, 4, 4, 4, 4)); - theme->set_stylebox("grabber_area", "HSlider", make_stylebox(hslider_bg_png, 4, 4, 4, 4)); - theme->set_stylebox("grabber_area_highlight", "HSlider", make_stylebox(hslider_bg_png, 4, 4, 4, 4)); + theme->set_stylebox("slider", "HSlider", style_slider); + theme->set_stylebox("grabber_area", "HSlider", style_slider_grabber); + theme->set_stylebox("grabber_area_highlight", "HSlider", style_slider_grabber_highlight); - theme->set_icon("grabber", "HSlider", make_icon(hslider_grabber_png)); - theme->set_icon("grabber_highlight", "HSlider", make_icon(hslider_grabber_hl_png)); - theme->set_icon("grabber_disabled", "HSlider", make_icon(hslider_grabber_disabled_png)); - theme->set_icon("tick", "HSlider", make_icon(hslider_tick_png)); + theme->set_icon("grabber", "HSlider", icons["slider_grabber"]); + theme->set_icon("grabber_highlight", "HSlider", icons["slider_grabber_hl"]); + theme->set_icon("grabber_disabled", "HSlider", icons["slider_grabber_disabled"]); + theme->set_icon("tick", "HSlider", icons["hslider_tick"]); // VSlider - theme->set_stylebox("slider", "VSlider", make_stylebox(vslider_bg_png, 4, 4, 4, 4)); - theme->set_stylebox("grabber_area", "VSlider", make_stylebox(vslider_bg_png, 4, 4, 4, 4)); - theme->set_stylebox("grabber_area_highlight", "VSlider", make_stylebox(vslider_bg_png, 4, 4, 4, 4)); + theme->set_stylebox("slider", "VSlider", style_slider); + theme->set_stylebox("grabber_area", "VSlider", style_slider_grabber); + theme->set_stylebox("grabber_area_highlight", "VSlider", style_slider_grabber_highlight); - theme->set_icon("grabber", "VSlider", make_icon(vslider_grabber_png)); - theme->set_icon("grabber_highlight", "VSlider", make_icon(vslider_grabber_hl_png)); - theme->set_icon("grabber_disabled", "VSlider", make_icon(vslider_grabber_disabled_png)); - theme->set_icon("tick", "VSlider", make_icon(vslider_tick_png)); + theme->set_icon("grabber", "VSlider", icons["slider_grabber"]); + theme->set_icon("grabber_highlight", "VSlider", icons["slider_grabber_hl"]); + theme->set_icon("grabber_disabled", "VSlider", icons["slider_grabber_disabled"]); + theme->set_icon("tick", "VSlider", icons["vslider_tick"]); // SpinBox - theme->set_icon("updown", "SpinBox", make_icon(spinbox_updown_png)); + theme->set_icon("updown", "SpinBox", icons["updown"]); // ScrollContainer @@ -570,67 +565,88 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // Window - theme->set_stylebox("embedded_border", "Window", sb_expand(make_stylebox(popup_window_png, 10, 26, 10, 8), 8, 24, 8, 6)); + theme->set_stylebox("embedded_border", "Window", sb_expand(make_flat_stylebox(style_popup_color, 10, 28, 10, 8), 8, 32, 8, 6)); theme->set_constant("scaleborder_size", "Window", 4 * scale); - theme->set_font("title_font", "Window", large_font); + theme->set_font("title_font", "Window", Ref<Font>()); theme->set_font_size("title_font_size", "Window", -1); - - theme->set_color("title_color", "Window", Color(0, 0, 0)); + theme->set_color("title_color", "Window", control_font_color); theme->set_color("title_outline_modulate", "Window", Color(1, 1, 1)); - theme->set_constant("title_outline_size", "Window", 0); - theme->set_constant("title_height", "Window", 20 * scale); + theme->set_constant("title_height", "Window", 36 * scale); theme->set_constant("resize_margin", "Window", 4 * scale); - theme->set_icon("close", "Window", make_icon(close_png)); - theme->set_icon("close_pressed", "Window", make_icon(close_hl_png)); + theme->set_icon("close", "Window", icons["close"]); + theme->set_icon("close_pressed", "Window", icons["close_hl"]); theme->set_constant("close_h_ofs", "Window", 18 * scale); - theme->set_constant("close_v_ofs", "Window", 18 * scale); + theme->set_constant("close_v_ofs", "Window", 24 * scale); + + // Dialogs + + theme->set_constant("margin", "Dialogs", 8 * scale); + theme->set_constant("button_margin", "Dialogs", 32 * scale); // AcceptDialog - theme->set_stylebox("panel", "AcceptDialog", make_stylebox(dialog_bg_png, 0, 0, 0, 0)); + theme->set_stylebox("panel", "AcceptDialog", make_flat_stylebox(style_popup_color, 0, 0, 0, 0)); // File Dialog - theme->set_icon("parent_folder", "FileDialog", make_icon(icon_parent_folder_png)); - theme->set_icon("back_folder", "FileDialog", make_icon(arrow_left_png)); - theme->set_icon("forward_folder", "FileDialog", make_icon(arrow_right_png)); - theme->set_icon("reload", "FileDialog", make_icon(icon_reload_png)); - theme->set_icon("toggle_hidden", "FileDialog", make_icon(icon_visibility_png)); + theme->set_icon("parent_folder", "FileDialog", icons["folder_up"]); + theme->set_icon("back_folder", "FileDialog", icons["arrow_left"]); + theme->set_icon("forward_folder", "FileDialog", icons["arrow_right"]); + theme->set_icon("reload", "FileDialog", icons["reload"]); + theme->set_icon("toggle_hidden", "FileDialog", icons["visibility_visible"]); + theme->set_icon("folder", "FileDialog", icons["folder"]); + theme->set_icon("file", "FileDialog", icons["file"]); + theme->set_color("folder_icon_modulate", "FileDialog", Color(1, 1, 1)); + theme->set_color("file_icon_modulate", "FileDialog", Color(1, 1, 1)); + theme->set_color("files_disabled", "FileDialog", Color(0, 0, 0, 0.7)); // Popup - Ref<StyleBoxTexture> style_pp = sb_expand(make_stylebox(popup_bg_png, 5, 5, 5, 5, 4, 4, 4, 4), 2, 2, 2, 2); - - Ref<StyleBoxTexture> selected = make_stylebox(selection_png, 6, 6, 6, 6); - for (int i = 0; i < 4; i++) { - selected->set_expand_margin_size(Side(i), 2 * scale); - } - - theme->set_stylebox("panel", "PopupPanel", style_pp); + theme->set_stylebox("panel", "PopupPanel", make_flat_stylebox(style_normal_color)); // PopupDialog - Ref<StyleBoxTexture> style_pd = make_stylebox(popup_bg_png, 4, 4, 4, 4, 10, 10, 10, 10); - theme->set_stylebox("panel", "PopupDialog", style_pd); + theme->set_stylebox("panel", "PopupDialog", make_flat_stylebox(style_normal_color)); // PopupMenu - theme->set_stylebox("panel", "PopupMenu", style_pd); - theme->set_stylebox("panel_disabled", "PopupMenu", make_stylebox(popup_bg_disabled_png, 4, 4, 4, 4)); - theme->set_stylebox("hover", "PopupMenu", selected); - theme->set_stylebox("separator", "PopupMenu", make_stylebox(vseparator_png, 3, 3, 3, 3)); - theme->set_stylebox("labeled_separator_left", "PopupMenu", make_stylebox(vseparator_png, 0, 0, 0, 0)); - theme->set_stylebox("labeled_separator_right", "PopupMenu", make_stylebox(vseparator_png, 0, 0, 0, 0)); - - theme->set_icon("checked", "PopupMenu", make_icon(checked_png)); - theme->set_icon("unchecked", "PopupMenu", make_icon(unchecked_png)); - theme->set_icon("radio_checked", "PopupMenu", make_icon(radio_checked_png)); - theme->set_icon("radio_unchecked", "PopupMenu", make_icon(radio_unchecked_png)); - theme->set_icon("submenu", "PopupMenu", make_icon(submenu_png)); - theme->set_icon("submenu_mirrored", "PopupMenu", make_icon(submenu_mirrored_png)); + Ref<StyleBoxLine> separator_horizontal = memnew(StyleBoxLine); + separator_horizontal->set_thickness(Math::round(scale)); + separator_horizontal->set_color(style_separator_color); + separator_horizontal->set_default_margin(SIDE_LEFT, default_margin); + separator_horizontal->set_default_margin(SIDE_TOP, 0); + separator_horizontal->set_default_margin(SIDE_RIGHT, default_margin); + separator_horizontal->set_default_margin(SIDE_BOTTOM, 0); + Ref<StyleBoxLine> separator_vertical = separator_horizontal->duplicate(); + separator_vertical->set_vertical(true); + separator_vertical->set_default_margin(SIDE_LEFT, 0); + separator_vertical->set_default_margin(SIDE_TOP, default_margin); + separator_vertical->set_default_margin(SIDE_RIGHT, 0); + separator_vertical->set_default_margin(SIDE_BOTTOM, default_margin); + + // Always display a border for PopupMenus so they can be distinguished from their background. + Ref<StyleBoxFlat> style_popup_panel = make_flat_stylebox(style_popup_color); + style_popup_panel->set_border_width_all(2); + style_popup_panel->set_border_color(style_popup_border_color); + Ref<StyleBoxFlat> style_popup_panel_disabled = style_popup_panel->duplicate(); + style_popup_panel_disabled->set_bg_color(style_disabled_color); + + theme->set_stylebox("panel", "PopupMenu", style_popup_panel); + theme->set_stylebox("panel_disabled", "PopupMenu", style_popup_panel_disabled); + theme->set_stylebox("hover", "PopupMenu", make_flat_stylebox(style_popup_hover_color)); + theme->set_stylebox("separator", "PopupMenu", separator_horizontal); + theme->set_stylebox("labeled_separator_left", "PopupMenu", separator_horizontal); + theme->set_stylebox("labeled_separator_right", "PopupMenu", separator_horizontal); + + theme->set_icon("checked", "PopupMenu", icons["checked"]); + theme->set_icon("unchecked", "PopupMenu", icons["unchecked"]); + theme->set_icon("radio_checked", "PopupMenu", icons["radio_checked"]); + theme->set_icon("radio_unchecked", "PopupMenu", icons["radio_unchecked"]); + theme->set_icon("submenu", "PopupMenu", icons["arrow_right"]); + theme->set_icon("submenu_mirrored", "PopupMenu", icons["arrow_left"]); theme->set_font("font", "PopupMenu", Ref<Font>()); theme->set_font_size("font_size", "PopupMenu", -1); @@ -649,65 +665,63 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("item_end_padding", "PopupMenu", 2 * scale); // GraphNode - - Ref<StyleBoxTexture> graphsb = make_stylebox(graph_node_png, 6, 24, 6, 5, 16, 24, 16, 6); - Ref<StyleBoxTexture> graphsbcomment = make_stylebox(graph_node_comment_png, 6, 24, 6, 5, 16, 24, 16, 6); - Ref<StyleBoxTexture> graphsbcommentselected = make_stylebox(graph_node_comment_focus_png, 6, 24, 6, 5, 16, 24, 16, 6); - Ref<StyleBoxTexture> graphsbselected = make_stylebox(graph_node_selected_png, 6, 24, 6, 5, 16, 24, 16, 6); - Ref<StyleBoxTexture> graphsbdefault = make_stylebox(graph_node_default_png, 4, 4, 4, 4, 6, 4, 4, 4); - Ref<StyleBoxTexture> graphsbdeffocus = make_stylebox(graph_node_default_focus_png, 4, 4, 4, 4, 6, 4, 4, 4); - Ref<StyleBoxTexture> graph_bpoint = make_stylebox(graph_node_breakpoint_png, 6, 24, 6, 5, 16, 24, 16, 6); - Ref<StyleBoxTexture> graph_position = make_stylebox(graph_node_position_png, 6, 24, 6, 5, 16, 24, 16, 6); - - //graphsb->set_expand_margin_size(SIDE_LEFT,10); - //graphsb->set_expand_margin_size(SIDE_RIGHT,10); - theme->set_stylebox("frame", "GraphNode", graphsb); - theme->set_stylebox("selectedframe", "GraphNode", graphsbselected); - theme->set_stylebox("defaultframe", "GraphNode", graphsbdefault); - theme->set_stylebox("defaultfocus", "GraphNode", graphsbdeffocus); - theme->set_stylebox("comment", "GraphNode", graphsbcomment); - theme->set_stylebox("commentfocus", "GraphNode", graphsbcommentselected); - theme->set_stylebox("breakpoint", "GraphNode", graph_bpoint); - theme->set_stylebox("position", "GraphNode", graph_position); - theme->set_constant("separation", "GraphNode", 1 * scale); - theme->set_icon("port", "GraphNode", make_icon(graph_port_png)); - theme->set_icon("close", "GraphNode", make_icon(graph_node_close_png)); - theme->set_icon("resizer", "GraphNode", make_icon(window_resizer_png)); + Ref<StyleBoxFlat> graphnode_normal = make_flat_stylebox(style_normal_color, 18, 42, 18, 12); + graphnode_normal->set_border_width(SIDE_TOP, 30); + graphnode_normal->set_border_color(Color(0.325, 0.325, 0.325, 0.6)); + Ref<StyleBoxFlat> graphnode_selected = graphnode_normal->duplicate(); + graphnode_selected->set_border_color(Color(0.625, 0.625, 0.625, 0.6)); + Ref<StyleBoxFlat> graphnode_comment_normal = make_flat_stylebox(style_pressed_color, 18, 42, 18, 12, 3, true, 2); + graphnode_comment_normal->set_border_color(style_pressed_color); + Ref<StyleBoxFlat> graphnode_comment_selected = graphnode_comment_normal->duplicate(); + graphnode_comment_selected->set_border_color(style_hover_color); + Ref<StyleBoxFlat> graphnode_breakpoint = make_flat_stylebox(style_pressed_color, 18, 42, 18, 12, 6, true, 4); + graphnode_breakpoint->set_border_color(Color(0.9, 0.29, 0.3)); + Ref<StyleBoxFlat> graphnode_position = make_flat_stylebox(style_pressed_color, 18, 42, 18, 12, 6, true, 4); + graphnode_position->set_border_color(Color(0.98, 0.89, 0.27)); + + theme->set_stylebox("frame", "GraphNode", graphnode_normal); + theme->set_stylebox("selectedframe", "GraphNode", graphnode_selected); + theme->set_stylebox("comment", "GraphNode", graphnode_comment_normal); + theme->set_stylebox("commentfocus", "GraphNode", graphnode_comment_selected); + theme->set_stylebox("breakpoint", "GraphNode", graphnode_breakpoint); + theme->set_stylebox("position", "GraphNode", graphnode_position); + + theme->set_icon("port", "GraphNode", icons["graph_port"]); + theme->set_icon("close", "GraphNode", icons["close"]); + theme->set_icon("resizer", "GraphNode", icons["resizer_se"]); theme->set_font("title_font", "GraphNode", Ref<Font>()); - theme->set_color("title_color", "GraphNode", Color(0, 0, 0, 1)); - theme->set_color("close_color", "GraphNode", Color(0, 0, 0, 1)); - theme->set_color("resizer_color", "GraphNode", Color(0, 0, 0, 1)); - theme->set_constant("title_offset", "GraphNode", 20 * scale); - theme->set_constant("close_offset", "GraphNode", 18 * scale); - theme->set_constant("port_offset", "GraphNode", 3 * scale); + theme->set_color("title_color", "GraphNode", control_font_color); + theme->set_color("close_color", "GraphNode", control_font_color); + theme->set_color("resizer_color", "GraphNode", control_font_color); + theme->set_constant("separation", "GraphNode", 2 * scale); + theme->set_constant("title_offset", "GraphNode", 26 * scale); + theme->set_constant("close_offset", "GraphNode", 22 * scale); + theme->set_constant("port_offset", "GraphNode", 0); // Tree - Ref<StyleBoxTexture> tree_selected = make_stylebox(selection_png, 4, 4, 4, 4, 8, 0, 8, 0); - Ref<StyleBoxTexture> tree_selected_oof = make_stylebox(selection_oof_png, 4, 4, 4, 4, 8, 0, 8, 0); - - theme->set_stylebox("bg", "Tree", make_stylebox(tree_bg_png, 4, 4, 4, 5)); + theme->set_stylebox("bg", "Tree", make_flat_stylebox(style_normal_color, 4, 4, 4, 5)); theme->set_stylebox("bg_focus", "Tree", focus); - theme->set_stylebox("selected", "Tree", tree_selected_oof); - theme->set_stylebox("selected_focus", "Tree", tree_selected); + theme->set_stylebox("selected", "Tree", make_flat_stylebox(style_selected_color)); + theme->set_stylebox("selected_focus", "Tree", make_flat_stylebox(style_selected_color)); theme->set_stylebox("cursor", "Tree", focus); theme->set_stylebox("cursor_unfocused", "Tree", focus); - theme->set_stylebox("button_pressed", "Tree", make_stylebox(button_pressed_png, 4, 4, 4, 4)); - theme->set_stylebox("title_button_normal", "Tree", make_stylebox(tree_title_png, 4, 4, 4, 4)); - theme->set_stylebox("title_button_pressed", "Tree", make_stylebox(tree_title_pressed_png, 4, 4, 4, 4)); - theme->set_stylebox("title_button_hover", "Tree", make_stylebox(tree_title_png, 4, 4, 4, 4)); - theme->set_stylebox("custom_button", "Tree", sb_button_normal); - theme->set_stylebox("custom_button_pressed", "Tree", sb_button_pressed); - theme->set_stylebox("custom_button_hover", "Tree", sb_button_hover); - - theme->set_icon("checked", "Tree", make_icon(checked_png)); - theme->set_icon("unchecked", "Tree", make_icon(unchecked_png)); - theme->set_icon("indeterminate", "Tree", make_icon(indeterminate_png)); - theme->set_icon("updown", "Tree", make_icon(updown_png)); - theme->set_icon("select_arrow", "Tree", make_icon(dropdown_png)); - theme->set_icon("arrow", "Tree", make_icon(arrow_down_png)); - theme->set_icon("arrow_collapsed", "Tree", make_icon(arrow_right_png)); - theme->set_icon("arrow_collapsed_mirrored", "Tree", make_icon(arrow_left_png)); + theme->set_stylebox("button_pressed", "Tree", button_pressed); + theme->set_stylebox("title_button_normal", "Tree", make_flat_stylebox(style_pressed_color, 4, 4, 4, 4)); + theme->set_stylebox("title_button_pressed", "Tree", make_flat_stylebox(style_hover_color, 4, 4, 4, 4)); + theme->set_stylebox("title_button_hover", "Tree", make_flat_stylebox(style_normal_color, 4, 4, 4, 4)); + theme->set_stylebox("custom_button", "Tree", button_normal); + theme->set_stylebox("custom_button_pressed", "Tree", button_pressed); + theme->set_stylebox("custom_button_hover", "Tree", button_hover); + + theme->set_icon("checked", "Tree", icons["checked"]); + theme->set_icon("unchecked", "Tree", icons["unchecked"]); + theme->set_icon("indeterminate", "Tree", icons["indeterminate"]); + theme->set_icon("updown", "Tree", icons["updown"]); + theme->set_icon("select_arrow", "Tree", icons["option_button_arrow"]); + theme->set_icon("arrow", "Tree", icons["arrow_down"]); + theme->set_icon("arrow_collapsed", "Tree", icons["arrow_right"]); + theme->set_icon("arrow_collapsed_mirrored", "Tree", icons["arrow_left"]); theme->set_font("title_button_font", "Tree", Ref<Font>()); theme->set_font("font", "Tree", Ref<Font>()); @@ -717,7 +731,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_color("font_color", "Tree", control_font_low_color); theme->set_color("font_selected_color", "Tree", control_font_pressed_color); theme->set_color("font_outline_color", "Tree", Color(1, 1, 1)); - theme->set_color("guide_color", "Tree", Color(0, 0, 0, 0.1)); + theme->set_color("guide_color", "Tree", Color(0.7, 0.7, 0.7, 0.25)); theme->set_color("drop_position_color", "Tree", Color(1, 0.3, 0.2)); theme->set_color("relationship_line_color", "Tree", Color(0.27, 0.27, 0.27)); theme->set_color("parent_hl_line_color", "Tree", Color(0.27, 0.27, 0.27)); @@ -726,7 +740,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("hseparation", "Tree", 4 * scale); theme->set_constant("vseparation", "Tree", 4 * scale); - theme->set_constant("item_margin", "Tree", 12 * scale); + theme->set_constant("item_margin", "Tree", 16 * scale); theme->set_constant("button_margin", "Tree", 4 * scale); theme->set_constant("draw_relationship_lines", "Tree", 0); theme->set_constant("relationship_line_width", "Tree", 1); @@ -740,10 +754,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // ItemList - Ref<StyleBoxTexture> item_selected = make_stylebox(selection_png, 4, 4, 4, 4, 8, 2, 8, 2); - Ref<StyleBoxTexture> item_selected_oof = make_stylebox(selection_oof_png, 4, 4, 4, 4, 8, 2, 8, 2); - - theme->set_stylebox("bg", "ItemList", make_stylebox(tree_bg_png, 4, 4, 4, 5)); + theme->set_stylebox("bg", "ItemList", make_flat_stylebox(style_normal_color)); theme->set_stylebox("bg_focus", "ItemList", focus); theme->set_constant("hseparation", "ItemList", 4); theme->set_constant("vseparation", "ItemList", 2); @@ -757,8 +768,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_color("font_selected_color", "ItemList", control_font_pressed_color); theme->set_color("font_outline_color", "ItemList", Color(1, 1, 1)); theme->set_color("guide_color", "ItemList", Color(0, 0, 0, 0.1)); - theme->set_stylebox("selected", "ItemList", item_selected_oof); - theme->set_stylebox("selected_focus", "ItemList", item_selected); + theme->set_stylebox("selected", "ItemList", make_flat_stylebox(style_selected_color)); + theme->set_stylebox("selected_focus", "ItemList", make_flat_stylebox(style_selected_color)); theme->set_stylebox("cursor", "ItemList", focus); theme->set_stylebox("cursor_unfocused", "ItemList", focus); @@ -766,22 +777,28 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // TabContainer - Ref<StyleBoxTexture> tc_sb = sb_expand(make_stylebox(tab_container_bg_png, 4, 4, 4, 4, 4, 4, 4, 4), 3, 3, 3, 3); - - tc_sb->set_expand_margin_size(SIDE_TOP, 2 * scale); - tc_sb->set_default_margin(SIDE_TOP, 8 * scale); - - theme->set_stylebox("tab_selected", "TabContainer", sb_expand(make_stylebox(tab_current_png, 4, 4, 4, 1, 16, 4, 16, 4), 2, 2, 2, 2)); - theme->set_stylebox("tab_unselected", "TabContainer", sb_expand(make_stylebox(tab_behind_png, 5, 5, 5, 1, 16, 6, 16, 4), 3, 0, 3, 0)); - theme->set_stylebox("tab_disabled", "TabContainer", sb_expand(make_stylebox(tab_disabled_png, 5, 5, 5, 1, 16, 6, 16, 4), 3, 0, 3, 0)); - theme->set_stylebox("panel", "TabContainer", tc_sb); - - theme->set_icon("increment", "TabContainer", make_icon(scroll_button_right_png)); - theme->set_icon("increment_highlight", "TabContainer", make_icon(scroll_button_right_hl_png)); - theme->set_icon("decrement", "TabContainer", make_icon(scroll_button_left_png)); - theme->set_icon("decrement_highlight", "TabContainer", make_icon(scroll_button_left_hl_png)); - theme->set_icon("menu", "TabContainer", make_icon(tab_menu_png)); - theme->set_icon("menu_highlight", "TabContainer", make_icon(tab_menu_hl_png)); + Ref<StyleBoxFlat> style_tab_selected = make_flat_stylebox(style_normal_color, 10, 4, 10, 4, 0); + style_tab_selected->set_border_width(SIDE_TOP, Math::round(2 * scale)); + style_tab_selected->set_border_color(style_focus_color); + Ref<StyleBoxFlat> style_tab_unselected = make_flat_stylebox(style_pressed_color, 10, 4, 10, 4, 0); + // Add some spacing between unselected tabs to make them easier to distinguish from each other. + style_tab_unselected->set_border_width(SIDE_LEFT, Math::round(scale)); + style_tab_unselected->set_border_width(SIDE_RIGHT, Math::round(scale)); + style_tab_unselected->set_border_color(style_popup_border_color); + Ref<StyleBoxFlat> style_tab_disabled = style_tab_unselected->duplicate(); + style_tab_disabled->set_bg_color(style_disabled_color); + + theme->set_stylebox("tab_selected", "TabContainer", style_tab_selected); + theme->set_stylebox("tab_unselected", "TabContainer", style_tab_unselected); + theme->set_stylebox("tab_disabled", "TabContainer", style_tab_disabled); + theme->set_stylebox("panel", "TabContainer", make_flat_stylebox(style_normal_color, 0, 0, 0, 0)); + + theme->set_icon("increment", "TabContainer", icons["scroll_button_right"]); + theme->set_icon("increment_highlight", "TabContainer", icons["scroll_button_right_hl"]); + theme->set_icon("decrement", "TabContainer", icons["scroll_button_left"]); + theme->set_icon("decrement_highlight", "TabContainer", icons["scroll_button_left_hl"]); + theme->set_icon("menu", "TabContainer", icons["tabs_menu"]); + theme->set_icon("menu_highlight", "TabContainer", icons["tabs_menu_hl"]); theme->set_font("font", "TabContainer", Ref<Font>()); theme->set_font_size("font_size", "TabContainer", -1); @@ -797,17 +814,17 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // TabBar - theme->set_stylebox("tab_selected", "TabBar", sb_expand(make_stylebox(tab_current_png, 4, 4, 4, 1, 16, 4, 16, 4), 2, 2, 2, 2)); - theme->set_stylebox("tab_unselected", "TabBar", sb_expand(make_stylebox(tab_behind_png, 5, 5, 5, 1, 16, 6, 16, 4), 3, 0, 3, 0)); - theme->set_stylebox("tab_disabled", "TabBar", sb_expand(make_stylebox(tab_disabled_png, 5, 5, 5, 1, 16, 6, 16, 4), 3, 0, 3, 0)); - theme->set_stylebox("close_bg_pressed", "TabBar", make_stylebox(button_pressed_png, 4, 4, 4, 4)); - theme->set_stylebox("close_bg_highlight", "TabBar", make_stylebox(button_normal_png, 4, 4, 4, 4)); + theme->set_stylebox("tab_selected", "TabBar", style_tab_selected); + theme->set_stylebox("tab_unselected", "TabBar", style_tab_unselected); + theme->set_stylebox("tab_disabled", "TabBar", style_tab_disabled); + theme->set_stylebox("close_bg_pressed", "TabBar", button_pressed); + theme->set_stylebox("close_bg_highlight", "TabBar", button_normal); - theme->set_icon("increment", "TabBar", make_icon(scroll_button_right_png)); - theme->set_icon("increment_highlight", "TabBar", make_icon(scroll_button_right_hl_png)); - theme->set_icon("decrement", "TabBar", make_icon(scroll_button_left_png)); - theme->set_icon("decrement_highlight", "TabBar", make_icon(scroll_button_left_hl_png)); - theme->set_icon("close", "TabBar", make_icon(tab_close_png)); + theme->set_icon("increment", "TabBar", icons["scroll_button_right"]); + theme->set_icon("increment_highlight", "TabBar", icons["scroll_button_right_hl"]); + theme->set_icon("decrement", "TabBar", icons["scroll_button_left"]); + theme->set_icon("decrement_highlight", "TabBar", icons["scroll_button_left_hl"]); + theme->set_icon("close", "TabBar", icons["close"]); theme->set_font("font", "TabBar", Ref<Font>()); theme->set_font_size("font_size", "TabBar", -1); @@ -822,29 +839,16 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // Separators - theme->set_stylebox("separator", "HSeparator", make_stylebox(vseparator_png, 3, 3, 3, 3)); - theme->set_stylebox("separator", "VSeparator", make_stylebox(hseparator_png, 3, 3, 3, 3)); + theme->set_stylebox("separator", "HSeparator", separator_horizontal); + theme->set_stylebox("separator", "VSeparator", separator_vertical); - theme->set_icon("close", "Icons", make_icon(icon_close_png)); + theme->set_icon("close", "Icons", icons["close"]); theme->set_font("normal", "Fonts", Ref<Font>()); - theme->set_font("large", "Fonts", large_font); + theme->set_font("large", "Fonts", Ref<Font>()); theme->set_constant("separation", "HSeparator", 4 * scale); theme->set_constant("separation", "VSeparator", 4 * scale); - // Dialogs - - theme->set_constant("margin", "Dialogs", 8 * scale); - theme->set_constant("button_margin", "Dialogs", 32 * scale); - - // FileDialog - - theme->set_icon("folder", "FileDialog", make_icon(icon_folder_png)); - theme->set_icon("file", "FileDialog", make_icon(icon_file_png)); - theme->set_color("folder_icon_modulate", "FileDialog", Color(1, 1, 1)); - theme->set_color("file_icon_modulate", "FileDialog", Color(1, 1, 1)); - theme->set_color("files_disabled", "FileDialog", Color(0, 0, 0, 0.7)); - // ColorPicker theme->set_constant("margin", "ColorPicker", 4 * scale); @@ -853,23 +857,23 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("h_width", "ColorPicker", 30 * scale); theme->set_constant("label_width", "ColorPicker", 10 * scale); - theme->set_icon("screen_picker", "ColorPicker", make_icon(icon_color_pick_png)); - theme->set_icon("add_preset", "ColorPicker", make_icon(icon_add_png)); - theme->set_icon("color_hue", "ColorPicker", make_icon(color_picker_hue_png)); - theme->set_icon("color_sample", "ColorPicker", make_icon(color_picker_sample_png)); - theme->set_icon("sample_bg", "ColorPicker", make_icon(mini_checkerboard_png)); - theme->set_icon("overbright_indicator", "ColorPicker", make_icon(overbright_indicator_png)); - theme->set_icon("bar_arrow", "ColorPicker", make_icon(bar_arrow_png)); - theme->set_icon("picker_cursor", "ColorPicker", make_icon(picker_cursor_png)); + theme->set_icon("screen_picker", "ColorPicker", icons["color_picker_pipette"]); + theme->set_icon("add_preset", "ColorPicker", icons["add"]); + theme->set_icon("color_hue", "ColorPicker", icons["color_picker_hue"]); + theme->set_icon("color_sample", "ColorPicker", icons["color_picker_sample"]); + theme->set_icon("sample_bg", "ColorPicker", icons["mini_checkerboard"]); + theme->set_icon("overbright_indicator", "ColorPicker", icons["color_picker_overbright"]); + theme->set_icon("bar_arrow", "ColorPicker", icons["color_picker_bar_arrow"]); + theme->set_icon("picker_cursor", "ColorPicker", icons["color_picker_cursor"]); // ColorPickerButton - theme->set_icon("bg", "ColorPickerButton", make_icon(mini_checkerboard_png)); - theme->set_stylebox("normal", "ColorPickerButton", sb_button_normal); - theme->set_stylebox("pressed", "ColorPickerButton", sb_button_pressed); - theme->set_stylebox("hover", "ColorPickerButton", sb_button_hover); - theme->set_stylebox("disabled", "ColorPickerButton", sb_button_disabled); - theme->set_stylebox("focus", "ColorPickerButton", sb_button_focus); + theme->set_icon("bg", "ColorPickerButton", icons["mini_checkerboard"]); + theme->set_stylebox("normal", "ColorPickerButton", button_normal); + theme->set_stylebox("pressed", "ColorPickerButton", button_pressed); + theme->set_stylebox("hover", "ColorPickerButton", button_hover); + theme->set_stylebox("disabled", "ColorPickerButton", button_disabled); + theme->set_stylebox("focus", "ColorPickerButton", focus); theme->set_font("font", "ColorPickerButton", Ref<Font>()); theme->set_font_size("font_size", "ColorPickerButton", -1); @@ -892,24 +896,20 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const preset_sb->set_anti_aliased(false); theme->set_stylebox("preset_fg", "ColorPresetButton", preset_sb); - theme->set_icon("preset_bg", "ColorPresetButton", make_icon(mini_checkerboard_png)); - theme->set_icon("overbright_indicator", "ColorPresetButton", make_icon(overbright_indicator_png)); - - // TooltipPanel + theme->set_icon("preset_bg", "ColorPresetButton", icons["mini_checkerboard"]); + theme->set_icon("overbright_indicator", "ColorPresetButton", icons["color_picker_overbright"]); - Ref<StyleBoxTexture> style_tt = make_stylebox(tooltip_bg_png, 4, 4, 4, 4); - for (int i = 0; i < 4; i++) { - style_tt->set_expand_margin_size((Side)i, 4 * scale); - } + // TooltipPanel + TooltipLabel - theme->set_stylebox("panel", "TooltipPanel", style_tt); + theme->set_stylebox("panel", "TooltipPanel", + make_flat_stylebox(Color(0, 0, 0, 0.5), 2 * default_margin, 0.5 * default_margin, 2 * default_margin, 0.5 * default_margin)); theme->set_font("font", "TooltipLabel", Ref<Font>()); theme->set_font_size("font_size", "TooltipLabel", -1); - theme->set_color("font_color", "TooltipLabel", Color(0, 0, 0)); - theme->set_color("font_shadow_color", "TooltipLabel", Color(0, 0, 0, 0.1)); - theme->set_color("font_outline_color", "TooltipLabel", Color(1, 1, 1)); + theme->set_color("font_color", "TooltipLabel", control_font_color); + theme->set_color("font_shadow_color", "TooltipLabel", Color(0, 0, 0, 0)); + theme->set_color("font_outline_color", "TooltipLabel", Color(0, 0, 0, 0)); theme->set_constant("shadow_offset_x", "TooltipLabel", 1); theme->set_constant("shadow_offset_y", "TooltipLabel", 1); @@ -956,11 +956,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // Containers - theme->set_stylebox("bg", "VSplitContainer", make_stylebox(vsplit_bg_png, 1, 1, 1, 1)); - theme->set_stylebox("bg", "HSplitContainer", make_stylebox(hsplit_bg_png, 1, 1, 1, 1)); - - theme->set_icon("grabber", "VSplitContainer", make_icon(vsplitter_png)); - theme->set_icon("grabber", "HSplitContainer", make_icon(hsplitter_png)); + theme->set_icon("grabber", "VSplitContainer", icons["vsplitter"]); + theme->set_icon("grabber", "HSplitContainer", icons["hsplitter"]); theme->set_constant("separation", "HBoxContainer", 4 * scale); theme->set_constant("separation", "VBoxContainer", 4 * scale); @@ -974,17 +971,20 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("separation", "VSplitContainer", 12 * scale); theme->set_constant("autohide", "HSplitContainer", 1 * scale); theme->set_constant("autohide", "VSplitContainer", 1 * scale); - - Ref<StyleBoxTexture> sb_pc = make_stylebox(tab_container_bg_png, 4, 4, 4, 4, 7, 7, 7, 7); - theme->set_stylebox("panel", "PanelContainer", sb_pc); - - theme->set_icon("minus", "GraphEdit", make_icon(icon_zoom_less_png)); - theme->set_icon("reset", "GraphEdit", make_icon(icon_zoom_reset_png)); - theme->set_icon("more", "GraphEdit", make_icon(icon_zoom_more_png)); - theme->set_icon("snap", "GraphEdit", make_icon(icon_snap_grid_png)); - theme->set_icon("minimap", "GraphEdit", make_icon(icon_grid_minimap_png)); - theme->set_icon("layout", "GraphEdit", make_icon(icon_grid_layout_png)); - theme->set_stylebox("bg", "GraphEdit", make_stylebox(tree_bg_png, 4, 4, 4, 5)); + theme->set_constant("hseparation", "HFlowContainer", 4 * scale); + theme->set_constant("vseparation", "HFlowContainer", 4 * scale); + theme->set_constant("hseparation", "VFlowContainer", 4 * scale); + theme->set_constant("vseparation", "VFlowContainer", 4 * scale); + + theme->set_stylebox("panel", "PanelContainer", make_flat_stylebox(style_normal_color, 0, 0, 0, 0)); + + theme->set_icon("minus", "GraphEdit", icons["zoom_less"]); + theme->set_icon("reset", "GraphEdit", icons["zoom_reset"]); + theme->set_icon("more", "GraphEdit", icons["zoom_more"]); + theme->set_icon("snap", "GraphEdit", icons["grid_snap"]); + theme->set_icon("minimap", "GraphEdit", icons["grid_minimap"]); + theme->set_icon("layout", "GraphEdit", icons["grid_layout"]); + theme->set_stylebox("bg", "GraphEdit", make_flat_stylebox(style_normal_color, 4, 4, 4, 5)); theme->set_color("grid_minor", "GraphEdit", Color(1, 1, 1, 0.05)); theme->set_color("grid_major", "GraphEdit", Color(1, 1, 1, 0.2)); theme->set_color("selection_fill", "GraphEdit", Color(1, 1, 1, 0.3)); @@ -999,33 +999,30 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("port_grab_distance_vertical", "GraphEdit", 26 * scale); theme->set_stylebox("bg", "GraphEditMinimap", make_flat_stylebox(Color(0.24, 0.24, 0.24), 0, 0, 0, 0)); - Ref<StyleBoxFlat> style_minimap_camera = make_flat_stylebox(Color(0.65, 0.65, 0.65, 0.2), 0, 0, 0, 0); + Ref<StyleBoxFlat> style_minimap_camera = make_flat_stylebox(Color(0.65, 0.65, 0.65, 0.2), 0, 0, 0, 0, 0); style_minimap_camera->set_border_color(Color(0.65, 0.65, 0.65, 0.45)); style_minimap_camera->set_border_width_all(1); theme->set_stylebox("camera", "GraphEditMinimap", style_minimap_camera); - Ref<StyleBoxFlat> style_minimap_node = make_flat_stylebox(Color(1, 1, 1), 0, 0, 0, 0); - style_minimap_node->set_corner_radius_all(2); - theme->set_stylebox("node", "GraphEditMinimap", style_minimap_node); + theme->set_stylebox("node", "GraphEditMinimap", make_flat_stylebox(Color(1, 1, 1), 0, 0, 0, 0, 2)); - Ref<Texture2D> resizer_icon = make_icon(window_resizer_png); - theme->set_icon("resizer", "GraphEditMinimap", flip_icon(resizer_icon, true, true)); + theme->set_icon("resizer", "GraphEditMinimap", icons["resizer_nw"]); theme->set_color("resizer_color", "GraphEditMinimap", Color(1, 1, 1, 0.85)); // Theme - default_icon = make_icon(error_icon_png); - default_style = make_stylebox(error_icon_png, 2, 2, 2, 2); - - memdelete(tex_cache); + default_icon = icons["error_icon"]; + // Same color as the error icon. + default_style = make_flat_stylebox(Color(1, 0.365, 0.365), 4, 4, 4, 4, 0, false, 2); } -void make_default_theme(bool p_hidpi, Ref<Font> p_font) { +void make_default_theme(float p_scale, Ref<Font> p_font) { Ref<Theme> t; t.instantiate(); Ref<StyleBox> default_style; Ref<Texture2D> default_icon; Ref<Font> default_font; + float default_scale = CLAMP(p_scale, 0.5, 8.0); if (p_font.is_valid()) { // Use the custom font defined in the Project Settings. @@ -1045,21 +1042,14 @@ void make_default_theme(bool p_hidpi, Ref<Font> p_font) { default_font = dynamic_font; } - Ref<Font> large_font = default_font; - - float default_scale = 1.0; - if (p_hidpi) { - default_scale = 2.0; - } - - fill_default_theme(t, default_font, large_font, default_icon, default_style, default_scale); + fill_default_theme(t, default_font, default_icon, default_style, default_scale); Theme::set_default(t); Theme::set_fallback_base_scale(default_scale); Theme::set_fallback_icon(default_icon); Theme::set_fallback_style(default_style); Theme::set_fallback_font(default_font); - Theme::set_fallback_font_size(default_font_size); + Theme::set_fallback_font_size(default_font_size * default_scale); } void clear_default_theme() { diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h index e6d7b31b3e..3016517824 100644 --- a/scene/resources/default_theme/default_theme.h +++ b/scene/resources/default_theme/default_theme.h @@ -35,8 +35,8 @@ const int default_font_size = 16; -void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &large_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale); -void make_default_theme(bool p_hidpi, Ref<Font> p_font); +void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale); +void make_default_theme(float p_scale, Ref<Font> p_font); void clear_default_theme(); #endif diff --git a/scene/resources/default_theme/default_theme_icons_builders.py b/scene/resources/default_theme/default_theme_icons_builders.py new file mode 100644 index 0000000000..4dd5819a23 --- /dev/null +++ b/scene/resources/default_theme/default_theme_icons_builders.py @@ -0,0 +1,78 @@ +"""Functions used to generate source files during build time + +All such functions are invoked in a subprocess on Windows to prevent build flakiness. + +""" + +import os +from io import StringIO +from platform_methods import subprocess_main + + +# See also `editor/icons/editor_icons_builders.py`. +def make_default_theme_icons_action(target, source, env): + + dst = target[0] + svg_icons = source + + icons_string = StringIO() + + for f in svg_icons: + + fname = str(f) + + icons_string.write('\t"') + + with open(fname, "rb") as svgf: + b = svgf.read(1) + while len(b) == 1: + icons_string.write("\\" + str(hex(ord(b)))[1:]) + b = svgf.read(1) + + icons_string.write('"') + if fname != svg_icons[-1]: + icons_string.write(",") + icons_string.write("\n") + + s = StringIO() + s.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n\n") + s.write('#include "modules/modules_enabled.gen.h"\n\n') + s.write("#ifndef _DEFAULT_THEME_ICONS_H\n") + s.write("#define _DEFAULT_THEME_ICONS_H\n") + s.write("static const int default_theme_icons_count = {};\n\n".format(len(svg_icons))) + s.write("#ifdef MODULE_SVG_ENABLED\n") + s.write("static const char *default_theme_icons_sources[] = {\n") + s.write(icons_string.getvalue()) + s.write("};\n") + s.write("#endif // MODULE_SVG_ENABLED\n\n") + s.write("static const char *default_theme_icons_names[] = {\n") + + index = 0 + for f in svg_icons: + + fname = str(f) + + # Trim the `.svg` extension from the string. + icon_name = os.path.basename(fname)[:-4] + + s.write('\t"{0}"'.format(icon_name)) + + if fname != svg_icons[-1]: + s.write(",") + s.write("\n") + + index += 1 + + s.write("};\n") + + s.write("#endif\n") + + with open(dst, "w") as f: + f.write(s.getvalue()) + + s.close() + icons_string.close() + + +if __name__ == "__main__": + subprocess_main(globals()) diff --git a/scene/resources/default_theme/dialog_bg.png b/scene/resources/default_theme/dialog_bg.png Binary files differdeleted file mode 100644 index a23a10b48a..0000000000 --- a/scene/resources/default_theme/dialog_bg.png +++ /dev/null diff --git a/scene/resources/default_theme/dropdown.png b/scene/resources/default_theme/dropdown.png Binary files differdeleted file mode 100644 index b5d9ffbbb4..0000000000 --- a/scene/resources/default_theme/dropdown.png +++ /dev/null diff --git a/scene/resources/default_theme/ellipsis.png b/scene/resources/default_theme/ellipsis.png Binary files differdeleted file mode 100644 index c949e2c95b..0000000000 --- a/scene/resources/default_theme/ellipsis.png +++ /dev/null diff --git a/scene/resources/default_theme/error_icon.png b/scene/resources/default_theme/error_icon.png Binary files differdeleted file mode 100644 index 30336b91a4..0000000000 --- a/scene/resources/default_theme/error_icon.png +++ /dev/null diff --git a/scene/resources/default_theme/error_icon.svg b/scene/resources/default_theme/error_icon.svg new file mode 100644 index 0000000000..2f5099aa29 --- /dev/null +++ b/scene/resources/default_theme/error_icon.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1v8.5859l1.293-1.293a1.0001 1.0001 0 0 1 .69141-.29102 1.0001 1.0001 0 0 1 .72266.29102l2.293 2.293 2.293-2.293a1.0001 1.0001 0 0 1 1.4141 0l2.293 2.293 1-1v-3.5859h-5v-5h-7zm8 0v4h4zm-6 9.4141-2 2v2.5859h12v-2.5859l-.29297.29297a1.0001 1.0001 0 0 1 -1.4141 0l-2.293-2.293-2.293 2.293a1.0001 1.0001 0 0 1 -1.4141 0l-2.293-2.293z" fill="#ff5d5d" transform="translate(0 -.000017)"/></svg> diff --git a/scene/resources/default_theme/error_icon.xpm b/scene/resources/default_theme/error_icon.xpm deleted file mode 100644 index 666a60338d..0000000000 --- a/scene/resources/default_theme/error_icon.xpm +++ /dev/null @@ -1,38 +0,0 @@ -/* XPM */ -static const char * error_icon_xpm[] = { -"32 32 3 1", -" c None", -". c #FF00FF", -"+ c #000000", -"................................", -"................................", -"................................", -"................................", -"................................", -"................................", -"................................", -"................................", -"................................", -"................................", -"................................", -"................................", -"................................", -"....++++.+++..+++...++..+++.....", -"....+....+..+.+..+.+..+.+..+....", -"....+....+..+.+..+.+..+.+..+....", -"....+++..+++..+++..+..+.+++.....", -"....+....+..+.+..+.+..+.+..+....", -"....+....+..+.+..+.+..+.+..+....", -"....++++.+..+.+..+..++..+..+....", -"................................", -"................................", -"................................", -"................................", -"................................", -"................................", -"................................", -"................................", -"................................", -"................................", -"................................", -"................................"}; diff --git a/scene/resources/default_theme/file.svg b/scene/resources/default_theme/file.svg new file mode 100644 index 0000000000..974644c5da --- /dev/null +++ b/scene/resources/default_theme/file.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1v14h12v-9h-5v-5zm8 0v4h4z" fill="#b2b2b2" fill-rule="nonzero"/></svg> diff --git a/scene/resources/default_theme/focus.png b/scene/resources/default_theme/focus.png Binary files differdeleted file mode 100644 index f51ea89e8f..0000000000 --- a/scene/resources/default_theme/focus.png +++ /dev/null diff --git a/scene/resources/default_theme/folder.svg b/scene/resources/default_theme/folder.svg new file mode 100644 index 0000000000..ca4c8c9c70 --- /dev/null +++ b/scene/resources/default_theme/folder.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m2 2c-.549 0-1 .451-1 1v10c0 .549.451 1 1 1h12c.549 0 1-.451 1-1v-7c0-.549-.451-1-1-1h-4c-.549 0-1-.451-1-1v-1c0-.549-.451-1-1-1z" fill="#b2b2b2" fill-rule="nonzero"/></svg> diff --git a/scene/resources/default_theme/folder_up.svg b/scene/resources/default_theme/folder_up.svg new file mode 100644 index 0000000000..aaf5693d38 --- /dev/null +++ b/scene/resources/default_theme/folder_up.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m3 8c.003.26.107.509.291.693.388.388 1.026.388 1.414 0l2.293-2.293v4.586c0 .553.448 1 1 1s1-.447 1-1v-4.586l2.293 2.293c.388.388 1.026.388 1.414 0 .388-.387.388-1.026 0-1.414l-4-4c-.388-.387-1.026-.387-1.414 0l-4 4c-.19.191-.295.451-.291.721z" fill="#b2b2b2" fill-rule="nonzero"/></svg> diff --git a/scene/resources/default_theme/graph_node.png b/scene/resources/default_theme/graph_node.png Binary files differdeleted file mode 100644 index d4b4dd3c1f..0000000000 --- a/scene/resources/default_theme/graph_node.png +++ /dev/null diff --git a/scene/resources/default_theme/graph_node_breakpoint.png b/scene/resources/default_theme/graph_node_breakpoint.png Binary files differdeleted file mode 100644 index e18c6f42e1..0000000000 --- a/scene/resources/default_theme/graph_node_breakpoint.png +++ /dev/null diff --git a/scene/resources/default_theme/graph_node_close.png b/scene/resources/default_theme/graph_node_close.png Binary files differdeleted file mode 100644 index 5c962ae1c6..0000000000 --- a/scene/resources/default_theme/graph_node_close.png +++ /dev/null diff --git a/scene/resources/default_theme/graph_node_comment.png b/scene/resources/default_theme/graph_node_comment.png Binary files differdeleted file mode 100644 index cdec1d1eac..0000000000 --- a/scene/resources/default_theme/graph_node_comment.png +++ /dev/null diff --git a/scene/resources/default_theme/graph_node_comment_focus.png b/scene/resources/default_theme/graph_node_comment_focus.png Binary files differdeleted file mode 100644 index 472a6b6f53..0000000000 --- a/scene/resources/default_theme/graph_node_comment_focus.png +++ /dev/null diff --git a/scene/resources/default_theme/graph_node_default.png b/scene/resources/default_theme/graph_node_default.png Binary files differdeleted file mode 100644 index 359bbdc205..0000000000 --- a/scene/resources/default_theme/graph_node_default.png +++ /dev/null diff --git a/scene/resources/default_theme/graph_node_default_focus.png b/scene/resources/default_theme/graph_node_default_focus.png Binary files differdeleted file mode 100644 index 204dd16ac0..0000000000 --- a/scene/resources/default_theme/graph_node_default_focus.png +++ /dev/null diff --git a/scene/resources/default_theme/graph_node_position.png b/scene/resources/default_theme/graph_node_position.png Binary files differdeleted file mode 100644 index 24c2759be6..0000000000 --- a/scene/resources/default_theme/graph_node_position.png +++ /dev/null diff --git a/scene/resources/default_theme/graph_node_selected.png b/scene/resources/default_theme/graph_node_selected.png Binary files differdeleted file mode 100644 index c52d88586b..0000000000 --- a/scene/resources/default_theme/graph_node_selected.png +++ /dev/null diff --git a/scene/resources/default_theme/graph_port.png b/scene/resources/default_theme/graph_port.png Binary files differdeleted file mode 100644 index 358934f4d8..0000000000 --- a/scene/resources/default_theme/graph_port.png +++ /dev/null diff --git a/scene/resources/default_theme/graph_port.svg b/scene/resources/default_theme/graph_port.svg new file mode 100644 index 0000000000..423819ea68 --- /dev/null +++ b/scene/resources/default_theme/graph_port.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero"><path d="m10 5c0 2.743-2.257 5-5 5s-5-2.257-5-5 2.257-5 5-5 5 2.257 5 5" fill="#fff"/><path d="m8.667 5c0 2.011-1.656 3.667-3.667 3.667s-3.667-1.656-3.667-3.667 1.656-3.667 3.667-3.667 3.667 1.656 3.667 3.667" fill="#b2b2b2" fill-opacity=".65"/></g></svg> diff --git a/scene/resources/default_theme/grid_layout.svg b/scene/resources/default_theme/grid_layout.svg new file mode 100644 index 0000000000..d5cafca687 --- /dev/null +++ b/scene/resources/default_theme/grid_layout.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="1.5" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke-width="1.3"><g stroke="#fefffe"><path d="m1.87 6.541h2.917v2.917h-2.917z"/><path d="m6.536 6.541h2.917v2.917h-2.917z"/><path d="m11.202 6.541h2.917v2.917h-2.917z"/></g><g stroke="#e0e0e0" stroke-opacity=".65"><path d="m5.432 1.112-1.95 1.95 1.95 1.95" stroke-linejoin="miter" stroke-miterlimit="10"/><path d="m3.482 3.062h9.386"/><path d="m10.731 11.112 1.95 1.95-1.95 1.95" stroke-linejoin="miter" stroke-miterlimit="10"/><path d="m3.294 13.062h9.387"/></g></g></svg> diff --git a/scene/resources/default_theme/grid_minimap.svg b/scene/resources/default_theme/grid_minimap.svg new file mode 100644 index 0000000000..a7e5150bc3 --- /dev/null +++ b/scene/resources/default_theme/grid_minimap.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero"><path d="m14 2.199v2.615l-2.625 1.313v-2.615zm-12 4.065 2.625 1.312v2.551l-2.625-1.313zm12 0v2.55l-2.625 1.313v-2.551zm-8 1.455h4v2.64h-4zm-4 2.56 2.625 1.313v2.521l-2.625-1.312zm12 0v2.522l-2.625 1.312v-2.521zm-8 1.455h4v2.641h-4zm1.701-8.109h2.299v2.734h-4.156s-.749.647-.875.641c-.131-.007-1.51-1.456-1.51-1.456l-1.459-.73v-2.615l.068.034s.027-.457.063-.676c.034-.212.197-.592.197-.592l-1.049-.524c-.079-.04-.167-.062-.256-.066-.354-.013-.648.27-.648.625v12c0 .237.134.453.346.559l4 2c.086.043.182.066.279.066h6c.097 0 .193-.023.279-.066l4-2c.212-.106.346-.322.346-.559v-12c0-.464-.489-.766-.904-.559l-3.869 1.934h-2.971s.033.417.016.625c-.03.346-.196.625-.196.625z" fill="#b2b2b2" fill-opacity=".65"/><path d="m5 6s-2.219-2.162-2.219-3.243c0-1.08 0-2.607 2.219-2.607s2.219 1.527 2.219 2.607c0 1.081-2.219 3.243-2.219 3.243z" fill="#fefffe"/></g></svg> diff --git a/scene/resources/default_theme/grid_snap.svg b/scene/resources/default_theme/grid_snap.svg new file mode 100644 index 0000000000..633c85fe79 --- /dev/null +++ b/scene/resources/default_theme/grid_snap.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero"><path d="m3 0v3h-3v2h3v4h-3v2h3v3h2v-9h9v-2h-3v-3h-2v3h-4v-3zm4 13v2h2v-2zm6 0v2h2v-2z" fill="#b2b2b2" fill-opacity=".65"/><path d="m11 7c-2.194 0-4 1.806-4 4v2h2v-2c0-1.097.903-2 2-2s2 .903 2 2v2h2v-2c0-2.194-1.806-4-4-4z" fill="#fefffe"/></g></svg> diff --git a/scene/resources/default_theme/hseparator.png b/scene/resources/default_theme/hseparator.png Binary files differdeleted file mode 100644 index d4fd71ace5..0000000000 --- a/scene/resources/default_theme/hseparator.png +++ /dev/null diff --git a/scene/resources/default_theme/hslider_bg.png b/scene/resources/default_theme/hslider_bg.png Binary files differdeleted file mode 100644 index b402bd370d..0000000000 --- a/scene/resources/default_theme/hslider_bg.png +++ /dev/null diff --git a/scene/resources/default_theme/hslider_grabber.png b/scene/resources/default_theme/hslider_grabber.png Binary files differdeleted file mode 100644 index d273b491ee..0000000000 --- a/scene/resources/default_theme/hslider_grabber.png +++ /dev/null diff --git a/scene/resources/default_theme/hslider_grabber_disabled.png b/scene/resources/default_theme/hslider_grabber_disabled.png Binary files differdeleted file mode 100644 index dddd1a468e..0000000000 --- a/scene/resources/default_theme/hslider_grabber_disabled.png +++ /dev/null diff --git a/scene/resources/default_theme/hslider_grabber_hl.png b/scene/resources/default_theme/hslider_grabber_hl.png Binary files differdeleted file mode 100644 index e3defb3610..0000000000 --- a/scene/resources/default_theme/hslider_grabber_hl.png +++ /dev/null diff --git a/scene/resources/default_theme/hslider_tick.png b/scene/resources/default_theme/hslider_tick.png Binary files differdeleted file mode 100644 index 1ba19c37a1..0000000000 --- a/scene/resources/default_theme/hslider_tick.png +++ /dev/null diff --git a/scene/resources/default_theme/hslider_tick.svg b/scene/resources/default_theme/hslider_tick.svg new file mode 100644 index 0000000000..a97d05b9e8 --- /dev/null +++ b/scene/resources/default_theme/hslider_tick.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 4 15.999999" width="4" xmlns="http://www.w3.org/2000/svg"><path d="m1 0h2v16h-2z" fill="#fff" fill-opacity=".25" stroke-width=".285079"/></svg> diff --git a/scene/resources/default_theme/hsplit_bg.png b/scene/resources/default_theme/hsplit_bg.png Binary files differdeleted file mode 100644 index a5749f6d5c..0000000000 --- a/scene/resources/default_theme/hsplit_bg.png +++ /dev/null diff --git a/scene/resources/default_theme/hsplitter.png b/scene/resources/default_theme/hsplitter.png Binary files differdeleted file mode 100644 index 2287753c9d..0000000000 --- a/scene/resources/default_theme/hsplitter.png +++ /dev/null diff --git a/scene/resources/default_theme/hsplitter.svg b/scene/resources/default_theme/hsplitter.svg new file mode 100644 index 0000000000..effc6996cc --- /dev/null +++ b/scene/resources/default_theme/hsplitter.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" viewBox="0 0 8 48" xmlns="http://www.w3.org/2000/svg"><path d="m4 4.012v39.976" fill="none" stroke="#808080" stroke-opacity=".65" stroke-width="1.7"/></svg> diff --git a/scene/resources/default_theme/icon_add.png b/scene/resources/default_theme/icon_add.png Binary files differdeleted file mode 100644 index eccb69b363..0000000000 --- a/scene/resources/default_theme/icon_add.png +++ /dev/null diff --git a/scene/resources/default_theme/icon_close.png b/scene/resources/default_theme/icon_close.png Binary files differdeleted file mode 100644 index 4d4ac4a551..0000000000 --- a/scene/resources/default_theme/icon_close.png +++ /dev/null diff --git a/scene/resources/default_theme/icon_color_pick.png b/scene/resources/default_theme/icon_color_pick.png Binary files differdeleted file mode 100644 index 46953febb8..0000000000 --- a/scene/resources/default_theme/icon_color_pick.png +++ /dev/null diff --git a/scene/resources/default_theme/icon_file.png b/scene/resources/default_theme/icon_file.png Binary files differdeleted file mode 100644 index bb4c361a8d..0000000000 --- a/scene/resources/default_theme/icon_file.png +++ /dev/null diff --git a/scene/resources/default_theme/icon_folder.png b/scene/resources/default_theme/icon_folder.png Binary files differdeleted file mode 100644 index d1b308e88d..0000000000 --- a/scene/resources/default_theme/icon_folder.png +++ /dev/null diff --git a/scene/resources/default_theme/icon_grid_layout.png b/scene/resources/default_theme/icon_grid_layout.png Binary files differdeleted file mode 100644 index a249252a79..0000000000 --- a/scene/resources/default_theme/icon_grid_layout.png +++ /dev/null diff --git a/scene/resources/default_theme/icon_grid_minimap.png b/scene/resources/default_theme/icon_grid_minimap.png Binary files differdeleted file mode 100644 index 00a6179d5e..0000000000 --- a/scene/resources/default_theme/icon_grid_minimap.png +++ /dev/null diff --git a/scene/resources/default_theme/icon_parent_folder.png b/scene/resources/default_theme/icon_parent_folder.png Binary files differdeleted file mode 100644 index 35d218722e..0000000000 --- a/scene/resources/default_theme/icon_parent_folder.png +++ /dev/null diff --git a/scene/resources/default_theme/icon_reload.png b/scene/resources/default_theme/icon_reload.png Binary files differdeleted file mode 100644 index bec5f3f4f9..0000000000 --- a/scene/resources/default_theme/icon_reload.png +++ /dev/null diff --git a/scene/resources/default_theme/icon_snap_grid.png b/scene/resources/default_theme/icon_snap_grid.png Binary files differdeleted file mode 100644 index 0680317d86..0000000000 --- a/scene/resources/default_theme/icon_snap_grid.png +++ /dev/null diff --git a/scene/resources/default_theme/icon_visibility.png b/scene/resources/default_theme/icon_visibility.png Binary files differdeleted file mode 100644 index b2df8cbdb8..0000000000 --- a/scene/resources/default_theme/icon_visibility.png +++ /dev/null diff --git a/scene/resources/default_theme/icon_zoom_less.png b/scene/resources/default_theme/icon_zoom_less.png Binary files differdeleted file mode 100644 index 03119c60ca..0000000000 --- a/scene/resources/default_theme/icon_zoom_less.png +++ /dev/null diff --git a/scene/resources/default_theme/icon_zoom_more.png b/scene/resources/default_theme/icon_zoom_more.png Binary files differdeleted file mode 100644 index 31467ec3de..0000000000 --- a/scene/resources/default_theme/icon_zoom_more.png +++ /dev/null diff --git a/scene/resources/default_theme/icon_zoom_reset.png b/scene/resources/default_theme/icon_zoom_reset.png Binary files differdeleted file mode 100644 index cac68c09fa..0000000000 --- a/scene/resources/default_theme/icon_zoom_reset.png +++ /dev/null diff --git a/scene/resources/default_theme/indeterminate.png b/scene/resources/default_theme/indeterminate.png Binary files differdeleted file mode 100644 index 28a457b251..0000000000 --- a/scene/resources/default_theme/indeterminate.png +++ /dev/null diff --git a/scene/resources/default_theme/indeterminate.svg b/scene/resources/default_theme/indeterminate.svg new file mode 100644 index 0000000000..2a742e1475 --- /dev/null +++ b/scene/resources/default_theme/indeterminate.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.3333333 1c-1.2887 0-2.3333333 1.0446683-2.3333333 2.3333333v9.3333337c0 1.2887 1.0446683 2.333333 2.3333333 2.333333h9.3333337c1.2887 0 2.333333-1.044668 2.333333-2.333333v-9.3333337c0-1.2887-1.044668-2.3333333-2.333333-2.3333333z" fill="#fff" fill-opacity=".75" stroke-width="1.16667"/><path d="m3 7h10v2h-10z" fill="#1a1a1a" stroke-linecap="square" stroke-opacity=".75" stroke-width="2"/></svg> diff --git a/scene/resources/default_theme/line_edit.png b/scene/resources/default_theme/line_edit.png Binary files differdeleted file mode 100644 index 2b0c506f34..0000000000 --- a/scene/resources/default_theme/line_edit.png +++ /dev/null diff --git a/scene/resources/default_theme/line_edit_clear.png b/scene/resources/default_theme/line_edit_clear.png Binary files differdeleted file mode 100644 index af2775a132..0000000000 --- a/scene/resources/default_theme/line_edit_clear.png +++ /dev/null diff --git a/scene/resources/default_theme/line_edit_clear.svg b/scene/resources/default_theme/line_edit_clear.svg new file mode 100644 index 0000000000..3709c43410 --- /dev/null +++ b/scene/resources/default_theme/line_edit_clear.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m1 3 2-2 5 5 5-5 2 2-5 5 5 5-2 2-5.302-5-4.698 5-2-2 5-5z" fill="#fff" fill-opacity=".75" fill-rule="nonzero"/></svg> diff --git a/scene/resources/default_theme/line_edit_disabled.png b/scene/resources/default_theme/line_edit_disabled.png Binary files differdeleted file mode 100644 index 69d78febd9..0000000000 --- a/scene/resources/default_theme/line_edit_disabled.png +++ /dev/null diff --git a/scene/resources/default_theme/make_header.py b/scene/resources/default_theme/make_header.py deleted file mode 100755 index efad3b2815..0000000000 --- a/scene/resources/default_theme/make_header.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python - -import glob -import os - -enc = "utf-8" - -# Change to the directory where the script is located, -# so that the script can be run from any location -os.chdir(os.path.dirname(os.path.realpath(__file__))) - -# Generate include files - -f = open("theme_data.h", "wb") - -f.write(b"// THIS FILE HAS BEEN AUTOGENERATED, DON'T EDIT!!\n") - -# Generate png image block -f.write(b"\n// png image block\n") - -pixmaps = glob.glob("*.png") -pixmaps.sort() - -for x in pixmaps: - - var_str = x[:-4] + "_png" - - s = "\nstatic const unsigned char " + var_str + "[] = {\n\t" - f.write(s.encode(enc)) - - pngf = open(x, "rb") - - b = pngf.read(1) - while len(b) == 1: - f.write(hex(ord(b)).encode(enc)) - b = pngf.read(1) - if len(b) == 1: - f.write(b", ") - - f.write(b"\n};\n") - pngf.close() - -# Generate shaders block -f.write(b"\n// shaders block\n") - -shaders = glob.glob("*.gsl") -shaders.sort() - -for x in shaders: - - var_str = x[:-4] + "_shader_code" - - s = "\nstatic const char *" + var_str + " = \n" - f.write(s.encode(enc)) - - sf = open(x, "rb") - - b = sf.readline() - while b != "": - if b.endswith("\r\n"): - b = b[:-2] - if b.endswith("\n"): - b = b[:-1] - s = ' "' + b - f.write(s.encode(enc)) - b = sf.readline() - if b != "": - f.write(b'"\n') - - f.write(b'";\n') - sf.close() - -f.close() diff --git a/scene/resources/default_theme/mini_checkerboard.png b/scene/resources/default_theme/mini_checkerboard.png Binary files differdeleted file mode 100644 index d8279bda80..0000000000 --- a/scene/resources/default_theme/mini_checkerboard.png +++ /dev/null diff --git a/scene/resources/default_theme/mini_checkerboard.svg b/scene/resources/default_theme/mini_checkerboard.svg new file mode 100644 index 0000000000..0ae6a855bd --- /dev/null +++ b/scene/resources/default_theme/mini_checkerboard.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-linecap="round" stroke-linejoin="round" stroke-width="1.9994"><path d="m0 0v8h8v-8zm8 8v8h8v-8z" fill="#e0e0e0"/><path d="m8 0v8h8v-8zm0 8h-8v8h8z" fill="#fff"/></g></svg> diff --git a/scene/resources/default_theme/option_arrow.png b/scene/resources/default_theme/option_arrow.png Binary files differdeleted file mode 100644 index 40590fd60a..0000000000 --- a/scene/resources/default_theme/option_arrow.png +++ /dev/null diff --git a/scene/resources/default_theme/option_button_arrow.svg b/scene/resources/default_theme/option_button_arrow.svg new file mode 100644 index 0000000000..1a33668708 --- /dev/null +++ b/scene/resources/default_theme/option_button_arrow.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg"><path d="m10 3c-.264.01-.514.117-.697.307l-3.293 3.293-3.293-3.293c-.189-.194-.447-.303-.717-.303-.897 0-1.34 1.091-.697 1.717l4 4c.39.39 1.023.39 1.414 0l4-4c.657-.632.195-1.742-.717-1.721z" fill="#b2b2b2" fill-opacity=".85" fill-rule="nonzero"/></svg> diff --git a/scene/resources/default_theme/option_button_disabled.png b/scene/resources/default_theme/option_button_disabled.png Binary files differdeleted file mode 100644 index 1961b673cd..0000000000 --- a/scene/resources/default_theme/option_button_disabled.png +++ /dev/null diff --git a/scene/resources/default_theme/option_button_disabled_mirrored.png b/scene/resources/default_theme/option_button_disabled_mirrored.png Binary files differdeleted file mode 100644 index 9d149a35ca..0000000000 --- a/scene/resources/default_theme/option_button_disabled_mirrored.png +++ /dev/null diff --git a/scene/resources/default_theme/option_button_hover.png b/scene/resources/default_theme/option_button_hover.png Binary files differdeleted file mode 100644 index 826fe1c9ca..0000000000 --- a/scene/resources/default_theme/option_button_hover.png +++ /dev/null diff --git a/scene/resources/default_theme/option_button_hover_mirrored.png b/scene/resources/default_theme/option_button_hover_mirrored.png Binary files differdeleted file mode 100644 index d49c165645..0000000000 --- a/scene/resources/default_theme/option_button_hover_mirrored.png +++ /dev/null diff --git a/scene/resources/default_theme/option_button_normal.png b/scene/resources/default_theme/option_button_normal.png Binary files differdeleted file mode 100644 index 43fc29e958..0000000000 --- a/scene/resources/default_theme/option_button_normal.png +++ /dev/null diff --git a/scene/resources/default_theme/option_button_normal_mirrored.png b/scene/resources/default_theme/option_button_normal_mirrored.png Binary files differdeleted file mode 100644 index feec848f33..0000000000 --- a/scene/resources/default_theme/option_button_normal_mirrored.png +++ /dev/null diff --git a/scene/resources/default_theme/option_button_pressed.png b/scene/resources/default_theme/option_button_pressed.png Binary files differdeleted file mode 100644 index 68796f9d85..0000000000 --- a/scene/resources/default_theme/option_button_pressed.png +++ /dev/null diff --git a/scene/resources/default_theme/option_button_pressed_mirrored.png b/scene/resources/default_theme/option_button_pressed_mirrored.png Binary files differdeleted file mode 100644 index 94cabb18d6..0000000000 --- a/scene/resources/default_theme/option_button_pressed_mirrored.png +++ /dev/null diff --git a/scene/resources/default_theme/overbright_indicator.png b/scene/resources/default_theme/overbright_indicator.png Binary files differdeleted file mode 100644 index e13f15dd02..0000000000 --- a/scene/resources/default_theme/overbright_indicator.png +++ /dev/null diff --git a/scene/resources/default_theme/panel_bg.png b/scene/resources/default_theme/panel_bg.png Binary files differdeleted file mode 100644 index b496e2177e..0000000000 --- a/scene/resources/default_theme/panel_bg.png +++ /dev/null diff --git a/scene/resources/default_theme/picker_cursor.png b/scene/resources/default_theme/picker_cursor.png Binary files differdeleted file mode 100644 index 2f403492d2..0000000000 --- a/scene/resources/default_theme/picker_cursor.png +++ /dev/null diff --git a/scene/resources/default_theme/popup_bg.png b/scene/resources/default_theme/popup_bg.png Binary files differdeleted file mode 100644 index 023029f936..0000000000 --- a/scene/resources/default_theme/popup_bg.png +++ /dev/null diff --git a/scene/resources/default_theme/popup_bg_disabled.png b/scene/resources/default_theme/popup_bg_disabled.png Binary files differdeleted file mode 100644 index 8eab5f27bc..0000000000 --- a/scene/resources/default_theme/popup_bg_disabled.png +++ /dev/null diff --git a/scene/resources/default_theme/popup_window.png b/scene/resources/default_theme/popup_window.png Binary files differdeleted file mode 100644 index 442084049d..0000000000 --- a/scene/resources/default_theme/popup_window.png +++ /dev/null diff --git a/scene/resources/default_theme/progress_bar.png b/scene/resources/default_theme/progress_bar.png Binary files differdeleted file mode 100644 index 057557e567..0000000000 --- a/scene/resources/default_theme/progress_bar.png +++ /dev/null diff --git a/scene/resources/default_theme/progress_fill.png b/scene/resources/default_theme/progress_fill.png Binary files differdeleted file mode 100644 index e39bb2a021..0000000000 --- a/scene/resources/default_theme/progress_fill.png +++ /dev/null diff --git a/scene/resources/default_theme/radio_checked.png b/scene/resources/default_theme/radio_checked.png Binary files differdeleted file mode 100644 index 0ce575c15f..0000000000 --- a/scene/resources/default_theme/radio_checked.png +++ /dev/null diff --git a/scene/resources/default_theme/radio_checked.svg b/scene/resources/default_theme/radio_checked.svg new file mode 100644 index 0000000000..73d1c8e34a --- /dev/null +++ b/scene/resources/default_theme/radio_checked.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 8a7 7 0 0 1 -7 7 7 7 0 0 1 -7-7 7 7 0 0 1 7-7 7 7 0 0 1 7 7" fill="#fff" fill-opacity=".75" stroke-width="2.33333"/><path d="m12 8a4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4 4 4 0 0 1 4 4" fill="#1a1a1a" stroke-width="1.33333"/></svg> diff --git a/scene/resources/default_theme/radio_checked_disabled.png b/scene/resources/default_theme/radio_checked_disabled.png Binary files differdeleted file mode 100644 index 72f08ecb96..0000000000 --- a/scene/resources/default_theme/radio_checked_disabled.png +++ /dev/null diff --git a/scene/resources/default_theme/radio_checked_disabled.svg b/scene/resources/default_theme/radio_checked_disabled.svg new file mode 100644 index 0000000000..ef5eff8d97 --- /dev/null +++ b/scene/resources/default_theme/radio_checked_disabled.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 8a7 7 0 0 1 -7 7 7 7 0 0 1 -7-7 7 7 0 0 1 7-7 7 7 0 0 1 7 7" fill="#fff" fill-opacity=".37" stroke-width="2.33333"/><path d="m12 8a4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4 4 4 0 0 1 4 4" fill="#1a1a1a" fill-opacity=".5" stroke-width="1.33333"/></svg> diff --git a/scene/resources/default_theme/radio_unchecked.png b/scene/resources/default_theme/radio_unchecked.png Binary files differdeleted file mode 100644 index fe5bcf6ab1..0000000000 --- a/scene/resources/default_theme/radio_unchecked.png +++ /dev/null diff --git a/scene/resources/default_theme/radio_unchecked.svg b/scene/resources/default_theme/radio_unchecked.svg new file mode 100644 index 0000000000..5429855db5 --- /dev/null +++ b/scene/resources/default_theme/radio_unchecked.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 8a7 7 0 0 1 -7 7 7 7 0 0 1 -7-7 7 7 0 0 1 7-7 7 7 0 0 1 7 7" fill="#1a1a1a" fill-opacity=".5" stroke-width="2.33333"/></svg> diff --git a/scene/resources/default_theme/radio_unchecked_disabled.png b/scene/resources/default_theme/radio_unchecked_disabled.png Binary files differdeleted file mode 100644 index a8f4c1b555..0000000000 --- a/scene/resources/default_theme/radio_unchecked_disabled.png +++ /dev/null diff --git a/scene/resources/default_theme/radio_unchecked_disabled.svg b/scene/resources/default_theme/radio_unchecked_disabled.svg new file mode 100644 index 0000000000..1e827d9374 --- /dev/null +++ b/scene/resources/default_theme/radio_unchecked_disabled.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 8a7 7 0 0 1 -7 7 7 7 0 0 1 -7-7 7 7 0 0 1 7-7 7 7 0 0 1 7 7" fill="#1a1a1a" fill-opacity=".25" stroke-width="2.33333"/></svg> diff --git a/scene/resources/default_theme/reload.svg b/scene/resources/default_theme/reload.svg new file mode 100644 index 0000000000..66809f8374 --- /dev/null +++ b/scene/resources/default_theme/reload.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#b2b2b2" fill-rule="nonzero"><path d="m8.987 2c-3.292 0-6 2.708-6 6h2c0-2.194 1.806-4 4-4s4 1.806 4 4-1.806 4-4 4v2c3.291 0 6-2.708 6-6s-2.709-6-6-6z"/><path d="m7.013 7.989-1.5 2-1.5 2-1.5-2-1.5-2z"/></g></svg> diff --git a/scene/resources/default_theme/resizer_nw.svg b/scene/resources/default_theme/resizer_nw.svg new file mode 100644 index 0000000000..92e25c3be2 --- /dev/null +++ b/scene/resources/default_theme/resizer_nw.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill-opacity=".65"><path d="m4 12c.552 0 1-.448 1-1v-6h6c.552 0 1-.448 1-1s-.448-1-1-1h-7c-.552 0-1 .448-1 1v7c0 .552.448 1 1 1z" fill="#fefffe" fill-rule="nonzero"/><circle cx="7.5" cy="7.5" fill="#b2b2b2" r="1.479"/></g></svg> diff --git a/scene/resources/default_theme/resizer_se.svg b/scene/resources/default_theme/resizer_se.svg new file mode 100644 index 0000000000..2d492e976e --- /dev/null +++ b/scene/resources/default_theme/resizer_se.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill-opacity=".65"><path d="m11 3c-.552 0-1 .448-1 1v6h-6c-.552 0-1 .448-1 1s.448 1 1 1h7c.552 0 1-.448 1-1v-7c0-.552-.448-1-1-1z" fill="#fefffe" fill-rule="nonzero"/><circle cx="7.5" cy="7.5" fill="#b2b2b2" r="1.479"/></g></svg> diff --git a/scene/resources/default_theme/scroll_bg.png b/scene/resources/default_theme/scroll_bg.png Binary files differdeleted file mode 100644 index fb151a48b1..0000000000 --- a/scene/resources/default_theme/scroll_bg.png +++ /dev/null diff --git a/scene/resources/default_theme/scroll_button_left.png b/scene/resources/default_theme/scroll_button_left.png Binary files differdeleted file mode 100644 index e430cb4673..0000000000 --- a/scene/resources/default_theme/scroll_button_left.png +++ /dev/null diff --git a/scene/resources/default_theme/scroll_button_left.svg b/scene/resources/default_theme/scroll_button_left.svg new file mode 100644 index 0000000000..947b417a00 --- /dev/null +++ b/scene/resources/default_theme/scroll_button_left.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" fill="#fefffe" fill-opacity=".75" r="6"/><path d="m9.014 4c-.27-.004-.53.102-.721.293l-3 3c-.388.388-.388 1.026 0 1.414l3 3c.388.388 1.026.388 1.414 0s.388-1.026 0-1.414l-2.293-2.293 2.293-2.293c.388-.388.388-1.026 0-1.414-.184-.184-.433-.289-.693-.293z" fill="#1a1a1a" fill-opacity=".65"/></svg> diff --git a/scene/resources/default_theme/scroll_button_left_hl.png b/scene/resources/default_theme/scroll_button_left_hl.png Binary files differdeleted file mode 100644 index 2a6ef17a34..0000000000 --- a/scene/resources/default_theme/scroll_button_left_hl.png +++ /dev/null diff --git a/scene/resources/default_theme/scroll_button_left_hl.svg b/scene/resources/default_theme/scroll_button_left_hl.svg new file mode 100644 index 0000000000..fa092c861a --- /dev/null +++ b/scene/resources/default_theme/scroll_button_left_hl.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" fill="#fefffe" r="6"/><path d="m9.014 4c-.27-.004-.53.102-.721.293l-3 3c-.388.388-.388 1.026 0 1.414l3 3c.388.388 1.026.388 1.414 0s.388-1.026 0-1.414l-2.293-2.293 2.293-2.293c.388-.388.388-1.026 0-1.414-.184-.184-.433-.289-.693-.293z" fill="#1a1a1a"/></svg> diff --git a/scene/resources/default_theme/scroll_button_right.png b/scene/resources/default_theme/scroll_button_right.png Binary files differdeleted file mode 100644 index 4f61687aa4..0000000000 --- a/scene/resources/default_theme/scroll_button_right.png +++ /dev/null diff --git a/scene/resources/default_theme/scroll_button_right.svg b/scene/resources/default_theme/scroll_button_right.svg new file mode 100644 index 0000000000..84619e7aa9 --- /dev/null +++ b/scene/resources/default_theme/scroll_button_right.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" fill="#fefffe" fill-opacity=".75" r="6"/><path d="m6.986 4c.27-.004.53.102.721.293l3 3c.388.388.388 1.026 0 1.414l-3 3c-.388.388-1.026.388-1.414 0s-.388-1.026 0-1.414l2.293-2.293-2.293-2.293c-.388-.388-.388-1.026 0-1.414.184-.184.433-.289.693-.293z" fill="#1a1a1a" fill-opacity=".65"/></svg> diff --git a/scene/resources/default_theme/scroll_button_right_hl.png b/scene/resources/default_theme/scroll_button_right_hl.png Binary files differdeleted file mode 100644 index 10e2722509..0000000000 --- a/scene/resources/default_theme/scroll_button_right_hl.png +++ /dev/null diff --git a/scene/resources/default_theme/scroll_button_right_hl.svg b/scene/resources/default_theme/scroll_button_right_hl.svg new file mode 100644 index 0000000000..601f98c0d5 --- /dev/null +++ b/scene/resources/default_theme/scroll_button_right_hl.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" fill="#fefffe" r="6"/><path d="m6.986 4c.27-.004.53.102.721.293l3 3c.388.388.388 1.026 0 1.414l-3 3c-.388.388-1.026.388-1.414 0s-.388-1.026 0-1.414l2.293-2.293-2.293-2.293c-.388-.388-.388-1.026 0-1.414.184-.184.433-.289.693-.293z" fill="#1a1a1a"/></svg> diff --git a/scene/resources/default_theme/scroll_grabber.png b/scene/resources/default_theme/scroll_grabber.png Binary files differdeleted file mode 100644 index 732725a28f..0000000000 --- a/scene/resources/default_theme/scroll_grabber.png +++ /dev/null diff --git a/scene/resources/default_theme/scroll_grabber_hl.png b/scene/resources/default_theme/scroll_grabber_hl.png Binary files differdeleted file mode 100644 index 21ee486e0b..0000000000 --- a/scene/resources/default_theme/scroll_grabber_hl.png +++ /dev/null diff --git a/scene/resources/default_theme/scroll_grabber_pressed.png b/scene/resources/default_theme/scroll_grabber_pressed.png Binary files differdeleted file mode 100644 index f4886158fa..0000000000 --- a/scene/resources/default_theme/scroll_grabber_pressed.png +++ /dev/null diff --git a/scene/resources/default_theme/selection.png b/scene/resources/default_theme/selection.png Binary files differdeleted file mode 100644 index 7d1c985b35..0000000000 --- a/scene/resources/default_theme/selection.png +++ /dev/null diff --git a/scene/resources/default_theme/selection_oof.png b/scene/resources/default_theme/selection_oof.png Binary files differdeleted file mode 100644 index 2da0538389..0000000000 --- a/scene/resources/default_theme/selection_oof.png +++ /dev/null diff --git a/scene/resources/default_theme/slider_grabber.svg b/scene/resources/default_theme/slider_grabber.svg new file mode 100644 index 0000000000..0813830134 --- /dev/null +++ b/scene/resources/default_theme/slider_grabber.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 8a7 7 0 0 1 -7 7 7 7 0 0 1 -7-7 7 7 0 0 1 7-7 7 7 0 0 1 7 7" fill="#fefefe" fill-opacity=".75" stroke-width="2.33333"/></svg> diff --git a/scene/resources/default_theme/slider_grabber_disabled.svg b/scene/resources/default_theme/slider_grabber_disabled.svg new file mode 100644 index 0000000000..659c2e9e14 --- /dev/null +++ b/scene/resources/default_theme/slider_grabber_disabled.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 8a7 7 0 0 1 -7 7 7 7 0 0 1 -7-7 7 7 0 0 1 7-7 7 7 0 0 1 7 7" fill="#fefefe" fill-opacity=".37" stroke-width="2.33333"/></svg> diff --git a/scene/resources/default_theme/slider_grabber_hl.svg b/scene/resources/default_theme/slider_grabber_hl.svg new file mode 100644 index 0000000000..d7d0594d67 --- /dev/null +++ b/scene/resources/default_theme/slider_grabber_hl.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 8a7 7 0 0 1 -7 7 7 7 0 0 1 -7-7 7 7 0 0 1 7-7 7 7 0 0 1 7 7" fill="#fefefe" fill-opacity=".997951" stroke-width="2.33333"/></svg> diff --git a/scene/resources/default_theme/space.png b/scene/resources/default_theme/space.png Binary files differdeleted file mode 100644 index 3c66316074..0000000000 --- a/scene/resources/default_theme/space.png +++ /dev/null diff --git a/scene/resources/default_theme/spinbox_updown.png b/scene/resources/default_theme/spinbox_updown.png Binary files differdeleted file mode 100644 index 74fab19f34..0000000000 --- a/scene/resources/default_theme/spinbox_updown.png +++ /dev/null diff --git a/scene/resources/default_theme/submenu.png b/scene/resources/default_theme/submenu.png Binary files differdeleted file mode 100644 index 8f7de446d4..0000000000 --- a/scene/resources/default_theme/submenu.png +++ /dev/null diff --git a/scene/resources/default_theme/submenu_mirrored.png b/scene/resources/default_theme/submenu_mirrored.png Binary files differdeleted file mode 100644 index 1142b9ba9f..0000000000 --- a/scene/resources/default_theme/submenu_mirrored.png +++ /dev/null diff --git a/scene/resources/default_theme/tab.png b/scene/resources/default_theme/tab.png Binary files differdeleted file mode 100644 index 895daa65e2..0000000000 --- a/scene/resources/default_theme/tab.png +++ /dev/null diff --git a/scene/resources/default_theme/tab_behind.png b/scene/resources/default_theme/tab_behind.png Binary files differdeleted file mode 100644 index 2803d9db65..0000000000 --- a/scene/resources/default_theme/tab_behind.png +++ /dev/null diff --git a/scene/resources/default_theme/tab_close.png b/scene/resources/default_theme/tab_close.png Binary files differdeleted file mode 100644 index af2775a132..0000000000 --- a/scene/resources/default_theme/tab_close.png +++ /dev/null diff --git a/scene/resources/default_theme/tab_container_bg.png b/scene/resources/default_theme/tab_container_bg.png Binary files differdeleted file mode 100644 index c189b61b89..0000000000 --- a/scene/resources/default_theme/tab_container_bg.png +++ /dev/null diff --git a/scene/resources/default_theme/tab_current.png b/scene/resources/default_theme/tab_current.png Binary files differdeleted file mode 100644 index ce2b9b0925..0000000000 --- a/scene/resources/default_theme/tab_current.png +++ /dev/null diff --git a/scene/resources/default_theme/tab_disabled.png b/scene/resources/default_theme/tab_disabled.png Binary files differdeleted file mode 100644 index a7c04effa3..0000000000 --- a/scene/resources/default_theme/tab_disabled.png +++ /dev/null diff --git a/scene/resources/default_theme/tab_menu.png b/scene/resources/default_theme/tab_menu.png Binary files differdeleted file mode 100644 index fa4421a28a..0000000000 --- a/scene/resources/default_theme/tab_menu.png +++ /dev/null diff --git a/scene/resources/default_theme/tab_menu_hl.png b/scene/resources/default_theme/tab_menu_hl.png Binary files differdeleted file mode 100644 index fa4421a28a..0000000000 --- a/scene/resources/default_theme/tab_menu_hl.png +++ /dev/null diff --git a/scene/resources/default_theme/tabs_menu.svg b/scene/resources/default_theme/tabs_menu.svg new file mode 100644 index 0000000000..4670a5deae --- /dev/null +++ b/scene/resources/default_theme/tabs_menu.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 0c-1.097 0-2 .903-2 2s.903 2 2 2 2-.903 2-2-.903-2-2-2zm0 6c-1.097 0-2 .903-2 2s.903 2 2 2 2-.903 2-2-.903-2-2-2zm0 6c-1.097 0-2 .903-2 2s.903 2 2 2 2-.903 2-2-.903-2-2-2z" fill="#b2b2b2" fill-opacity=".45" fill-rule="nonzero"/></svg> diff --git a/scene/resources/default_theme/tabs_menu_hl.svg b/scene/resources/default_theme/tabs_menu_hl.svg new file mode 100644 index 0000000000..4ea54a2fda --- /dev/null +++ b/scene/resources/default_theme/tabs_menu_hl.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 0c-1.097 0-2 .903-2 2s.903 2 2 2 2-.903 2-2-.903-2-2-2zm0 6c-1.097 0-2 .903-2 2s.903 2 2 2 2-.903 2-2-.903-2-2-2zm0 6c-1.097 0-2 .903-2 2s.903 2 2 2 2-.903 2-2-.903-2-2-2z" fill="#fefffe" fill-opacity=".65" fill-rule="nonzero"/></svg> diff --git a/scene/resources/default_theme/text_edit_ellipsis.svg b/scene/resources/default_theme/text_edit_ellipsis.svg new file mode 100644 index 0000000000..026a1fcba7 --- /dev/null +++ b/scene/resources/default_theme/text_edit_ellipsis.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 14 8" xmlns="http://www.w3.org/2000/svg"><path d="m3.859 0c-2.138 0-3.859 1.721-3.859 3.859v.282c0 2.138 1.721 3.859 3.859 3.859h6.282c2.138 0 3.859-1.721 3.859-3.859v-.282c0-2.138-1.721-3.859-3.859-3.859zm-.859 3c.549 0 1 .451 1 1s-.451 1-1 1-1-.451-1-1 .451-1 1-1zm4 0c.549 0 1 .451 1 1s-.451 1-1 1-1-.451-1-1 .451-1 1-1zm4 0c.549 0 1 .451 1 1s-.451 1-1 1-1-.451-1-1 .451-1 1-1z" fill="#fefffe" fill-opacity=".25" fill-rule="nonzero"/></svg> diff --git a/scene/resources/default_theme/text_edit_space.svg b/scene/resources/default_theme/text_edit_space.svg new file mode 100644 index 0000000000..b2b1dd4676 --- /dev/null +++ b/scene/resources/default_theme/text_edit_space.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg"><circle cx="4" cy="4" fill="#b2b2b2" fill-opacity=".25" r="1.5"/></svg> diff --git a/scene/resources/default_theme/text_edit_tab.svg b/scene/resources/default_theme/text_edit_tab.svg new file mode 100644 index 0000000000..1968afb1e7 --- /dev/null +++ b/scene/resources/default_theme/text_edit_tab.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg"><path d="m6 0v8h2v-8zm-5.014.002c-.26.003-.509.108-.693.291-.388.388-.388 1.026 0 1.414l2.293 2.293-2.293 2.293c-.388.388-.388 1.026 0 1.414s1.026.388 1.414 0l3-3c.388-.388.388-1.026 0-1.414l-3-3c-.191-.19-.451-.295-.721-.291z" fill="#b2b2b2" fill-opacity=".25" fill-rule="nonzero"/></svg> diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h deleted file mode 100644 index 1cec50eab4..0000000000 --- a/scene/resources/default_theme/theme_data.h +++ /dev/null @@ -1,517 +0,0 @@ -// THIS FILE HAS BEEN AUTOGENERATED, DON'T EDIT!! - -// png image block - -static const unsigned char arrow_down_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x4, 0x0, 0x0, 0x0, 0xfc, 0x7c, 0x94, 0x6c, 0x0, 0x0, 0x0, 0x34, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xa0, 0x32, 0x78, 0xf0, 0x1f, 0x15, 0x52, 0x20, 0xf1, 0x30, 0xee, 0xc1, 0x17, 0xb8, 0xf0, 0xb7, 0x87, 0x69, 0x48, 0xb6, 0xdc, 0xd7, 0xb8, 0x7f, 0x9, 0x2c, 0x7c, 0xfd, 0xb1, 0x2e, 0x9a, 0x3, 0x5e, 0x70, 0x3f, 0x9c, 0xff, 0x70, 0xfe, 0xb, 0x6e, 0x6, 0xea, 0x3, 0x0, 0xfb, 0x81, 0x48, 0xb8, 0x4d, 0xe4, 0x75, 0xd9, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char arrow_left_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x4, 0x0, 0x0, 0x0, 0xfc, 0x7c, 0x94, 0x6c, 0x0, 0x0, 0x0, 0x1, 0x6f, 0x72, 0x4e, 0x54, 0x1, 0xcf, 0xa2, 0x77, 0x9a, 0x0, 0x0, 0x0, 0x59, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x63, 0x60, 0xa0, 0x0, 0xdc, 0x4f, 0x78, 0xf0, 0xff, 0xc1, 0xff, 0x7, 0xff, 0x21, 0x3c, 0x46, 0x98, 0xf0, 0x43, 0xed, 0xff, 0x27, 0x19, 0xb8, 0x19, 0x18, 0x18, 0x18, 0x14, 0x18, 0x19, 0x18, 0x18, 0x18, 0x98, 0x20, 0xc2, 0x2f, 0xb8, 0xff, 0xaf, 0x82, 0x8, 0xc3, 0x0, 0x54, 0xe2, 0xe7, 0x14, 0x6, 0x2d, 0x54, 0x83, 0x99, 0x70, 0xd9, 0x8, 0x95, 0x60, 0xcf, 0x61, 0xb8, 0x86, 0x55, 0x42, 0xe2, 0x2b, 0x63, 0x18, 0xc3, 0x57, 0xac, 0x46, 0xc9, 0x5f, 0xfd, 0x9f, 0x43, 0x89, 0x67, 0x19, 0x18, 0x0, 0xf4, 0x30, 0x14, 0x49, 0xef, 0xe6, 0x74, 0x60, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char arrow_right_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x4, 0x0, 0x0, 0x0, 0xfc, 0x7c, 0x94, 0x6c, 0x0, 0x0, 0x0, 0x2e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x17, 0x3c, 0xf8, 0xf, 0x82, 0xf7, 0x13, 0x70, 0x48, 0x3c, 0xf8, 0xf2, 0x50, 0x1b, 0x43, 0x2, 0xa, 0xaf, 0xbe, 0xe0, 0xc6, 0x2e, 0xf1, 0xff, 0xe1, 0x7c, 0x12, 0x24, 0x10, 0x46, 0x11, 0xb6, 0x1c, 0xe1, 0x5c, 0xa, 0x0, 0x0, 0xe0, 0x14, 0x48, 0xb1, 0x3d, 0x1b, 0x7a, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char bar_arrow_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x14, 0x8, 0x4, 0x0, 0x0, 0x0, 0x2e, 0x6b, 0x75, 0xfc, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x1, 0x73, 0x52, 0x47, 0x42, 0x0, 0xae, 0xce, 0x1c, 0xe9, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xe, 0xc0, 0x0, 0x0, 0xe, 0xc0, 0x1, 0x6a, 0xd6, 0x89, 0x9, 0x0, 0x0, 0x0, 0x65, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0xfc, 0xcf, 0x80, 0x1f, 0x30, 0x8e, 0x20, 0x5, 0x8c, 0x38, 0x24, 0xff, 0x53, 0x5f, 0xc1, 0xb, 0xee, 0x9f, 0x53, 0x18, 0x18, 0xd8, 0x73, 0x24, 0xbe, 0x62, 0x55, 0x70, 0x5f, 0x83, 0x61, 0x15, 0xa3, 0x2e, 0x3, 0x3, 0xc3, 0xd, 0xe6, 0x30, 0xd9, 0xcb, 0x18, 0xa, 0x1e, 0xc6, 0xfd, 0x9f, 0xc6, 0xc0, 0xd, 0x35, 0xea, 0x3b, 0x63, 0x81, 0xfc, 0x2c, 0x14, 0x5, 0xf, 0x2a, 0x18, 0xda, 0xd1, 0x1c, 0x50, 0xa9, 0xd0, 0x1, 0x57, 0xf0, 0x10, 0x53, 0x9a, 0x81, 0x81, 0x81, 0xa1, 0x52, 0xbe, 0x83, 0x81, 0x81, 0xf1, 0x3f, 0x2e, 0x69, 0xa8, 0x12, 0x3a, 0x4, 0x14, 0x0, 0x7b, 0xda, 0x34, 0x1, 0xbb, 0xb5, 0x3e, 0x6c, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char bookmark_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x4, 0x73, 0x42, 0x49, 0x54, 0x8, 0x8, 0x8, 0x8, 0x7c, 0x8, 0x64, 0x88, 0x0, 0x0, 0x0, 0x57, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xed, 0x93, 0x31, 0xa, 0xc0, 0x30, 0xc, 0x3, 0xa5, 0xd0, 0xff, 0x7f, 0x59, 0x1d, 0x8a, 0x42, 0x8, 0x9, 0x95, 0xc9, 0xd2, 0xa1, 0x9a, 0x8c, 0xf1, 0xdd, 0x62, 0x1b, 0x38, 0xc, 0x87, 0x5a, 0x5, 0xae, 0x79, 0xde, 0x2, 0x1, 0x80, 0x94, 0x39, 0x48, 0x76, 0x49, 0x17, 0xa4, 0xf0, 0x24, 0x61, 0x2b, 0x51, 0x8b, 0xfc, 0x82, 0xcf, 0xb, 0x48, 0x7a, 0xdf, 0x75, 0x81, 0xf, 0xe5, 0x29, 0xf7, 0x92, 0x6b, 0x3, 0x1a, 0x1e, 0xda, 0x7c, 0x3d, 0x77, 0x21, 0x7b, 0xa8, 0x74, 0x2e, 0xcb, 0xd, 0xc8, 0x75, 0x13, 0x28, 0x9, 0xed, 0xc2, 0xc8, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char button_disabled_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0xc7, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x6c, 0xd0, 0x81, 0x66, 0x43, 0x31, 0x14, 0x87, 0xf1, 0xf, 0x5, 0x17, 0xb8, 0x28, 0x2e, 0x8, 0x71, 0xf3, 0x6, 0x19, 0xb6, 0xb9, 0xcb, 0xac, 0x95, 0xa4, 0xb7, 0xad, 0x6a, 0xd5, 0x68, 0x5f, 0xe4, 0x3e, 0x76, 0x1e, 0xe1, 0xbf, 0x21, 0xa6, 0xab, 0xf8, 0x1, 0x7c, 0x9c, 0x73, 0xe, 0xac, 0xe8, 0xe8, 0x19, 0x30, 0x58, 0xc6, 0xca, 0x62, 0x18, 0xe8, 0xe9, 0x58, 0x41, 0xc7, 0x1a, 0x87, 0x27, 0x10, 0x49, 0xe4, 0x5f, 0x89, 0x48, 0xc0, 0xe3, 0x58, 0xd3, 0x41, 0x8f, 0xb, 0xcb, 0xbd, 0x7c, 0xeb, 0xbf, 0x7b, 0x9, 0xb, 0x8e, 0x1e, 0x6, 0xfc, 0xad, 0x64, 0x6d, 0xb5, 0x79, 0xb0, 0x55, 0xd6, 0xad, 0xe0, 0x19, 0xc0, 0x10, 0xae, 0xda, 0x34, 0x5c, 0x45, 0xc0, 0x80, 0x25, 0x5e, 0xf4, 0xd5, 0x70, 0x11, 0x11, 0xb, 0x23, 0xe9, 0xac, 0xcf, 0x86, 0xb3, 0x48, 0x8c, 0x30, 0x92, 0x4f, 0xa, 0xd, 0x27, 0x91, 0x6b, 0x70, 0xd4, 0x47, 0xc3, 0xf1, 0x2f, 0x48, 0x7, 0x4d, 0xd, 0x87, 0x3a, 0xc2, 0x12, 0x67, 0xbd, 0x37, 0xcc, 0x75, 0x49, 0x43, 0xd8, 0xe9, 0xad, 0x61, 0x57, 0xcf, 0x1c, 0xf0, 0xfb, 0x32, 0xe9, 0xf5, 0xc9, 0xa4, 0x7d, 0x7d, 0x54, 0x8f, 0x7b, 0x59, 0xe6, 0x92, 0x14, 0x1f, 0x24, 0xcd, 0x3f, 0x7b, 0x6b, 0xa, 0xe, 0x6a, 0x82, 0x91, 0x45, 0x30, 0xba, 0x1, 0x4a, 0x51, 0xc4, 0x35, 0x1f, 0xe5, 0xa1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char button_focus_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x2d, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x62, 0xed, 0x5e, 0xfc, 0x0, 0x0, 0x0, 0xf, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xe, 0x39, 0x68, 0x7a, 0x7b, 0x3a, 0x74, 0x10, 0x8, 0x69, 0xf, 0x6, 0x75, 0x11, 0xb8, 0x16, 0x0, 0x1, 0x0, 0x0, 0x0, 0x3e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xc0, 0x2, 0x84, 0x4c, 0x42, 0x43, 0x9d, 0x15, 0x81, 0x8c, 0xf4, 0xce, 0x99, 0x33, 0x67, 0x94, 0x1, 0x19, 0xab, 0x41, 0xc2, 0xbb, 0x80, 0x38, 0x6, 0xc4, 0x38, 0xa, 0xc4, 0x91, 0x20, 0xc6, 0x54, 0x3c, 0xc, 0xb8, 0x62, 0x98, 0x76, 0x29, 0x20, 0xce, 0xdd, 0x39, 0x73, 0xe6, 0x3c, 0x90, 0x81, 0x62, 0x10, 0x2b, 0x30, 0x1, 0x0, 0xec, 0xe0, 0x11, 0x6d, 0xb5, 0xe0, 0x8c, 0x99, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char button_hover_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x8a, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x40, 0x4b, 0x5f, 0x5a, 0x6c, 0x5f, 0x5a, 0x6b, 0x56, 0x53, 0x64, 0x57, 0x53, 0x64, 0x3e, 0x3b, 0x46, 0x57, 0x53, 0x63, 0x57, 0x53, 0x63, 0x5b, 0x57, 0x68, 0x5a, 0x56, 0x67, 0x4d, 0x4a, 0x57, 0x49, 0x46, 0x52, 0x48, 0x45, 0x51, 0x5b, 0x57, 0x66, 0x59, 0x55, 0x64, 0x47, 0x44, 0x50, 0x58, 0x54, 0x64, 0x46, 0x43, 0x50, 0x56, 0x53, 0x63, 0x45, 0x42, 0x4f, 0x56, 0x53, 0x62, 0x45, 0x42, 0x4e, 0x55, 0x51, 0x62, 0x44, 0x41, 0x4e, 0x55, 0x51, 0x60, 0x44, 0x41, 0x4d, 0x43, 0x40, 0x4c, 0x47, 0x43, 0x51, 0x43, 0x3f, 0x4d, 0x42, 0x3f, 0x4c, 0x53, 0x50, 0x5f, 0x53, 0x4f, 0x5e, 0x40, 0xdc, 0xe6, 0x80, 0x0, 0x0, 0x0, 0x16, 0x74, 0x52, 0x4e, 0x53, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x77, 0xef, 0xef, 0xef, 0xef, 0x77, 0xef, 0xed, 0x6b, 0x28, 0x52, 0x7a, 0x0, 0x0, 0x0, 0x65, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x6d, 0xcf, 0xc5, 0x1, 0x84, 0x40, 0x14, 0x4, 0xd1, 0x2e, 0x5c, 0xf3, 0xf, 0x92, 0xbd, 0xaf, 0xd3, 0xb8, 0x53, 0x30, 0xf6, 0x6e, 0x1f, 0x31, 0x26, 0xc9, 0x63, 0x90, 0xcc, 0xe2, 0xb1, 0x4f, 0x34, 0x48, 0x8a, 0x86, 0xfc, 0xf6, 0x87, 0x1e, 0x82, 0x8c, 0x19, 0xf2, 0x17, 0x4, 0x50, 0xce, 0x6f, 0x8d, 0xd7, 0x88, 0x7e, 0x69, 0xc9, 0x23, 0x4, 0x1c, 0x40, 0x47, 0x50, 0x24, 0xed, 0x41, 0x3d, 0x78, 0xf, 0x56, 0xe4, 0x23, 0xb8, 0x7, 0x69, 0x11, 0xf7, 0x12, 0x12, 0x7e, 0xea, 0x60, 0xa, 0x9a, 0xef, 0x3f, 0xb0, 0x83, 0x26, 0x98, 0x7b, 0x70, 0x33, 0xdc, 0x65, 0xfc, 0xe, 0x81, 0x4e, 0x3b, 0x55, 0xea, 0xaa, 0xb0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char button_normal_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x87, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x3a, 0x44, 0x56, 0x53, 0x61, 0x56, 0x52, 0x60, 0x47, 0x44, 0x52, 0x33, 0x31, 0x39, 0x47, 0x44, 0x50, 0x47, 0x44, 0x51, 0x52, 0x50, 0x5d, 0x51, 0x4f, 0x5d, 0x46, 0x42, 0x4e, 0x42, 0x3e, 0x4a, 0x41, 0x3e, 0x49, 0x51, 0x4e, 0x5b, 0x40, 0x3e, 0x48, 0x4f, 0x4c, 0x59, 0x3f, 0x3d, 0x47, 0x4e, 0x4a, 0x58, 0x3e, 0x3b, 0x46, 0x4b, 0x49, 0x55, 0x3c, 0x3a, 0x44, 0x4a, 0x47, 0x54, 0x3b, 0x39, 0x43, 0x49, 0x46, 0x53, 0x3a, 0x38, 0x42, 0x47, 0x45, 0x50, 0x39, 0x37, 0x40, 0x47, 0x43, 0x50, 0x38, 0x35, 0x3f, 0x36, 0x34, 0x3e, 0x44, 0x42, 0x4d, 0x44, 0x41, 0x4c, 0x3f, 0x38, 0xaa, 0x5e, 0x0, 0x0, 0x0, 0x15, 0x74, 0x52, 0x4e, 0x53, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x77, 0xef, 0xef, 0xef, 0x77, 0xef, 0xed, 0xe8, 0xff, 0x76, 0xed, 0x0, 0x0, 0x0, 0x63, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x6d, 0xcf, 0x45, 0x2, 0x84, 0x30, 0x0, 0x4, 0xc1, 0x69, 0x1c, 0xfe, 0xff, 0xca, 0xd5, 0xeb, 0x2a, 0x83, 0x6b, 0xd2, 0xb7, 0x54, 0x1c, 0x31, 0x26, 0xc9, 0x63, 0x50, 0xcc, 0x32, 0x8d, 0x3f, 0xd9, 0x20, 0x5, 0x1a, 0xf2, 0xc7, 0x1f, 0x7a, 0x48, 0x4a, 0x66, 0xa8, 0xde, 0xc, 0xd0, 0x38, 0xd1, 0x54, 0xdb, 0x4c, 0x2b, 0xd0, 0x5c, 0x62, 0x8e, 0xa0, 0x1, 0x74, 0x4, 0x65, 0xd2, 0x1e, 0xd4, 0x83, 0xf7, 0x60, 0x65, 0x3e, 0x82, 0x3, 0x48, 0x49, 0xdf, 0x55, 0xca, 0xd4, 0xef, 0xfa, 0xfb, 0x27, 0x36, 0xf, 0x92, 0x31, 0x9e, 0x44, 0x3e, 0x17, 0x7c, 0xbf, 0x3, 0xef, 0x34, 0x3f, 0x3e, 0xe0, 0x24, 0x67, 0xb9, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char button_pressed_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x7, 0x1c, 0xc, 0x14, 0x2b, 0xf9, 0x77, 0x52, 0x64, 0x0, 0x0, 0x1, 0x92, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0x8d, 0x93, 0x4d, 0x4e, 0x1b, 0x41, 0x10, 0x85, 0xbf, 0xea, 0xaa, 0x1e, 0x20, 0x83, 0xf9, 0x9, 0x36, 0xb2, 0x85, 0x72, 0x84, 0x8, 0x65, 0x11, 0xe5, 0xc, 0x9c, 0x80, 0x73, 0x10, 0xee, 0xc1, 0x41, 0x38, 0x1, 0xab, 0xec, 0xa3, 0x2c, 0x2, 0x8a, 0xe0, 0x2, 0x51, 0xc2, 0x48, 0x46, 0x42, 0x64, 0xc6, 0x91, 0x21, 0xf4, 0x74, 0x16, 0x2e, 0xb0, 0x71, 0x2, 0xf2, 0x93, 0x9e, 0xba, 0x16, 0xdd, 0xaf, 0x5e, 0xa9, 0x5f, 0x9, 0x60, 0x40, 0x1, 0x2c, 0x1, 0xcb, 0x5e, 0x2b, 0x10, 0x78, 0x8a, 0x16, 0x48, 0xc0, 0x1d, 0x30, 0x6, 0x6e, 0x81, 0x3b, 0xf3, 0x87, 0x25, 0xb0, 0x9, 0xac, 0x7b, 0xbd, 0xc, 0x88, 0x13, 0x20, 0x3b, 0xc7, 0xc0, 0x8, 0xb8, 0x1, 0xae, 0x81, 0x91, 0xf9, 0xe5, 0xad, 0x77, 0xbb, 0x1f, 0xf6, 0x7b, 0xdd, 0xfe, 0x41, 0x4a, 0x69, 0x2d, 0x93, 0xf9, 0x1f, 0x4, 0x41, 0x55, 0x7f, 0xd, 0xaf, 0xaa, 0xa3, 0xaf, 0x67, 0x9f, 0x8f, 0x81, 0x64, 0xde, 0xb1, 0xbb, 0xdd, 0x1b, 0x7c, 0xac, 0x9b, 0x9b, 0xce, 0xd9, 0xb7, 0x2f, 0xfc, 0xf3, 0x5e, 0xa6, 0xe5, 0xee, 0xdb, 0xf7, 0x6b, 0xdb, 0xbd, 0xc1, 0x21, 0xf0, 0x9, 0x18, 0x5, 0x60, 0x5, 0xd8, 0x48, 0x6d, 0xdb, 0x39, 0xbf, 0x38, 0xc5, 0x34, 0x62, 0x36, 0x47, 0x9d, 0xf2, 0xfc, 0xe2, 0x94, 0xd4, 0xb6, 0x1d, 0x60, 0x3, 0x58, 0x31, 0x20, 0x2, 0x65, 0x40, 0x88, 0x31, 0x92, 0xbd, 0xbb, 0x8, 0xe4, 0x3c, 0x39, 0x67, 0x91, 0x33, 0x84, 0x89, 0xa5, 0x12, 0x88, 0xf, 0x3f, 0x10, 0x45, 0x5, 0xb3, 0xc8, 0x73, 0x10, 0x11, 0xb2, 0xab, 0x8b, 0xa, 0xde, 0xb8, 0x30, 0x9f, 0xb0, 0x8, 0xa2, 0xc4, 0x58, 0xb0, 0x8, 0x82, 0x28, 0xde, 0x58, 0xcc, 0xff, 0x5c, 0x45, 0x64, 0x61, 0x1, 0x99, 0xcc, 0xa5, 0x80, 0x4e, 0x5, 0xc2, 0xcb, 0x2, 0xe2, 0x41, 0x10, 0x40, 0xc2, 0x53, 0x81, 0xc, 0xa8, 0x8a, 0x52, 0x2c, 0xe8, 0x40, 0x27, 0x23, 0x28, 0x90, 0xcd, 0xe3, 0x79, 0x1b, 0x34, 0x50, 0x14, 0x4b, 0xf0, 0x4c, 0x88, 0x66, 0xbd, 0x4, 0xd, 0x78, 0x94, 0x93, 0x79, 0x3c, 0x9b, 0x18, 0x63, 0x7a, 0xbd, 0xb9, 0xa5, 0xcd, 0xa8, 0x7e, 0xb4, 0x3a, 0x2f, 0x15, 0x10, 0xca, 0x72, 0x95, 0x18, 0x8b, 0x4, 0x34, 0xc0, 0xd8, 0x80, 0x1a, 0x18, 0x56, 0xd5, 0xcf, 0x93, 0x41, 0x7f, 0x67, 0xaf, 0xb3, 0xba, 0x1e, 0x5e, 0x8a, 0xb2, 0x99, 0xb5, 0x97, 0xd5, 0x8f, 0x13, 0x60, 0x8, 0xd4, 0x2, 0x74, 0x9d, 0x6f, 0x80, 0xbe, 0x2f, 0x55, 0xe9, 0x26, 0xc2, 0xcc, 0x26, 0x66, 0x5f, 0xa4, 0x6b, 0xa0, 0x2, 0xbe, 0x3, 0x57, 0xe6, 0x56, 0x1e, 0x66, 0x1a, 0x2, 0xaf, 0x3c, 0x24, 0x36, 0x67, 0xe0, 0x1e, 0xf8, 0x3, 0xfc, 0xf6, 0x6d, 0xac, 0x81, 0xe6, 0x2f, 0x7c, 0x22, 0x6d, 0x74, 0x25, 0xb, 0xb3, 0xa2, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char checked_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x8d, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x58, 0x56, 0x63, 0xb0, 0xaf, 0xb5, 0x38, 0x37, 0x40, 0x20, 0x20, 0x24, 0xb6, 0xb6, 0xb9, 0x57, 0x57, 0x5a, 0x20, 0x20, 0x24, 0x38, 0x36, 0x40, 0x20, 0x20, 0x25, 0x1e, 0x1e, 0x22, 0x1f, 0x1f, 0x23, 0x8b, 0x8b, 0x8d, 0xff, 0xff, 0xff, 0x20, 0x20, 0x24, 0x22, 0x22, 0x27, 0x23, 0x23, 0x28, 0x42, 0x42, 0x47, 0xf8, 0xf8, 0xf8, 0xfe, 0xfe, 0xfe, 0x25, 0x25, 0x2a, 0x4e, 0x4e, 0x52, 0x26, 0x26, 0x2b, 0xc5, 0xc5, 0xc7, 0xaa, 0xaa, 0xab, 0xb8, 0xb8, 0xba, 0x5f, 0x5f, 0x63, 0x74, 0x74, 0x77, 0xed, 0xed, 0xed, 0x33, 0x33, 0x38, 0x8d, 0x8d, 0x8f, 0xb8, 0xb8, 0xb9, 0x35, 0x35, 0x39, 0x3a, 0x3a, 0x3e, 0xfb, 0xfb, 0xfb, 0xfa, 0xfa, 0xfa, 0xb2, 0xb2, 0xb4, 0x45, 0x45, 0x49, 0x61, 0x61, 0x65, 0x8f, 0x8f, 0x92, 0x63, 0x63, 0x66, 0x2a, 0x2a, 0x2f, 0x40, 0x82, 0xb, 0xf6, 0x0, 0x0, 0x0, 0xf, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x7, 0x27, 0x50, 0x66, 0x68, 0x6a, 0x81, 0xb4, 0xfa, 0xdd, 0xfb, 0xfb, 0xb4, 0xfa, 0xb8, 0xf0, 0x7f, 0x59, 0x0, 0x0, 0x0, 0x7e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x5d, 0xca, 0x5, 0xb2, 0x2, 0x30, 0x18, 0x3, 0xe1, 0x4d, 0xed, 0xb9, 0x60, 0xf7, 0x3f, 0x20, 0xee, 0x4e, 0x99, 0xe0, 0xb0, 0x63, 0xfd, 0xbf, 0x86, 0xd7, 0x12, 0x72, 0x38, 0x69, 0x5b, 0x6b, 0x42, 0x45, 0xe5, 0xa, 0xab, 0x95, 0x41, 0x9f, 0x32, 0x20, 0x69, 0x2d, 0xbc, 0x50, 0x46, 0x3a, 0x10, 0x17, 0x5f, 0x49, 0x4, 0x7f, 0x90, 0x57, 0x89, 0xb7, 0xc5, 0x5f, 0x96, 0x17, 0x2e, 0x93, 0xcb, 0x8e, 0x3a, 0x83, 0xb, 0xc4, 0x8e, 0xd4, 0xff, 0x5c, 0x73, 0x83, 0x69, 0x9e, 0x95, 0xfc, 0x3b, 0xf4, 0x33, 0xe0, 0xf8, 0x61, 0xd3, 0xf1, 0x7d, 0x5d, 0x30, 0x7a, 0x6f, 0x89, 0xb, 0xd4, 0x5a, 0xe1, 0x40, 0xf, 0xfc, 0x34, 0x6c, 0xd2, 0x56, 0x80, 0xef, 0xfd, 0x9, 0xd2, 0x3a, 0x5e, 0x41, 0x15, 0x21, 0x77, 0x6, 0xc7, 0x6b, 0x47, 0x4e, 0x3a, 0x2f, 0x53, 0xb4, 0x10, 0xc7, 0x8c, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char checked_disabled_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x99, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x73, 0x72, 0x7b, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x82, 0x80, 0x8a, 0x90, 0x90, 0x93, 0x6a, 0x69, 0x70, 0x6a, 0x68, 0x70, 0x93, 0x93, 0x95, 0x58, 0x58, 0x5c, 0x58, 0x58, 0x5b, 0x7d, 0x7d, 0x7f, 0x58, 0x58, 0x5b, 0xa4, 0xa4, 0xa4, 0x9e, 0x9e, 0xa0, 0x9e, 0x9e, 0x9e, 0x9b, 0x9b, 0x9c, 0x9b, 0x9b, 0x9b, 0x9a, 0x9a, 0x9a, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x95, 0x95, 0x95, 0x93, 0x93, 0x94, 0x8f, 0x8f, 0x8f, 0x86, 0x86, 0x88, 0x85, 0x85, 0x86, 0x82, 0x82, 0x83, 0x81, 0x81, 0x83, 0x7f, 0x7f, 0x81, 0x7c, 0x7c, 0x7e, 0x7a, 0x7a, 0x7d, 0x78, 0x78, 0x7b, 0x71, 0x71, 0x74, 0x68, 0x68, 0x6c, 0x66, 0x66, 0x6a, 0x65, 0x65, 0x68, 0x63, 0x63, 0x66, 0x5f, 0x5f, 0x63, 0x5c, 0x5c, 0x60, 0x5c, 0x5c, 0x5f, 0x5a, 0x5a, 0x5e, 0x59, 0x59, 0x5d, 0x59, 0x59, 0x5c, 0x58, 0x58, 0x5b, 0x57, 0x57, 0x5a, 0x56, 0x56, 0x59, 0x10, 0x13, 0xbb, 0xf, 0x0, 0x0, 0x0, 0x10, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x7, 0x27, 0x27, 0x50, 0x66, 0x68, 0x6a, 0x81, 0xb4, 0xb4, 0xdd, 0xfa, 0xfa, 0xfb, 0xfb, 0x5b, 0xd1, 0xf1, 0xe6, 0x0, 0x0, 0x0, 0x96, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5e, 0x5d, 0x8f, 0xc9, 0x12, 0x82, 0x30, 0x14, 0x4, 0x87, 0x18, 0x50, 0x51, 0x44, 0x25, 0x42, 0x4, 0x77, 0xc4, 0x8d, 0x97, 0x0, 0xf9, 0xff, 0x8f, 0xb3, 0x88, 0xa4, 0x4a, 0xed, 0x63, 0x5f, 0xa6, 0x7, 0xf8, 0x7, 0x1e, 0xe3, 0x7e, 0x60, 0x19, 0x4f, 0x46, 0x1e, 0x0, 0x36, 0x8d, 0x4c, 0x67, 0x59, 0x65, 0x33, 0x6, 0x80, 0x47, 0xad, 0x56, 0x3d, 0xb7, 0x3c, 0x5d, 0x70, 0x0, 0xbe, 0xd1, 0x44, 0x65, 0x4d, 0x94, 0xc8, 0xc2, 0xf8, 0x0, 0x82, 0x4e, 0x91, 0x94, 0x15, 0x5d, 0xd2, 0xec, 0xde, 0x5, 0x83, 0x38, 0xc8, 0xe3, 0x63, 0x23, 0xce, 0xca, 0x9, 0x7a, 0x6e, 0xf3, 0x93, 0x48, 0x1a, 0x27, 0x14, 0x35, 0x3b, 0xb9, 0x5e, 0x56, 0xe4, 0x84, 0x22, 0xba, 0xa, 0x51, 0xd0, 0xb7, 0xa8, 0xcb, 0xfd, 0xcb, 0x9, 0x3b, 0xfb, 0x41, 0xdb, 0x59, 0x17, 0xa6, 0x94, 0x6e, 0xe3, 0x3e, 0x8c, 0x85, 0xf1, 0x90, 0x6e, 0xe6, 0x21, 0xfb, 0x39, 0xe7, 0x73, 0xe6, 0xfd, 0x5f, 0x7, 0xde, 0xc3, 0xb5, 0x16, 0x87, 0xb0, 0x9e, 0x42, 0x46, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char checker_bg_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0xe1, 0x64, 0xe1, 0x57, 0x0, 0x0, 0x0, 0x14, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xfc, 0xcf, 0xc0, 0xc0, 0xd0, 0x0, 0xc4, 0xf8, 0x18, 0xf5, 0x84, 0x19, 0x0, 0x9f, 0x5f, 0xa, 0x1, 0xf8, 0xef, 0x65, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char close_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x62, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xa0, 0x16, 0xe0, 0x8c, 0xe0, 0x11, 0x43, 0xe6, 0xf3, 0x88, 0x71, 0x46, 0xa0, 0x48, 0x73, 0xfc, 0xe3, 0xb8, 0xcc, 0x23, 0x86, 0x90, 0xe6, 0xb8, 0xcc, 0xf1, 0xf, 0x49, 0x9, 0x8f, 0x28, 0xe7, 0x25, 0x8e, 0xff, 0x1c, 0xd7, 0xb9, 0x24, 0x91, 0x79, 0xdc, 0x12, 0x40, 0xe, 0xa6, 0x12, 0x54, 0x69, 0x4c, 0x25, 0xb7, 0x38, 0xae, 0x21, 0xa4, 0x31, 0x94, 0x80, 0x24, 0x81, 0xf0, 0x36, 0x48, 0x1a, 0xaf, 0x2, 0x88, 0x5b, 0xf0, 0x5a, 0x81, 0xa1, 0x4, 0xe1, 0x34, 0x84, 0x73, 0xb1, 0x4a, 0xa3, 0x7b, 0x9a, 0x70, 0x40, 0x11, 0xe, 0x6a, 0xca, 0x1, 0x0, 0x2a, 0x28, 0x37, 0x83, 0x3e, 0x27, 0xb0, 0x34, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char close_hl_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x62, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xa0, 0x16, 0xe0, 0x8c, 0xe0, 0x11, 0x43, 0xe6, 0xf3, 0x88, 0x71, 0x46, 0xa0, 0x48, 0x73, 0xfc, 0xe3, 0xb8, 0xcc, 0x23, 0x86, 0x90, 0xe6, 0xb8, 0xcc, 0xf1, 0xf, 0x49, 0x9, 0x8f, 0x28, 0xe7, 0x25, 0x8e, 0xff, 0x1c, 0xd7, 0xb9, 0x24, 0x91, 0x79, 0xdc, 0x12, 0x40, 0xe, 0xa6, 0x12, 0x54, 0x69, 0x4c, 0x25, 0xb7, 0x38, 0xae, 0x21, 0xa4, 0x31, 0x94, 0x80, 0x24, 0x81, 0xf0, 0x36, 0x48, 0x1a, 0xaf, 0x2, 0x88, 0x5b, 0xf0, 0x5a, 0x81, 0xa1, 0x4, 0xe1, 0x34, 0x84, 0x73, 0xb1, 0x4a, 0xa3, 0x7b, 0x9a, 0x70, 0x40, 0x11, 0xe, 0x6a, 0xca, 0x1, 0x0, 0x2a, 0x28, 0x37, 0x83, 0x3e, 0x27, 0xb0, 0x34, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char color_picker_hue_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x0, 0x8, 0x2, 0x0, 0x0, 0x0, 0xfd, 0x5c, 0x8b, 0xcf, 0x0, 0x0, 0x0, 0x54, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xcd, 0xc9, 0x1, 0x6, 0x43, 0x31, 0x10, 0x45, 0xd1, 0x63, 0xc8, 0xcf, 0xfe, 0x97, 0xdb, 0x9f, 0xf0, 0x1a, 0x15, 0xb4, 0x0, 0xa5, 0x1a, 0x1c, 0xd7, 0xcc, 0x13, 0x4a, 0x5b, 0xae, 0x2f, 0xf5, 0xdd, 0xdf, 0x92, 0xc9, 0x88, 0xba, 0x1d, 0x4d, 0xb, 0xa2, 0xb8, 0x96, 0xb6, 0xf4, 0x93, 0xcb, 0x48, 0xb9, 0x9d, 0x8c, 0x16, 0xa4, 0x2e, 0x5e, 0xda, 0x6e, 0xe7, 0xe3, 0xd7, 0xff, 0xbf, 0x9b, 0x22, 0x66, 0x71, 0x2f, 0x8f, 0xdd, 0xc5, 0x78, 0xbb, 0xc7, 0x9, 0xbb, 0xf0, 0x4, 0x75, 0x7b, 0x8a, 0xe5, 0x7c, 0x23, 0x8a, 0xd3, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char color_picker_sample_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x14, 0x8, 0x0, 0x0, 0x0, 0x0, 0x47, 0x29, 0xbc, 0x83, 0x0, 0x0, 0x0, 0x3c, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0xd5, 0x21, 0x11, 0x0, 0x30, 0xc, 0x4, 0xc1, 0xfa, 0x57, 0x53, 0x87, 0xed, 0x4, 0x45, 0xc4, 0xed, 0xa3, 0xc3, 0x4b, 0xfe, 0xbc, 0xd9, 0x9d, 0x35, 0x2b, 0xe, 0x0, 0x0, 0x0, 0x80, 0xed, 0x66, 0xc5, 0x1, 0x0, 0x0, 0x0, 0xe0, 0x6, 0x1, 0x0, 0x0, 0x90, 0x6, 0x70, 0x83, 0x0, 0x0, 0x0, 0x28, 0x3, 0x7c, 0x54, 0x93, 0xd6, 0xf1, 0xd1, 0x16, 0x8a, 0x17, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char dialog_bg_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x26, 0x8, 0x3, 0x0, 0x0, 0x0, 0xf7, 0x10, 0x9b, 0xa4, 0x0, 0x0, 0x2, 0xf5, 0x7a, 0x54, 0x58, 0x74, 0x52, 0x61, 0x77, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x65, 0x78, 0x69, 0x66, 0x0, 0x0, 0x78, 0xda, 0xb5, 0x95, 0x6d, 0x72, 0xe4, 0x28, 0xc, 0x86, 0xff, 0x73, 0x8a, 0x3d, 0x2, 0xfa, 0x42, 0x70, 0x1c, 0xc, 0xa6, 0x6a, 0x6f, 0xb0, 0xc7, 0x9f, 0x17, 0xec, 0x38, 0xd9, 0x4c, 0x57, 0xda, 0x49, 0xcf, 0x40, 0xb5, 0xa5, 0x92, 0x5, 0x12, 0x3c, 0x92, 0x3b, 0xec, 0xff, 0xfd, 0x3b, 0xc2, 0x3f, 0x18, 0xa4, 0x39, 0x6, 0x35, 0xcf, 0xa9, 0xa4, 0x14, 0x31, 0xb4, 0x68, 0xe1, 0xa, 0x25, 0xc7, 0xf7, 0xb1, 0x9f, 0xf2, 0xb0, 0x51, 0xd4, 0xf5, 0x5c, 0xa3, 0xe8, 0xf9, 0x8e, 0x22, 0x85, 0x8f, 0x2f, 0x2e, 0x8d, 0x21, 0x5, 0x52, 0xe, 0xa3, 0xbf, 0x2d, 0x90, 0xd3, 0xfe, 0xe6, 0x9f, 0x2e, 0x89, 0x8d, 0x1e, 0xbc, 0x20, 0xfb, 0xb4, 0x40, 0xae, 0x30, 0xfc, 0x31, 0xb0, 0xd7, 0xd3, 0xce, 0x91, 0xff, 0x97, 0x91, 0x7a, 0xb4, 0xf8, 0x71, 0xe4, 0xf7, 0xdf, 0x18, 0x3d, 0x8f, 0xb1, 0x1f, 0xa7, 0xab, 0x9a, 0x70, 0xd, 0xe9, 0x38, 0xd4, 0x11, 0x22, 0xbc, 0x6d, 0x3, 0xc7, 0xd, 0x5b, 0xc9, 0x5a, 0x96, 0x30, 0x1d, 0x3f, 0x83, 0xee, 0x6b, 0x16, 0xcc, 0x1c, 0x6b, 0x6c, 0xa4, 0xb1, 0xc7, 0x16, 0x37, 0xcc, 0x46, 0x85, 0x98, 0x24, 0xe, 0x52, 0xea, 0x81, 0x2a, 0xd, 0xda, 0xa9, 0x43, 0x36, 0x6a, 0xc8, 0x51, 0x79, 0x67, 0x87, 0x64, 0x6e, 0x2c, 0xcb, 0x96, 0xc5, 0xb9, 0x70, 0x93, 0x28, 0x24, 0x3a, 0x27, 0xd, 0x76, 0x29, 0xd2, 0x25, 0xb, 0x4b, 0xe3, 0x5d, 0x44, 0x34, 0x8, 0x5f, 0xb9, 0xd0, 0x8a, 0x5b, 0x56, 0xbc, 0x46, 0x19, 0x91, 0x3b, 0xc1, 0x95, 0x9, 0x9b, 0x11, 0x96, 0x7c, 0x39, 0xc3, 0x33, 0x87, 0x3b, 0x73, 0x8c, 0x16, 0x71, 0x47, 0x44, 0x38, 0x3d, 0x9d, 0x75, 0x81, 0xbc, 0x98, 0x27, 0x7, 0x9a, 0xd7, 0x28, 0xf3, 0x9, 0x37, 0x0, 0xa1, 0x71, 0x72, 0xb3, 0x75, 0xc1, 0x6f, 0xf3, 0x1a, 0xe1, 0x3, 0x58, 0x1, 0x41, 0x5b, 0xd7, 0x9c, 0x71, 0xc0, 0x1a, 0xb7, 0x63, 0x8b, 0xcd, 0xe8, 0xbd, 0xb6, 0x64, 0x15, 0x80, 0xc0, 0xcf, 0x20, 0x8f, 0xfa, 0x22, 0xef, 0x93, 0x1a, 0xaf, 0x2a, 0x51, 0xc4, 0x36, 0x24, 0x43, 0x2, 0x4, 0x31, 0x91, 0x18, 0x25, 0x8a, 0xce, 0xec, 0x44, 0x2a, 0x9c, 0x1, 0xa8, 0x22, 0x73, 0x16, 0xe5, 0xd, 0x4, 0xc8, 0x8c, 0x3b, 0x92, 0x64, 0x15, 0x49, 0x60, 0x93, 0x51, 0x47, 0x88, 0x8d, 0x35, 0x4e, 0xcb, 0x97, 0x8d, 0xf, 0x3b, 0x5a, 0x5, 0x7c, 0x4c, 0x92, 0x38, 0xd8, 0x14, 0xa9, 0x80, 0xa5, 0x6a, 0xa8, 0x1f, 0xd7, 0x8c, 0x1a, 0xaa, 0x26, 0xa6, 0x66, 0x96, 0xcc, 0x2d, 0x5b, 0xb1, 0x1a, 0x92, 0x24, 0x4d, 0x96, 0x52, 0xf2, 0x34, 0x7b, 0xae, 0xba, 0xb8, 0xba, 0x79, 0x72, 0xf7, 0xec, 0xc5, 0x6b, 0x96, 0xac, 0xd9, 0x72, 0xca, 0x9e, 0x73, 0x2e, 0xb9, 0x16, 0x2e, 0x82, 0x96, 0xb4, 0x92, 0x8a, 0x97, 0x5c, 0x4a, 0xa9, 0x15, 0x31, 0xab, 0x86, 0x6a, 0x15, 0xab, 0x2b, 0x3c, 0x6a, 0xdd, 0x78, 0x93, 0x4d, 0x37, 0xdb, 0xd2, 0xe6, 0x5b, 0xde, 0xca, 0x56, 0x1b, 0xca, 0xa7, 0x69, 0xb3, 0x96, 0x9a, 0xb7, 0xdc, 0x4a, 0xab, 0x9d, 0xbb, 0x74, 0xed, 0xd6, 0x53, 0xf7, 0x9e, 0x7b, 0xe9, 0x75, 0xa7, 0x1d, 0xa5, 0x14, 0x76, 0xdd, 0x6d, 0x4f, 0xbb, 0xef, 0x79, 0x2f, 0x7b, 0x1d, 0xa8, 0xb5, 0x21, 0x43, 0x87, 0x8d, 0x34, 0x7c, 0xe4, 0x51, 0x46, 0xbd, 0xa8, 0xd1, 0xd9, 0xb6, 0x9f, 0xe7, 0x37, 0xa8, 0xd1, 0x49, 0x8d, 0x17, 0xa9, 0xe9, 0xe7, 0x17, 0x35, 0x58, 0xdd, 0xe7, 0x46, 0x6b, 0xb, 0x9a, 0xdf, 0x19, 0x9b, 0xcc, 0x40, 0x8c, 0x95, 0x40, 0xdc, 0x27, 0x1, 0x14, 0x34, 0x4f, 0x66, 0x31, 0x93, 0x2a, 0x4f, 0x72, 0x93, 0x59, 0x2c, 0x8c, 0xae, 0x30, 0x46, 0x92, 0x36, 0xd9, 0x74, 0x8a, 0x35, 0x50, 0x2, 0x42, 0xdd, 0x89, 0x6d, 0xd0, 0xc5, 0xee, 0x9d, 0xdc, 0x6d, 0x6e, 0x1, 0x77, 0xfd, 0x8c, 0x1b, 0xdf, 0x21, 0x17, 0x26, 0xba, 0x3f, 0x40, 0x8e, 0xc3, 0x2e, 0x9f, 0xb8, 0x3d, 0xa0, 0xd6, 0xe7, 0x97, 0xb0, 0x2d, 0x62, 0x47, 0x17, 0xce, 0x3b, 0x8d, 0x82, 0xee, 0x83, 0x6f, 0xe5, 0x5c, 0x79, 0x53, 0x50, 0x5b, 0x5a, 0x7e, 0x55, 0xfe, 0x85, 0x8d, 0x68, 0x9, 0x1c, 0xe2, 0x67, 0x32, 0x3c, 0x7c, 0xa1, 0x6b, 0xe7, 0xf4, 0x1d, 0x25, 0xdc, 0x70, 0x42, 0xce, 0x65, 0x85, 0xb0, 0x2f, 0x94, 0x70, 0xc7, 0xe9, 0x37, 0xe5, 0x41, 0xd2, 0xe1, 0x47, 0xe7, 0x78, 0x90, 0x74, 0x40, 0x91, 0x8a, 0xa6, 0x74, 0x1a, 0x5b, 0xa7, 0x72, 0x86, 0xfe, 0xa6, 0x39, 0xdc, 0x72, 0x47, 0x97, 0x1b, 0xa1, 0xbf, 0xf0, 0x3f, 0x8c, 0xe, 0x7d, 0xa8, 0x84, 0x2f, 0xde, 0x7d, 0xad, 0x90, 0x1a, 0xdb, 0xc, 0xb1, 0x2d, 0x25, 0x5c, 0xda, 0x8b, 0x4a, 0x38, 0xb3, 0x2e, 0x15, 0xa7, 0x39, 0x8c, 0x38, 0x53, 0xeb, 0x67, 0xe8, 0xfb, 0xe6, 0x70, 0xdb, 0xfd, 0x49, 0xa9, 0x86, 0x17, 0xa9, 0x5f, 0x5c, 0xc2, 0x8b, 0xd4, 0x2f, 0x73, 0x78, 0x4e, 0xdd, 0x6e, 0xc9, 0x70, 0xd7, 0xf1, 0x59, 0x3d, 0x84, 0x17, 0xca, 0x88, 0x3e, 0xca, 0xf0, 0xd9, 0xf0, 0x53, 0xf9, 0xe7, 0x36, 0xf2, 0x81, 0x8f, 0x7b, 0x81, 0xf2, 0xb, 0x12, 0xea, 0xac, 0x15, 0x79, 0x70, 0x44, 0x63, 0x0, 0x0, 0x1, 0x68, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xe8, 0xe5, 0xf1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x1d, 0x22, 0x0, 0x0, 0x0, 0x1a, 0x19, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x1e, 0x23, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x1d, 0x21, 0x17, 0x16, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21, 0x1f, 0x24, 0x1b, 0x1a, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21, 0x1f, 0x24, 0x1e, 0x1c, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22, 0x20, 0x25, 0x20, 0x1e, 0x23, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21, 0x1f, 0x24, 0x0, 0x0, 0x0, 0x21, 0x1f, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22, 0x20, 0x25, 0x0, 0x0, 0x0, 0x20, 0x20, 0x25, 0x20, 0x1d, 0x25, 0x20, 0x1d, 0x22, 0x1d, 0x1d, 0x22, 0x1d, 0x1d, 0x20, 0x1d, 0x1a, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32, 0x30, 0x38, 0xe8, 0xe5, 0xf1, 0xe5, 0xe2, 0xeb, 0xe3, 0xe1, 0xe8, 0xe1, 0xdf, 0xe7, 0xe0, 0xde, 0xe6, 0xdf, 0xdd, 0xe5, 0xde, 0xdc, 0xe4, 0xdd, 0xdb, 0xe3, 0xdc, 0xda, 0xe2, 0xda, 0xd8, 0xe0, 0xd9, 0xd7, 0xdf, 0xd7, 0xd6, 0xdf, 0xd6, 0xd4, 0xdd, 0xd5, 0xd3, 0xdc, 0xd4, 0xd1, 0xdb, 0xd3, 0xd0, 0xda, 0xd1, 0xce, 0xd8, 0xd0, 0xcd, 0xd7, 0xcf, 0xcd, 0xd7, 0xe2, 0xdf, 0xeb, 0x48, 0x46, 0x51, 0x42, 0x40, 0x4b, 0x40, 0x3e, 0x48, 0x40, 0x3d, 0x48, 0x48, 0x45, 0x50, 0x42, 0x3f, 0x4a, 0x3f, 0x3d, 0x48, 0x47, 0x44, 0x50, 0x41, 0x3f, 0x4a, 0x3f, 0x3d, 0x47, 0x41, 0x3e, 0x49, 0x3f, 0x3c, 0x47, 0x46, 0x43, 0x4f, 0x3e, 0x3c, 0x46, 0x40, 0x3e, 0x49, 0x3d, 0x3b, 0x46, 0x45, 0x43, 0x4e, 0x3d, 0x3b, 0x45, 0x44, 0x42, 0x4d, 0x3d, 0x3a, 0x45, 0x3e, 0x3c, 0x47, 0x3c, 0x3a, 0x44, 0x43, 0x42, 0x4c, 0x43, 0x40, 0x4c, 0x3e, 0x3b, 0x46, 0x3b, 0x39, 0x43, 0x43, 0x3f, 0x4c, 0x43, 0x3f, 0x4b, 0x3a, 0x38, 0x42, 0x42, 0x3e, 0x4b, 0x42, 0x3e, 0x49, 0x3a, 0x37, 0x41, 0x39, 0x37, 0x41, 0x3f, 0x3e, 0x48, 0x39, 0x37, 0x40, 0x38, 0x36, 0x40, 0x3e, 0x3d, 0x48, 0x38, 0x36, 0x3f, 0x3e, 0x3d, 0x47, 0x3a, 0x38, 0x41, 0x38, 0x35, 0x3f, 0x37, 0x35, 0x3e, 0x39, 0x36, 0x40, 0x37, 0x34, 0x3e, 0x3d, 0x3a, 0x46, 0x36, 0x34, 0x3d, 0x3d, 0x3a, 0x44, 0x37, 0x35, 0x3f, 0x35, 0x33, 0x3c, 0x6b, 0xff, 0x8f, 0xb1, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x0, 0x88, 0x5, 0x1d, 0x48, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe5, 0x7, 0x1b, 0x17, 0x11, 0x18, 0xe6, 0xb9, 0x22, 0xac, 0x0, 0x0, 0x0, 0x3f, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0xf4, 0x64, 0xc0, 0x6, 0x98, 0x18, 0x68, 0x27, 0xcc, 0xc2, 0x88, 0x5d, 0x98, 0x99, 0x24, 0x61, 0x26, 0x52, 0x84, 0x71, 0xb9, 0x84, 0x89, 0x76, 0xc2, 0xb8, 0xac, 0x64, 0x21, 0x49, 0x35, 0x33, 0x15, 0x54, 0xe3, 0xa, 0x6f, 0x26, 0x6a, 0xa8, 0x26, 0xc9, 0x4a, 0xaa, 0x44, 0x3, 0x89, 0x89, 0x8d, 0x99, 0xee, 0xe9, 0x1b, 0x87, 0x30, 0x0, 0x20, 0x4, 0x0, 0xed, 0x48, 0xa7, 0x26, 0x6c, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char dropdown_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x4, 0x0, 0x0, 0x0, 0x6e, 0x6, 0x76, 0x0, 0x0, 0x0, 0x0, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0x60, 0xf8, 0xc0, 0xcc, 0x0, 0x2, 0x60, 0x16, 0x98, 0x78, 0x67, 0x8, 0x81, 0x6f, 0x4d, 0xde, 0x9a, 0x0, 0x5, 0xde, 0x3a, 0x3d, 0xfc, 0x8f, 0x80, 0xaf, 0xba, 0x18, 0xde, 0x29, 0x2, 0x19, 0xbf, 0x61, 0x2, 0x6f, 0x62, 0x18, 0x3e, 0xb0, 0xbd, 0x97, 0x4, 0x32, 0xff, 0x80, 0xb9, 0xb1, 0x20, 0x93, 0xc0, 0x42, 0x8, 0x2e, 0x54, 0xe8, 0x9d, 0xdc, 0x9b, 0x54, 0x10, 0xb, 0x21, 0xc4, 0x4, 0x63, 0x1, 0x0, 0x86, 0x1f, 0x3b, 0x1e, 0x92, 0x22, 0x3f, 0x40, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char ellipsis_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x8, 0x8, 0x6, 0x0, 0x0, 0x0, 0xc9, 0x11, 0xce, 0xcc, 0x0, 0x0, 0x0, 0x4, 0x73, 0x42, 0x49, 0x54, 0x8, 0x8, 0x8, 0x8, 0x7c, 0x8, 0x64, 0x88, 0x0, 0x0, 0x0, 0x78, 0x49, 0x44, 0x41, 0x54, 0x18, 0x95, 0x95, 0xd1, 0x31, 0xa, 0xc2, 0x50, 0x10, 0x4, 0xd0, 0xb7, 0x1f, 0xf, 0x60, 0x67, 0xa, 0xf, 0x12, 0x6f, 0x60, 0xe9, 0x51, 0x5, 0x3d, 0x44, 0xee, 0x61, 0xa1, 0xa5, 0xf6, 0x81, 0xb5, 0xc8, 0x47, 0x82, 0x84, 0x4f, 0xb2, 0xdd, 0xb0, 0x33, 0xb3, 0xb3, 0x4c, 0x40, 0x66, 0xee, 0x71, 0xc2, 0x1, 0x3b, 0xcb, 0x33, 0xe2, 0x85, 0x21, 0x22, 0xde, 0x51, 0x45, 0x97, 0x86, 0x60, 0xc9, 0xe0, 0x5a, 0xea, 0xa5, 0xb5, 0x22, 0x95, 0xdb, 0x97, 0x1a, 0xf, 0x6e, 0xb8, 0xcf, 0x8, 0x2d, 0xdc, 0x95, 0xd9, 0x22, 0xfe, 0x9c, 0x9b, 0x38, 0x32, 0xf3, 0x8c, 0xe3, 0x86, 0xa8, 0xf0, 0x28, 0x18, 0x4c, 0xf, 0xaf, 0x9d, 0x11, 0x43, 0xf0, 0xab, 0xa3, 0x47, 0xa7, 0x5d, 0xc7, 0xd3, 0x54, 0xc7, 0xe7, 0xb, 0xb9, 0xce, 0x1f, 0xc6, 0x2d, 0x99, 0x55, 0xc7, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char error_icon_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0xe, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0x60, 0x18, 0x5, 0xa3, 0x0, 0x1, 0x0, 0x2, 0x10, 0x0, 0x1, 0x14, 0xc2, 0xc0, 0x92, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char focus_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x4, 0x3, 0x0, 0x0, 0x0, 0xa4, 0x5b, 0x41, 0xd4, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0xff, 0xff, 0xff, 0xb9, 0xa2, 0x9b, 0xc9, 0x0, 0x0, 0x0, 0xf, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xe, 0x39, 0x68, 0x7a, 0x7b, 0x3a, 0x74, 0x10, 0x8, 0x69, 0xf, 0x6, 0x75, 0x11, 0xb8, 0x16, 0x0, 0x1, 0x0, 0x0, 0x0, 0x38, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x10, 0x32, 0x9, 0xd, 0x75, 0x56, 0x64, 0x48, 0xef, 0x9c, 0x39, 0x73, 0x46, 0x19, 0xc3, 0x6a, 0x6, 0x20, 0xd8, 0xc5, 0x10, 0x3, 0xa2, 0x8e, 0x32, 0x44, 0x82, 0xa8, 0xa9, 0xd8, 0x29, 0xa8, 0x12, 0xb0, 0x6, 0x29, 0x86, 0xdc, 0x9d, 0x33, 0x67, 0xce, 0x2b, 0x63, 0x10, 0x3, 0x1b, 0x6, 0x0, 0xdf, 0xc6, 0x11, 0x6d, 0xb8, 0xf4, 0x9c, 0xac, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char graph_node_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x40, 0x8, 0x6, 0x0, 0x0, 0x0, 0x13, 0x7d, 0xf7, 0x96, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x8, 0x17, 0xd, 0x5, 0x12, 0xa1, 0x38, 0x83, 0x9b, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x2, 0x74, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xed, 0x97, 0x3d, 0x6f, 0xd3, 0x60, 0x10, 0xc7, 0x7f, 0x17, 0x9b, 0x26, 0x25, 0x22, 0xad, 0xa, 0x8, 0xf1, 0x52, 0x75, 0x0, 0x16, 0x24, 0x90, 0x2a, 0x96, 0x7c, 0x1, 0x6, 0xc4, 0xce, 0xc4, 0x17, 0x0, 0x31, 0xb0, 0x30, 0x0, 0x23, 0x82, 0x85, 0x5, 0x9, 0x4, 0x5f, 0x80, 0x89, 0x1d, 0x31, 0xf0, 0x5, 0x58, 0x50, 0x25, 0x50, 0x59, 0x80, 0xa1, 0xe2, 0xad, 0x28, 0x34, 0x4a, 0x3, 0x25, 0x76, 0xea, 0xe7, 0x39, 0x6, 0x3f, 0x76, 0x6d, 0xc7, 0x49, 0x5f, 0xd8, 0x90, 0x6f, 0xb1, 0xf5, 0xe4, 0xb9, 0xdf, 0xdd, 0xfd, 0xef, 0x22, 0xf9, 0x84, 0x2d, 0x13, 0xa0, 0x6, 0x78, 0xee, 0x29, 0xe4, 0x4d, 0x1, 0xb, 0x18, 0xf7, 0x54, 0x32, 0x97, 0x6a, 0xc0, 0x7e, 0x60, 0xe, 0x38, 0xc, 0xb4, 0x80, 0x7d, 0x5, 0xc0, 0x26, 0xd0, 0x7, 0x3a, 0x40, 0x17, 0xf8, 0x3, 0xd8, 0x24, 0x6a, 0x13, 0x38, 0x35, 0x73, 0x60, 0xf6, 0x6a, 0xa3, 0xde, 0xb8, 0x38, 0x35, 0x55, 0x3f, 0x41, 0x89, 0xd, 0x87, 0xe1, 0x97, 0x20, 0xc, 0x5e, 0xae, 0xff, 0xea, 0x3d, 0x5, 0x3e, 0x2, 0x1b, 0xe2, 0x22, 0x2d, 0xcc, 0xcd, 0x1e, 0x7c, 0x78, 0x72, 0xe1, 0xf4, 0xa5, 0x7b, 0xb7, 0x1f, 0x7c, 0x9e, 0x6e, 0x35, 0xca, 0xfc, 0x19, 0xf4, 0x3, 0xee, 0xdc, 0xbf, 0x39, 0xff, 0x69, 0xe5, 0xc3, 0x8b, 0x6e, 0x6f, 0xed, 0x6, 0xb0, 0x22, 0x40, 0x3, 0x58, 0x3c, 0x7a, 0xe4, 0xf8, 0xab, 0x67, 0x4f, 0x9e, 0x77, 0xa3, 0xc8, 0x12, 0xd, 0xa3, 0x52, 0x80, 0x3f, 0xe5, 0xe3, 0xfb, 0x35, 0xae, 0x5c, 0xbb, 0x3c, 0xf7, 0xfd, 0xc7, 0xd7, 0xb, 0xc0, 0x92, 0xef, 0x74, 0x68, 0xfa, 0x9e, 0xdf, 0x1c, 0xfc, 0xe, 0xbb, 0x88, 0xc6, 0x47, 0xa, 0x2a, 0x59, 0x85, 0x95, 0x61, 0xb8, 0xc9, 0x30, 0x4, 0xdf, 0xf3, 0x9b, 0xae, 0x6c, 0x49, 0x0, 0x1e, 0x80, 0x51, 0x1b, 0xfb, 0xc7, 0x2, 0xc7, 0x5a, 0x3b, 0x88, 0x66, 0xcf, 0x63, 0xf3, 0x12, 0x80, 0x26, 0xbf, 0xa8, 0xb5, 0xa8, 0xa, 0x88, 0x22, 0x8, 0x8a, 0x22, 0x2a, 0x19, 0x37, 0x1d, 0xe9, 0xad, 0x9f, 0x6b, 0xb4, 0x55, 0x14, 0x5, 0x55, 0x44, 0xe2, 0x32, 0x6c, 0xe2, 0x24, 0x71, 0x18, 0x9d, 0x4, 0xb0, 0x6a, 0xd3, 0x1b, 0x2a, 0xe9, 0x4b, 0xfc, 0xae, 0xe4, 0x45, 0x19, 0x9f, 0x81, 0x2b, 0xdb, 0x15, 0xa6, 0xa2, 0x19, 0x2d, 0xec, 0x8, 0x24, 0x7, 0x30, 0xd6, 0x16, 0xf8, 0x82, 0xa8, 0xc6, 0x45, 0x68, 0x52, 0xbf, 0x4e, 0xce, 0x60, 0xeb, 0x42, 0x5c, 0xb4, 0x66, 0x9c, 0x6c, 0xc9, 0x1f, 0xa4, 0x0, 0xb0, 0x39, 0xc5, 0xc9, 0xa1, 0x28, 0x89, 0x5f, 0x14, 0xd1, 0x5a, 0x37, 0x32, 0x89, 0xf2, 0x82, 0xc6, 0x3, 0xe0, 0xda, 0xa, 0x22, 0x3a, 0xa9, 0xb, 0x9a, 0x26, 0xaa, 0xf1, 0x41, 0x9a, 0x42, 0x2, 0xb2, 0xb2, 0x6d, 0x6, 0x5b, 0xa3, 0xab, 0x23, 0xd5, 0x48, 0x32, 0x92, 0xe3, 0x33, 0x10, 0x37, 0xb7, 0x2a, 0xea, 0xee, 0x4a, 0x2a, 0x42, 0xe, 0x5a, 0x2a, 0xa2, 0x51, 0x37, 0x40, 0x85, 0x48, 0x96, 0xb4, 0x23, 0xdb, 0x88, 0x68, 0x5c, 0xc4, 0xcc, 0x3c, 0x14, 0xa7, 0x6f, 0xa2, 0x6, 0xaa, 0xb1, 0x7c, 0xd9, 0x30, 0xaa, 0x79, 0xc7, 0x49, 0x93, 0x78, 0xf7, 0xd1, 0xad, 0x79, 0x76, 0x69, 0x29, 0x20, 0xda, 0x34, 0x2c, 0x9e, 0x3d, 0xff, 0x7a, 0x27, 0x4e, 0x4b, 0xef, 0xde, 0xb4, 0x4b, 0x33, 0x58, 0xef, 0xf7, 0x76, 0x9b, 0x0, 0x35, 0xfe, 0xd1, 0x2a, 0x40, 0x5, 0xa8, 0x0, 0x15, 0xa0, 0x2, 0x54, 0x80, 0xa, 0xf0, 0x5f, 0x2, 0xa4, 0xe4, 0x13, 0x78, 0xd7, 0x19, 0xd8, 0x3d, 0xf8, 0xda, 0x4, 0x60, 0x81, 0xc0, 0x18, 0x13, 0xda, 0x68, 0x7, 0x5e, 0x11, 0x18, 0x63, 0x42, 0x20, 0x0, 0x6c, 0xcd, 0xad, 0xb2, 0x6b, 0x41, 0x38, 0x58, 0xee, 0x74, 0x57, 0xdb, 0x93, 0x20, 0x36, 0x82, 0x4e, 0x77, 0xb5, 0x1d, 0x84, 0x83, 0x65, 0x60, 0xd, 0x30, 0xc9, 0xe6, 0x3a, 0x3, 0x9c, 0x6b, 0x35, 0x67, 0x1f, 0x37, 0xea, 0xd3, 0x67, 0x3c, 0xcf, 0x2b, 0x15, 0xd7, 0x18, 0x63, 0x83, 0x70, 0xf0, 0xbe, 0xbf, 0xd1, 0xbb, 0xe, 0xbc, 0x5, 0xd6, 0x25, 0xb3, 0xc2, 0xb5, 0x80, 0x63, 0xc0, 0x21, 0xa0, 0x3e, 0x66, 0xf9, 0xe, 0x81, 0x9f, 0xc0, 0x37, 0xb7, 0x47, 0x1b, 0x29, 0x8, 0xea, 0x27, 0xfb, 0xe0, 0x98, 0x2a, 0xd4, 0x95, 0x1c, 0xed, 0x51, 0xf8, 0x51, 0xfb, 0xb, 0x1, 0xbe, 0x20, 0x9f, 0x90, 0x81, 0x17, 0xaa, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char graph_node_breakpoint_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x40, 0x2, 0x3, 0x0, 0x0, 0x0, 0x6e, 0x13, 0x1f, 0x5, 0x0, 0x0, 0x0, 0x9, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xf4, 0xe7, 0x2c, 0xf4, 0xe7, 0x2c, 0xec, 0x5a, 0x6b, 0x42, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xe4, 0xd1, 0xf4, 0xeb, 0x59, 0x0, 0x0, 0x0, 0x30, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x0, 0x3, 0xb6, 0x55, 0xab, 0x26, 0x30, 0x88, 0x30, 0x0, 0x91, 0x42, 0xd6, 0x4a, 0xe, 0x6, 0x45, 0x7, 0x46, 0xf, 0x6, 0x25, 0x6, 0x86, 0xe, 0x20, 0x31, 0x4a, 0x80, 0x42, 0x3, 0x1c, 0x2e, 0xe0, 0x10, 0x82, 0x84, 0x15, 0x1c, 0x0, 0x0, 0x41, 0x2d, 0x2b, 0x21, 0xbb, 0xb7, 0x1a, 0xa9, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char graph_node_close_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x4, 0x0, 0x0, 0x0, 0xfc, 0x7c, 0x94, 0x6c, 0x0, 0x0, 0x0, 0x5f, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x75, 0x90, 0xb5, 0x1, 0xc0, 0x30, 0x10, 0x3, 0x55, 0x1a, 0xbe, 0xc, 0x6e, 0xe6, 0xb5, 0xc3, 0x34, 0x4b, 0x98, 0xcc, 0xee, 0x7c, 0x4f, 0x92, 0x0, 0x70, 0x45, 0x19, 0x8c, 0x47, 0x19, 0x57, 0x37, 0x66, 0x1b, 0x6b, 0x74, 0x89, 0x32, 0xd6, 0xb0, 0xed, 0x2c, 0x51, 0xca, 0x6b, 0xb6, 0xb3, 0x41, 0x94, 0x0, 0xfe, 0x9f, 0x2c, 0x0, 0xa3, 0x64, 0x61, 0xa3, 0x6f, 0x66, 0xbd, 0xc6, 0x7f, 0xe9, 0x86, 0x3b, 0x5b, 0x34, 0x76, 0xa, 0xcf, 0xad, 0xe0, 0xaa, 0xbf, 0xa4, 0x4f, 0x5a, 0xa, 0x6d, 0x25, 0xba, 0x14, 0x37, 0x18, 0x8b, 0xe4, 0x0, 0x6f, 0xe9, 0x37, 0x83, 0x22, 0x73, 0x83, 0x23, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char graph_node_comment_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x40, 0x8, 0x3, 0x0, 0x0, 0x0, 0x24, 0xa3, 0x7, 0xa4, 0x0, 0x0, 0x0, 0x78, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xd, 0x10, 0x17, 0x14, 0x18, 0x1d, 0x1a, 0x1f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x10, 0x13, 0x35, 0x2f, 0x38, 0x96, 0x42, 0x2b, 0x0, 0x0, 0x0, 0x19, 0x17, 0x1b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x19, 0x15, 0x1c, 0x77, 0x2f, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0x12, 0x19, 0x0, 0x0, 0x0, 0xe, 0xb, 0x10, 0x24, 0x1e, 0x27, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0xb, 0x10, 0x16, 0x12, 0x19, 0x0, 0x0, 0x0, 0x85, 0xbb, 0x9b, 0xdf, 0x0, 0x0, 0x0, 0x28, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x1, 0x3, 0x6, 0x8, 0x9, 0x2, 0xc, 0x1e, 0x33, 0x41, 0x46, 0xd, 0x31, 0x9a, 0xe3, 0xff, 0x5, 0x24, 0xb4, 0xff, 0xe2, 0x39, 0xf4, 0x44, 0xa, 0x47, 0xff, 0x42, 0x45, 0x3d, 0xf8, 0x2a, 0xcd, 0xff, 0x11, 0x3f, 0xd3, 0xfd, 0x2b, 0x31, 0x64, 0xfe, 0xeb, 0x0, 0x0, 0x0, 0x8d, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0xc8, 0x35, 0x62, 0x3, 0x41, 0x14, 0x4, 0xd1, 0xee, 0x21, 0x33, 0x33, 0xdb, 0xf7, 0xbf, 0x93, 0x99, 0x49, 0xcc, 0xd2, 0x7c, 0x2d, 0x53, 0xa6, 0x58, 0x5b, 0x59, 0x3d, 0x2, 0xc, 0x3, 0x20, 0x61, 0x20, 0x5c, 0x9, 0xc6, 0x74, 0x11, 0x20, 0x2c, 0x86, 0xbd, 0xec, 0x63, 0xa1, 0xd9, 0xa7, 0x47, 0x9a, 0x92, 0x7f, 0xda, 0x83, 0xa1, 0xcd, 0x60, 0xb2, 0xfa, 0xc7, 0x33, 0xf6, 0xb, 0xb0, 0x2e, 0xb4, 0xce, 0x2e, 0x17, 0x20, 0x2f, 0x82, 0x5d, 0x66, 0x2f, 0xb2, 0x20, 0xd4, 0x50, 0xc3, 0x19, 0x59, 0x1, 0xe3, 0xb, 0xa0, 0xa6, 0x34, 0xe7, 0x9c, 0x65, 0xa0, 0xe5, 0x9d, 0x7b, 0x3b, 0xe4, 0x38, 0x79, 0x27, 0xd2, 0xa2, 0xbb, 0x22, 0xd9, 0x8b, 0x7e, 0x43, 0x44, 0x5e, 0x8, 0x75, 0x67, 0x66, 0x1f, 0x3b, 0x0, 0x5a, 0x67, 0x7a, 0xfa, 0xe0, 0x9, 0xb8, 0x99, 0x3a, 0x44, 0xd8, 0xaf, 0xd7, 0x63, 0x10, 0x95, 0xe6, 0x1e, 0x57, 0xc1, 0x90, 0xf7, 0xdc, 0x9d, 0x9f, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char graph_node_comment_focus_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x40, 0x8, 0x3, 0x0, 0x0, 0x0, 0x24, 0xa3, 0x7, 0xa4, 0x0, 0x0, 0x0, 0x6f, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xae, 0x6d, 0x5b, 0xae, 0x6d, 0x5b, 0xae, 0x6d, 0x5b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xae, 0x6d, 0x5b, 0x96, 0x42, 0x2b, 0x0, 0x0, 0x0, 0xae, 0x6d, 0x5b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x77, 0x2f, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xae, 0x6d, 0x5b, 0x0, 0x0, 0x0, 0xae, 0x6d, 0x5b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xae, 0x6d, 0x5b, 0xae, 0x6d, 0x5b, 0x0, 0x0, 0x0, 0x5f, 0x8c, 0x8b, 0xc7, 0x0, 0x0, 0x0, 0x25, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x1, 0x3, 0x6, 0x8, 0x9, 0x2, 0xc, 0x1e, 0x33, 0x41, 0x46, 0xd, 0x31, 0x9a, 0xe3, 0xff, 0x5, 0x24, 0xb4, 0xe2, 0x39, 0xf4, 0x44, 0xa, 0x47, 0x42, 0x45, 0x3d, 0xf8, 0x2a, 0xcd, 0x11, 0x3f, 0xd3, 0xfd, 0x2b, 0xb1, 0x1b, 0xa4, 0x4f, 0x0, 0x0, 0x0, 0x90, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0xca, 0xb5, 0x75, 0xc4, 0x50, 0x0, 0x5, 0xd1, 0xf7, 0x49, 0xcc, 0xcc, 0xdc, 0x7f, 0x8b, 0x2b, 0xe6, 0xc8, 0xb1, 0x75, 0xc3, 0x39, 0x3, 0x80, 0x50, 0xc6, 0xc5, 0x84, 0x33, 0x4a, 0x30, 0x91, 0x64, 0x45, 0xd5, 0xf4, 0x89, 0xa6, 0x2a, 0xb2, 0x4, 0x48, 0x86, 0x69, 0xd9, 0xce, 0xc2, 0xb6, 0x4c, 0x43, 0x82, 0xeb, 0xf9, 0x4e, 0xb0, 0x71, 0x7c, 0xcf, 0x5, 0xf, 0xa3, 0xe0, 0x10, 0x85, 0x1c, 0x22, 0x76, 0xce, 0xe0, 0xc4, 0x2, 0x49, 0x7a, 0xd, 0x69, 0x2, 0xa1, 0xff, 0xb3, 0x70, 0xda, 0x42, 0x76, 0xf8, 0x73, 0xf8, 0xc2, 0x17, 0x92, 0xf4, 0x19, 0xf2, 0x6b, 0xc8, 0x13, 0xf0, 0xa2, 0x3c, 0x43, 0x59, 0x70, 0xb8, 0x55, 0x7d, 0x2c, 0x4e, 0x5d, 0xb9, 0x90, 0x9a, 0xb6, 0xeb, 0x9d, 0x45, 0xdf, 0xb5, 0x8d, 0x4, 0xd0, 0x66, 0x68, 0xf5, 0x74, 0xa2, 0xb7, 0x43, 0x43, 0x31, 0x91, 0x98, 0x48, 0x16, 0x82, 0x49, 0x78, 0x1b, 0x1, 0xf, 0xa7, 0x50, 0x68, 0x35, 0xb8, 0x84, 0x4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char graph_node_default_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x36, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0x12, 0x19, 0xe, 0xb, 0x10, 0xe, 0xb, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0x12, 0x19, 0x0, 0x0, 0x0, 0x19, 0x15, 0x1c, 0x24, 0x1e, 0x27, 0x16, 0x12, 0x19, 0x76, 0x9, 0xd2, 0x13, 0x0, 0x0, 0x0, 0xf, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x46, 0x47, 0x3f, 0x2b, 0x11, 0x3, 0xfd, 0xd3, 0xcd, 0x2a, 0x73, 0x45, 0xf8, 0x3d, 0x3f, 0x57, 0xda, 0x84, 0x0, 0x0, 0x0, 0x37, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0x64, 0x2, 0x2, 0x46, 0x8, 0xc9, 0xcc, 0xc2, 0xca, 0xc6, 0xc0, 0x8f, 0x4, 0xd8, 0x39, 0x98, 0x59, 0x19, 0x50, 0x80, 0x0, 0x27, 0x17, 0x3, 0x2a, 0x10, 0xe4, 0x46, 0x13, 0xe0, 0x67, 0x1a, 0x18, 0x1, 0x1e, 0x34, 0x1, 0x5e, 0x3e, 0xc, 0xa7, 0x63, 0x78, 0xe, 0xc3, 0xfb, 0x0, 0x89, 0x4d, 0x2, 0xf2, 0xa2, 0x23, 0x3b, 0xc4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char graph_node_default_focus_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x8a, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x0, 0x81, 0xff, 0x8c, 0xff, 0x99, 0xff, 0xb3, 0x2, 0x21, 0x3b, 0x4, 0x82, 0xd8, 0x40, 0x11, 0x46, 0x88, 0xa4, 0xf8, 0x7f, 0x49, 0x20, 0x14, 0xff, 0x2f, 0xa, 0x84, 0x8, 0xb6, 0xe0, 0x7f, 0x6e, 0xa0, 0x22, 0x90, 0x92, 0x92, 0xff, 0xd8, 0x60, 0xe5, 0x9b, 0xb6, 0x15, 0xff, 0x79, 0xc1, 0x4a, 0xb0, 0x83, 0x17, 0xc2, 0x29, 0xff, 0x1b, 0xe, 0x1, 0x4d, 0x61, 0xc6, 0xa1, 0x80, 0x5b, 0xf9, 0xf, 0x63, 0xe9, 0x77, 0xa0, 0x45, 0xac, 0xc, 0x38, 0x0, 0xd8, 0x72, 0xa0, 0x5b, 0xd8, 0xf1, 0x2b, 0x10, 0x27, 0xa4, 0x40, 0x92, 0x7c, 0x5, 0x8, 0x2b, 0xc8, 0x77, 0xe4, 0xb, 0xe1, 0xd2, 0x6f, 0x78, 0xbc, 0xf9, 0x87, 0x17, 0x18, 0x50, 0x7, 0x40, 0x1, 0x85, 0x23, 0xa8, 0x4b, 0xbf, 0x3, 0xc3, 0x91, 0x1f, 0x14, 0xd4, 0x78, 0x23, 0xb, 0x2d, 0xa0, 0xff, 0xb3, 0x23, 0x20, 0x22, 0xba, 0x1, 0x39, 0x96, 0x8a, 0xa5, 0x9b, 0x88, 0xa3, 0x56, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char graph_node_position_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x40, 0x2, 0x3, 0x0, 0x0, 0x0, 0x6e, 0x13, 0x1f, 0x5, 0x0, 0x0, 0x0, 0x9, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xf4, 0x3f, 0x2c, 0xf4, 0x3f, 0x2c, 0x1c, 0x3e, 0x10, 0xcd, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xe4, 0xd1, 0xf4, 0xeb, 0x59, 0x0, 0x0, 0x0, 0x30, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x0, 0x3, 0xb6, 0x55, 0xab, 0x26, 0x30, 0x88, 0x30, 0x0, 0x91, 0x42, 0xd6, 0x4a, 0xe, 0x6, 0x45, 0x7, 0x46, 0xf, 0x6, 0x25, 0x6, 0x86, 0xe, 0x20, 0x31, 0x4a, 0x80, 0x42, 0x3, 0x1c, 0x2e, 0xe0, 0x10, 0x82, 0x84, 0x15, 0x1c, 0x0, 0x0, 0x41, 0x2d, 0x2b, 0x21, 0xbb, 0xb7, 0x1a, 0xa9, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char graph_node_selected_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x40, 0x8, 0x3, 0x0, 0x0, 0x0, 0x24, 0xa3, 0x7, 0xa4, 0x0, 0x0, 0x1, 0x5f, 0x50, 0x4c, 0x54, 0x45, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb2, 0xb2, 0xcc, 0xae, 0xa0, 0xbb, 0x9c, 0x92, 0xa6, 0x9a, 0x91, 0xa4, 0x95, 0x8c, 0x9e, 0xaf, 0x9f, 0xaf, 0xa0, 0x94, 0xa5, 0x8e, 0x84, 0x95, 0x7f, 0x75, 0x84, 0x73, 0x6a, 0x78, 0x6d, 0x64, 0x72, 0xa2, 0xa2, 0xb9, 0x9c, 0x90, 0xa2, 0x8b, 0x81, 0x90, 0xdc, 0xda, 0xce, 0xe2, 0xe1, 0xd2, 0x9d, 0x91, 0xa9, 0x85, 0x7c, 0x8c, 0xdb, 0xd9, 0xce, 0xdb, 0xd9, 0xcd, 0xda, 0xce, 0xe0, 0xde, 0xd5, 0xe3, 0xdf, 0xd6, 0xe4, 0x97, 0x8d, 0xa0, 0x7a, 0x70, 0x7f, 0xdb, 0xd0, 0xdf, 0xdb, 0xd0, 0xe1, 0xda, 0xd0, 0xe1, 0x70, 0x67, 0x75, 0xd8, 0xcb, 0xde, 0xda, 0xcf, 0xdf, 0xdb, 0xce, 0xe1, 0xdb, 0xcf, 0xe1, 0xdb, 0xd0, 0xe0, 0xda, 0xcf, 0xe0, 0xd8, 0xcc, 0xde, 0x90, 0x87, 0x99, 0x6d, 0x67, 0x72, 0xd7, 0xcc, 0xdf, 0xda, 0xce, 0xdf, 0xd8, 0xcb, 0xdf, 0xd7, 0xca, 0xde, 0xd9, 0xcc, 0xdf, 0xd9, 0xcd, 0xdf, 0xd6, 0xc9, 0xdd, 0xd9, 0xcd, 0xde, 0xd6, 0xc8, 0xdc, 0xd5, 0xc8, 0xdc, 0xd7, 0xcb, 0xdd, 0xd7, 0xca, 0xdd, 0xd5, 0xc7, 0xdc, 0xd3, 0xc6, 0xdb, 0xd5, 0xc9, 0xdc, 0xd5, 0xc9, 0xdd, 0xd6, 0xc9, 0xdc, 0xd4, 0xc6, 0xdb, 0xd3, 0xc5, 0xdb, 0xd5, 0xc8, 0xdb, 0xd4, 0xc8, 0xdc, 0xd3, 0xc4, 0xd9, 0xd4, 0xc6, 0xda, 0xd2, 0xc3, 0xd9, 0xd3, 0xc5, 0xda, 0xd2, 0xc5, 0xd9, 0xd3, 0xc5, 0xd9, 0xd2, 0xc5, 0xda, 0xd1, 0xc2, 0xd9, 0xd2, 0xc4, 0xd8, 0xd2, 0xc4, 0xd9, 0xd0, 0xc2, 0xd9, 0xd0, 0xc1, 0xd7, 0xd0, 0xc2, 0xd7, 0xd0, 0xc2, 0xd8, 0xd1, 0xc2, 0xd7, 0xcf, 0xc1, 0xd7, 0xd0, 0xc2, 0xd6, 0xcf, 0xc1, 0xd6, 0xcf, 0xc2, 0xd7, 0xcf, 0xc0, 0xd7, 0xce, 0xbf, 0xd6, 0xce, 0xc0, 0xd5, 0xce, 0xc0, 0xd6, 0xce, 0xbf, 0xd5, 0xcd, 0xbf, 0xd5, 0xcd, 0xbe, 0xd5, 0xcd, 0xbe, 0xd4, 0xcc, 0xbd, 0xd5, 0xcc, 0xbd, 0xd4, 0xcc, 0xbc, 0xd4, 0x47, 0x40, 0x4a, 0x1d, 0x1a, 0x1f, 0x69, 0x5f, 0x6f, 0x4a, 0x42, 0x4f, 0x5e, 0x54, 0x63, 0x3b, 0x34, 0x3f, 0x5e, 0x55, 0x63, 0x63, 0x59, 0x67, 0x77, 0x6d, 0x7b, 0x6d, 0x62, 0x73, 0x7f, 0x76, 0x85, 0xdb, 0xd9, 0xcd, 0xdb, 0xd8, 0xcd, 0x6d, 0x62, 0x74, 0x8f, 0x84, 0x94, 0x7f, 0x76, 0x83, 0xdb, 0xd8, 0xcd, 0xa4, 0x95, 0xa4, 0x7e, 0x74, 0x84, 0x74, 0x6b, 0x79, 0x6f, 0x66, 0x74, 0x96, 0x8a, 0xa2, 0x91, 0x88, 0x9b, 0x0, 0x0, 0x0, 0xaa, 0xaa, 0xaa, 0xbf, 0xbf, 0xbf, 0xf0, 0xc9, 0xec, 0x71, 0x0, 0x0, 0x0, 0x75, 0x74, 0x52, 0x4e, 0x53, 0x1, 0x3, 0xa, 0x13, 0x1a, 0x1c, 0x1d, 0x10, 0x2b, 0x4d, 0x64, 0x6e, 0x72, 0xb, 0x2c, 0x6a, 0xfc, 0xff, 0x15, 0x52, 0xfd, 0xff, 0xe2, 0xe2, 0xe2, 0x1b, 0x68, 0xe2, 0xe2, 0xe2, 0x71, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0x1e, 0x72, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0x6b, 0xc7, 0x56, 0xfe, 0xff, 0xc7, 0x30, 0x74, 0xfe, 0x11, 0x57, 0x6d, 0x72, 0x16, 0x1c, 0x0, 0x3, 0x4, 0x35, 0xf5, 0x4, 0x26, 0x0, 0x0, 0x1, 0x16, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0xcc, 0xc5, 0x61, 0x95, 0x61, 0x10, 0x85, 0xe1, 0xf7, 0x8c, 0x5c, 0xc3, 0xdd, 0x65, 0x4d, 0xea, 0xc8, 0x6, 0xdb, 0x63, 0xab, 0x74, 0x90, 0x42, 0xe8, 0x20, 0x5b, 0x3a, 0xa0, 0x12, 0xaa, 0xc0, 0x25, 0xd7, 0xe5, 0x1f, 0xec, 0xc3, 0xa5, 0x82, 0x9c, 0xdd, 0x79, 0x46, 0x84, 0xbe, 0x4, 0xa8, 0x2f, 0x91, 0x7a, 0xbf, 0xc0, 0x52, 0x47, 0x5a, 0xa5, 0x51, 0xe4, 0x6f, 0x27, 0xd1, 0xd7, 0x6c, 0x24, 0x15, 0xa0, 0xaa, 0xe9, 0xb0, 0xec, 0x75, 0x10, 0x51, 0x9, 0xbd, 0xde, 0x60, 0x44, 0xbc, 0xb6, 0xeb, 0x43, 0x86, 0xc, 0x56, 0x3d, 0x96, 0xfb, 0x99, 0xc, 0xaf, 0xfb, 0xfe, 0xd4, 0x8f, 0xf5, 0xf3, 0xc3, 0x72, 0xb3, 0x39, 0x67, 0xec, 0xbf, 0x3b, 0x12, 0x80, 0x97, 0x9d, 0x3, 0xc0, 0x81, 0x0, 0xec, 0x2d, 0x3d, 0x96, 0x3d, 0x96, 0x27, 0x1a, 0xe8, 0x14, 0xa8, 0x54, 0x58, 0x83, 0x10, 0x48, 0x55, 0xa6, 0x6, 0x29, 0xa6, 0x0, 0x87, 0xba, 0x6, 0x2e, 0x8e, 0x0, 0xa0, 0x6, 0x26, 0xa9, 0x13, 0xe5, 0x6b, 0xc0, 0x80, 0xcc, 0x8c, 0xea, 0xb2, 0xd6, 0x83, 0xef, 0x4f, 0x25, 0x87, 0x91, 0xba, 0xb6, 0x11, 0x74, 0x96, 0xde, 0xf3, 0xae, 0x6d, 0x90, 0x3d, 0x15, 0xea, 0x12, 0xd1, 0x0, 0x41, 0x39, 0xd0, 0xc0, 0x4, 0x88, 0xa2, 0x1a, 0xb8, 0x0, 0xe0, 0x3b, 0xd8, 0x7f, 0xc1, 0xf8, 0x25, 0x7, 0xf0, 0x4b, 0x3b, 0x80, 0xb8, 0xae, 0x17, 0x56, 0xad, 0x18, 0x97, 0xca, 0x98, 0xa1, 0xd6, 0x11, 0x33, 0x6c, 0x7f, 0x1b, 0xe3, 0xfb, 0xc6, 0xf6, 0xbe, 0xf7, 0xb6, 0xb6, 0x2c, 0x3b, 0xa, 0xb3, 0xbe, 0x6e, 0xe8, 0x59, 0xac, 0x42, 0x7a, 0xd2, 0x36, 0xee, 0x57, 0xad, 0x62, 0xec, 0x1b, 0x7f, 0xa4, 0x3d, 0x60, 0xa7, 0x6a, 0xed, 0x63, 0xa1, 0xc3, 0x3b, 0x7a, 0xa, 0xc0, 0xad, 0xda, 0x1b, 0x57, 0xec, 0xf2, 0xd8, 0x75, 0x17, 0x0, 0x6a, 0x7f, 0x97, 0x8f, 0x54, 0xa2, 0x67, 0xc8, 0xba, 0xb8, 0x46, 0x24, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char graph_port_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0xa, 0x8, 0x4, 0x0, 0x0, 0x0, 0x27, 0x3b, 0x7, 0x36, 0x0, 0x0, 0x0, 0x6e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x65, 0x8e, 0xc1, 0xd, 0xc2, 0x30, 0x10, 0x4, 0xb7, 0x31, 0x22, 0x2a, 0x48, 0x41, 0x88, 0x4f, 0xa, 0x73, 0x42, 0x17, 0x1e, 0xd2, 0x40, 0xde, 0x3e, 0xf3, 0xb5, 0x8c, 0x8f, 0x13, 0x8, 0x29, 0x3b, 0xbf, 0xd1, 0x9e, 0xf6, 0xe4, 0xc9, 0x57, 0x36, 0x5e, 0x83, 0x95, 0x59, 0x11, 0xee, 0x34, 0xfa, 0x97, 0xbc, 0x44, 0x6b, 0xa8, 0xa3, 0xdb, 0xe0, 0x70, 0xdd, 0xf6, 0x49, 0x3c, 0x5c, 0xd5, 0x20, 0xf4, 0x2a, 0x2a, 0xdd, 0x7e, 0xb2, 0xb8, 0x34, 0x61, 0x27, 0x59, 0xc4, 0x76, 0x3a, 0x4f, 0x62, 0xa6, 0xbb, 0x2e, 0x83, 0x18, 0x7a, 0x5e, 0x7c, 0x7f, 0xf9, 0x7b, 0xa9, 0xe5, 0x9b, 0x22, 0xfb, 0x44, 0xa2, 0x62, 0xa4, 0x4f, 0x4b, 0x6f, 0x69, 0x3b, 0x9a, 0x7e, 0xcd, 0xde, 0x94, 0x27, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char hseparator_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x2, 0x3, 0x0, 0x0, 0x0, 0xb9, 0x61, 0x56, 0x18, 0x0, 0x0, 0x0, 0xc, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x73, 0x9b, 0xaa, 0xce, 0xdc, 0xe1, 0xff, 0xff, 0xff, 0x64, 0x6c, 0x1, 0xd2, 0x0, 0x0, 0x0, 0x3, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xb3, 0xb3, 0x67, 0xf6, 0xdb, 0x93, 0x0, 0x0, 0x0, 0x10, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x64, 0x60, 0x60, 0xc2, 0x40, 0x8c, 0xc, 0x0, 0x0, 0xc7, 0x0, 0xf, 0xf5, 0x92, 0x2f, 0xa7, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char hslider_bg_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4b, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x40, 0x3e, 0x4a, 0x2a, 0x29, 0x2f, 0x20, 0x20, 0x24, 0x3f, 0x3e, 0x49, 0x1f, 0x1f, 0x24, 0x20, 0x20, 0x24, 0x4d, 0x4b, 0x59, 0x3f, 0x3e, 0x49, 0x3f, 0x3e, 0x49, 0x1e, 0x1e, 0x23, 0x1f, 0x1f, 0x23, 0x20, 0x20, 0x25, 0x22, 0x22, 0x27, 0x23, 0x23, 0x27, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2a, 0x57, 0x2e, 0xcb, 0x70, 0x0, 0x0, 0x0, 0x12, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x4, 0x19, 0x40, 0x5d, 0x66, 0x68, 0x28, 0x93, 0xf0, 0xfc, 0x94, 0xfc, 0xfd, 0x1a, 0x96, 0x95, 0x6b, 0xe2, 0xd5, 0x49, 0x0, 0x0, 0x0, 0x59, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x85, 0x4f, 0x83, 0x11, 0x3, 0x1, 0x10, 0xcc, 0x39, 0xef, 0xfe, 0xb, 0x7d, 0xdb, 0xc6, 0x8e, 0x8e, 0xb, 0xf8, 0x9d, 0x70, 0x1d, 0x9c, 0x46, 0x2d, 0xcc, 0x18, 0xea, 0x11, 0x80, 0xda, 0xb7, 0x36, 0xe, 0xf2, 0xbe, 0x2f, 0x80, 0x1c, 0xb0, 0xe5, 0xa2, 0x1f, 0xa5, 0xc0, 0xea, 0x12, 0x2c, 0x4, 0x75, 0x52, 0x80, 0x38, 0x46, 0x2b, 0x65, 0x9d, 0xa7, 0x97, 0xc1, 0xf5, 0x25, 0x82, 0x7a, 0x47, 0x4a, 0x83, 0xac, 0x93, 0x33, 0x8f, 0x83, 0xaa, 0xb2, 0xb4, 0xb8, 0x18, 0xbb, 0x58, 0xff, 0x4e, 0xdb, 0x1, 0xc3, 0xf1, 0x34, 0x3b, 0x7e, 0xbc, 0xb3, 0xc3, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char hslider_grabber_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0xf3, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x1e, 0x30, 0x33, 0xf0, 0x32, 0xc8, 0x30, 0xa8, 0x3, 0xa1, 0xc, 0x90, 0xc5, 0x8c, 0x29, 0x2d, 0x96, 0x96, 0xd7, 0x79, 0x70, 0xc6, 0xfb, 0x19, 0xef, 0x3b, 0xf, 0xa6, 0xe5, 0x31, 0x88, 0xa1, 0x2b, 0xe1, 0x4d, 0xcb, 0x9b, 0xf4, 0xa2, 0xef, 0x7f, 0x3b, 0x10, 0xf6, 0xfd, 0x9f, 0xf4, 0x2, 0xa8, 0x84, 0x17, 0x55, 0x81, 0x4c, 0xe7, 0xc1, 0xbe, 0xff, 0x2d, 0xff, 0x9b, 0x81, 0xb0, 0x5, 0xa8, 0xa4, 0xf3, 0x20, 0xd0, 0x22, 0x14, 0xa0, 0x3e, 0xe3, 0x7d, 0x3b, 0x50, 0x12, 0xc, 0x81, 0xa6, 0xcc, 0x78, 0xf, 0x74, 0xb, 0xa, 0xd0, 0x98, 0xf6, 0x1, 0x59, 0xc1, 0xd4, 0xf, 0xc, 0x1a, 0xa8, 0xa, 0x94, 0xfa, 0x6f, 0x77, 0xc1, 0x15, 0x74, 0xfc, 0xef, 0xbb, 0xc7, 0xa0, 0x82, 0xaa, 0x40, 0xbc, 0x71, 0x7d, 0x3f, 0x5c, 0x41, 0xef, 0xff, 0xde, 0xa3, 0xc, 0x52, 0xa8, 0xa, 0xb8, 0x82, 0x52, 0xa7, 0xfd, 0x69, 0x5, 0x4b, 0xb7, 0xfe, 0x9f, 0xf6, 0xcf, 0x37, 0x85, 0x81, 0x7, 0x2d, 0x1c, 0x14, 0xd, 0xfb, 0x1f, 0x74, 0x82, 0x15, 0x74, 0xfe, 0x9f, 0xf8, 0x80, 0x45, 0x83, 0x81, 0x9, 0x55, 0x1, 0x23, 0x83, 0x48, 0xc5, 0x9c, 0xc9, 0xff, 0x5b, 0x81, 0x70, 0xf2, 0xff, 0x92, 0xa9, 0xc, 0xc2, 0x98, 0x41, 0xcd, 0xca, 0xa3, 0x33, 0xe1, 0x76, 0xcf, 0xff, 0x9e, 0xff, 0x13, 0xef, 0xf0, 0xe8, 0x30, 0xb0, 0x62, 0x8b, 0xd, 0x6e, 0xb, 0xff, 0x39, 0x5f, 0xe6, 0x7c, 0x77, 0x8, 0x45, 0xd8, 0x8f, 0x61, 0x4d, 0x51, 0x71, 0x55, 0x2d, 0x83, 0x18, 0x90, 0x85, 0x3, 0xb0, 0x30, 0x70, 0x3, 0x75, 0xb3, 0x20, 0xb, 0x1, 0x0, 0x86, 0xe, 0x79, 0x54, 0x16, 0xbe, 0x69, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char hslider_grabber_disabled_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0xe7, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x1e, 0x30, 0x33, 0xf0, 0x32, 0xc8, 0x30, 0xa8, 0x3, 0xa1, 0xc, 0x90, 0xc5, 0x8c, 0x29, 0x2d, 0x66, 0x9c, 0xe7, 0x7a, 0xd0, 0xe7, 0xbd, 0xcf, 0x7b, 0xd7, 0x83, 0xc6, 0x79, 0xc, 0x62, 0xe8, 0x4a, 0x78, 0x8d, 0xf3, 0x3c, 0x5f, 0xb8, 0xff, 0x77, 0x1, 0x42, 0xf7, 0xff, 0x9e, 0x2f, 0x80, 0x4a, 0x78, 0x51, 0x15, 0xc8, 0xb8, 0x1e, 0x74, 0xff, 0xef, 0x4, 0x81, 0x40, 0x25, 0xae, 0x7, 0x81, 0x16, 0xa1, 0x0, 0x75, 0x9f, 0xf7, 0x2e, 0x30, 0x5, 0x40, 0x53, 0x7c, 0xde, 0x3, 0xdd, 0x82, 0x2, 0x34, 0xbc, 0x3f, 0x20, 0x2b, 0xf0, 0xfe, 0xc0, 0xa0, 0x81, 0xaa, 0x40, 0xc9, 0xe3, 0xb6, 0x2b, 0x92, 0x2, 0xf7, 0x7b, 0xc, 0x2a, 0xa8, 0xa, 0xc4, 0x1d, 0xd7, 0x7b, 0x20, 0xb9, 0xc1, 0xfd, 0x28, 0x83, 0x14, 0xaa, 0x2, 0x2e, 0xcd, 0x54, 0xef, 0x3f, 0xce, 0x60, 0x69, 0xe7, 0xff, 0xde, 0xff, 0xd4, 0x53, 0x18, 0x78, 0xd0, 0xc2, 0x41, 0xd0, 0xd0, 0xe3, 0x1, 0xc4, 0x12, 0xd7, 0xff, 0x9e, 0xf, 0x98, 0x34, 0x18, 0x98, 0x50, 0x15, 0x30, 0x32, 0x88, 0xd8, 0xcc, 0xf1, 0xfa, 0xef, 0xc, 0x84, 0x5e, 0xff, 0xad, 0xa6, 0x32, 0x8, 0x63, 0x6, 0x35, 0x2b, 0x9b, 0x8e, 0xc7, 0x6d, 0xb7, 0xff, 0x6e, 0xff, 0x3d, 0xef, 0xb0, 0xe9, 0x30, 0xb0, 0x62, 0x8b, 0xd, 0x6e, 0x19, 0x7f, 0xbf, 0x2f, 0x7e, 0xdf, 0x15, 0x42, 0x11, 0xf6, 0x63, 0x58, 0x63, 0x59, 0x6c, 0x5b, 0xcb, 0x20, 0x6, 0x64, 0xe1, 0x0, 0x2c, 0xc, 0xdc, 0x40, 0xdd, 0x2c, 0xc8, 0x42, 0x0, 0x4, 0x5c, 0x63, 0x9b, 0xfc, 0xae, 0x1b, 0x2a, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char hslider_grabber_hl_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0xc3, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x48, 0x83, 0x83, 0x60, 0xaf, 0xb1, 0x65, 0xbb, 0xca, 0x61, 0xb3, 0xc2, 0x0, 0x0, 0x0, 0x63, 0xb7, 0xc8, 0x63, 0xb7, 0xc7, 0x0, 0x0, 0x0, 0x61, 0xb3, 0xbc, 0x60, 0xb1, 0xbc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5b, 0xa6, 0xa5, 0x63, 0xb4, 0xb6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x69, 0x69, 0x5e, 0xb1, 0xcd, 0x5e, 0xb0, 0xcd, 0x36, 0x63, 0x63, 0x0, 0x0, 0x0, 0x17, 0x2a, 0x29, 0x60, 0xb2, 0xbd, 0x62, 0xb3, 0xbf, 0x3, 0x5, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0x9b, 0x9a, 0x52, 0x96, 0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0xf, 0xf, 0x62, 0xb4, 0xbd, 0x63, 0xb7, 0xbf, 0x0, 0x0, 0x0, 0x27, 0x48, 0x47, 0x68, 0xc0, 0xcf, 0x68, 0xc1, 0xcf, 0x2d, 0x52, 0x52, 0x51, 0x93, 0x92, 0x56, 0x9d, 0x9c, 0x0, 0x0, 0x0, 0x54, 0xa2, 0xc8, 0x4c, 0x94, 0xc2, 0x48, 0x8e, 0xc0, 0x47, 0x8c, 0xbf, 0x4b, 0x93, 0xc2, 0x4b, 0x92, 0xc2, 0x4f, 0x98, 0xc4, 0x4d, 0x96, 0xc3, 0x55, 0xa3, 0xc8, 0x53, 0x9f, 0xc7, 0x49, 0x8f, 0xc0, 0x4e, 0x97, 0xc4, 0x5a, 0xab, 0xcb, 0x5a, 0xac, 0xcc, 0x52, 0x9e, 0xc6, 0x51, 0x9d, 0xc6, 0xd4, 0xd, 0x1d, 0x1c, 0x0, 0x0, 0x0, 0x31, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x3, 0xd, 0x1c, 0x27, 0x16, 0x6e, 0xc1, 0xef, 0xe8, 0x28, 0xf0, 0xf0, 0x22, 0xdb, 0xde, 0x24, 0x17, 0xaf, 0xc5, 0x1a, 0xa, 0x65, 0xfc, 0xfe, 0x64, 0xc, 0x31, 0xe0, 0xe0, 0x28, 0x2, 0x1, 0x14, 0x9c, 0x95, 0x13, 0x5, 0x2c, 0xdb, 0xdc, 0xb, 0x4f, 0xf4, 0xf7, 0x55, 0x73, 0x7d, 0x4, 0x28, 0xf1, 0xfd, 0xa1, 0x0, 0x0, 0x0, 0x7d, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x5d, 0xcc, 0x81, 0x6, 0xc3, 0x40, 0x10, 0x84, 0xe1, 0xdd, 0x9d, 0xd9, 0x3d, 0x40, 0x1f, 0xa1, 0x0, 0xd1, 0xbe, 0xff, 0xbb, 0x94, 0x10, 0x29, 0x40, 0x1a, 0x40, 0x9, 0xa, 0xbd, 0x34, 0x7b, 0x39, 0xfa, 0x63, 0xf0, 0x61, 0x4c, 0xfe, 0xfa, 0x81, 0x1a, 0x48, 0x98, 0x36, 0x50, 0x66, 0xda, 0x40, 0x71, 0xab, 0x41, 0x3b, 0xc, 0x56, 0x1b, 0x3a, 0xd4, 0x8e, 0x4d, 0x8, 0x40, 0x6a, 0x64, 0x24, 0x0, 0xb6, 0x83, 0xa1, 0x1, 0x79, 0x0, 0x79, 0xc2, 0x54, 0x44, 0xca, 0x14, 0x91, 0xb0, 0xba, 0xef, 0xa7, 0xee, 0x9e, 0x70, 0x8d, 0xd0, 0x52, 0x2c, 0xe2, 0x99, 0x30, 0x93, 0xb, 0x7d, 0x81, 0x4a, 0x82, 0x8c, 0xc0, 0xba, 0xfa, 0x7b, 0x3c, 0x41, 0xb6, 0xd, 0x78, 0x84, 0x74, 0x98, 0x2f, 0x9f, 0xd7, 0x7d, 0x96, 0xbd, 0x2f, 0xa5, 0x6b, 0x13, 0xc4, 0x35, 0x90, 0x18, 0xcd, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char hslider_tick_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xc3, 0x98, 0xc3, 0xc0, 0x0, 0x0, 0x0, 0x1b, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x38, 0x55, 0x5f, 0x8c, 0xac, 0xb8, 0x81, 0xa2, 0xad, 0x98, 0x98, 0x98, 0x4e, 0x4e, 0x4e, 0x8d, 0x8d, 0x8d, 0x82, 0x82, 0x82, 0x4e, 0x4e, 0x4e, 0xc9, 0xf6, 0x7, 0x31, 0x0, 0x0, 0x0, 0x9, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x79, 0x31, 0x79, 0x79, 0x1c, 0x7e, 0xed, 0x4b, 0xf4, 0x0, 0x0, 0x0, 0x20, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0x9, 0x60, 0x60, 0xb, 0x60, 0x60, 0xf, 0x60, 0x60, 0x6d, 0x60, 0x60, 0x14, 0x60, 0xc0, 0x4, 0x4c, 0x2, 0xc, 0xcc, 0x2, 0x70, 0x65, 0x0, 0x46, 0x9d, 0x2, 0xbe, 0xb7, 0xdf, 0x14, 0x38, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char hsplit_bg_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x1, 0x3, 0x0, 0x0, 0x0, 0xfe, 0xc1, 0x2c, 0xc8, 0x0, 0x0, 0x0, 0x6, 0x50, 0x4c, 0x54, 0x45, 0x27, 0x27, 0x29, 0xff, 0xff, 0xff, 0x11, 0xab, 0xb9, 0xf3, 0x0, 0x0, 0x0, 0xa, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x40, 0x3, 0x0, 0x0, 0x10, 0x0, 0x1, 0xb3, 0xac, 0xe2, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char hsplitter_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x40, 0x8, 0x0, 0x0, 0x0, 0x0, 0x2, 0x6f, 0x69, 0x56, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x76, 0x93, 0xcd, 0x38, 0x0, 0x0, 0x0, 0x1a, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x40, 0x80, 0x5, 0xa9, 0x10, 0xcc, 0x90, 0x6a, 0xd, 0xc6, 0x70, 0x80, 0x4b, 0xcd, 0xa8, 0x9a, 0x51, 0x35, 0x0, 0x78, 0xd5, 0x34, 0xa1, 0x54, 0x8c, 0xd5, 0x84, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char icon_add_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x1d, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x11, 0x3c, 0xf8, 0xff, 0xe0, 0xff, 0xd0, 0x52, 0x80, 0x10, 0xc4, 0xd, 0x9, 0x2a, 0x18, 0x26, 0xe1, 0x40, 0x18, 0x0, 0x0, 0x5b, 0x26, 0x61, 0x4d, 0xc9, 0xc1, 0x48, 0x81, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char icon_close_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x62, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xa0, 0x16, 0xe0, 0x8c, 0xe0, 0x11, 0x43, 0xe6, 0xf3, 0x88, 0x71, 0x46, 0xa0, 0x48, 0x73, 0xfc, 0xe3, 0xb8, 0xcc, 0x23, 0x86, 0x90, 0xe6, 0xb8, 0xcc, 0xf1, 0xf, 0x49, 0x9, 0x8f, 0x28, 0xe7, 0x25, 0x8e, 0xff, 0x1c, 0xd7, 0xb9, 0x24, 0x91, 0x79, 0xdc, 0x12, 0x40, 0xe, 0xa6, 0x12, 0x54, 0x69, 0x4c, 0x25, 0xb7, 0x38, 0xae, 0x21, 0xa4, 0x31, 0x94, 0x80, 0x24, 0x81, 0xf0, 0x36, 0x48, 0x1a, 0xaf, 0x2, 0x88, 0x5b, 0xf0, 0x5a, 0x81, 0xa1, 0x4, 0xe1, 0x34, 0x84, 0x73, 0xb1, 0x4a, 0xa3, 0x7b, 0x9a, 0x70, 0x40, 0x11, 0xe, 0x6a, 0xca, 0x1, 0x0, 0x2a, 0x28, 0x37, 0x83, 0x3e, 0x27, 0xb0, 0x34, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char icon_color_pick_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0xaa, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x9d, 0x8e, 0x35, 0x82, 0x2, 0x41, 0x10, 0x45, 0x3b, 0xda, 0x3d, 0xca, 0xba, 0x44, 0x2b, 0x70, 0x9, 0xdc, 0xe1, 0x20, 0xe8, 0x91, 0x90, 0x78, 0x6e, 0x40, 0x4c, 0x82, 0x74, 0xff, 0xc2, 0x9d, 0x18, 0xa7, 0x6, 0x77, 0x7b, 0x23, 0x2d, 0xaf, 0x4c, 0xdc, 0xc, 0xbd, 0x65, 0x1e, 0x84, 0x80, 0x19, 0x55, 0x34, 0x60, 0x3e, 0xd0, 0xea, 0x17, 0x3d, 0x4a, 0xc8, 0x80, 0x1a, 0x60, 0xc2, 0x4f, 0xfd, 0x30, 0xe0, 0x1b, 0x2d, 0x16, 0xab, 0xa7, 0x2c, 0xe, 0x41, 0x68, 0xa5, 0xb9, 0xca, 0x91, 0x16, 0x2e, 0x54, 0xe0, 0x59, 0x54, 0x91, 0xfe, 0xa3, 0x3a, 0xff, 0xce, 0xab, 0x5b, 0xf, 0xa0, 0x4, 0x8f, 0x7b, 0x4c, 0xd3, 0x1b, 0xca, 0x32, 0xcc, 0x55, 0x7a, 0xf4, 0x76, 0x42, 0x2b, 0x97, 0x3e, 0xae, 0xfa, 0xdd, 0xd2, 0xd2, 0x8e, 0x72, 0xe1, 0x83, 0xaf, 0x9f, 0xa9, 0x28, 0x7d, 0x5b, 0xe2, 0x2a, 0xd, 0xc3, 0xa2, 0x78, 0xfe, 0x7d, 0x51, 0xfc, 0x0, 0x8a, 0x41, 0xcb, 0x3d, 0xb2, 0xae, 0x1c, 0xd3, 0xc, 0xa5, 0x30, 0x81, 0xc6, 0xda, 0x29, 0x8e, 0x83, 0x34, 0x25, 0x29, 0x4a, 0x46, 0x71, 0x1f, 0x33, 0xbe, 0x51, 0x89, 0xaf, 0x78, 0xe3, 0x97, 0x7e, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char icon_file_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x2, 0x3, 0x0, 0x0, 0x0, 0x62, 0x9d, 0x17, 0xf2, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xe, 0xc3, 0x0, 0x0, 0xe, 0xc3, 0x1, 0xc7, 0x6f, 0xa8, 0x64, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x0, 0x0, 0x0, 0x9, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0x42, 0xf, 0xc7, 0x49, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x88, 0x95, 0xf0, 0xc6, 0x2a, 0x0, 0x0, 0x0, 0x21, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x0, 0x1, 0xae, 0x55, 0x2d, 0x20, 0xa2, 0x13, 0x44, 0x74, 0x39, 0x80, 0x88, 0x9, 0x40, 0xa2, 0x1, 0xc4, 0x5d, 0xb5, 0x80, 0x68, 0x2, 0x4, 0x0, 0x95, 0x34, 0x18, 0xe4, 0x5e, 0x46, 0xf7, 0x27, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char icon_folder_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x2e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xa0, 0x6, 0x78, 0x70, 0xf4, 0xc1, 0x7f, 0x24, 0x78, 0x18, 0x53, 0xc1, 0x7f, 0x54, 0x48, 0x50, 0xc1, 0x43, 0x1b, 0xbc, 0xa, 0x50, 0xad, 0x23, 0xa4, 0xe0, 0xff, 0x70, 0x52, 0x70, 0x18, 0x97, 0xf4, 0xfd, 0x43, 0xd4, 0x88, 0x4a, 0x0, 0x5a, 0xcb, 0x18, 0xab, 0x5e, 0xd9, 0x1a, 0x53, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char icon_grid_layout_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x5, 0x52, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x3f, 0x78, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x3d, 0x22, 0xef, 0xbb, 0xbf, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x57, 0x35, 0x4d, 0x30, 0x4d, 0x70, 0x43, 0x65, 0x68, 0x69, 0x48, 0x7a, 0x72, 0x65, 0x53, 0x7a, 0x4e, 0x54, 0x63, 0x7a, 0x6b, 0x63, 0x39, 0x64, 0x22, 0x3f, 0x3e, 0xa, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x35, 0x2e, 0x30, 0x22, 0x3e, 0xa, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0xa, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x64, 0x63, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x64, 0x63, 0x2f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x31, 0x2e, 0x31, 0x2f, 0x22, 0xa, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0xa, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0xa, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x73, 0x68, 0x6f, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x73, 0x68, 0x6f, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0xa, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0xa, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x4d, 0x4d, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x6d, 0x6d, 0x2f, 0x22, 0xa, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x73, 0x74, 0x45, 0x76, 0x74, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x73, 0x54, 0x79, 0x70, 0x65, 0x2f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x23, 0x22, 0xa, 0x20, 0x20, 0x20, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, 0x36, 0x22, 0xa, 0x20, 0x20, 0x20, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, 0x36, 0x22, 0xa, 0x20, 0x20, 0x20, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3d, 0x22, 0x31, 0x22, 0xa, 0x20, 0x20, 0x20, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x31, 0x36, 0x22, 0xa, 0x20, 0x20, 0x20, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3d, 0x22, 0x31, 0x36, 0x22, 0xa, 0x20, 0x20, 0x20, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3d, 0x22, 0x32, 0x22, 0xa, 0x20, 0x20, 0x20, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x37, 0x32, 0x2e, 0x30, 0x22, 0xa, 0x20, 0x20, 0x20, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x37, 0x32, 0x2e, 0x30, 0x22, 0xa, 0x20, 0x20, 0x20, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x73, 0x68, 0x6f, 0x70, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x3d, 0x22, 0x33, 0x22, 0xa, 0x20, 0x20, 0x20, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x73, 0x68, 0x6f, 0x70, 0x3a, 0x49, 0x43, 0x43, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x3d, 0x22, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x22, 0xa, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3d, 0x22, 0x32, 0x30, 0x32, 0x31, 0x2d, 0x30, 0x38, 0x2d, 0x31, 0x35, 0x54, 0x30, 0x39, 0x3a, 0x34, 0x31, 0x3a, 0x34, 0x30, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x22, 0xa, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x44, 0x61, 0x74, 0x65, 0x3d, 0x22, 0x32, 0x30, 0x32, 0x31, 0x2d, 0x30, 0x38, 0x2d, 0x31, 0x35, 0x54, 0x30, 0x39, 0x3a, 0x34, 0x31, 0x3a, 0x34, 0x30, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x22, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x63, 0x3a, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x41, 0x6c, 0x74, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x6c, 0x69, 0x20, 0x78, 0x6d, 0x6c, 0x3a, 0x6c, 0x61, 0x6e, 0x67, 0x3d, 0x22, 0x78, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0x3e, 0x47, 0x72, 0x69, 0x64, 0x4c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x6c, 0x69, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x41, 0x6c, 0x74, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x63, 0x3a, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x4d, 0x4d, 0x3a, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x53, 0x65, 0x71, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x6c, 0x69, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x45, 0x76, 0x74, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x22, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x45, 0x76, 0x74, 0x3a, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x41, 0x66, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, 0x20, 0x44, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x20, 0x31, 0x2e, 0x39, 0x2e, 0x31, 0x22, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x45, 0x76, 0x74, 0x3a, 0x77, 0x68, 0x65, 0x6e, 0x3d, 0x22, 0x32, 0x30, 0x32, 0x31, 0x2d, 0x30, 0x38, 0x2d, 0x31, 0x35, 0x54, 0x30, 0x39, 0x3a, 0x34, 0x31, 0x3a, 0x34, 0x30, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x22, 0x2f, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x53, 0x65, 0x71, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x4d, 0x4d, 0x3a, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0xa, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0xa, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0xa, 0x3c, 0x3f, 0x78, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x65, 0x6e, 0x64, 0x3d, 0x22, 0x72, 0x22, 0x3f, 0x3e, 0x10, 0xfa, 0x51, 0xae, 0x0, 0x0, 0x1, 0x82, 0x69, 0x43, 0x43, 0x50, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x0, 0x0, 0x28, 0x91, 0x75, 0x91, 0xbf, 0x4b, 0x42, 0x51, 0x14, 0xc7, 0x3f, 0x5a, 0xa1, 0x94, 0x61, 0x50, 0x43, 0x43, 0x83, 0x84, 0x45, 0x83, 0x85, 0x15, 0x84, 0x2d, 0xd, 0x4a, 0xbf, 0xa0, 0x1a, 0xd4, 0x20, 0xab, 0x45, 0x9f, 0xbf, 0x2, 0xb5, 0xc7, 0x7b, 0x4a, 0x48, 0x6b, 0xd0, 0x2a, 0x14, 0x44, 0x2d, 0xfd, 0x1a, 0xea, 0x2f, 0xa8, 0x35, 0x68, 0xe, 0x82, 0xa2, 0x8, 0xa2, 0x2d, 0x68, 0x2e, 0x6a, 0xa9, 0x78, 0x9d, 0xa7, 0x82, 0x11, 0x79, 0x2e, 0xe7, 0x9e, 0xcf, 0xfd, 0xde, 0x7b, 0xe, 0xf7, 0x9e, 0xb, 0xd6, 0x70, 0x46, 0xc9, 0xea, 0x8d, 0x5e, 0xc8, 0xe6, 0xf2, 0x5a, 0x70, 0xd2, 0xef, 0x5a, 0x88, 0x2c, 0xba, 0x6c, 0xcf, 0xd8, 0x71, 0x62, 0xa3, 0xf, 0x5f, 0x54, 0xd1, 0xd5, 0xd9, 0xd0, 0x44, 0x98, 0xba, 0xf6, 0x71, 0x87, 0xc5, 0x8c, 0x37, 0xfd, 0x66, 0xad, 0xfa, 0xe7, 0xfe, 0xb5, 0x96, 0x78, 0x42, 0x57, 0xc0, 0x62, 0x17, 0x1e, 0x53, 0x54, 0x2d, 0x2f, 0x3c, 0x25, 0x3c, 0xb3, 0x96, 0x57, 0x4d, 0xde, 0x16, 0xee, 0x50, 0xd2, 0xd1, 0xb8, 0xf0, 0xa9, 0xb0, 0x47, 0x93, 0xb, 0xa, 0xdf, 0x9a, 0x7a, 0xac, 0xc2, 0x2f, 0x26, 0xa7, 0x2a, 0xfc, 0x65, 0xb2, 0x16, 0xe, 0x6, 0xc0, 0xda, 0x26, 0xec, 0x4a, 0xfd, 0xe2, 0xd8, 0x2f, 0x56, 0xd2, 0x5a, 0x56, 0x58, 0x5e, 0x8e, 0x3b, 0x9b, 0x29, 0x28, 0xd5, 0xfb, 0x98, 0x2f, 0x71, 0x24, 0x72, 0xf3, 0x21, 0x89, 0xdd, 0xe2, 0x5d, 0xe8, 0x4, 0x99, 0xc4, 0x8f, 0x8b, 0x69, 0xc6, 0x9, 0x30, 0xc2, 0x20, 0xa3, 0x32, 0x8f, 0xd0, 0xcf, 0x10, 0x3, 0xb2, 0xa2, 0x4e, 0xbe, 0xb7, 0x9c, 0x3f, 0xc7, 0xaa, 0xe4, 0x2a, 0x32, 0xab, 0x14, 0xd1, 0x58, 0x21, 0x45, 0x9a, 0x3c, 0x1e, 0x51, 0xb, 0x52, 0x3d, 0x21, 0x31, 0x29, 0x7a, 0x42, 0x46, 0x86, 0xa2, 0xd9, 0xff, 0xbf, 0x7d, 0xd5, 0x93, 0xc3, 0x43, 0x95, 0xea, 0xe, 0x3f, 0x34, 0x3d, 0x19, 0xc6, 0x5b, 0xf, 0xd8, 0xb6, 0xe0, 0xbb, 0x64, 0x18, 0x9f, 0x87, 0x86, 0xf1, 0x7d, 0x4, 0xd, 0x8f, 0x70, 0x91, 0xab, 0xe5, 0xaf, 0x1e, 0x80, 0xef, 0x5d, 0xf4, 0x52, 0x4d, 0x73, 0xef, 0x83, 0x73, 0x3, 0xce, 0x2e, 0x6b, 0x5a, 0x6c, 0x7, 0xce, 0x37, 0xa1, 0xf3, 0x41, 0x8d, 0x6a, 0xd1, 0xb2, 0xd4, 0x20, 0x6e, 0x4d, 0x26, 0xe1, 0xf5, 0x4, 0x5a, 0x23, 0xd0, 0x7e, 0xd, 0xcd, 0x4b, 0x95, 0x9e, 0x55, 0xf7, 0x39, 0xbe, 0x87, 0xf0, 0xba, 0x7c, 0xd5, 0x15, 0xec, 0xee, 0x41, 0xaf, 0x9c, 0x77, 0x2e, 0xff, 0x0, 0xa6, 0xc4, 0x68, 0x3, 0x1f, 0xd7, 0x32, 0xd8, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x1, 0x40, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0x9d, 0xd2, 0xbd, 0x4a, 0x5d, 0x41, 0x14, 0x86, 0xe1, 0xe7, 0x84, 0xa3, 0x51, 0x22, 0x82, 0x41, 0x8c, 0x12, 0x2, 0xeb, 0x1a, 0x2c, 0x84, 0x4, 0x52, 0x88, 0xb1, 0xd2, 0x26, 0x76, 0x62, 0x67, 0xeb, 0xd, 0x78, 0x19, 0x56, 0x69, 0x82, 0x62, 0x67, 0x25, 0x82, 0x60, 0x97, 0xc2, 0x52, 0x8, 0x24, 0x95, 0x16, 0xa9, 0x6, 0x8c, 0x18, 0xb5, 0x30, 0x88, 0xa7, 0x90, 0x88, 0x5a, 0xec, 0x39, 0x66, 0xd8, 0x7a, 0x54, 0x5c, 0xb0, 0xd8, 0xcc, 0xbb, 0xe7, 0xfb, 0x58, 0x3f, 0xd3, 0x50, 0x8b, 0x94, 0xd2, 0x6b, 0xcc, 0x60, 0x25, 0x22, 0xae, 0xea, 0xff, 0xeb, 0xd1, 0xbc, 0x47, 0xfc, 0xd, 0xbd, 0x58, 0x7e, 0x4c, 0xc, 0x8d, 0x42, 0x3c, 0x82, 0x9f, 0xe8, 0xc1, 0x26, 0xce, 0x3b, 0x68, 0xae, 0xf1, 0x25, 0x22, 0x76, 0xeb, 0x15, 0xf4, 0xa3, 0xf, 0x97, 0x18, 0xce, 0xdf, 0x4e, 0x6, 0xfd, 0x77, 0x2a, 0xc8, 0x55, 0x4, 0xb6, 0xf1, 0x1b, 0x1f, 0x23, 0xe2, 0xfa, 0x49, 0x2d, 0xa4, 0x94, 0x7a, 0x30, 0x98, 0xd9, 0x5b, 0x4c, 0x63, 0x49, 0x35, 0xb, 0x68, 0xe1, 0x2f, 0x46, 0xf0, 0x22, 0xb3, 0x93, 0x88, 0xb8, 0x68, 0x1f, 0x36, 0xb0, 0x9f, 0x73, 0x7, 0x87, 0xf8, 0x53, 0xb0, 0x23, 0x2c, 0xe0, 0xa0, 0x60, 0xeb, 0xa, 0xb7, 0x1, 0xac, 0x60, 0x34, 0x5f, 0x1a, 0x52, 0xcd, 0x67, 0x16, 0x73, 0xe8, 0xca, 0x6c, 0x3f, 0xdf, 0x59, 0xcd, 0x9a, 0x5b, 0x83, 0x67, 0x47, 0x7b, 0xb, 0xa7, 0x98, 0xcf, 0x9, 0xc7, 0xaa, 0x2d, 0xac, 0xe5, 0xf3, 0xbf, 0xcc, 0xde, 0xe1, 0x47, 0x66, 0x5b, 0xa5, 0xc1, 0x67, 0xff, 0x87, 0x78, 0xa5, 0x9a, 0xc1, 0x1a, 0x5e, 0x65, 0xd6, 0xc2, 0x24, 0x3e, 0xe4, 0x36, 0xe0, 0x84, 0xda, 0x1a, 0x1f, 0x8a, 0x94, 0xd2, 0x6, 0xc6, 0x30, 0x1e, 0x11, 0xbf, 0xda, 0xbc, 0x7c, 0x89, 0xc3, 0x58, 0x44, 0x77, 0x7, 0x8f, 0x2e, 0x4c, 0xa9, 0x1e, 0xd1, 0xa7, 0x88, 0xd8, 0x29, 0x5b, 0xa0, 0x7a, 0xc2, 0xf1, 0x80, 0x41, 0x23, 0xe7, 0x4b, 0xbc, 0x79, 0x6a, 0xe5, 0x65, 0xb, 0x5f, 0x53, 0x4a, 0x67, 0x29, 0xa5, 0xf7, 0x25, 0x6f, 0x76, 0x12, 0xdc, 0x13, 0x7b, 0x98, 0x88, 0x88, 0xef, 0x25, 0xbc, 0x1, 0x6c, 0x4d, 0x56, 0x9e, 0x2a, 0x4e, 0x48, 0xae, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char icon_grid_minimap_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xe, 0xc3, 0x0, 0x0, 0xe, 0xc3, 0x1, 0xc7, 0x6f, 0xa8, 0x64, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x0, 0x0, 0x2, 0xd, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0x75, 0x93, 0x31, 0x68, 0x14, 0x51, 0x10, 0x86, 0xbf, 0xd9, 0xd, 0xbb, 0xde, 0x76, 0x82, 0x21, 0xf8, 0xe0, 0xbc, 0x5d, 0x8b, 0x80, 0x69, 0x6c, 0xd2, 0x5a, 0x6a, 0x91, 0xc3, 0xd2, 0x46, 0x22, 0x8, 0x9, 0x89, 0x70, 0x85, 0x10, 0x41, 0xd, 0x24, 0x45, 0xb0, 0xb, 0x68, 0x11, 0x14, 0x24, 0x10, 0x22, 0x62, 0x21, 0x41, 0xe, 0x4b, 0x21, 0xa4, 0xb7, 0x49, 0x17, 0xb1, 0x8, 0xb9, 0xdd, 0xc7, 0x86, 0x33, 0x21, 0xe1, 0x3a, 0x8f, 0x64, 0x61, 0x6f, 0x2c, 0xbc, 0x3b, 0x36, 0xb9, 0xdc, 0xc0, 0x2b, 0xde, 0xcc, 0xfc, 0xf3, 0xff, 0xfc, 0xcc, 0x48, 0xa3, 0xd1, 0x78, 0x20, 0x22, 0x13, 0xbe, 0xef, 0xaf, 0xdf, 0xac, 0xd7, 0x1f, 0xe1, 0x38, 0xd3, 0xa8, 0x2a, 0xf0, 0x45, 0x6a, 0xb5, 0xcf, 0x5c, 0x11, 0xcd, 0x66, 0x33, 0x38, 0x3f, 0x3f, 0x9f, 0x13, 0x91, 0x7d, 0xb1, 0xd6, 0x6e, 0xaa, 0xea, 0xd3, 0xe0, 0xe8, 0xe8, 0xde, 0xe8, 0xee, 0xee, 0x37, 0xc0, 0xe9, 0xf6, 0x75, 0xf0, 0xfd, 0x9, 0x99, 0x9d, 0x6d, 0x15, 0x81, 0x59, 0x96, 0x3d, 0x3, 0x5e, 0x2, 0x63, 0x22, 0xf2, 0x69, 0xa4, 0x57, 0x1c, 0xdd, 0xdb, 0xfb, 0x5b, 0x0, 0x3, 0x38, 0x67, 0x41, 0x30, 0x11, 0xc7, 0xf1, 0x13, 0x0, 0x11, 0x71, 0xb2, 0x2c, 0x7b, 0xd8, 0xad, 0xad, 0x2, 0x6f, 0xb9, 0x0, 0x38, 0x3c, 0xfc, 0x5, 0x9c, 0xf6, 0xff, 0x22, 0x27, 0x27, 0xe3, 0xe3, 0x7f, 0xa, 0x3, 0x67, 0x45, 0xe4, 0xbb, 0xe7, 0x79, 0xb7, 0xc3, 0x30, 0x7c, 0xd7, 0x67, 0xe9, 0xe3, 0x67, 0x66, 0x5c, 0x60, 0x1, 0x50, 0x40, 0x51, 0x7d, 0x71, 0x6b, 0x72, 0xf2, 0x20, 0x8a, 0xa2, 0xf9, 0x28, 0x8a, 0xe6, 0x1, 0x3a, 0x9d, 0xce, 0x4f, 0x63, 0x4c, 0x3b, 0x4d, 0xd3, 0xd2, 0xc0, 0x80, 0x3c, 0xcf, 0xf, 0x92, 0xa9, 0xa9, 0x31, 0x60, 0x5, 0x58, 0x91, 0x5a, 0xed, 0xc7, 0x15, 0xfe, 0x95, 0xac, 0xb5, 0xcf, 0xf3, 0x3c, 0x3f, 0xe8, 0x25, 0x46, 0xa, 0xc5, 0xd, 0x11, 0x59, 0xb3, 0xd5, 0xea, 0x1b, 0xa0, 0x95, 0x54, 0xab, 0x5b, 0x97, 0xd1, 0x22, 0xb2, 0xa6, 0xaa, 0x6d, 0x60, 0xd, 0x58, 0xba, 0xa0, 0x20, 0xc, 0xc3, 0x65, 0xd7, 0x75, 0x23, 0xe0, 0x2e, 0xb0, 0x1, 0x5c, 0xbf, 0xf4, 0x0, 0xbe, 0xba, 0xae, 0x1b, 0x85, 0x61, 0xb8, 0x3c, 0xa0, 0x20, 0x4d, 0xd3, 0x52, 0xb9, 0x5c, 0x6e, 0xc5, 0x71, 0xbc, 0x23, 0x22, 0xd3, 0x61, 0x18, 0xde, 0x2f, 0xb2, 0x27, 0x49, 0xa2, 0xaa, 0xba, 0x53, 0x2e, 0x97, 0x5b, 0x69, 0x9a, 0x96, 0xf2, 0x3c, 0x1f, 0xf0, 0xc0, 0x5a, 0x6b, 0x5f, 0x1, 0x25, 0x86, 0x84, 0xe3, 0x38, 0x9e, 0xb5, 0x76, 0x2e, 0xcf, 0xf3, 0xfd, 0x1, 0x5, 0x22, 0xb2, 0xa1, 0xaa, 0x4b, 0x22, 0x72, 0xad, 0xcb, 0x38, 0xe0, 0x81, 0xaa, 0x7e, 0x0, 0xce, 0x44, 0xe4, 0xbd, 0xaa, 0xbe, 0xbe, 0xa0, 0xa0, 0x52, 0xa9, 0x2c, 0x7a, 0x9e, 0x17, 0x1, 0x3d, 0xe0, 0x55, 0x1e, 0x6c, 0x79, 0x9e, 0x17, 0x55, 0x2a, 0x95, 0xc5, 0x1, 0x5, 0xcd, 0x66, 0x33, 0x30, 0xc6, 0x9c, 0xc6, 0x71, 0xbc, 0x2d, 0x22, 0x8f, 0x87, 0x78, 0xb0, 0x6d, 0x8c, 0x39, 0xed, 0xae, 0x74, 0xdf, 0x83, 0x3a, 0x70, 0x9c, 0x65, 0x59, 0x23, 0x49, 0x92, 0x5, 0x11, 0x9, 0x86, 0x79, 0x20, 0x22, 0x41, 0x92, 0x24, 0xb, 0x59, 0x96, 0x35, 0x80, 0x63, 0xa0, 0x2e, 0x3d, 0xf6, 0xc2, 0x91, 0xdc, 0x0, 0x5c, 0x55, 0x5d, 0xbf, 0x4, 0x9e, 0x3, 0x72, 0xfe, 0xaf, 0xfb, 0xaa, 0xe7, 0x79, 0x1f, 0x8d, 0x31, 0x6d, 0x29, 0x36, 0xf5, 0xce, 0x14, 0xb8, 0x33, 0x44, 0xc4, 0x6f, 0xdf, 0xf7, 0xd7, 0x8d, 0x31, 0xed, 0x5e, 0xe2, 0x1f, 0xb, 0x5c, 0xe2, 0xcb, 0xd, 0x9b, 0x69, 0xcb, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char icon_parent_folder_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x68, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xa0, 0x33, 0xb8, 0x27, 0xfe, 0xe0, 0xfc, 0x83, 0x73, 0xf7, 0xc4, 0x71, 0x48, 0xdf, 0x11, 0x7b, 0x78, 0xe9, 0xc1, 0x3f, 0x20, 0xbc, 0xfe, 0x40, 0x12, 0x8f, 0x34, 0x4c, 0x9, 0xa6, 0xe1, 0x57, 0x80, 0x12, 0x17, 0x81, 0xf8, 0x2f, 0x58, 0xe1, 0x15, 0x34, 0x8b, 0x1e, 0x9c, 0x5, 0xa, 0x5e, 0xb8, 0x23, 0x6, 0x52, 0x70, 0x5b, 0x14, 0xac, 0xf0, 0xc, 0xaa, 0x82, 0x7d, 0xf, 0x8e, 0xde, 0x14, 0xf9, 0xcf, 0x8, 0x52, 0xc0, 0xc0, 0x70, 0x5b, 0xf4, 0xe1, 0xc9, 0x7, 0x47, 0xb1, 0xb8, 0x3, 0xaa, 0x0, 0xa, 0x48, 0x52, 0x80, 0xb0, 0xea, 0xc8, 0xc3, 0x83, 0xc, 0x83, 0xe, 0x0, 0x0, 0xb8, 0x27, 0x55, 0x4c, 0xbe, 0xc0, 0xd2, 0xac, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char icon_reload_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0xb1, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xad, 0x50, 0x35, 0xba, 0xc2, 0x40, 0x10, 0x7e, 0xcd, 0x33, 0x5c, 0xca, 0x1c, 0x21, 0x87, 0xc1, 0xa9, 0xd3, 0x23, 0x47, 0xca, 0x69, 0xb0, 0x6, 0x77, 0xdb, 0xfd, 0x17, 0x2f, 0x91, 0x3e, 0xee, 0xd2, 0xc1, 0x4e, 0xb5, 0xdf, 0xcc, 0xaf, 0x5f, 0x9f, 0x7c, 0xdb, 0x5f, 0xda, 0x44, 0x17, 0x2f, 0x75, 0xba, 0xa4, 0xb1, 0xfd, 0xf5, 0xad, 0x8f, 0x1c, 0x86, 0x90, 0x5c, 0x33, 0x38, 0x72, 0x1e, 0xb4, 0xbe, 0x66, 0x28, 0xad, 0xe2, 0xab, 0x38, 0xcd, 0x63, 0xa9, 0x9d, 0xb8, 0x58, 0x68, 0x53, 0x5b, 0x1f, 0x33, 0xd6, 0x9f, 0xa5, 0xc1, 0x20, 0x91, 0xba, 0x7d, 0x80, 0x1e, 0x24, 0x94, 0xdc, 0x92, 0xa4, 0x2, 0x9, 0x1d, 0xe7, 0xe0, 0x9, 0x69, 0x15, 0xf7, 0x58, 0x4e, 0x40, 0xc2, 0xc3, 0x58, 0x8a, 0xb6, 0x31, 0xd1, 0x39, 0xd8, 0x27, 0xed, 0x83, 0x5b, 0x14, 0x33, 0x7d, 0x3d, 0xbb, 0x45, 0x5d, 0x12, 0x55, 0x97, 0x4, 0xe3, 0xb5, 0xf4, 0x8c, 0x77, 0xd6, 0xa7, 0x2c, 0x3b, 0x78, 0x4c, 0x52, 0x81, 0xa, 0x8e, 0x3a, 0xa9, 0x6a, 0x6b, 0xc, 0xe6, 0x3f, 0xa1, 0x8d, 0x86, 0x16, 0xe5, 0x39, 0x78, 0xa2, 0x4d, 0xea, 0xe, 0xfa, 0xdd, 0xa7, 0x0, 0x90, 0x4f, 0x8b, 0xd0, 0xe1, 0x9e, 0x1b, 0xc2, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char icon_snap_grid_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x33, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xf3, 0xf3, 0xf3, 0xff, 0x84, 0x84, 0xff, 0x84, 0x84, 0xff, 0x84, 0x84, 0xff, 0x85, 0x85, 0xff, 0x83, 0x83, 0xff, 0x84, 0x84, 0xff, 0x84, 0x84, 0xff, 0x84, 0x84, 0xff, 0x84, 0x84, 0xff, 0x84, 0x84, 0xff, 0x80, 0x80, 0xff, 0x84, 0x84, 0xff, 0x84, 0x84, 0xff, 0x84, 0x84, 0xff, 0xff, 0xff, 0xa, 0xa5, 0x43, 0x1, 0x0, 0x0, 0x0, 0x10, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xff, 0x1d, 0xac, 0xf2, 0xaf, 0x27, 0xed, 0xff, 0xee, 0xb4, 0x1b, 0x1c, 0xb6, 0xaa, 0xf1, 0x50, 0xa6, 0xdd, 0x5f, 0x0, 0x0, 0x0, 0x4e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x62, 0x0, 0x2, 0x40, 0x23, 0xd3, 0x60, 0x0, 0x40, 0xc, 0x3, 0xaf, 0x76, 0x93, 0xfd, 0x97, 0x7d, 0x9b, 0x55, 0x70, 0x12, 0x62, 0xaf, 0x68, 0x0, 0xc4, 0xe9, 0x3c, 0x1, 0x67, 0xf7, 0x17, 0x20, 0x95, 0xd6, 0xc6, 0xee, 0x80, 0x74, 0xde, 0x7b, 0x1f, 0x24, 0xb0, 0x64, 0x29, 0x1f, 0x53, 0x2e, 0xbe, 0x6e, 0x80, 0xf6, 0x19, 0x90, 0x9e, 0x36, 0x8b, 0xf7, 0xc0, 0x5c, 0xdf, 0x0, 0x66, 0x60, 0xae, 0xf3, 0xb9, 0x1, 0xfb, 0xe9, 0x1, 0xa6, 0x26, 0x1, 0xcd, 0x30, 0x66, 0x63, 0x6, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char icon_visibility_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xe, 0xc4, 0x0, 0x0, 0xe, 0xc4, 0x1, 0x95, 0x2b, 0xe, 0x1b, 0x0, 0x0, 0x0, 0x3, 0x73, 0x42, 0x49, 0x54, 0x8, 0x8, 0x8, 0xdb, 0xe1, 0x4f, 0xe0, 0x0, 0x0, 0x0, 0x96, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xdf, 0xdf, 0xdf, 0xe3, 0xe3, 0xe3, 0xe6, 0xe6, 0xe6, 0xd5, 0xd5, 0xd5, 0xd8, 0xd8, 0xd8, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xe1, 0xe1, 0xe1, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xde, 0xde, 0xde, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xb7, 0x7e, 0xd, 0xb6, 0x0, 0x0, 0x0, 0x32, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x8, 0x9, 0xa, 0xc, 0xd, 0xe, 0xf, 0x11, 0x12, 0x13, 0x2e, 0x2f, 0x32, 0x33, 0x36, 0x37, 0x38, 0x48, 0x49, 0x4b, 0x50, 0x53, 0x55, 0x56, 0x6c, 0x6d, 0x6e, 0x70, 0x77, 0x79, 0x7b, 0x7c, 0xc5, 0xd7, 0xd8, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1, 0xe2, 0xe3, 0xf0, 0xf2, 0xf3, 0xf4, 0xfe, 0x5e, 0x62, 0x1a, 0x26, 0x0, 0x0, 0x0, 0x83, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x8d, 0xc8, 0x45, 0x42, 0x3, 0x1, 0x0, 0xc0, 0xc0, 0xd4, 0x8b, 0x43, 0x1d, 0x5f, 0x77, 0xcb, 0xff, 0x1f, 0x87, 0xd3, 0xf3, 0xe6, 0x36, 0x61, 0x5c, 0x93, 0xc7, 0x70, 0xe8, 0xc3, 0xa7, 0xe9, 0xbf, 0xaf, 0x62, 0x55, 0x4d, 0x6e, 0x7e, 0x7d, 0xdd, 0x5a, 0x1d, 0x16, 0x8b, 0x7d, 0x64, 0x77, 0xfb, 0xed, 0x69, 0x66, 0x75, 0x1, 0xb0, 0xae, 0x2c, 0x67, 0xc0, 0xab, 0x1e, 0xd8, 0x35, 0xf5, 0x96, 0xa3, 0xbe, 0x1, 0x89, 0x2e, 0xa8, 0xb5, 0x62, 0xa9, 0x9, 0x90, 0x9e, 0xc7, 0x4a, 0x53, 0x20, 0xd0, 0x3d, 0xdb, 0xba, 0xda, 0x70, 0xd2, 0x77, 0x60, 0xde, 0x18, 0xad, 0x1, 0x2e, 0x6b, 0xab, 0x39, 0xc0, 0xc3, 0x60, 0x75, 0x5c, 0x2e, 0x4f, 0xb5, 0xc3, 0x1d, 0x3f, 0xdd, 0x17, 0xaa, 0x9a, 0xff, 0x19, 0x66, 0x2f, 0x61, 0xdf, 0x87, 0xcf, 0x33, 0x46, 0xf5, 0x9, 0xdb, 0xf3, 0x10, 0xc5, 0x55, 0x93, 0xc, 0xea, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char icon_zoom_less_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x13, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x18, 0x31, 0xe0, 0xc1, 0x7f, 0x3c, 0x90, 0xb0, 0x82, 0x11, 0x2, 0x0, 0xbf, 0x57, 0x36, 0x25, 0x52, 0x24, 0x7b, 0x26, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char icon_zoom_more_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x1c, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x11, 0x3c, 0xf8, 0xf, 0x84, 0x43, 0x4a, 0x1, 0x42, 0x10, 0xf, 0x24, 0xa8, 0x60, 0x78, 0x84, 0x3, 0x61, 0x0, 0x0, 0xca, 0x3a, 0x6d, 0x8d, 0x50, 0x1e, 0x9a, 0xaa, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char icon_zoom_reset_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x33, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0xa, 0x3c, 0xc, 0x7b, 0xf0, 0xff, 0xc1, 0x7f, 0x9c, 0x22, 0xcf, 0x44, 0x1e, 0xbc, 0x84, 0x72, 0xb1, 0x8b, 0x3c, 0x58, 0x5, 0xe4, 0x40, 0xb8, 0x38, 0x45, 0x18, 0x60, 0x5c, 0x84, 0x30, 0x59, 0xa, 0xa0, 0x80, 0x6e, 0xa, 0x86, 0x92, 0x2f, 0x8, 0x3, 0x0, 0x69, 0xc8, 0x86, 0x87, 0x72, 0xca, 0x85, 0x23, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char indeterminate_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x36, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x38, 0x37, 0x40, 0x20, 0x20, 0x24, 0x20, 0x20, 0x24, 0x38, 0x36, 0x40, 0x20, 0x20, 0x25, 0x1e, 0x1e, 0x22, 0x1f, 0x1f, 0x23, 0x20, 0x20, 0x24, 0x22, 0x22, 0x27, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2a, 0xfe, 0xfe, 0xfe, 0x98, 0x4d, 0x2d, 0x9a, 0x0, 0x0, 0x0, 0x12, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x7, 0x27, 0x50, 0x66, 0x68, 0xb4, 0xfa, 0xfb, 0xb4, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1c, 0x77, 0x5e, 0x7f, 0x0, 0x0, 0x0, 0x59, 0x49, 0x44, 0x41, 0x54, 0x18, 0x95, 0x85, 0xcf, 0xc1, 0x12, 0x80, 0x20, 0x8, 0x45, 0xd1, 0x4, 0x14, 0xd, 0xc5, 0xfa, 0xff, 0x9f, 0x8d, 0x9c, 0x6c, 0x9a, 0xb4, 0xe9, 0x2e, 0xcf, 0x42, 0x9e, 0xcb, 0x32, 0xe4, 0x0, 0xc9, 0xb7, 0x8, 0xc1, 0x19, 0x40, 0x60, 0xc9, 0x2d, 0xe1, 0x0, 0x6, 0xc8, 0x45, 0x6b, 0x4b, 0xb, 0xa3, 0x1, 0x89, 0x6e, 0x57, 0x2a, 0x64, 0xe0, 0x73, 0xed, 0x50, 0xb3, 0x9f, 0xc3, 0x7e, 0xf7, 0x5, 0x7f, 0x6f, 0xc, 0x67, 0x9f, 0xc3, 0xe2, 0x39, 0xc, 0x52, 0xec, 0xd3, 0xd7, 0x4, 0xb3, 0xcf, 0xbd, 0x3a, 0x0, 0xa0, 0xa2, 0x8, 0xbc, 0xf6, 0x84, 0x3a, 0x9d, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char line_edit_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0xa, 0x4, 0x3, 0x0, 0x0, 0x0, 0x7f, 0x1c, 0xd2, 0x8e, 0x0, 0x0, 0x0, 0x2a, 0x50, 0x4c, 0x54, 0x45, 0x17, 0x16, 0x1a, 0x1d, 0x1c, 0x21, 0x20, 0x1e, 0x24, 0x21, 0x1f, 0x25, 0x1d, 0x1c, 0x21, 0x20, 0x1e, 0x24, 0x1d, 0x1c, 0x21, 0x1d, 0x1c, 0x21, 0x24, 0x22, 0x29, 0x28, 0x26, 0x2d, 0x28, 0x26, 0x2e, 0x2b, 0x2a, 0x31, 0x2c, 0x2a, 0x32, 0xff, 0xff, 0xff, 0xb9, 0x11, 0x56, 0x3e, 0x0, 0x0, 0x0, 0x8, 0x74, 0x52, 0x4e, 0x53, 0x6f, 0xef, 0xf7, 0xf7, 0xf0, 0xf9, 0xf1, 0xee, 0xcf, 0x21, 0xd2, 0xdf, 0x0, 0x0, 0x0, 0x2d, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x54, 0x36, 0x36, 0x12, 0x60, 0xf0, 0x98, 0xb5, 0x6a, 0x65, 0xb, 0x43, 0xe4, 0x9e, 0x33, 0xa7, 0xa7, 0x32, 0x58, 0x9d, 0x39, 0x73, 0x66, 0x31, 0x16, 0x12, 0x22, 0xb, 0x52, 0xd9, 0xc6, 0xc0, 0x2, 0xd4, 0x55, 0x0, 0x0, 0xc, 0x14, 0x1a, 0x90, 0x55, 0x1a, 0xec, 0xdb, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char line_edit_clear_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x65, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xad, 0x90, 0x1, 0x6, 0xc0, 0x30, 0xc, 0x45, 0x77, 0x89, 0xd5, 0x76, 0xb3, 0x9e, 0x7b, 0x65, 0x63, 0xd, 0xf9, 0xbb, 0x48, 0x3b, 0xb3, 0x92, 0x54, 0x42, 0xb1, 0x5, 0x88, 0xf7, 0xc8, 0xcf, 0x9f, 0xfe, 0x1a, 0x8e, 0x14, 0xf4, 0x4e, 0x81, 0x63, 0x87, 0x51, 0x90, 0x28, 0x8, 0x46, 0x42, 0x51, 0x4a, 0x9e, 0x79, 0x43, 0xc5, 0x81, 0x55, 0x6f, 0xbc, 0x34, 0xdc, 0x2b, 0x2e, 0x16, 0xe5, 0x3a, 0xb1, 0xb, 0xb6, 0xca, 0x3, 0x2b, 0xb2, 0xc2, 0xbe, 0xf0, 0x66, 0x71, 0x4f, 0x70, 0x3b, 0x61, 0x14, 0x89, 0x26, 0x71, 0x5d, 0x6c, 0x9f, 0x1e, 0x17, 0x35, 0xae, 0xfa, 0xeb, 0xdc, 0x62, 0xc3, 0x84, 0x2d, 0x77, 0x22, 0xda, 0x98, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char line_edit_disabled_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0xa, 0x8, 0x4, 0x0, 0x0, 0x0, 0x27, 0x3b, 0x7, 0x36, 0x0, 0x0, 0x0, 0x4e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x94, 0xc8, 0x67, 0x6b, 0x60, 0xe6, 0x60, 0x64, 0x80, 0x80, 0xff, 0xc, 0x7f, 0x7f, 0xfc, 0x6a, 0x60, 0x94, 0xfb, 0xc0, 0xce, 0xcf, 0xc2, 0x80, 0x10, 0xfc, 0xc3, 0xf0, 0xf3, 0x23, 0xa3, 0xe2, 0x4f, 0xe, 0x36, 0x54, 0xc1, 0x1f, 0xbf, 0x18, 0x95, 0xbe, 0x73, 0x70, 0xb0, 0x30, 0xc0, 0x1, 0x48, 0xf0, 0x7, 0x85, 0x82, 0x58, 0x2d, 0xc2, 0xe6, 0xa4, 0x4f, 0x20, 0xc7, 0x37, 0x32, 0xb3, 0x23, 0x39, 0xfe, 0xfb, 0xaf, 0x46, 0x0, 0xee, 0x2a, 0x2f, 0xce, 0x4c, 0x47, 0x66, 0xf6, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char mini_checkerboard_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x98, 0xa0, 0xbd, 0x0, 0x0, 0x0, 0x17, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x78, 0x0, 0x5, 0xff, 0xa1, 0x60, 0xa0, 0x4, 0x60, 0xc, 0x98, 0xc4, 0x0, 0x9, 0x0, 0x0, 0x44, 0x81, 0xef, 0x81, 0xc1, 0x26, 0x8e, 0x8, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char option_arrow_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x4, 0x0, 0x0, 0x0, 0xfc, 0x7c, 0x94, 0x6c, 0x0, 0x0, 0x0, 0x3e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x2, 0xdc, 0x4f, 0xb8, 0x9f, 0x80, 0x45, 0xf8, 0xa1, 0xf6, 0x83, 0x2f, 0xf, 0xbe, 0x3c, 0xd4, 0x46, 0x13, 0x7e, 0xc1, 0xfd, 0xe0, 0xea, 0x83, 0xff, 0x40, 0x78, 0xf5, 0x5, 0x37, 0xaa, 0xfa, 0xf9, 0x40, 0x41, 0x30, 0x7c, 0x38, 0x9f, 0x81, 0x12, 0x80, 0x69, 0x14, 0x61, 0xcb, 0x11, 0xce, 0xc5, 0xe5, 0x41, 0xc2, 0x0, 0x0, 0x95, 0x48, 0x37, 0x91, 0x1f, 0xec, 0x77, 0x5, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char option_button_disabled_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x40, 0xde, 0x8d, 0x6b, 0x0, 0x0, 0x1, 0x2f, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x3f, 0x3f, 0x5a, 0x5a, 0x5a, 0x2b, 0x2b, 0x31, 0x2e, 0x2e, 0x34, 0x59, 0x59, 0x59, 0x2a, 0x2a, 0x30, 0x4b, 0x4b, 0x4b, 0x22, 0x22, 0x27, 0x35, 0x35, 0x35, 0x4a, 0x4a, 0x4a, 0x24, 0x24, 0x28, 0x24, 0x24, 0x29, 0x56, 0x56, 0x56, 0x62, 0x62, 0x62, 0x2a, 0x2a, 0x31, 0x2a, 0x2a, 0x30, 0x2d, 0x2d, 0x34, 0x2f, 0x2f, 0x36, 0x2e, 0x2e, 0x35, 0x2c, 0x2c, 0x32, 0x48, 0x48, 0x48, 0x44, 0x44, 0x44, 0x43, 0x43, 0x43, 0x54, 0x54, 0x54, 0x26, 0x26, 0x2b, 0x24, 0x24, 0x28, 0x27, 0x27, 0x2d, 0x29, 0x29, 0x2f, 0x28, 0x28, 0x2e, 0x25, 0x25, 0x2b, 0x23, 0x23, 0x28, 0x26, 0x26, 0x2c, 0x25, 0x25, 0x2a, 0x2a, 0x2a, 0x2f, 0x2b, 0x2b, 0x31, 0x22, 0x22, 0x26, 0x52, 0x52, 0x52, 0x42, 0x42, 0x42, 0x2d, 0x2d, 0x33, 0x22, 0x22, 0x27, 0x51, 0x51, 0x51, 0x40, 0x40, 0x40, 0x27, 0x27, 0x2b, 0x2e, 0x2e, 0x34, 0x2c, 0x2c, 0x31, 0x29, 0x29, 0x2e, 0x4f, 0x4f, 0x4f, 0x3f, 0x3f, 0x3f, 0x4d, 0x4d, 0x4d, 0x3e, 0x3e, 0x3e, 0x24, 0x24, 0x2a, 0x24, 0x24, 0x29, 0x20, 0x20, 0x25, 0x4c, 0x4c, 0x4c, 0x3d, 0x3d, 0x3d, 0x28, 0x28, 0x2d, 0x2b, 0x2b, 0x30, 0x29, 0x29, 0x2d, 0x20, 0x20, 0x23, 0x4a, 0x4a, 0x4a, 0x3b, 0x3b, 0x3b, 0x22, 0x22, 0x28, 0x27, 0x27, 0x2c, 0x1e, 0x1e, 0x22, 0x49, 0x49, 0x49, 0x3a, 0x3a, 0x3a, 0x21, 0x21, 0x26, 0x21, 0x21, 0x25, 0x23, 0x23, 0x27, 0x20, 0x20, 0x24, 0x1d, 0x1d, 0x21, 0x39, 0x39, 0x39, 0x47, 0x47, 0x47, 0x1f, 0x1f, 0x24, 0x1f, 0x1f, 0x23, 0x1e, 0x1e, 0x21, 0x46, 0x46, 0x46, 0xd3, 0xa7, 0xd4, 0x88, 0x0, 0x0, 0x0, 0x24, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x1d, 0x16, 0xd, 0x7, 0x2, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x43, 0x3a, 0x2d, 0x1b, 0x77, 0xef, 0xe6, 0x49, 0xef, 0xe6, 0xef, 0xe7, 0x77, 0xef, 0xe4, 0x4a, 0xba, 0xea, 0xc1, 0xeb, 0x0, 0x0, 0x0, 0xec, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x6c, 0x8e, 0x5, 0x4e, 0x0, 0x31, 0x10, 0x45, 0xff, 0xef, 0x56, 0xc2, 0xe2, 0xee, 0x4e, 0x3c, 0xc8, 0xd, 0xb8, 0x38, 0xa7, 0xc0, 0xdd, 0xdd, 0x5d, 0xbb, 0x94, 0x4c, 0xd2, 0xc1, 0xdf, 0x4a, 0x47, 0x5e, 0x27, 0xc3, 0xc, 0x80, 0x64, 0x24, 0xb8, 0xc7, 0x4f, 0x2c, 0x6b, 0xd5, 0x90, 0xff, 0xdd, 0x23, 0x7e, 0xc1, 0xa2, 0xb6, 0x64, 0xad, 0x26, 0x82, 0xc6, 0xef, 0x45, 0xbc, 0xe3, 0x1, 0x2c, 0x69, 0x9b, 0xc8, 0x7f, 0x5, 0x36, 0x1e, 0x41, 0x84, 0xd6, 0x4, 0x25, 0x90, 0xb7, 0x39, 0x6c, 0x4c, 0x2f, 0xbe, 0x68, 0xdf, 0x13, 0xa1, 0x9e, 0xc8, 0xa4, 0xb7, 0xe7, 0x47, 0x93, 0x63, 0x1b, 0xf9, 0xdc, 0x8, 0x88, 0x60, 0xbf, 0x4, 0xff, 0xd2, 0x56, 0x93, 0xe3, 0xb7, 0xb2, 0xf6, 0x2c, 0x36, 0x1, 0x16, 0xf4, 0x5f, 0x42, 0xc4, 0x17, 0x8f, 0xb5, 0xc0, 0xa5, 0x8, 0x30, 0x5f, 0xc2, 0x5d, 0xcf, 0xc9, 0xd, 0x74, 0x87, 0x8b, 0x5e, 0x56, 0x22, 0x24, 0xf7, 0x6d, 0xc2, 0xd1, 0x80, 0x26, 0x27, 0x5d, 0x5b, 0x67, 0x7d, 0x2f, 0x80, 0x4d, 0xc9, 0x7f, 0x9, 0x63, 0xa7, 0x61, 0x23, 0xc7, 0x74, 0x3d, 0xf, 0xae, 0x41, 0x84, 0x6f, 0x13, 0xe6, 0x26, 0xfa, 0x36, 0x46, 0x73, 0xbc, 0xba, 0x3b, 0xd6, 0xca, 0x8, 0xd0, 0xd6, 0x36, 0x4e, 0x35, 0xeb, 0xad, 0xd7, 0xb0, 0x60, 0x72, 0xdc, 0xda, 0x9c, 0x2, 0x67, 0x76, 0x64, 0x82, 0x99, 0x9b, 0xb6, 0x80, 0xb0, 0x7e, 0x8d, 0xf6, 0x5a, 0xdd, 0xe1, 0xb5, 0xba, 0xba, 0xb1, 0x0, 0xcd, 0xc7, 0x50, 0x23, 0xeb, 0xfb, 0x7f, 0xb4, 0xc8, 0x22, 0x18, 0xdd, 0x0, 0xd5, 0xec, 0x4e, 0x53, 0xc6, 0x18, 0x44, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char option_button_disabled_mirrored_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x40, 0xde, 0x8d, 0x6b, 0x0, 0x0, 0x1, 0x2f, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2d, 0x2d, 0x34, 0x2b, 0x2b, 0x31, 0x5a, 0x5a, 0x5a, 0x3e, 0x3e, 0x3e, 0x2a, 0x2a, 0x30, 0x59, 0x59, 0x59, 0x22, 0x22, 0x27, 0x4b, 0x4b, 0x4b, 0x22, 0x22, 0x29, 0x24, 0x24, 0x28, 0x4a, 0x4a, 0x4a, 0x36, 0x36, 0x36, 0x2a, 0x2a, 0x30, 0x2c, 0x2c, 0x32, 0x2d, 0x2d, 0x34, 0x2e, 0x2e, 0x35, 0x2f, 0x2f, 0x36, 0x2a, 0x2a, 0x31, 0x62, 0x62, 0x62, 0x56, 0x56, 0x56, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2b, 0x27, 0x27, 0x2d, 0x28, 0x28, 0x2e, 0x29, 0x29, 0x2f, 0x24, 0x24, 0x28, 0x26, 0x26, 0x2b, 0x54, 0x54, 0x54, 0x43, 0x43, 0x43, 0x44, 0x44, 0x44, 0x48, 0x48, 0x48, 0x22, 0x22, 0x26, 0x25, 0x25, 0x2a, 0x2a, 0x2a, 0x2f, 0x2b, 0x2b, 0x31, 0x26, 0x26, 0x2c, 0x22, 0x22, 0x27, 0x2d, 0x2d, 0x33, 0x52, 0x52, 0x52, 0x42, 0x42, 0x42, 0x27, 0x27, 0x2b, 0x29, 0x29, 0x2e, 0x2c, 0x2c, 0x31, 0x2e, 0x2e, 0x34, 0x51, 0x51, 0x51, 0x40, 0x40, 0x40, 0x4f, 0x4f, 0x4f, 0x3f, 0x3f, 0x3f, 0x20, 0x20, 0x25, 0x24, 0x24, 0x29, 0x24, 0x24, 0x2a, 0x4d, 0x4d, 0x4d, 0x3e, 0x3e, 0x3e, 0x20, 0x20, 0x23, 0x29, 0x29, 0x2d, 0x2b, 0x2b, 0x30, 0x28, 0x28, 0x2d, 0x4c, 0x4c, 0x4c, 0x3d, 0x3d, 0x3d, 0x1e, 0x1e, 0x22, 0x27, 0x27, 0x2c, 0x22, 0x22, 0x28, 0x4a, 0x4a, 0x4a, 0x3b, 0x3b, 0x3b, 0x1d, 0x1d, 0x21, 0x20, 0x20, 0x24, 0x23, 0x23, 0x27, 0x21, 0x21, 0x25, 0x21, 0x21, 0x26, 0x3a, 0x3a, 0x3a, 0x49, 0x49, 0x49, 0x1e, 0x1e, 0x21, 0x1f, 0x1f, 0x23, 0x1f, 0x1f, 0x24, 0x47, 0x47, 0x47, 0x39, 0x39, 0x39, 0x46, 0x46, 0x46, 0xda, 0x9d, 0x96, 0x5c, 0x0, 0x0, 0x0, 0x24, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x2, 0x7, 0xd, 0x16, 0x1d, 0x22, 0x24, 0x1f, 0x19, 0x11, 0xa, 0x4, 0x1b, 0x2d, 0x3a, 0x43, 0x48, 0x47, 0x46, 0x3f, 0x34, 0x25, 0x15, 0x49, 0xe6, 0xef, 0x77, 0xe6, 0xef, 0xe7, 0xef, 0x4a, 0xe4, 0xef, 0x77, 0x7e, 0xb9, 0x59, 0x66, 0x0, 0x0, 0x0, 0x1, 0x6f, 0x72, 0x4e, 0x54, 0x1, 0xcf, 0xa2, 0x77, 0x9a, 0x0, 0x0, 0x1, 0xf, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x85, 0xd1, 0xd9, 0x52, 0xc2, 0x30, 0x14, 0x80, 0xe1, 0x2a, 0x5a, 0x56, 0x97, 0xb2, 0xb9, 0xef, 0x50, 0x45, 0x4b, 0x6d, 0xe, 0x95, 0xa6, 0xa5, 0x40, 0xab, 0x15, 0x5, 0xdc, 0xc0, 0x8a, 0xa, 0xb8, 0xa1, 0xef, 0xff, 0xc, 0x86, 0x90, 0x30, 0xc, 0x17, 0xfa, 0x5d, 0x26, 0xff, 0x4c, 0x4e, 0x12, 0x41, 0x98, 0x32, 0x33, 0x1b, 0x98, 0x9b, 0x17, 0x83, 0x84, 0x18, 0xa, 0x47, 0xa2, 0xb1, 0xe9, 0x7d, 0x21, 0x16, 0x58, 0x58, 0x5c, 0x5a, 0x96, 0x24, 0x29, 0x9e, 0x48, 0xa6, 0xd2, 0x2b, 0x51, 0xb2, 0xb4, 0xba, 0x96, 0xc9, 0xca, 0x87, 0x47, 0x8c, 0x9c, 0xc9, 0x1d, 0x9f, 0x30, 0xeb, 0x1b, 0xe9, 0x8, 0x9, 0x36, 0x15, 0x25, 0xaf, 0x9e, 0x6a, 0x8c, 0x8a, 0xa0, 0xa0, 0x8f, 0x9c, 0x15, 0xb7, 0x52, 0x61, 0x12, 0xa8, 0x6, 0x56, 0x4d, 0x2b, 0xcb, 0x98, 0xb8, 0xc4, 0x3, 0x5d, 0x2f, 0x24, 0x43, 0xc3, 0xc0, 0x6, 0xcd, 0x2a, 0xcb, 0x4c, 0xe, 0x4a, 0x95, 0x2a, 0x57, 0x49, 0x88, 0x24, 0x70, 0xc, 0x70, 0xcf, 0xcb, 0x17, 0x8c, 0x5, 0x8e, 0x77, 0xc9, 0x79, 0xf1, 0x20, 0x9, 0x80, 0x4, 0xd6, 0x64, 0x50, 0xbb, 0xe2, 0x6a, 0xd2, 0x30, 0xc0, 0xd7, 0xf5, 0x89, 0x19, 0xb4, 0x46, 0xbe, 0x79, 0xc3, 0x35, 0x69, 0x80, 0x6e, 0x15, 0xb8, 0x33, 0xef, 0x99, 0x7, 0x84, 0x5a, 0x6d, 0xae, 0x45, 0x8f, 0xb0, 0x1f, 0xed, 0x86, 0x3f, 0xbe, 0xa6, 0x6f, 0x3f, 0x75, 0x9e, 0xb9, 0xe, 0x1d, 0xd2, 0x78, 0x79, 0xed, 0x62, 0xf0, 0x19, 0xdc, 0xeb, 0x17, 0xdf, 0xb8, 0x77, 0x7a, 0xcd, 0xed, 0x8f, 0xcf, 0x5e, 0xb7, 0x8e, 0x19, 0xe5, 0xab, 0x3f, 0xf8, 0x66, 0xda, 0x3b, 0xf4, 0xa1, 0x76, 0xf7, 0x90, 0xe3, 0x8e, 0x67, 0x70, 0x1, 0xbc, 0x9f, 0x91, 0xc1, 0xfe, 0x1, 0x7d, 0xea, 0x7f, 0x3f, 0xeb, 0xef, 0xef, 0xfe, 0x5, 0xd6, 0xe3, 0x56, 0x89, 0xd8, 0x62, 0xb6, 0x83, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char option_button_hover_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x40, 0xde, 0x8d, 0x6b, 0x0, 0x0, 0x1, 0x41, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x40, 0x4b, 0x5f, 0x5a, 0x6c, 0x2b, 0x2b, 0x31, 0x2e, 0x2e, 0x34, 0x5f, 0x5a, 0x6b, 0x2a, 0x2a, 0x30, 0x56, 0x53, 0x64, 0x22, 0x22, 0x27, 0x3e, 0x3b, 0x46, 0x57, 0x53, 0x63, 0x24, 0x24, 0x28, 0x24, 0x24, 0x29, 0x5b, 0x57, 0x68, 0x5a, 0x56, 0x67, 0x67, 0x63, 0x76, 0x2a, 0x2a, 0x31, 0x2a, 0x2a, 0x30, 0x2d, 0x2d, 0x34, 0x2f, 0x2f, 0x36, 0x2e, 0x2e, 0x35, 0x2c, 0x2c, 0x32, 0x4d, 0x4a, 0x57, 0x49, 0x46, 0x52, 0x48, 0x45, 0x51, 0x5a, 0x56, 0x65, 0x26, 0x26, 0x2b, 0x24, 0x24, 0x28, 0x27, 0x27, 0x2d, 0x29, 0x29, 0x2f, 0x28, 0x28, 0x2e, 0x25, 0x25, 0x2b, 0x23, 0x23, 0x28, 0x5b, 0x57, 0x66, 0x26, 0x26, 0x2c, 0x25, 0x25, 0x2a, 0x2a, 0x2a, 0x2f, 0x2b, 0x2b, 0x31, 0x22, 0x22, 0x26, 0x59, 0x55, 0x64, 0x47, 0x44, 0x50, 0x2d, 0x2d, 0x33, 0x22, 0x22, 0x27, 0x58, 0x54, 0x64, 0x46, 0x43, 0x50, 0x27, 0x27, 0x2b, 0x2e, 0x2e, 0x34, 0x2c, 0x2c, 0x31, 0x29, 0x29, 0x2e, 0x56, 0x53, 0x63, 0x45, 0x42, 0x4f, 0x56, 0x53, 0x62, 0x45, 0x42, 0x4e, 0x24, 0x24, 0x2a, 0x24, 0x24, 0x29, 0x20, 0x20, 0x25, 0x55, 0x51, 0x62, 0x44, 0x41, 0x4e, 0x28, 0x28, 0x2d, 0x2b, 0x2b, 0x30, 0x29, 0x29, 0x2d, 0x20, 0x20, 0x23, 0x55, 0x51, 0x60, 0x44, 0x41, 0x4d, 0x22, 0x22, 0x28, 0x27, 0x27, 0x2c, 0x1e, 0x1e, 0x22, 0x43, 0x40, 0x4c, 0x54, 0x50, 0x5f, 0x21, 0x21, 0x26, 0x21, 0x21, 0x25, 0x23, 0x23, 0x27, 0x20, 0x20, 0x24, 0x1d, 0x1d, 0x21, 0x47, 0x43, 0x51, 0x43, 0x3f, 0x4d, 0x42, 0x3f, 0x4c, 0x53, 0x4f, 0x5f, 0x1f, 0x1f, 0x24, 0x1f, 0x1f, 0x23, 0x1e, 0x1e, 0x21, 0x53, 0x50, 0x5f, 0x53, 0x4f, 0x5e, 0x5f, 0x5a, 0x6c, 0xd3, 0x26, 0x54, 0x35, 0x0, 0x0, 0x0, 0x24, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x1d, 0x16, 0xd, 0x7, 0x2, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x43, 0x3a, 0x2d, 0x1b, 0x77, 0xef, 0xe6, 0x49, 0xef, 0xe6, 0xef, 0xe7, 0x77, 0xef, 0xe4, 0x4a, 0xba, 0xea, 0xc1, 0xeb, 0x0, 0x0, 0x0, 0xe5, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x85, 0x91, 0x43, 0x62, 0xc5, 0x60, 0x18, 0x45, 0xef, 0x8d, 0x51, 0xdb, 0xee, 0x46, 0xca, 0x6d, 0x77, 0x58, 0xce, 0x6b, 0xdb, 0x7c, 0x8a, 0xad, 0xea, 0x44, 0x1f, 0x4e, 0x92, 0x1f, 0x4c, 0x0, 0xe0, 0x9, 0x61, 0xf0, 0x89, 0x32, 0x12, 0xcd, 0xd4, 0x8, 0xef, 0x1f, 0x35, 0x54, 0xa0, 0x68, 0x1a, 0x34, 0x89, 0x8, 0x86, 0xa4, 0xd, 0x57, 0xb4, 0xdf, 0x79, 0x5, 0x89, 0x94, 0xba, 0xf9, 0xb3, 0xc0, 0xce, 0xeb, 0xf0, 0x17, 0x1c, 0xab, 0x11, 0x9, 0x1a, 0xf9, 0x96, 0x84, 0x5d, 0x5e, 0x43, 0x15, 0x7, 0x2e, 0x42, 0x41, 0x51, 0xd3, 0xbe, 0x67, 0xd5, 0x6b, 0x42, 0x3a, 0x38, 0x9b, 0xf5, 0x2e, 0x20, 0xfa, 0x5, 0x33, 0x41, 0x69, 0xf4, 0xeb, 0x49, 0x6c, 0x19, 0xe6, 0xbd, 0xdd, 0xd, 0x48, 0xa0, 0x92, 0xb, 0x36, 0x72, 0x6a, 0x26, 0xf0, 0x14, 0xa, 0x10, 0x72, 0xe1, 0x7d, 0xf4, 0xf6, 0x35, 0x1b, 0xc3, 0xe3, 0x18, 0x9d, 0x50, 0xf0, 0xe4, 0xc2, 0x17, 0xae, 0x27, 0xd3, 0xe4, 0x6e, 0xe8, 0xf8, 0x7e, 0xbc, 0x1, 0x48, 0x9e, 0x57, 0xf8, 0xc5, 0xfc, 0xbd, 0x7a, 0x98, 0xc4, 0x94, 0x47, 0xbf, 0xe4, 0xce, 0x48, 0x8, 0x6e, 0x69, 0x91, 0x63, 0x47, 0x73, 0x49, 0xbc, 0x77, 0x3e, 0xd7, 0x4b, 0x3b, 0x12, 0x36, 0x16, 0xb3, 0x85, 0x6a, 0x68, 0xce, 0x39, 0x62, 0xc6, 0xba, 0x3d, 0x8d, 0xe7, 0x91, 0x20, 0xac, 0xad, 0xa6, 0xc2, 0xe, 0x6, 0xcc, 0x74, 0xc, 0x2d, 0xe7, 0xf9, 0x55, 0x2, 0x28, 0x94, 0x37, 0xab, 0xee, 0xa1, 0xcc, 0xbf, 0xdb, 0xed, 0x3, 0x70, 0xe6, 0x4f, 0x4a, 0xc3, 0xed, 0xed, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char option_button_hover_mirrored_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x40, 0xde, 0x8d, 0x6b, 0x0, 0x0, 0x1, 0x41, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2d, 0x2d, 0x34, 0x2b, 0x2b, 0x31, 0x5f, 0x5a, 0x6c, 0x42, 0x40, 0x4b, 0x2a, 0x2a, 0x30, 0x5f, 0x5a, 0x6b, 0x22, 0x22, 0x27, 0x56, 0x53, 0x64, 0x22, 0x22, 0x29, 0x24, 0x24, 0x28, 0x57, 0x53, 0x63, 0x3e, 0x3c, 0x47, 0x2a, 0x2a, 0x30, 0x2c, 0x2c, 0x32, 0x2d, 0x2d, 0x34, 0x2e, 0x2e, 0x35, 0x2f, 0x2f, 0x36, 0x2a, 0x2a, 0x31, 0x67, 0x63, 0x76, 0x5a, 0x56, 0x67, 0x5b, 0x57, 0x68, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2b, 0x27, 0x27, 0x2d, 0x28, 0x28, 0x2e, 0x29, 0x29, 0x2f, 0x24, 0x24, 0x28, 0x26, 0x26, 0x2b, 0x5a, 0x56, 0x65, 0x48, 0x45, 0x51, 0x49, 0x46, 0x52, 0x4d, 0x4a, 0x57, 0x22, 0x22, 0x26, 0x25, 0x25, 0x2a, 0x2a, 0x2a, 0x2f, 0x2b, 0x2b, 0x31, 0x26, 0x26, 0x2c, 0x5b, 0x57, 0x66, 0x22, 0x22, 0x27, 0x2d, 0x2d, 0x33, 0x59, 0x55, 0x64, 0x47, 0x44, 0x50, 0x27, 0x27, 0x2b, 0x29, 0x29, 0x2e, 0x2c, 0x2c, 0x31, 0x2e, 0x2e, 0x34, 0x58, 0x54, 0x64, 0x46, 0x43, 0x50, 0x56, 0x53, 0x63, 0x45, 0x42, 0x4f, 0x20, 0x20, 0x25, 0x24, 0x24, 0x29, 0x24, 0x24, 0x2a, 0x56, 0x53, 0x62, 0x45, 0x42, 0x4e, 0x20, 0x20, 0x23, 0x29, 0x29, 0x2d, 0x2b, 0x2b, 0x30, 0x28, 0x28, 0x2d, 0x55, 0x51, 0x62, 0x44, 0x41, 0x4e, 0x1e, 0x1e, 0x22, 0x27, 0x27, 0x2c, 0x22, 0x22, 0x28, 0x55, 0x51, 0x60, 0x44, 0x41, 0x4d, 0x1d, 0x1d, 0x21, 0x20, 0x20, 0x24, 0x23, 0x23, 0x27, 0x21, 0x21, 0x25, 0x21, 0x21, 0x26, 0x54, 0x50, 0x5f, 0x43, 0x40, 0x4c, 0x1e, 0x1e, 0x21, 0x1f, 0x1f, 0x23, 0x1f, 0x1f, 0x24, 0x53, 0x4f, 0x5f, 0x42, 0x3f, 0x4c, 0x43, 0x3f, 0x4d, 0x47, 0x43, 0x51, 0x5f, 0x5a, 0x6c, 0x53, 0x4f, 0x5e, 0x53, 0x50, 0x5f, 0x68, 0x6, 0xa3, 0x65, 0x0, 0x0, 0x0, 0x24, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x2, 0x7, 0xd, 0x16, 0x1d, 0x22, 0x24, 0x1f, 0x19, 0x11, 0xa, 0x4, 0x1b, 0x2d, 0x3a, 0x43, 0x48, 0x47, 0x46, 0x3f, 0x34, 0x25, 0x15, 0x49, 0xe6, 0xef, 0x77, 0xe6, 0xef, 0xe7, 0xef, 0x4a, 0xe4, 0xef, 0x77, 0x7e, 0xb9, 0x59, 0x66, 0x0, 0x0, 0x0, 0x1, 0x6f, 0x72, 0x4e, 0x54, 0x1, 0xcf, 0xa2, 0x77, 0x9a, 0x0, 0x0, 0x1, 0x15, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x85, 0xd1, 0xd9, 0x52, 0xc2, 0x30, 0x14, 0x80, 0xe1, 0x2a, 0x5a, 0x56, 0x97, 0xb2, 0xb9, 0x8b, 0xb, 0x54, 0x51, 0x4b, 0x6d, 0x8f, 0x60, 0xd3, 0x62, 0xc1, 0x56, 0x11, 0x5, 0xdc, 0xd0, 0x5a, 0x14, 0x70, 0x5f, 0xdf, 0xff, 0x1, 0xc, 0x69, 0xc2, 0x30, 0x5c, 0xe8, 0x77, 0x99, 0xfc, 0x33, 0x39, 0x49, 0x38, 0x6e, 0xc8, 0xc8, 0xa8, 0x6f, 0x6c, 0x9c, 0xf7, 0x63, 0x7c, 0x20, 0x18, 0xa, 0x47, 0x86, 0xf7, 0xb9, 0x88, 0x6f, 0x62, 0x72, 0x6a, 0x5a, 0x10, 0x84, 0x68, 0x2c, 0x9e, 0x48, 0xce, 0x84, 0xf1, 0xd2, 0xec, 0x5c, 0x3a, 0x23, 0x6e, 0x6c, 0x52, 0x62, 0x3a, 0xbb, 0xb5, 0xed, 0xd9, 0x99, 0x5f, 0x48, 0x86, 0x70, 0xb0, 0x28, 0x49, 0x39, 0x79, 0x57, 0xa1, 0x64, 0x15, 0xf6, 0xf2, 0x9e, 0xc2, 0xfe, 0x52, 0x22, 0x88, 0x3, 0x59, 0x43, 0xb2, 0x6e, 0x64, 0x28, 0x1d, 0x15, 0x59, 0x90, 0x2f, 0x1c, 0xc4, 0x3, 0xbd, 0xc0, 0x4, 0xc5, 0x28, 0x89, 0x54, 0x16, 0x8a, 0xe5, 0x43, 0xa6, 0x1c, 0xe3, 0x71, 0x60, 0x69, 0x60, 0x1f, 0x95, 0x8e, 0x29, 0x3, 0xac, 0xca, 0x9, 0x53, 0x89, 0xfa, 0x71, 0x0, 0x38, 0x30, 0x6, 0x83, 0xea, 0x29, 0x53, 0x15, 0x7a, 0x1, 0x3a, 0xab, 0xd, 0xcc, 0xa0, 0xd4, 0x73, 0x8d, 0x73, 0xa6, 0x41, 0x2, 0xf5, 0x42, 0x82, 0x4b, 0xfd, 0x8a, 0xba, 0x56, 0xd5, 0xe6, 0xd, 0xd3, 0x24, 0x47, 0x98, 0xb7, 0x66, 0xdd, 0xe9, 0x5f, 0xd3, 0x31, 0xef, 0xdc, 0x16, 0xe3, 0x92, 0x21, 0xb5, 0xfb, 0x87, 0x36, 0x2, 0x87, 0x42, 0x9d, 0xee, 0xe3, 0x13, 0xd5, 0x72, 0xc9, 0x35, 0x97, 0x9f, 0x5f, 0x3a, 0xed, 0x1a, 0xa2, 0xa4, 0xd7, 0xee, 0xdb, 0xbb, 0xe7, 0xe3, 0x33, 0x45, 0x1e, 0x6a, 0x65, 0x55, 0xb5, 0xec, 0xfe, 0xc, 0x36, 0xc0, 0xd7, 0xb7, 0xe7, 0x67, 0x6d, 0x9d, 0x3c, 0xf5, 0xbf, 0x9f, 0xf5, 0xf7, 0x77, 0xff, 0x2, 0xa7, 0xc5, 0x58, 0xc8, 0x6e, 0x59, 0x8, 0x3, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char option_button_normal_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x40, 0xde, 0x8d, 0x6b, 0x0, 0x0, 0x1, 0x41, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x3a, 0x44, 0x56, 0x53, 0x61, 0x2b, 0x2b, 0x31, 0x2e, 0x2e, 0x34, 0x56, 0x52, 0x60, 0x2a, 0x2a, 0x30, 0x47, 0x44, 0x52, 0x22, 0x22, 0x27, 0x33, 0x31, 0x39, 0x47, 0x44, 0x50, 0x24, 0x24, 0x28, 0x24, 0x24, 0x29, 0x52, 0x50, 0x5d, 0x51, 0x4f, 0x5d, 0x5d, 0x5a, 0x6a, 0x2a, 0x2a, 0x31, 0x2a, 0x2a, 0x30, 0x2d, 0x2d, 0x34, 0x2f, 0x2f, 0x36, 0x2e, 0x2e, 0x35, 0x2c, 0x2c, 0x32, 0x46, 0x42, 0x4e, 0x42, 0x3e, 0x4a, 0x41, 0x3e, 0x49, 0x51, 0x4e, 0x5b, 0x26, 0x26, 0x2b, 0x24, 0x24, 0x28, 0x27, 0x27, 0x2d, 0x29, 0x29, 0x2f, 0x28, 0x28, 0x2e, 0x25, 0x25, 0x2b, 0x23, 0x23, 0x28, 0x40, 0x3e, 0x48, 0x50, 0x4e, 0x5a, 0x26, 0x26, 0x2c, 0x25, 0x25, 0x2a, 0x2a, 0x2a, 0x2f, 0x2b, 0x2b, 0x31, 0x22, 0x22, 0x26, 0x4f, 0x4c, 0x59, 0x3f, 0x3d, 0x47, 0x2d, 0x2d, 0x33, 0x22, 0x22, 0x27, 0x4e, 0x4a, 0x58, 0x3e, 0x3b, 0x46, 0x27, 0x27, 0x2b, 0x2e, 0x2e, 0x34, 0x2c, 0x2c, 0x31, 0x29, 0x29, 0x2e, 0x4b, 0x49, 0x55, 0x3c, 0x3a, 0x44, 0x4a, 0x47, 0x54, 0x3b, 0x39, 0x43, 0x24, 0x24, 0x2a, 0x24, 0x24, 0x29, 0x20, 0x20, 0x25, 0x49, 0x46, 0x53, 0x3a, 0x38, 0x42, 0x28, 0x28, 0x2d, 0x2b, 0x2b, 0x30, 0x29, 0x29, 0x2d, 0x20, 0x20, 0x23, 0x47, 0x45, 0x50, 0x39, 0x37, 0x40, 0x22, 0x22, 0x28, 0x27, 0x27, 0x2c, 0x1e, 0x1e, 0x22, 0x47, 0x43, 0x50, 0x38, 0x35, 0x3f, 0x46, 0x42, 0x4f, 0x21, 0x21, 0x26, 0x21, 0x21, 0x25, 0x23, 0x23, 0x27, 0x20, 0x20, 0x24, 0x1d, 0x1d, 0x21, 0x36, 0x34, 0x3e, 0x44, 0x41, 0x4e, 0x1f, 0x1f, 0x24, 0x1f, 0x1f, 0x23, 0x1e, 0x1e, 0x21, 0x44, 0x42, 0x4d, 0x44, 0x41, 0x4c, 0x4e, 0x4b, 0x58, 0x8, 0xd9, 0x10, 0xcb, 0x0, 0x0, 0x0, 0x24, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x1d, 0x16, 0xd, 0x7, 0x2, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x43, 0x3a, 0x2d, 0x1b, 0x77, 0xef, 0xe6, 0x49, 0xef, 0xe6, 0xef, 0xe7, 0x77, 0xef, 0xe4, 0x4a, 0xba, 0xea, 0xc1, 0xeb, 0x0, 0x0, 0x0, 0xe6, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x6c, 0xd1, 0x55, 0x5a, 0xc4, 0x30, 0x14, 0x5, 0xe0, 0x73, 0xea, 0x82, 0xbb, 0x3b, 0x6c, 0x80, 0x45, 0xb0, 0x70, 0x5e, 0xb1, 0x37, 0xdc, 0x75, 0xdc, 0x3d, 0x43, 0x2a, 0x5f, 0x3a, 0x7e, 0x6a, 0xc9, 0xbd, 0x7f, 0x9d, 0x2a, 0x0, 0xa4, 0x16, 0xd, 0xaa, 0x18, 0x8e, 0x41, 0x3f, 0x11, 0xd1, 0xbe, 0x52, 0xc7, 0x48, 0xa8, 0xfb, 0x5e, 0x68, 0xd4, 0x24, 0x96, 0x6a, 0xfc, 0xaf, 0x8b, 0x32, 0xbf, 0x61, 0x90, 0xc6, 0x3c, 0x27, 0x3, 0xce, 0xfe, 0x20, 0x2, 0x4b, 0xd2, 0x45, 0x1f, 0x14, 0xd5, 0x78, 0x5e, 0x36, 0x1c, 0x7d, 0xe5, 0x33, 0x2, 0xb3, 0x84, 0x8a, 0xec, 0xd4, 0xeb, 0x9a, 0x1a, 0x1b, 0x82, 0xf5, 0x79, 0x20, 0x2, 0x46, 0x1f, 0x58, 0x8d, 0x95, 0xe4, 0x6a, 0x1d, 0xcf, 0x4f, 0x89, 0x85, 0x10, 0x80, 0x56, 0x1f, 0x8, 0xf4, 0x53, 0xf7, 0x81, 0x6c, 0x4, 0xa0, 0xf5, 0x41, 0x69, 0xeb, 0xb7, 0xd0, 0x7b, 0x86, 0xcc, 0x36, 0xbb, 0x11, 0x90, 0x66, 0x1f, 0x88, 0xef, 0xbd, 0x64, 0x92, 0x5a, 0x7b, 0x4e, 0xed, 0x34, 0x42, 0x20, 0xa5, 0xd5, 0x7, 0x27, 0x69, 0xfb, 0x51, 0x8d, 0x69, 0x6e, 0xd5, 0xcc, 0xb9, 0x18, 0xf4, 0xaf, 0x40, 0x6e, 0x3f, 0x1d, 0xab, 0xf1, 0xdd, 0xc7, 0xf1, 0x12, 0x45, 0xc, 0xce, 0x4f, 0x17, 0x12, 0xd0, 0xb6, 0xc4, 0x87, 0x1a, 0x6f, 0x2f, 0x48, 0x8b, 0xef, 0x31, 0xd0, 0x6e, 0xce, 0xa8, 0xc0, 0x25, 0x56, 0x7d, 0x5, 0x52, 0xed, 0x6e, 0xae, 0x68, 0x0, 0xd4, 0x86, 0x7f, 0x56, 0x43, 0x62, 0x38, 0xc, 0x46, 0x28, 0xba, 0x1, 0x7a, 0xad, 0x4f, 0x59, 0x90, 0xab, 0xbf, 0xa4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char option_button_normal_mirrored_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x40, 0xde, 0x8d, 0x6b, 0x0, 0x0, 0x1, 0x41, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2d, 0x2d, 0x34, 0x2b, 0x2b, 0x31, 0x56, 0x53, 0x61, 0x3c, 0x3a, 0x45, 0x2a, 0x2a, 0x30, 0x56, 0x52, 0x60, 0x22, 0x22, 0x27, 0x47, 0x44, 0x52, 0x22, 0x22, 0x29, 0x24, 0x24, 0x28, 0x47, 0x44, 0x50, 0x33, 0x31, 0x3a, 0x2a, 0x2a, 0x30, 0x2c, 0x2c, 0x32, 0x2d, 0x2d, 0x34, 0x2e, 0x2e, 0x35, 0x2f, 0x2f, 0x36, 0x2a, 0x2a, 0x31, 0x5d, 0x5a, 0x6a, 0x51, 0x4f, 0x5d, 0x52, 0x50, 0x5d, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2b, 0x27, 0x27, 0x2d, 0x28, 0x28, 0x2e, 0x29, 0x29, 0x2f, 0x24, 0x24, 0x28, 0x26, 0x26, 0x2b, 0x51, 0x4e, 0x5b, 0x41, 0x3e, 0x49, 0x42, 0x3e, 0x4a, 0x46, 0x42, 0x4e, 0x22, 0x22, 0x26, 0x25, 0x25, 0x2a, 0x2a, 0x2a, 0x2f, 0x2b, 0x2b, 0x31, 0x26, 0x26, 0x2c, 0x50, 0x4e, 0x5a, 0x40, 0x3e, 0x48, 0x22, 0x22, 0x27, 0x2d, 0x2d, 0x33, 0x4f, 0x4c, 0x59, 0x3f, 0x3d, 0x47, 0x27, 0x27, 0x2b, 0x29, 0x29, 0x2e, 0x2c, 0x2c, 0x31, 0x2e, 0x2e, 0x34, 0x4e, 0x4a, 0x58, 0x3e, 0x3b, 0x46, 0x4b, 0x49, 0x55, 0x3c, 0x3a, 0x44, 0x20, 0x20, 0x25, 0x24, 0x24, 0x29, 0x24, 0x24, 0x2a, 0x4a, 0x47, 0x54, 0x3b, 0x39, 0x43, 0x20, 0x20, 0x23, 0x29, 0x29, 0x2d, 0x2b, 0x2b, 0x30, 0x28, 0x28, 0x2d, 0x49, 0x46, 0x53, 0x3a, 0x38, 0x42, 0x1e, 0x1e, 0x22, 0x27, 0x27, 0x2c, 0x22, 0x22, 0x28, 0x47, 0x45, 0x50, 0x39, 0x37, 0x40, 0x1d, 0x1d, 0x21, 0x20, 0x20, 0x24, 0x23, 0x23, 0x27, 0x21, 0x21, 0x25, 0x21, 0x21, 0x26, 0x46, 0x42, 0x4f, 0x38, 0x35, 0x3f, 0x47, 0x43, 0x50, 0x1e, 0x1e, 0x21, 0x1f, 0x1f, 0x23, 0x1f, 0x1f, 0x24, 0x44, 0x41, 0x4e, 0x36, 0x34, 0x3e, 0x4e, 0x4b, 0x58, 0x44, 0x41, 0x4c, 0x44, 0x42, 0x4d, 0x7d, 0x2e, 0xcf, 0xc5, 0x0, 0x0, 0x0, 0x24, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x2, 0x7, 0xd, 0x16, 0x1d, 0x22, 0x24, 0x1f, 0x19, 0x11, 0xa, 0x4, 0x1b, 0x2d, 0x3a, 0x43, 0x48, 0x47, 0x46, 0x3f, 0x34, 0x25, 0x15, 0x49, 0xe6, 0xef, 0x77, 0xe6, 0xef, 0xe7, 0xef, 0x4a, 0xe4, 0xef, 0x77, 0x7e, 0xb9, 0x59, 0x66, 0x0, 0x0, 0x0, 0x1, 0x6f, 0x72, 0x4e, 0x54, 0x1, 0xcf, 0xa2, 0x77, 0x9a, 0x0, 0x0, 0x1, 0x13, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x85, 0xd1, 0xd9, 0x52, 0xc2, 0x30, 0x14, 0x80, 0xe1, 0x2a, 0x5a, 0x56, 0x97, 0xb2, 0xb9, 0x8b, 0xb, 0x54, 0x51, 0x4b, 0x6d, 0xf, 0x68, 0xd3, 0xa2, 0x5, 0x5b, 0x40, 0x14, 0x70, 0x3, 0x2b, 0x2a, 0xe0, 0xbe, 0xbd, 0xff, 0x3, 0x18, 0xd2, 0x84, 0x61, 0xb8, 0xd0, 0xef, 0x32, 0xf9, 0x67, 0x72, 0x92, 0x70, 0xdc, 0x88, 0xb1, 0x71, 0xcf, 0xc4, 0x24, 0xef, 0xc5, 0x78, 0x9f, 0x3f, 0x10, 0xc, 0x8d, 0xee, 0x73, 0x21, 0xcf, 0xd4, 0xf4, 0xcc, 0xac, 0x20, 0x8, 0xe1, 0x48, 0x34, 0x16, 0x9f, 0xb, 0xe2, 0xa5, 0xf9, 0x85, 0x64, 0x4a, 0xdc, 0xda, 0xa6, 0xc4, 0x64, 0x7a, 0x67, 0xd7, 0xb5, 0xb7, 0xb8, 0x14, 0xf, 0xe0, 0x60, 0x59, 0x92, 0x32, 0xf2, 0xbe, 0x42, 0xc9, 0x2a, 0x64, 0x73, 0xae, 0x83, 0xc3, 0x95, 0x98, 0x1f, 0x7, 0xb2, 0x86, 0x64, 0xdd, 0x48, 0x51, 0x3a, 0xca, 0x1f, 0x1d, 0x53, 0xb9, 0x6c, 0xd4, 0xd7, 0xf, 0x4c, 0x50, 0x8c, 0x82, 0x48, 0xa5, 0x21, 0x5f, 0x3c, 0x61, 0x8a, 0x11, 0x1e, 0x7, 0x96, 0x6, 0x76, 0xa9, 0x50, 0xa6, 0xc, 0xb0, 0x2a, 0xa7, 0x4c, 0x25, 0xec, 0xc5, 0x1, 0xe0, 0xc0, 0x18, 0xe, 0xaa, 0x67, 0x4c, 0x55, 0xe8, 0x7, 0xe8, 0xbc, 0x36, 0x34, 0x83, 0x52, 0xcf, 0x34, 0x2e, 0x98, 0x6, 0x9, 0xd4, 0x4b, 0x9, 0xae, 0xf4, 0x6b, 0xea, 0x46, 0x55, 0x9b, 0x2d, 0xa6, 0x49, 0x8e, 0x30, 0x6f, 0xcd, 0xba, 0x33, 0xb8, 0xa6, 0x63, 0xde, 0xb5, 0xef, 0x99, 0x36, 0x19, 0x52, 0x7b, 0x78, 0xec, 0x20, 0x70, 0x28, 0xd4, 0xed, 0x3d, 0x3d, 0x33, 0x2f, 0xe4, 0x9a, 0xab, 0xaf, 0x6f, 0xdd, 0x4e, 0xd, 0x51, 0xd2, 0x7b, 0xef, 0xe3, 0x93, 0x6a, 0x25, 0xc8, 0x43, 0xad, 0xad, 0xab, 0x96, 0x3d, 0x98, 0xc1, 0x6, 0xf8, 0xfa, 0x76, 0xfd, 0x6c, 0x6c, 0x92, 0xa7, 0xfe, 0xf7, 0xb3, 0xfe, 0xfe, 0xee, 0x5f, 0xa1, 0x5f, 0x59, 0xbd, 0x75, 0x41, 0x2b, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char option_button_pressed_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x40, 0xde, 0x8d, 0x6b, 0x0, 0x0, 0x1, 0x4a, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x31, 0x2f, 0x37, 0x46, 0x43, 0x4f, 0x2b, 0x2b, 0x31, 0x2e, 0x2e, 0x34, 0x47, 0x44, 0x50, 0x2a, 0x2a, 0x30, 0x55, 0x52, 0x5f, 0x22, 0x22, 0x27, 0x3d, 0x3a, 0x45, 0x56, 0x52, 0x60, 0x24, 0x24, 0x28, 0x24, 0x24, 0x29, 0x43, 0x40, 0x4c, 0x42, 0x40, 0x4b, 0x4c, 0x49, 0x56, 0x2a, 0x2a, 0x31, 0x2a, 0x2a, 0x30, 0x2d, 0x2d, 0x34, 0x2f, 0x2f, 0x36, 0x2e, 0x2e, 0x35, 0x2c, 0x2c, 0x32, 0x3a, 0x38, 0x41, 0x36, 0x34, 0x3d, 0x44, 0x41, 0x4c, 0x26, 0x26, 0x2b, 0x24, 0x24, 0x28, 0x27, 0x27, 0x2d, 0x29, 0x29, 0x2f, 0x28, 0x28, 0x2e, 0x25, 0x25, 0x2b, 0x23, 0x23, 0x28, 0x44, 0x42, 0x4e, 0x36, 0x34, 0x3e, 0x44, 0x41, 0x4e, 0x26, 0x26, 0x2c, 0x25, 0x25, 0x2a, 0x2a, 0x2a, 0x2f, 0x2b, 0x2b, 0x31, 0x22, 0x22, 0x26, 0x46, 0x42, 0x4f, 0x38, 0x35, 0x3f, 0x2d, 0x2d, 0x33, 0x22, 0x22, 0x27, 0x47, 0x45, 0x50, 0x39, 0x37, 0x40, 0x27, 0x27, 0x2b, 0x2e, 0x2e, 0x34, 0x2c, 0x2c, 0x31, 0x29, 0x29, 0x2e, 0x49, 0x46, 0x53, 0x3a, 0x38, 0x42, 0x4a, 0x47, 0x54, 0x3b, 0x39, 0x43, 0x24, 0x24, 0x2a, 0x24, 0x24, 0x29, 0x20, 0x20, 0x25, 0x4b, 0x49, 0x55, 0x3c, 0x3a, 0x44, 0x28, 0x28, 0x2d, 0x2b, 0x2b, 0x30, 0x29, 0x29, 0x2d, 0x20, 0x20, 0x23, 0x4e, 0x4a, 0x58, 0x3e, 0x3b, 0x46, 0x22, 0x22, 0x28, 0x27, 0x27, 0x2c, 0x1e, 0x1e, 0x22, 0x50, 0x4d, 0x5a, 0x3f, 0x3d, 0x48, 0x3f, 0x3d, 0x47, 0x4f, 0x4c, 0x59, 0x21, 0x21, 0x26, 0x21, 0x21, 0x25, 0x23, 0x23, 0x27, 0x20, 0x20, 0x24, 0x1d, 0x1d, 0x21, 0x45, 0x42, 0x4d, 0x41, 0x3e, 0x49, 0x40, 0x3e, 0x48, 0x50, 0x4e, 0x5a, 0x1f, 0x1f, 0x24, 0x1f, 0x1f, 0x23, 0x1e, 0x1e, 0x21, 0x52, 0x4e, 0x5c, 0x51, 0x4e, 0x5b, 0x5d, 0x59, 0x69, 0x10, 0x9d, 0xe0, 0x3c, 0x0, 0x0, 0x0, 0x24, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x1d, 0x16, 0xd, 0x7, 0x2, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x43, 0x3a, 0x2d, 0x1b, 0x77, 0xef, 0xe6, 0x49, 0xef, 0xe6, 0xef, 0xe7, 0x77, 0xef, 0xe4, 0x4a, 0xba, 0xea, 0xc1, 0xeb, 0x0, 0x0, 0x0, 0xe6, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x6c, 0xcf, 0x3, 0x62, 0x4, 0x51, 0x10, 0x4, 0xd0, 0xaa, 0x31, 0x62, 0xdb, 0xb8, 0x49, 0x2e, 0x9e, 0x3b, 0xc4, 0xb6, 0x9d, 0xc5, 0x58, 0x1f, 0xc1, 0xd6, 0xe8, 0x77, 0xf7, 0x1b, 0x59, 0x6c, 0x2, 0x20, 0x37, 0xaa, 0xc5, 0x17, 0x7e, 0xc7, 0x62, 0x28, 0x45, 0x75, 0xfe, 0x6c, 0xe1, 0x4f, 0x68, 0x86, 0x41, 0x69, 0x44, 0x51, 0x4b, 0xb1, 0xce, 0xcc, 0xe4, 0x83, 0xd7, 0xb0, 0x48, 0x6b, 0x98, 0xe8, 0x9, 0x38, 0x70, 0x8b, 0xa, 0xcc, 0x12, 0x1a, 0xf0, 0x4d, 0xac, 0x87, 0xf3, 0x96, 0x6f, 0x8e, 0x5f, 0x56, 0xc0, 0x53, 0x20, 0x8f, 0xbf, 0xdb, 0x86, 0x58, 0x5b, 0x9, 0xbf, 0x47, 0x80, 0xa, 0x58, 0x1a, 0x38, 0xad, 0x9, 0x5f, 0xac, 0xe3, 0x20, 0xbc, 0x4b, 0x46, 0x4b, 0x0, 0x3a, 0x1a, 0x24, 0xd0, 0x69, 0x85, 0xc0, 0x63, 0x5, 0x60, 0x68, 0xf0, 0x36, 0x7f, 0xf3, 0xaa, 0xbe, 0xe1, 0x61, 0x81, 0x69, 0x5, 0x72, 0x5b, 0x83, 0xe4, 0x6a, 0x59, 0x16, 0xf7, 0x53, 0x47, 0x77, 0x8b, 0xad, 0x12, 0xe4, 0xb9, 0xa3, 0xc1, 0xe6, 0x83, 0x7b, 0x20, 0xd6, 0xb4, 0xe7, 0xbf, 0xed, 0xe1, 0x1a, 0xd8, 0xfa, 0xdf, 0xb9, 0x70, 0xb8, 0x21, 0xd6, 0xbb, 0x17, 0x1b, 0xe3, 0x4c, 0x6a, 0xb0, 0xbd, 0x25, 0x5, 0x3b, 0x5e, 0x7c, 0x21, 0xc0, 0xc2, 0x68, 0xee, 0xf1, 0xbc, 0x6, 0x46, 0xb1, 0xbd, 0x5e, 0x30, 0x5, 0x27, 0x19, 0x24, 0xb8, 0x61, 0x6e, 0xf8, 0xf5, 0xf7, 0xcd, 0x47, 0x16, 0xa0, 0x18, 0x13, 0x6a, 0x64, 0x7d, 0xff, 0x8f, 0x1e, 0x59, 0x84, 0xa2, 0x1b, 0x0, 0xe5, 0xe0, 0x4e, 0x46, 0x1d, 0x98, 0x92, 0x5c, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char option_button_pressed_mirrored_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x40, 0xde, 0x8d, 0x6b, 0x0, 0x0, 0x1, 0x4a, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2d, 0x2d, 0x34, 0x2b, 0x2b, 0x31, 0x46, 0x43, 0x4f, 0x31, 0x2f, 0x38, 0x2a, 0x2a, 0x30, 0x47, 0x44, 0x50, 0x22, 0x22, 0x27, 0x55, 0x52, 0x5f, 0x22, 0x22, 0x29, 0x24, 0x24, 0x28, 0x56, 0x52, 0x60, 0x3c, 0x3a, 0x45, 0x2a, 0x2a, 0x30, 0x2c, 0x2c, 0x32, 0x2d, 0x2d, 0x34, 0x2e, 0x2e, 0x35, 0x2f, 0x2f, 0x36, 0x2a, 0x2a, 0x31, 0x4c, 0x49, 0x56, 0x42, 0x40, 0x4b, 0x43, 0x40, 0x4c, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2b, 0x27, 0x27, 0x2d, 0x28, 0x28, 0x2e, 0x29, 0x29, 0x2f, 0x24, 0x24, 0x28, 0x26, 0x26, 0x2b, 0x44, 0x41, 0x4c, 0x36, 0x34, 0x3d, 0x3a, 0x38, 0x41, 0x22, 0x22, 0x26, 0x25, 0x25, 0x2a, 0x2a, 0x2a, 0x2f, 0x2b, 0x2b, 0x31, 0x26, 0x26, 0x2c, 0x44, 0x41, 0x4e, 0x36, 0x34, 0x3e, 0x44, 0x42, 0x4e, 0x22, 0x22, 0x27, 0x2d, 0x2d, 0x33, 0x46, 0x42, 0x4f, 0x38, 0x35, 0x3f, 0x27, 0x27, 0x2b, 0x29, 0x29, 0x2e, 0x2c, 0x2c, 0x31, 0x2e, 0x2e, 0x34, 0x47, 0x45, 0x50, 0x39, 0x37, 0x40, 0x49, 0x46, 0x53, 0x3a, 0x38, 0x42, 0x20, 0x20, 0x25, 0x24, 0x24, 0x29, 0x24, 0x24, 0x2a, 0x4a, 0x47, 0x54, 0x3b, 0x39, 0x43, 0x20, 0x20, 0x23, 0x29, 0x29, 0x2d, 0x2b, 0x2b, 0x30, 0x28, 0x28, 0x2d, 0x4b, 0x49, 0x55, 0x3c, 0x3a, 0x44, 0x1e, 0x1e, 0x22, 0x27, 0x27, 0x2c, 0x22, 0x22, 0x28, 0x4e, 0x4a, 0x58, 0x3e, 0x3b, 0x46, 0x1d, 0x1d, 0x21, 0x20, 0x20, 0x24, 0x23, 0x23, 0x27, 0x21, 0x21, 0x25, 0x21, 0x21, 0x26, 0x4f, 0x4c, 0x59, 0x3f, 0x3d, 0x47, 0x3f, 0x3d, 0x48, 0x50, 0x4d, 0x5a, 0x1e, 0x1e, 0x21, 0x1f, 0x1f, 0x23, 0x1f, 0x1f, 0x24, 0x50, 0x4e, 0x5a, 0x40, 0x3e, 0x48, 0x41, 0x3e, 0x49, 0x45, 0x42, 0x4d, 0x5d, 0x59, 0x69, 0x51, 0x4e, 0x5b, 0x52, 0x4e, 0x5c, 0x49, 0x7e, 0x80, 0x9, 0x0, 0x0, 0x0, 0x24, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x2, 0x7, 0xd, 0x16, 0x1d, 0x22, 0x24, 0x1f, 0x19, 0x11, 0xa, 0x4, 0x1b, 0x2d, 0x3a, 0x43, 0x48, 0x47, 0x46, 0x3f, 0x34, 0x25, 0x15, 0x49, 0xe6, 0xef, 0x77, 0xe6, 0xef, 0xe7, 0xef, 0x4a, 0xe4, 0xef, 0x77, 0x7e, 0xb9, 0x59, 0x66, 0x0, 0x0, 0x0, 0x1, 0x6f, 0x72, 0x4e, 0x54, 0x1, 0xcf, 0xa2, 0x77, 0x9a, 0x0, 0x0, 0x1, 0x14, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0x60, 0x40, 0x3, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x40, 0xc0, 0xc6, 0xc1, 0xc9, 0xc5, 0xcd, 0x83, 0x2e, 0xcf, 0xc0, 0xc3, 0xcc, 0xcb, 0xc7, 0x2f, 0x20, 0x28, 0x28, 0x28, 0x24, 0x2c, 0x22, 0x2a, 0x26, 0xce, 0xd, 0x14, 0x92, 0x90, 0x54, 0x51, 0x55, 0x53, 0xd7, 0x80, 0x2, 0x35, 0x15, 0x4d, 0x2d, 0x6d, 0x8, 0xd0, 0x91, 0x92, 0x16, 0xe3, 0x2, 0x2a, 0x90, 0xd1, 0xd5, 0xd5, 0xd3, 0x37, 0x30, 0x84, 0x2, 0x7d, 0x23, 0x63, 0x13, 0x53, 0x28, 0x30, 0x93, 0x15, 0xe5, 0x4, 0x2a, 0xd0, 0x37, 0xb7, 0xd0, 0xb7, 0xb4, 0x52, 0x85, 0x2, 0x4b, 0xb, 0x6b, 0x1b, 0x5b, 0x18, 0xb0, 0x13, 0xe1, 0x0, 0x29, 0xb0, 0x37, 0x36, 0xb4, 0x72, 0x50, 0x83, 0x2, 0x4d, 0x63, 0x6b, 0x47, 0x27, 0x18, 0x70, 0x14, 0x66, 0x3, 0x2a, 0x70, 0x36, 0x37, 0x76, 0x71, 0x75, 0x70, 0x83, 0x2, 0x2b, 0x63, 0x67, 0x77, 0xf, 0x18, 0x70, 0x17, 0x62, 0x7, 0x2a, 0x30, 0x6, 0x2a, 0xb0, 0x42, 0x56, 0xe0, 0xe9, 0x5, 0x3, 0x9e, 0x82, 0x20, 0x5, 0x16, 0xde, 0x3e, 0x48, 0x6e, 0x30, 0xf4, 0xd5, 0xf3, 0xf3, 0x87, 0x1, 0x3f, 0xb0, 0x2, 0xa3, 0x0, 0x5d, 0xe3, 0x40, 0xcb, 0x20, 0x28, 0x8, 0x36, 0x32, 0xa, 0x9, 0x85, 0x81, 0x10, 0xb0, 0x15, 0xf6, 0x61, 0xf6, 0xbe, 0xe1, 0x70, 0x6f, 0x86, 0xdb, 0x47, 0x44, 0x46, 0xc1, 0x40, 0x24, 0xd8, 0x91, 0xe6, 0xd1, 0x31, 0xb1, 0x16, 0xc6, 0xe1, 0x50, 0x60, 0x11, 0x17, 0x9f, 0x90, 0x8, 0x5, 0x49, 0xc9, 0x60, 0x6f, 0xca, 0xa5, 0xa4, 0xc6, 0xc5, 0xfa, 0x58, 0x40, 0x81, 0x6e, 0x5a, 0x7c, 0x7a, 0x6, 0x4, 0x64, 0x66, 0xc9, 0x83, 0x3, 0x4a, 0x41, 0xd1, 0xc8, 0xd9, 0x5, 0xee, 0x6, 0x17, 0x63, 0xe3, 0xec, 0x1c, 0x8, 0xc8, 0x55, 0x52, 0x6, 0x7, 0x35, 0xc1, 0xc8, 0xc2, 0x1f, 0xdd, 0x0, 0xa5, 0xe, 0x59, 0xe5, 0x7f, 0xe9, 0xa4, 0x40, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char overbright_indicator_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xe, 0xc3, 0x0, 0x0, 0xe, 0xc3, 0x1, 0xc7, 0x6f, 0xa8, 0x64, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x0, 0x0, 0x0, 0x5f, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xcd, 0xcd, 0x4b, 0xe, 0x80, 0x20, 0xc, 0x45, 0xd1, 0x9b, 0xea, 0xbe, 0x40, 0x97, 0x87, 0x8b, 0xae, 0x13, 0x34, 0x88, 0x1f, 0xa, 0x9d, 0xf8, 0x92, 0xe, 0xcf, 0x2d, 0x80, 0xda, 0x4f, 0x14, 0x26, 0x5, 0x49, 0x14, 0x53, 0xcb, 0x42, 0x58, 0xe, 0xbc, 0x51, 0xcd, 0x85, 0x9b, 0x81, 0x16, 0xfe, 0xc, 0x58, 0xf0, 0x6b, 0xc0, 0x8a, 0x1f, 0x3, 0x3d, 0xf8, 0x16, 0xe8, 0xc5, 0x97, 0x40, 0x81, 0x53, 0x9b, 0x55, 0x81, 0x91, 0xcf, 0x67, 0x20, 0xc6, 0x75, 0xe8, 0x73, 0x9e, 0xc, 0x7f, 0xce, 0x73, 0x61, 0x80, 0xd9, 0x83, 0x7f, 0xb0, 0x1d, 0xec, 0x30, 0xf0, 0x78, 0x5a, 0x7, 0xa8, 0x21, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char panel_bg_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x1, 0x3, 0x0, 0x0, 0x0, 0xfe, 0xc1, 0x2c, 0xc8, 0x0, 0x0, 0x0, 0x6, 0x50, 0x4c, 0x54, 0x45, 0x25, 0x25, 0x2a, 0x35, 0x32, 0x3b, 0x4a, 0x73, 0x58, 0x4a, 0x0, 0x0, 0x0, 0xa, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x40, 0x3, 0x0, 0x0, 0x10, 0x0, 0x1, 0xb3, 0xac, 0xe2, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char picker_cursor_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x4, 0x0, 0x0, 0x0, 0xfc, 0x7c, 0x94, 0x6c, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xe, 0xc3, 0x0, 0x0, 0xe, 0xc3, 0x1, 0xc7, 0x6f, 0xa8, 0x64, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x0, 0x0, 0x0, 0xb9, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x6d, 0x8f, 0x3d, 0x8a, 0xc2, 0x50, 0x18, 0x45, 0xcf, 0x6b, 0x92, 0x2a, 0x19, 0xd4, 0xa4, 0x72, 0x47, 0x3, 0x42, 0xc0, 0x9f, 0x55, 0x44, 0x17, 0x24, 0x88, 0xee, 0x24, 0x53, 0x4d, 0x7e, 0xa, 0xbf, 0x94, 0xd6, 0x71, 0x5, 0xf2, 0x5e, 0x7f, 0x2d, 0xa2, 0xa2, 0xe0, 0x29, 0xef, 0xb9, 0xcd, 0x1, 0x40, 0xb1, 0x76, 0x6a, 0x14, 0x14, 0xd4, 0x68, 0xab, 0x98, 0x11, 0xcd, 0xd5, 0xef, 0x9b, 0xac, 0x27, 0x10, 0x32, 0x3b, 0xb4, 0x32, 0xcd, 0xc7, 0x77, 0xff, 0xfb, 0xc7, 0xc0, 0x92, 0x84, 0x84, 0x82, 0xcb, 0xa2, 0x92, 0x29, 0x46, 0xbb, 0x7d, 0xc3, 0xc0, 0x94, 0x27, 0x13, 0x86, 0x63, 0xa7, 0x12, 0xb5, 0x59, 0xcf, 0x8a, 0x77, 0xd6, 0xb9, 0xa9, 0x46, 0xde, 0x5, 0x92, 0xf, 0x91, 0x3a, 0x2f, 0xff, 0x4d, 0xfc, 0x38, 0xaf, 0x1b, 0x6a, 0x33, 0xa3, 0xf8, 0x10, 0x9b, 0xfc, 0xac, 0x1a, 0x6d, 0xf, 0x2d, 0x17, 0x26, 0xaf, 0x79, 0xc6, 0xf5, 0xd4, 0xa9, 0x44, 0xb1, 0x6c, 0x51, 0x31, 0xb0, 0x26, 0x25, 0x65, 0xc3, 0xb5, 0xa8, 0x64, 0x8a, 0xc6, 0x40, 0x3b, 0x76, 0xb9, 0xb9, 0xe0, 0x42, 0x7e, 0x3e, 0x75, 0x8f, 0x40, 0x0, 0x45, 0x2a, 0x55, 0xcb, 0xcb, 0xeb, 0x5f, 0xa5, 0x22, 0x80, 0x3b, 0xa0, 0x2c, 0x6c, 0xa1, 0x40, 0x2f, 0xda, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char popup_bg_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0xa2, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3b, 0x3b, 0x43, 0x42, 0x42, 0x4b, 0x3e, 0x3e, 0x47, 0x3e, 0x3e, 0x46, 0x41, 0x41, 0x4a, 0x0, 0x0, 0x0, 0x3d, 0x3d, 0x45, 0x3b, 0x3b, 0x43, 0x3a, 0x3a, 0x42, 0x38, 0x38, 0x41, 0x37, 0x37, 0x3e, 0x36, 0x36, 0x3d, 0x35, 0x35, 0x3c, 0x0, 0x0, 0x0, 0x38, 0x38, 0x40, 0x38, 0x38, 0x40, 0x31, 0x31, 0x38, 0x34, 0x34, 0x3b, 0x34, 0x34, 0x3b, 0x39, 0x39, 0x3f, 0x31, 0x31, 0x38, 0x2f, 0x2f, 0x36, 0x2d, 0x2d, 0x33, 0x2c, 0x2c, 0x32, 0x2b, 0x2b, 0x31, 0x2a, 0x2a, 0x31, 0x2a, 0x2a, 0x30, 0x29, 0x29, 0x30, 0x29, 0x29, 0x2f, 0x28, 0x28, 0x2e, 0x28, 0x28, 0x2d, 0x27, 0x27, 0x2d, 0x27, 0x27, 0x2c, 0x29, 0x29, 0x2e, 0x26, 0x26, 0x2c, 0x36, 0xc6, 0xc8, 0x93, 0x0, 0x0, 0x0, 0x28, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x1, 0x3, 0x5, 0x8, 0xa, 0xb, 0x4, 0x13, 0x19, 0x1f, 0x22, 0x23, 0x16, 0x27, 0x35, 0x3f, 0x45, 0x46, 0x94, 0xf5, 0xfa, 0xfb, 0xf5, 0x40, 0xfc, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0x1a, 0xf5, 0xf6, 0x95, 0xfa, 0xfb, 0xf4, 0x94, 0x71, 0xda, 0xac, 0x92, 0x0, 0x0, 0x0, 0x7f, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x65, 0x8f, 0x35, 0x82, 0xc3, 0x0, 0xc, 0x4, 0x77, 0x24, 0x85, 0xba, 0xe3, 0xff, 0xff, 0xee, 0xca, 0x74, 0x41, 0xdb, 0x32, 0xf3, 0x94, 0x82, 0x85, 0x10, 0x1d, 0x92, 0xb2, 0x3, 0x8e, 0x95, 0x77, 0x93, 0x6c, 0x28, 0xed, 0x15, 0x54, 0x67, 0xa6, 0x41, 0x3e, 0x8, 0x9c, 0xc3, 0xf4, 0xf2, 0xf6, 0x2a, 0x80, 0xf8, 0x44, 0x2d, 0x79, 0x2d, 0x20, 0xe0, 0x2, 0xa8, 0xc3, 0x2e, 0x6f, 0xc, 0x9e, 0x4c, 0x3c, 0x21, 0x4, 0xd8, 0xf0, 0x2, 0x28, 0x24, 0xcd, 0x3, 0xa9, 0x19, 0x64, 0xce, 0x83, 0x4c, 0x45, 0xe6, 0x69, 0x1a, 0xd8, 0xe9, 0x99, 0x96, 0x7f, 0x77, 0x37, 0x59, 0x83, 0xcc, 0xef, 0x7f, 0x89, 0x1f, 0x8e, 0xbf, 0x95, 0xd3, 0x1d, 0xf0, 0xff, 0x7a, 0x63, 0x7e, 0x86, 0xcb, 0x73, 0x8c, 0x5e, 0xee, 0xca, 0xb1, 0xad, 0x5f, 0x3, 0xaf, 0xdb, 0x49, 0x94, 0x4b, 0x90, 0x40, 0xdf, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char popup_bg_disabled_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x78, 0x50, 0x4c, 0x54, 0x45, 0xff, 0x0, 0xff, 0x67, 0x7a, 0x85, 0x66, 0x7a, 0x86, 0x68, 0x7b, 0x86, 0x57, 0x51, 0x51, 0x4c, 0x42, 0x40, 0x4d, 0x43, 0x41, 0x56, 0x4c, 0x4b, 0x4d, 0x44, 0x41, 0x4e, 0x44, 0x42, 0x4f, 0x45, 0x43, 0x67, 0x7b, 0x87, 0x4f, 0x44, 0x43, 0x50, 0x45, 0x44, 0x52, 0x46, 0x44, 0x51, 0x46, 0x45, 0x4b, 0x40, 0x3f, 0x51, 0x47, 0x45, 0x52, 0x48, 0x46, 0x53, 0x48, 0x47, 0x4b, 0x41, 0x3f, 0x54, 0x49, 0x46, 0x55, 0x4a, 0x47, 0x55, 0x49, 0x47, 0x68, 0x7c, 0x88, 0x4a, 0x40, 0x3e, 0x55, 0x4b, 0x49, 0x56, 0x4d, 0x4b, 0x53, 0x49, 0x47, 0x50, 0x46, 0x44, 0x4a, 0x41, 0x3e, 0x48, 0x3e, 0x3c, 0x4b, 0x42, 0x3f, 0x49, 0x3f, 0x3d, 0x46, 0x3d, 0x3c, 0x47, 0x3d, 0x3b, 0x47, 0x3e, 0x3b, 0x49, 0x40, 0x3d, 0x45, 0x3c, 0x3b, 0x46, 0x3c, 0x3a, 0xdd, 0x63, 0x56, 0x8d, 0x0, 0x0, 0x0, 0xad, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x2d, 0x88, 0x35, 0x42, 0x4, 0x0, 0xc, 0x4, 0x77, 0x93, 0x9c, 0xbb, 0xf4, 0xc8, 0xff, 0xdf, 0x84, 0xb5, 0xb8, 0x5b, 0x84, 0x0, 0x37, 0xc5, 0xca, 0x10, 0xd, 0xc9, 0xce, 0xaa, 0xea, 0x24, 0x40, 0xca, 0x41, 0x64, 0x2b, 0x5, 0x87, 0x34, 0xa8, 0x88, 0x54, 0xef, 0x82, 0x80, 0x89, 0x34, 0x36, 0x96, 0xe0, 0x14, 0xa4, 0x12, 0xa6, 0x24, 0x18, 0xe1, 0xa8, 0x50, 0x59, 0x7c, 0x73, 0x30, 0x50, 0x55, 0x4a, 0x31, 0xd7, 0xb4, 0x89, 0xa1, 0x51, 0xb2, 0x9c, 0x1, 0x2c, 0x4, 0x83, 0x15, 0x12, 0x30, 0xab, 0xe9, 0x5a, 0x1, 0xb4, 0x40, 0xa1, 0x29, 0xbe, 0x75, 0xe, 0x5a, 0x70, 0xbe, 0x2a, 0xff, 0x12, 0xf1, 0xef, 0x1b, 0x5f, 0x8d, 0x5b, 0x68, 0xd, 0xdc, 0xe3, 0xf1, 0x71, 0x16, 0x3e, 0x5b, 0xc8, 0x33, 0xa9, 0xc7, 0xbc, 0x7f, 0xa4, 0x22, 0x6a, 0xb5, 0x90, 0xcb, 0xb2, 0x1a, 0x25, 0x67, 0x8b, 0x8f, 0x6f, 0xf8, 0x64, 0xa8, 0x35, 0x7a, 0x25, 0xa8, 0xa7, 0x1, 0x38, 0xc, 0xcc, 0xab, 0x4c, 0x5, 0xea, 0xe3, 0x76, 0x2f, 0x54, 0x93, 0xf3, 0xf, 0x4f, 0x10, 0x8d, 0x4c, 0x16, 0x9d, 0xcf, 0x1f, 0xd1, 0xf9, 0x3, 0x34, 0xc8, 0x4a, 0xb4, 0x1d, 0xb, 0xcd, 0x83, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char popup_window_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x0, 0x0, 0x48, 0x8, 0x3, 0x0, 0x0, 0x0, 0xb7, 0x21, 0x97, 0x38, 0x0, 0x0, 0x1, 0x71, 0x69, 0x43, 0x43, 0x50, 0x69, 0x63, 0x63, 0x0, 0x0, 0x28, 0x91, 0x75, 0x91, 0x3d, 0x4b, 0xc3, 0x50, 0x14, 0x86, 0xdf, 0xb6, 0x96, 0x8a, 0xad, 0x74, 0xd0, 0x41, 0xa4, 0x43, 0x86, 0x2a, 0xe, 0x2d, 0x14, 0x5, 0x71, 0xd4, 0x3a, 0x74, 0x29, 0x52, 0x6a, 0x5, 0xab, 0x2e, 0xc9, 0x6d, 0xd2, 0xa, 0x49, 0x1a, 0x6e, 0x52, 0xa4, 0xb8, 0xa, 0x2e, 0xe, 0x5, 0x7, 0xd1, 0xc5, 0xaf, 0xc1, 0x7f, 0xa0, 0xab, 0xe0, 0xaa, 0x20, 0x8, 0x8a, 0x20, 0xe2, 0xe2, 0x1f, 0xf0, 0x6b, 0x91, 0x12, 0xcf, 0x6d, 0xa, 0x2d, 0xd2, 0x9e, 0x70, 0x73, 0x1e, 0xde, 0x7b, 0xde, 0xc3, 0xbd, 0xe7, 0x2, 0xfe, 0xac, 0xce, 0xc, 0x7b, 0x20, 0x5, 0x18, 0xa6, 0xc3, 0xf3, 0x99, 0xb4, 0xb4, 0x5a, 0x5c, 0x93, 0x42, 0xef, 0x8, 0x21, 0x6, 0x1f, 0x82, 0x8, 0xcb, 0xcc, 0xb6, 0x16, 0x72, 0xb9, 0x2c, 0xfa, 0xc6, 0xcf, 0x23, 0x55, 0x52, 0x3c, 0x24, 0x45, 0xaf, 0xfe, 0x75, 0x3d, 0x23, 0x5c, 0x52, 0x6d, 0x6, 0xf8, 0x6, 0x89, 0x67, 0x99, 0xc5, 0x1d, 0xe2, 0x79, 0xe2, 0xec, 0x96, 0x63, 0x9, 0xde, 0x23, 0x1e, 0x65, 0x15, 0xb9, 0x44, 0x7c, 0x42, 0x9c, 0xe0, 0x74, 0x40, 0xe2, 0x5b, 0xa1, 0x2b, 0x1e, 0xbf, 0x9, 0x2e, 0x7b, 0xfc, 0x25, 0x98, 0x17, 0xf2, 0x8b, 0x80, 0x5f, 0xf4, 0x94, 0xca, 0x5d, 0xac, 0x74, 0x31, 0xab, 0x70, 0x83, 0x78, 0x8a, 0x38, 0x6e, 0xe8, 0x35, 0xd6, 0x3e, 0x8f, 0xb8, 0x49, 0x44, 0x35, 0x57, 0x96, 0x29, 0x8f, 0xd3, 0x8a, 0xc1, 0x46, 0x1e, 0x19, 0xa4, 0x21, 0x41, 0x41, 0xd, 0x9b, 0xd0, 0xe1, 0x20, 0x49, 0xd9, 0xa4, 0x99, 0xf5, 0xf6, 0xa5, 0x5a, 0xbe, 0x25, 0x54, 0xc9, 0xc3, 0xe8, 0x6f, 0xa1, 0xe, 0x4e, 0x8e, 0x32, 0x2a, 0xe4, 0x4d, 0x90, 0x5a, 0xa3, 0xae, 0x2a, 0x65, 0x8d, 0x74, 0x95, 0x3e, 0x1d, 0x75, 0x31, 0xf7, 0xff, 0xf3, 0xb4, 0xb5, 0x99, 0x69, 0xaf, 0x7b, 0x24, 0xd, 0x4, 0x5f, 0x5d, 0xf7, 0x73, 0x2, 0x8, 0xed, 0x3, 0xcd, 0x86, 0xeb, 0xfe, 0x9e, 0xba, 0x6e, 0xf3, 0xc, 0x8, 0xbc, 0x0, 0xd7, 0x66, 0xc7, 0x5f, 0xa5, 0x39, 0xcd, 0x7d, 0x93, 0xde, 0xe8, 0x68, 0xf1, 0x63, 0x20, 0xba, 0x3, 0x5c, 0xde, 0x74, 0x34, 0xe5, 0x0, 0xb8, 0xda, 0x5, 0xc6, 0x9e, 0x2d, 0x99, 0xcb, 0x2d, 0x29, 0x40, 0xcb, 0xaf, 0x69, 0xc0, 0xc7, 0x5, 0x30, 0x5c, 0x4, 0x46, 0xee, 0x81, 0xa1, 0x75, 0x6f, 0x56, 0xed, 0x7d, 0x9c, 0x3f, 0x1, 0x85, 0x6d, 0x7a, 0xa2, 0x3b, 0xe0, 0xf0, 0x8, 0x98, 0xa4, 0xfa, 0xe8, 0xc6, 0x1f, 0x7b, 0xde, 0x67, 0xcd, 0xda, 0x7, 0x3a, 0xfb, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x12, 0x0, 0x0, 0xb, 0x12, 0x1, 0xd2, 0xdd, 0x7e, 0xfc, 0x0, 0x0, 0x0, 0xa8, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe8, 0xe5, 0xf1, 0x20, 0x1e, 0x23, 0x21, 0x1f, 0x24, 0x21, 0x1f, 0x24, 0x22, 0x20, 0x25, 0x1d, 0x1a, 0x20, 0x1d, 0x1d, 0x20, 0x1d, 0x1d, 0x22, 0x20, 0x1d, 0x22, 0x20, 0x1d, 0x25, 0x20, 0x20, 0x25, 0x22, 0x20, 0x25, 0xcf, 0xcd, 0xd7, 0xd0, 0xcd, 0xd7, 0xd1, 0xce, 0xd8, 0xd3, 0xd0, 0xda, 0xd4, 0xd1, 0xdb, 0xd5, 0xd3, 0xdc, 0xd6, 0xd4, 0xdd, 0xd7, 0xd6, 0xdf, 0xd9, 0xd7, 0xdf, 0xda, 0xd8, 0xe0, 0xdc, 0xda, 0xe2, 0xdd, 0xdb, 0xe3, 0xde, 0xdc, 0xe4, 0xdf, 0xdd, 0xe5, 0xe0, 0xde, 0xe6, 0xe1, 0xdf, 0xe7, 0xe2, 0xdf, 0xeb, 0xe3, 0xe1, 0xe8, 0xe5, 0xe2, 0xeb, 0xe8, 0xe5, 0xf1, 0xe8, 0x4e, 0x48, 0xd9, 0x0, 0x0, 0x0, 0x24, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x3, 0x9, 0xc, 0xf, 0x15, 0x1d, 0x20, 0x22, 0x25, 0x30, 0x3a, 0x44, 0x52, 0x57, 0x59, 0x5b, 0x5e, 0x60, 0x7e, 0x92, 0x9e, 0x9f, 0xa1, 0xa2, 0xb8, 0xba, 0xbd, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf5, 0xb3, 0x97, 0xfb, 0x0, 0x0, 0x0, 0xea, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xed, 0x96, 0x31, 0xe, 0x83, 0x30, 0xc, 0x45, 0x6d, 0x93, 0xc2, 0xda, 0xb5, 0x13, 0xf7, 0x3f, 0x4a, 0xef, 0xd0, 0xa5, 0xc7, 0x28, 0x10, 0xff, 0xe, 0x4, 0x35, 0x88, 0xc6, 0x25, 0x48, 0x34, 0x2a, 0x6a, 0x16, 0x86, 0x3c, 0x7d, 0xbe, 0xfd, 0x49, 0x30, 0x51, 0xe1, 0xc5, 0xe1, 0xc1, 0xc2, 0xcc, 0xbc, 0xd8, 0x6, 0x0, 0x5, 0x22, 0x94, 0xa5, 0x72, 0xc2, 0x22, 0xb, 0x54, 0x15, 0x3a, 0x78, 0x5, 0x11, 0x91, 0x1b, 0xd1, 0xea, 0xd4, 0xf0, 0x1b, 0x59, 0x0, 0xc0, 0x83, 0x10, 0xa1, 0xe2, 0x9a, 0xba, 0x4d, 0x58, 0xbc, 0x13, 0x54, 0x23, 0x55, 0xe1, 0x36, 0x38, 0x5a, 0x14, 0xd3, 0xde, 0x64, 0x7c, 0x59, 0x40, 0x99, 0xc9, 0x27, 0x54, 0xdd, 0xe4, 0x4b, 0x26, 0x55, 0xa3, 0x49, 0x73, 0x55, 0x61, 0xc2, 0x3a, 0x94, 0xc8, 0x42, 0x27, 0x27, 0xaf, 0xc6, 0x7c, 0x4a, 0xcb, 0x85, 0xaa, 0xea, 0x34, 0x5a, 0xf7, 0xcc, 0xd8, 0xa0, 0x7a, 0x5c, 0x34, 0x23, 0x82, 0x1d, 0xd2, 0xda, 0x11, 0x3d, 0xaf, 0x45, 0xdd, 0x35, 0x89, 0x5c, 0x6, 0x1f, 0x9d, 0x2, 0xfb, 0xaa, 0x98, 0x1d, 0x98, 0x2, 0x68, 0x13, 0x32, 0x90, 0xf5, 0xd7, 0xdb, 0x6, 0xd4, 0x8, 0x0, 0xf4, 0xd, 0x3, 0xc5, 0xcb, 0xfa, 0xa5, 0xe, 0x1c, 0x34, 0xad, 0xff, 0xe7, 0x72, 0x44, 0x14, 0x40, 0x97, 0x46, 0x3a, 0x8c, 0x63, 0xcd, 0x9e, 0x69, 0x41, 0x2d, 0x34, 0x6c, 0xe6, 0xa3, 0xb0, 0x50, 0x64, 0xab, 0x86, 0x3f, 0x82, 0xb3, 0xc6, 0xc7, 0x7e, 0x88, 0x66, 0x42, 0x78, 0x82, 0x31, 0x94, 0x22, 0x77, 0xd4, 0x2d, 0xbe, 0x9e, 0x25, 0x9d, 0x7b, 0xb0, 0x59, 0x6d, 0x9f, 0xd7, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char progress_bar_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2d, 0x2c, 0x2f, 0x48, 0x46, 0x4a, 0x4c, 0x4a, 0x4e, 0x48, 0x46, 0x4a, 0x40, 0x3e, 0x42, 0x38, 0x36, 0x3a, 0x43, 0x65, 0x7d, 0x95, 0x0, 0x0, 0x0, 0xc, 0x74, 0x52, 0x4e, 0x53, 0xa, 0x1a, 0x26, 0x29, 0x2a, 0x48, 0x65, 0x6d, 0x6e, 0x66, 0xf5, 0xfe, 0xb7, 0x4a, 0xbe, 0x33, 0x0, 0x0, 0x0, 0x35, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x64, 0x54, 0x52, 0x64, 0x60, 0x60, 0x78, 0x77, 0x8f, 0x51, 0x34, 0x8, 0xcc, 0xb8, 0xcd, 0xa8, 0xd9, 0x4, 0x66, 0xdc, 0x60, 0x74, 0x9f, 0xe, 0x66, 0xb4, 0x33, 0x7a, 0xb4, 0x1b, 0x0, 0x19, 0x7f, 0x3b, 0x28, 0x64, 0xc0, 0xd, 0x84, 0x5b, 0x1, 0xb7, 0x14, 0xee, 0xc, 0x0, 0xcf, 0x9d, 0x26, 0xff, 0xba, 0xcb, 0x90, 0x39, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char progress_fill_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x37, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x18, 0x4c, 0xc0, 0xc1, 0xc2, 0xf8, 0xa5, 0xfa, 0x7f, 0x8, 0x34, 0x7e, 0xe9, 0x60, 0x81, 0xa1, 0xc0, 0xf8, 0xa5, 0xca, 0x17, 0x85, 0xff, 0x10, 0xa8, 0xf2, 0xc5, 0xf8, 0x25, 0x86, 0x2, 0x75, 0xa0, 0x4, 0x1c, 0x2, 0x4d, 0xa1, 0xbf, 0x2, 0x4c, 0x47, 0x12, 0xf6, 0xe6, 0x20, 0x2, 0x0, 0x78, 0x21, 0x45, 0x61, 0x7f, 0xe2, 0xad, 0xaf, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char radio_checked_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x42, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4, 0x3, 0x4, 0x9, 0x9, 0x9, 0x6, 0x6, 0x6, 0xa, 0xa, 0xb, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x7f, 0x7f, 0x82, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0x47, 0x47, 0x48, 0xd3, 0xd3, 0xd3, 0xa2, 0xa2, 0xa2, 0x79, 0x79, 0x79, 0x73, 0x73, 0x73, 0x1c, 0x1c, 0x1c, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0xd1, 0xa7, 0xf5, 0xaa, 0x0, 0x0, 0x0, 0xb, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x88, 0xd1, 0xf7, 0x64, 0xf6, 0x2, 0xb3, 0xed, 0xd7, 0x0, 0x0, 0x0, 0x63, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x6d, 0x4f, 0x55, 0x2, 0x43, 0x31, 0x8, 0x4b, 0xe8, 0x6a, 0xf7, 0xbf, 0xeb, 0xc, 0x9b, 0x6b, 0x1f, 0x9f, 0xc4, 0x89, 0xbf, 0xbb, 0x3f, 0x2a, 0x49, 0x64, 0xa6, 0x3e, 0x1e, 0x1c, 0x7c, 0x3e, 0xf2, 0x14, 0xb7, 0xc7, 0xac, 0xf1, 0x10, 0xa6, 0xe8, 0x1, 0x44, 0xad, 0x42, 0xb9, 0x33, 0x22, 0x43, 0x95, 0x68, 0x55, 0xa4, 0xdc, 0x1f, 0x1e, 0xa1, 0x67, 0xa2, 0x57, 0x96, 0x22, 0x0, 0xc2, 0x3d, 0xf5, 0x44, 0x8c, 0x8a, 0x5d, 0x21, 0x80, 0x74, 0x83, 0x1e, 0x97, 0xc7, 0x22, 0x59, 0x4c, 0xd7, 0xd8, 0xb5, 0x18, 0x4a, 0x7b, 0x57, 0x57, 0xdb, 0x1a, 0xf7, 0x77, 0x17, 0x3a, 0x56, 0x4e, 0x11, 0x6f, 0x82, 0x20, 0xde, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char radio_checked_disabled_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x45, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x3, 0x4, 0x9, 0x9, 0x9, 0x6, 0x6, 0x6, 0xa, 0xa, 0xb, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x7f, 0x7f, 0x82, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0x47, 0x47, 0x48, 0xd3, 0xd3, 0xd3, 0xa2, 0xa2, 0xa2, 0x79, 0x79, 0x79, 0x73, 0x73, 0x73, 0x1c, 0x1c, 0x1c, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x83, 0xac, 0xe9, 0xaf, 0x0, 0x0, 0x0, 0x1, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x40, 0xe6, 0xd8, 0x66, 0x0, 0x0, 0x0, 0x3f, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x63, 0x60, 0x20, 0xe, 0xf0, 0x8, 0x2, 0x1, 0xf, 0x9c, 0x2b, 0x2c, 0x8, 0x5, 0xc2, 0x50, 0x1, 0xb0, 0x34, 0x58, 0x11, 0x5c, 0xbd, 0x10, 0x3f, 0x10, 0x8, 0xc1, 0x74, 0x1, 0x65, 0xf8, 0xc1, 0x0, 0xa6, 0x4, 0x28, 0x1, 0x11, 0xe0, 0xc1, 0x2d, 0x80, 0xa6, 0x5, 0xc3, 0x50, 0xc, 0x6b, 0x31, 0x1d, 0x86, 0xe1, 0x74, 0xfc, 0x0, 0x0, 0x1b, 0xc, 0x7, 0xb9, 0xa, 0x5e, 0x2e, 0x12, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char radio_unchecked_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x2a, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4, 0x3, 0x4, 0x9, 0x9, 0x9, 0x6, 0x6, 0x6, 0xa, 0xa, 0xb, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x7f, 0x7f, 0x82, 0xd9, 0xd9, 0xd9, 0x47, 0x47, 0x48, 0x2b, 0x6e, 0xf2, 0xbf, 0x0, 0x0, 0x0, 0xb, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x88, 0xd1, 0xf7, 0x64, 0xf6, 0x2, 0xb3, 0xed, 0xd7, 0x0, 0x0, 0x0, 0x49, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x40, 0x2, 0x61, 0x15, 0xed, 0xa9, 0x20, 0x5a, 0x72, 0xf5, 0x99, 0x33, 0xbb, 0x26, 0x1, 0x19, 0x73, 0xcf, 0x0, 0xc1, 0x4d, 0x6, 0x6, 0xd6, 0x35, 0x20, 0xc6, 0xa9, 0x0, 0x6, 0xb6, 0x3d, 0x20, 0xc6, 0xe9, 0x4, 0x6, 0xf6, 0x33, 0x60, 0x50, 0xc0, 0xc0, 0x1, 0x61, 0x34, 0xc0, 0x19, 0x70, 0x29, 0xb8, 0x62, 0xb8, 0x76, 0x84, 0x81, 0xc, 0x96, 0x20, 0x2b, 0xa6, 0xc0, 0x2d, 0x45, 0x0, 0x0, 0x37, 0xca, 0x3d, 0x81, 0xb4, 0x84, 0xb6, 0x80, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char radio_unchecked_disabled_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0xf, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x54, 0x54, 0x54, 0xad, 0xad, 0xad, 0x80, 0x80, 0x81, 0x64, 0x64, 0x64, 0xf4, 0x17, 0x36, 0x28, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x1b, 0xfc, 0xf6, 0x4, 0xd4, 0x0, 0x0, 0x0, 0x40, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5e, 0x7d, 0x8d, 0xb1, 0x11, 0x80, 0x40, 0xc, 0xc3, 0x94, 0xd, 0x12, 0x60, 0x1, 0xc4, 0x4, 0xb0, 0x1, 0xfb, 0x2f, 0x45, 0xe5, 0x3b, 0xaa, 0x57, 0xe5, 0xc2, 0xb6, 0x20, 0xc0, 0xcc, 0xc, 0x40, 0xed, 0x7a, 0x37, 0x70, 0xa8, 0xbe, 0x50, 0x9b, 0xea, 0xd9, 0xd4, 0xa3, 0x7a, 0x35, 0xa5, 0xaa, 0xeb, 0x90, 0x72, 0xe6, 0x39, 0xfc, 0x2b, 0x22, 0xd, 0x1f, 0xe7, 0x64, 0xa, 0x5d, 0x6c, 0xfe, 0xc1, 0x3b, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char scroll_bg_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x3, 0x0, 0x0, 0x0, 0x61, 0xab, 0xac, 0xd5, 0x0, 0x0, 0x0, 0x45, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x40, 0x3e, 0x4a, 0x2a, 0x29, 0x2f, 0x20, 0x20, 0x24, 0x3f, 0x3e, 0x49, 0x1f, 0x1f, 0x24, 0x20, 0x20, 0x24, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x3f, 0x3e, 0x49, 0x3f, 0x3e, 0x49, 0x1e, 0x1e, 0x23, 0x20, 0x20, 0x25, 0x22, 0x22, 0x27, 0x23, 0x23, 0x27, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2a, 0x14, 0xee, 0x69, 0x20, 0x0, 0x0, 0x0, 0x11, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x4, 0x19, 0x40, 0x5d, 0x66, 0x28, 0x93, 0xf0, 0xfc, 0x94, 0xfc, 0xfd, 0x67, 0x1a, 0x96, 0x95, 0x1c, 0xf0, 0x43, 0x52, 0x0, 0x0, 0x0, 0x55, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x55, 0x8e, 0x45, 0x2, 0x80, 0x50, 0x10, 0x42, 0xc1, 0xee, 0xfb, 0x5f, 0xd4, 0xd6, 0xdf, 0xfd, 0x36, 0xd3, 0x3, 0x4, 0xd, 0x90, 0x6, 0xb2, 0x25, 0x39, 0xe0, 0xd2, 0xf9, 0xcb, 0x6a, 0x60, 0x6f, 0x27, 0xb7, 0xbc, 0x58, 0xb7, 0x53, 0x4d, 0x0, 0xf2, 0x3f, 0x5e, 0x36, 0x43, 0x5f, 0xc3, 0xf0, 0xdf, 0x17, 0xd7, 0xa6, 0xae, 0x60, 0x10, 0xff, 0x57, 0x16, 0xc5, 0x5a, 0xf1, 0x60, 0xe3, 0xe7, 0x5f, 0x37, 0x46, 0x74, 0xba, 0x9a, 0x16, 0xef, 0x37, 0x1c, 0x6f, 0x61, 0x47, 0x1, 0xa5, 0xc7, 0x32, 0x47, 0x38, 0x12, 0x92, 0xb1, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char scroll_button_left_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0x2d, 0x2c, 0x2f, 0x48, 0x46, 0x4a, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x4c, 0x4a, 0x4e, 0x48, 0x46, 0x4a, 0x40, 0x3e, 0x42, 0x38, 0x36, 0x3a, 0xc3, 0xc3, 0xc3, 0xc2, 0xc2, 0xc2, 0xc1, 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xbf, 0xbf, 0xbf, 0xbe, 0xbe, 0xbe, 0x59, 0x59, 0x59, 0x8e, 0x47, 0x76, 0xf1, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x8, 0xfe, 0x9, 0xd, 0x19, 0x4a, 0xb6, 0xc1, 0xe6, 0x0, 0x0, 0x0, 0x3e, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0xc, 0x5, 0x3, 0x21, 0x86, 0xf4, 0xe, 0x30, 0x28, 0x63, 0x88, 0x80, 0x30, 0x5a, 0x51, 0x19, 0x33, 0xa1, 0x8c, 0xae, 0x55, 0x50, 0xc6, 0x2e, 0x28, 0xa3, 0x7b, 0xf7, 0x6e, 0x8, 0xa3, 0xe7, 0xcc, 0x19, 0xa8, 0x14, 0x9c, 0xd1, 0x7b, 0x17, 0xa6, 0xfd, 0x1d, 0x86, 0x81, 0x60, 0x6, 0xdc, 0x52, 0x43, 0x88, 0x33, 0x44, 0x0, 0xcc, 0x4e, 0x3f, 0xd1, 0x4, 0x90, 0xbf, 0x60, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char scroll_button_left_hl_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0x3d, 0x3b, 0x3f, 0x60, 0x5d, 0x62, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x65, 0x62, 0x67, 0x60, 0x5d, 0x62, 0x56, 0x53, 0x58, 0x4b, 0x49, 0x4e, 0xc9, 0xc9, 0xc9, 0xc8, 0xc8, 0xc8, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc5, 0xc5, 0xc5, 0xc4, 0xc4, 0xc4, 0xc3, 0xc3, 0xc3, 0x58, 0xf9, 0x63, 0x6a, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x7, 0xfe, 0xc, 0x9, 0x1c, 0xda, 0x2b, 0xa5, 0x57, 0x0, 0x0, 0x0, 0x42, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0xc, 0x5, 0x3, 0x21, 0x86, 0xf4, 0xe, 0x30, 0x28, 0x63, 0x88, 0x80, 0x30, 0x5a, 0x51, 0x19, 0x33, 0xa1, 0x8c, 0xae, 0x55, 0x50, 0xc6, 0x9e, 0x3d, 0x10, 0x46, 0xf7, 0xee, 0xdb, 0x10, 0x46, 0xef, 0xdd, 0xbb, 0x50, 0xa9, 0x77, 0xef, 0xa0, 0x8c, 0xfe, 0x7f, 0x30, 0xed, 0xff, 0x81, 0xc, 0x4c, 0x93, 0x11, 0x96, 0x1a, 0x42, 0x9c, 0x21, 0x2, 0x0, 0xfe, 0x97, 0x40, 0xa0, 0xa6, 0x84, 0xb1, 0xf6, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char scroll_button_right_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0x2d, 0x2c, 0x2f, 0x48, 0x46, 0x4a, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x4c, 0x4a, 0x4e, 0x48, 0x46, 0x4a, 0x40, 0x3e, 0x42, 0x38, 0x36, 0x3a, 0xc3, 0xc3, 0xc3, 0xc2, 0xc2, 0xc2, 0xc1, 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xbf, 0xbf, 0xbf, 0xbe, 0xbe, 0xbe, 0x59, 0x59, 0x59, 0x8e, 0x47, 0x76, 0xf1, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x8, 0xfe, 0x9, 0xd, 0x19, 0x4a, 0xb6, 0xc1, 0xe6, 0x0, 0x0, 0x0, 0x40, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0xc, 0x5, 0x3, 0x21, 0x86, 0xf4, 0xe, 0x30, 0x28, 0x63, 0x88, 0x80, 0x30, 0x5a, 0x51, 0x18, 0x33, 0x61, 0x8c, 0x59, 0x2b, 0xa0, 0x8c, 0x5d, 0xab, 0xa0, 0x8c, 0xdd, 0xbb, 0x77, 0x40, 0x18, 0x67, 0xce, 0x9c, 0x80, 0x31, 0xa0, 0x52, 0x77, 0x6f, 0x40, 0x19, 0xef, 0x30, 0xc, 0x84, 0x30, 0xe0, 0x96, 0x1a, 0x42, 0x9c, 0x21, 0x2, 0x0, 0xfd, 0x36, 0x40, 0x93, 0xf1, 0x83, 0x5f, 0xf2, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char scroll_button_right_hl_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x33, 0x50, 0x4c, 0x54, 0x45, 0x3d, 0x3b, 0x3f, 0x60, 0x5d, 0x62, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x65, 0x62, 0x67, 0x60, 0x5d, 0x62, 0x56, 0x53, 0x58, 0x4b, 0x49, 0x4e, 0xc9, 0xc9, 0xc9, 0xc8, 0xc8, 0xc8, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc5, 0xc5, 0xc5, 0xc4, 0xc4, 0xc4, 0xc3, 0xc3, 0xc3, 0xc2, 0xc2, 0xc2, 0x2e, 0x3d, 0xb1, 0x1e, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x7, 0xfe, 0xc, 0x9, 0x1c, 0xda, 0x2b, 0xa5, 0x57, 0x0, 0x0, 0x0, 0x49, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x65, 0xc8, 0x31, 0x16, 0x2, 0x20, 0x10, 0x43, 0xc1, 0xe4, 0x83, 0xdc, 0xff, 0xb8, 0x88, 0xf, 0x57, 0xb, 0x8b, 0x80, 0x53, 0xe, 0xf2, 0x23, 0x18, 0xc6, 0x68, 0x61, 0x74, 0xca, 0xa, 0x2e, 0x74, 0xf9, 0x85, 0xfd, 0x17, 0x5c, 0x81, 0xfb, 0x11, 0x2a, 0xaa, 0x65, 0x80, 0x20, 0xc3, 0x5f, 0xaf, 0x2b, 0x96, 0xce, 0x78, 0xea, 0x88, 0x39, 0x95, 0x91, 0x70, 0x29, 0x94, 0xd9, 0x6b, 0x87, 0xf5, 0xfe, 0x0, 0xc6, 0xa7, 0x1b, 0x66, 0x7b, 0x42, 0xf1, 0x14, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char scroll_grabber_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x3, 0x0, 0x0, 0x0, 0x61, 0xab, 0xac, 0xd5, 0x0, 0x0, 0x0, 0x5d, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x5b, 0x59, 0x61, 0x5b, 0x59, 0x61, 0x5a, 0x58, 0x60, 0x59, 0x57, 0x5f, 0x5a, 0x58, 0x60, 0x5a, 0x58, 0x60, 0x57, 0x56, 0x5e, 0x58, 0x56, 0x5e, 0x56, 0x55, 0x5d, 0x57, 0x55, 0x5d, 0x57, 0x55, 0x5d, 0x55, 0x53, 0x5b, 0x55, 0x53, 0x5b, 0x54, 0x53, 0x5b, 0x55, 0x54, 0x5c, 0x54, 0x52, 0x5a, 0x55, 0x53, 0x5b, 0x5a, 0x58, 0x60, 0x56, 0x54, 0x5c, 0x54, 0x53, 0x5a, 0x55, 0x53, 0x5b, 0x53, 0x51, 0x59, 0x52, 0x51, 0x59, 0x52, 0x50, 0x58, 0x51, 0x50, 0x58, 0x51, 0x4f, 0x57, 0x50, 0x4e, 0x56, 0x4f, 0x4d, 0x55, 0x50, 0x4f, 0x57, 0x54, 0x52, 0x5a, 0xae, 0x55, 0xff, 0xf7, 0x0, 0x0, 0x0, 0x12, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x2c, 0xb8, 0xf4, 0x2e, 0xf2, 0xb8, 0xf4, 0xf5, 0xf4, 0xf5, 0xb8, 0x2f, 0xf2, 0x2e, 0xb8, 0xf4, 0xb8, 0x66, 0xf6, 0xf7, 0x12, 0x0, 0x0, 0x0, 0x48, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x64, 0xc7, 0xb1, 0x11, 0x80, 0x40, 0x8, 0x45, 0x41, 0xff, 0x83, 0x2, 0xe, 0xfb, 0x2f, 0x13, 0xe2, 0xf3, 0x6, 0x12, 0x1d, 0x37, 0x5b, 0xae, 0x97, 0x5f, 0x84, 0xdd, 0x68, 0xe2, 0x1e, 0x41, 0xb8, 0x77, 0x58, 0x6, 0xb6, 0xe8, 0x88, 0xd1, 0xe1, 0x93, 0xad, 0x63, 0xab, 0xa3, 0x3a, 0xa3, 0x26, 0xa9, 0x4a, 0x52, 0xf9, 0xc, 0x62, 0xcf, 0xa7, 0x8f, 0x1f, 0x1e, 0xbd, 0xff, 0x84, 0xee, 0x2, 0x0, 0x54, 0x76, 0x10, 0x19, 0x1e, 0xd7, 0x1d, 0x9b, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char scroll_grabber_hl_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x3, 0x0, 0x0, 0x0, 0x61, 0xab, 0xac, 0xd5, 0x0, 0x0, 0x0, 0x69, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x97, 0xd0, 0xdf, 0x92, 0xcb, 0xdc, 0x84, 0xbb, 0xd4, 0x92, 0xca, 0xdc, 0x95, 0xd0, 0xdd, 0x83, 0xbb, 0xd3, 0x8b, 0xc8, 0xd7, 0x79, 0xb5, 0xcb, 0x78, 0xb4, 0xca, 0x73, 0xb0, 0xc7, 0x73, 0xb0, 0xc7, 0x7b, 0xc0, 0xcf, 0x79, 0xc5, 0xd1, 0x6b, 0xae, 0xc1, 0x75, 0xc6, 0xcf, 0x70, 0xbc, 0xca, 0x64, 0xa6, 0xbc, 0x71, 0xbc, 0xc9, 0x82, 0xba, 0xd4, 0x6a, 0xa2, 0xc6, 0x62, 0x9a, 0xc2, 0x61, 0x9a, 0xc1, 0x68, 0x9f, 0xc2, 0x5d, 0x92, 0xbb, 0x5c, 0x92, 0xb8, 0x58, 0x8d, 0xb6, 0x59, 0x8e, 0xb3, 0x56, 0x89, 0xb0, 0x5c, 0x91, 0xb2, 0x53, 0x84, 0xa9, 0x58, 0x8f, 0xae, 0x54, 0x83, 0xa4, 0x57, 0x8e, 0xad, 0x64, 0xa5, 0xba, 0x17, 0x3b, 0xfc, 0x67, 0x0, 0x0, 0x0, 0x13, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x25, 0xad, 0xf1, 0xad, 0x27, 0xef, 0xad, 0xf1, 0xf3, 0xf1, 0xf3, 0xad, 0x28, 0xef, 0x27, 0xad, 0xf2, 0xad, 0xcd, 0x8a, 0x27, 0xfe, 0x0, 0x0, 0x0, 0x46, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x7d, 0x8a, 0x25, 0x2, 0xc4, 0x40, 0x0, 0x3, 0x27, 0x39, 0x52, 0x57, 0xfa, 0xff, 0x1f, 0x17, 0x54, 0x19, 0x6d, 0x61, 0x4c, 0x90, 0x5b, 0x5e, 0x80, 0xec, 0x66, 0x58, 0x76, 0x3, 0x1f, 0x15, 0xd2, 0x9c, 0x97, 0x61, 0xf, 0xbf, 0x4a, 0xc0, 0x12, 0x3b, 0xde, 0xfb, 0xeb, 0x8, 0x66, 0xf, 0xbe, 0x8, 0x2, 0x83, 0x92, 0xec, 0x57, 0x12, 0x8, 0x28, 0xa5, 0x3a, 0x4e, 0x89, 0x7, 0x56, 0x51, 0x36, 0x11, 0x22, 0x4, 0xb, 0xcc, 0xf7, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char scroll_grabber_pressed_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x4, 0x0, 0x0, 0x0, 0xfc, 0x7c, 0x94, 0x6c, 0x0, 0x0, 0x0, 0x2f, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xa0, 0x3a, 0xd8, 0xcf, 0xb2, 0xc1, 0x7d, 0xc3, 0x14, 0x20, 0x74, 0xdf, 0xcf, 0x82, 0x22, 0xb1, 0xc1, 0x7d, 0xfd, 0x2e, 0x8, 0xdc, 0xe0, 0x8e, 0x2a, 0x31, 0x5, 0x2e, 0x31, 0x85, 0x90, 0x4, 0xa6, 0x51, 0xb8, 0x2d, 0xa7, 0x36, 0x0, 0x0, 0x7b, 0xcd, 0x2b, 0x75, 0x45, 0x5e, 0xf8, 0x88, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char selection_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x2d, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfd, 0xfb, 0xff, 0xfd, 0xf7, 0xff, 0xfd, 0xf7, 0xff, 0xfd, 0xf7, 0xff, 0xfd, 0xf6, 0xff, 0xf6, 0xf4, 0xff, 0x15, 0x15, 0x17, 0xff, 0x70, 0xc0, 0x21, 0x0, 0x0, 0x0, 0xe, 0x74, 0x52, 0x4e, 0x53, 0x6, 0xf, 0x16, 0x18, 0x2a, 0x3b, 0x40, 0x3c, 0x6, 0x3d, 0x44, 0x3e, 0x31, 0x25, 0x8, 0x3d, 0x16, 0xb4, 0x0, 0x0, 0x0, 0x37, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x54, 0x36, 0x6, 0x2, 0x23, 0x1, 0x6, 0x91, 0xb0, 0x34, 0x20, 0x48, 0x75, 0x64, 0x50, 0xef, 0x5c, 0x5, 0x4, 0x33, 0x8a, 0x18, 0xcc, 0xf6, 0xdc, 0x5, 0x82, 0xd3, 0xc9, 0xc, 0x66, 0x6b, 0x41, 0x8c, 0x5b, 0x94, 0x33, 0x60, 0x6, 0xc2, 0xad, 0x80, 0x5b, 0xa, 0x73, 0x6, 0x0, 0x45, 0x34, 0x48, 0x41, 0xa3, 0xc5, 0x91, 0x23, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char selection_oof_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x2d, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2c, 0x2, 0xfd, 0xfb, 0xff, 0xfd, 0xfb, 0xff, 0xfd, 0xfb, 0xff, 0xfd, 0xfb, 0xff, 0xaf, 0xdf, 0x90, 0xa5, 0x0, 0x0, 0x0, 0xf, 0x74, 0x52, 0x4e, 0x53, 0xa, 0x1a, 0x26, 0x29, 0x2a, 0x48, 0x65, 0x6d, 0x6e, 0x66, 0x3, 0x20, 0x25, 0x16, 0xc, 0x1f, 0x74, 0xbf, 0x74, 0x0, 0x0, 0x0, 0x37, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x64, 0x54, 0x52, 0x64, 0x60, 0x60, 0x78, 0x77, 0x8f, 0x51, 0x34, 0x8, 0xcc, 0xb8, 0xcd, 0xa8, 0xd9, 0x4, 0x66, 0xdc, 0x60, 0x74, 0x2f, 0x33, 0x4, 0x32, 0xde, 0xce, 0x64, 0xf4, 0x68, 0x53, 0x0, 0x32, 0xfe, 0xcd, 0xa0, 0x90, 0x1, 0x37, 0x10, 0x6e, 0x5, 0xdc, 0x52, 0xb8, 0x33, 0x0, 0xcc, 0x7, 0x26, 0xff, 0x1f, 0x38, 0x23, 0x97, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char space_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x4, 0x0, 0x0, 0x0, 0x6e, 0x6, 0x76, 0x0, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x1c, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x16, 0xfc, 0x17, 0xfc, 0x2f, 0x88, 0xcc, 0x15, 0xfa, 0x6f, 0x4, 0x84, 0x82, 0x18, 0x2, 0xe8, 0x5a, 0x88, 0x4, 0x0, 0x8c, 0xa4, 0xd, 0x47, 0x8, 0xea, 0xcc, 0xbb, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char spinbox_updown_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x59, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x11, 0xdc, 0x4f, 0x7f, 0x98, 0x86, 0x47, 0xfa, 0x81, 0xe5, 0x83, 0x1f, 0xf, 0x7e, 0x3d, 0xb2, 0xc5, 0xa5, 0x5b, 0xe2, 0xc1, 0x93, 0x7, 0xff, 0x81, 0xf0, 0xf9, 0x63, 0x69, 0x2c, 0xd2, 0x67, 0x58, 0xef, 0x1f, 0x2, 0x4a, 0x42, 0xe0, 0xf1, 0xdb, 0xec, 0x98, 0xfa, 0x67, 0x2, 0x25, 0xe0, 0xf0, 0xe1, 0x2, 0x86, 0x41, 0x7, 0x30, 0x1d, 0x39, 0x3, 0xbf, 0x37, 0x8f, 0xdd, 0x66, 0x27, 0x29, 0xa0, 0x10, 0x4a, 0x2c, 0xa0, 0x41, 0x8d, 0x1b, 0x3c, 0x4c, 0x3, 0x46, 0x16, 0x69, 0x0, 0x0, 0x87, 0x2a, 0x58, 0xb5, 0x18, 0xe9, 0x80, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char submenu_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x4, 0x0, 0x0, 0x0, 0x6e, 0x6, 0x76, 0x0, 0x0, 0x0, 0x0, 0x2e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x78, 0xc0, 0xf0, 0xe0, 0x3f, 0x8, 0xde, 0x4f, 0x60, 0x0, 0x3, 0xb8, 0xc0, 0x83, 0x2f, 0xf, 0xb5, 0xe1, 0x2, 0x50, 0x78, 0xf5, 0x5, 0x37, 0xaa, 0xc0, 0xff, 0x87, 0xf3, 0x31, 0x4, 0x30, 0xb5, 0x60, 0x1a, 0x8a, 0x61, 0x2d, 0x0, 0xa6, 0x55, 0x4f, 0xb1, 0x91, 0xd6, 0xa7, 0xae, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char submenu_mirrored_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x4, 0x0, 0x0, 0x0, 0x6e, 0x6, 0x76, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6f, 0x72, 0x4e, 0x54, 0x1, 0xcf, 0xa2, 0x77, 0x9a, 0x0, 0x0, 0x0, 0x57, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x55, 0xcb, 0xa1, 0x11, 0x83, 0x40, 0x14, 0x45, 0xd1, 0xb3, 0x6b, 0x10, 0x34, 0x10, 0x47, 0x34, 0xf4, 0x13, 0x9d, 0x2, 0x28, 0x87, 0x2a, 0xe8, 0x84, 0x2, 0x82, 0x65, 0x71, 0x69, 0x0, 0x11, 0xf5, 0x11, 0x4c, 0x66, 0xd8, 0xe7, 0xee, 0x99, 0x79, 0x80, 0xed, 0x5d, 0xa2, 0x44, 0x9, 0x12, 0xec, 0x43, 0x2c, 0x5a, 0x78, 0xa6, 0xcc, 0xb7, 0x8d, 0xf9, 0x4a, 0xc8, 0xfc, 0x26, 0x3d, 0x37, 0xa8, 0x97, 0x69, 0x46, 0x6b, 0x5, 0x8f, 0x23, 0xbd, 0x1c, 0xd5, 0xa5, 0xfb, 0xc4, 0xf8, 0x87, 0x13, 0xd2, 0x2f, 0x14, 0x49, 0x6f, 0xb1, 0x11, 0xe1, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char tab_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x4, 0x0, 0x0, 0x0, 0x6e, 0x6, 0x76, 0x0, 0x0, 0x0, 0x0, 0x19, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xc0, 0x2, 0xfe, 0x47, 0xfe, 0x17, 0x1, 0xc2, 0x48, 0xd2, 0x84, 0x10, 0x2, 0x84, 0xb9, 0x98, 0x0, 0x0, 0xbf, 0x67, 0x1d, 0x5, 0x89, 0x9b, 0x48, 0x90, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char tab_behind_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x57, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x2e, 0x36, 0x43, 0x40, 0x4d, 0x0, 0x0, 0x0, 0x43, 0x40, 0x4c, 0x3e, 0x3c, 0x47, 0x3e, 0x3b, 0x46, 0x31, 0x2f, 0x38, 0x2d, 0x2b, 0x33, 0x3f, 0x3c, 0x47, 0x91, 0xf8, 0xc4, 0xb2, 0x0, 0x0, 0x0, 0x18, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x1, 0x3, 0x5, 0x8, 0xa, 0xb, 0xc, 0x4, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x77, 0xf3, 0x7, 0xef, 0xd3, 0x51, 0x5e, 0xca, 0x0, 0x0, 0x0, 0x5a, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xb5, 0x8c, 0x35, 0x2, 0x80, 0x30, 0x10, 0x4, 0x6f, 0x73, 0xc4, 0x53, 0xf3, 0xff, 0x3f, 0xe2, 0xee, 0x4e, 0x9d, 0xe9, 0x56, 0x41, 0xd8, 0xa1, 0x69, 0x7, 0xd0, 0x43, 0x72, 0x19, 0x3d, 0x37, 0x10, 0x6c, 0x1f, 0x8d, 0x6a, 0x0, 0x2b, 0x25, 0xc1, 0x20, 0xa2, 0x69, 0x98, 0xba, 0xb6, 0x45, 0x9a, 0x2b, 0xbd, 0xe9, 0xd5, 0x69, 0xda, 0x0, 0xa9, 0x94, 0x9f, 0x68, 0x7, 0xc5, 0xd2, 0x50, 0x4a, 0x69, 0x71, 0x18, 0x63, 0xb3, 0x18, 0x7a, 0x71, 0x2e, 0xa3, 0xfd, 0x1b, 0xff, 0xc9, 0xff, 0x34, 0x86, 0x31, 0x3, 0x12, 0xb2, 0x4c, 0x6a, 0xfb, 0x60, 0xc7, 0xdc, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char tab_close_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x65, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xad, 0x90, 0x1, 0x6, 0xc0, 0x30, 0xc, 0x45, 0x77, 0x89, 0xd5, 0x76, 0xb3, 0x9e, 0x7b, 0x65, 0x63, 0xd, 0xf9, 0xbb, 0x48, 0x3b, 0xb3, 0x92, 0x54, 0x42, 0xb1, 0x5, 0x88, 0xf7, 0xc8, 0xcf, 0x9f, 0xfe, 0x1a, 0x8e, 0x14, 0xf4, 0x4e, 0x81, 0x63, 0x87, 0x51, 0x90, 0x28, 0x8, 0x46, 0x42, 0x51, 0x4a, 0x9e, 0x79, 0x43, 0xc5, 0x81, 0x55, 0x6f, 0xbc, 0x34, 0xdc, 0x2b, 0x2e, 0x16, 0xe5, 0x3a, 0xb1, 0xb, 0xb6, 0xca, 0x3, 0x2b, 0xb2, 0xc2, 0xbe, 0xf0, 0x66, 0x71, 0x4f, 0x70, 0x3b, 0x61, 0x14, 0x89, 0x26, 0x71, 0x5d, 0x6c, 0x9f, 0x1e, 0x17, 0x35, 0xae, 0xfa, 0xeb, 0xdc, 0x62, 0xc3, 0x84, 0x2d, 0x77, 0x22, 0xda, 0x98, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char tab_container_bg_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x87, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x3a, 0x44, 0x56, 0x53, 0x61, 0x56, 0x52, 0x60, 0x47, 0x44, 0x52, 0x33, 0x31, 0x39, 0x47, 0x44, 0x50, 0x47, 0x44, 0x51, 0x52, 0x50, 0x5d, 0x51, 0x4f, 0x5d, 0x46, 0x42, 0x4e, 0x42, 0x3e, 0x4a, 0x41, 0x3e, 0x49, 0x51, 0x4e, 0x5b, 0x40, 0x3e, 0x48, 0x4f, 0x4c, 0x59, 0x3f, 0x3d, 0x47, 0x4e, 0x4a, 0x58, 0x3e, 0x3b, 0x46, 0x4b, 0x49, 0x55, 0x3c, 0x3a, 0x44, 0x4a, 0x47, 0x54, 0x3b, 0x39, 0x43, 0x49, 0x46, 0x53, 0x3a, 0x38, 0x42, 0x47, 0x45, 0x50, 0x39, 0x37, 0x40, 0x47, 0x43, 0x50, 0x38, 0x35, 0x3f, 0x36, 0x34, 0x3e, 0x44, 0x42, 0x4d, 0x44, 0x41, 0x4c, 0x3f, 0x38, 0xaa, 0x5e, 0x0, 0x0, 0x0, 0x15, 0x74, 0x52, 0x4e, 0x53, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x77, 0xef, 0xef, 0xef, 0x77, 0xef, 0xed, 0xe8, 0xff, 0x76, 0xed, 0x0, 0x0, 0x0, 0x63, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x6d, 0xcf, 0x45, 0x2, 0x84, 0x30, 0x0, 0x4, 0xc1, 0x69, 0x1c, 0xfe, 0xff, 0xca, 0xd5, 0xeb, 0x2a, 0x83, 0x6b, 0xd2, 0xb7, 0x54, 0x1c, 0x31, 0x26, 0xc9, 0x63, 0x50, 0xcc, 0x32, 0x8d, 0x3f, 0xd9, 0x20, 0x5, 0x1a, 0xf2, 0xc7, 0x1f, 0x7a, 0x48, 0x4a, 0x66, 0xa8, 0xde, 0xc, 0xd0, 0x38, 0xd1, 0x54, 0xdb, 0x4c, 0x2b, 0xd0, 0x5c, 0x62, 0x8e, 0xa0, 0x1, 0x74, 0x4, 0x65, 0xd2, 0x1e, 0xd4, 0x83, 0xf7, 0x60, 0x65, 0x3e, 0x82, 0x3, 0x48, 0x49, 0xdf, 0x55, 0xca, 0xd4, 0xef, 0xfa, 0xfb, 0x27, 0x36, 0xf, 0x92, 0x31, 0x9e, 0x44, 0x3e, 0x17, 0x7c, 0xbf, 0x3, 0xef, 0x34, 0x3f, 0x3e, 0xe0, 0x24, 0x67, 0xb9, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char tab_current_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x1, 0x71, 0x69, 0x43, 0x43, 0x50, 0x69, 0x63, 0x63, 0x0, 0x0, 0x28, 0x91, 0x75, 0x91, 0x3d, 0x4b, 0xc3, 0x50, 0x14, 0x86, 0xdf, 0xb6, 0x8a, 0xa2, 0x91, 0xe, 0x15, 0x11, 0x71, 0xc8, 0x50, 0xc5, 0xa1, 0x85, 0xa2, 0x20, 0x8e, 0x5a, 0x87, 0x2e, 0x45, 0x4a, 0xad, 0x60, 0xd5, 0x25, 0xb9, 0x4d, 0x5a, 0x21, 0x49, 0xc3, 0x4d, 0x8a, 0x14, 0x57, 0xc1, 0xc5, 0xa1, 0xe0, 0x20, 0xba, 0xf8, 0x35, 0xf8, 0xf, 0x74, 0x15, 0x5c, 0x15, 0x4, 0x41, 0x11, 0x44, 0x9c, 0xfc, 0x1, 0x7e, 0x2d, 0x52, 0xe2, 0xb9, 0x4d, 0xa1, 0x45, 0xda, 0x13, 0x6e, 0xce, 0xc3, 0x7b, 0xcf, 0x7b, 0xb8, 0xf7, 0x5c, 0x20, 0x98, 0x36, 0x98, 0xe9, 0xf4, 0x24, 0x0, 0xd3, 0x72, 0x79, 0x36, 0x95, 0x94, 0x57, 0xf3, 0x6b, 0x72, 0xdf, 0x3b, 0x2, 0x90, 0x30, 0x82, 0x8, 0x24, 0x85, 0x39, 0xf6, 0x42, 0x26, 0x93, 0x46, 0xd7, 0xf8, 0x79, 0xa4, 0x6a, 0x8a, 0x87, 0xb8, 0xe8, 0xd5, 0xbd, 0xae, 0x63, 0xc, 0x16, 0x34, 0x87, 0x1, 0x81, 0x7e, 0xe2, 0x59, 0x66, 0x73, 0x97, 0x78, 0x9e, 0x38, 0xbd, 0xe5, 0xda, 0x82, 0xf7, 0x88, 0x87, 0x59, 0x49, 0x29, 0x10, 0x9f, 0x10, 0xc7, 0x38, 0x1d, 0x90, 0xf8, 0x56, 0xe8, 0xaa, 0xcf, 0x6f, 0x82, 0x8b, 0x3e, 0x7f, 0x9, 0xe6, 0xb9, 0xec, 0x22, 0x10, 0x14, 0x3d, 0xe5, 0x62, 0x1b, 0xab, 0x6d, 0xcc, 0x4a, 0xdc, 0x24, 0x9e, 0x22, 0x8e, 0x9a, 0x46, 0x85, 0x35, 0xcf, 0x23, 0x6e, 0x22, 0x69, 0xd6, 0xca, 0x32, 0xe5, 0x31, 0x5a, 0xe3, 0x70, 0x90, 0x45, 0xa, 0x49, 0xc8, 0x50, 0x51, 0xc1, 0x26, 0xc, 0xb8, 0x88, 0x53, 0xb6, 0x68, 0x66, 0x9d, 0x7d, 0x89, 0x86, 0x6f, 0x9, 0x65, 0xf2, 0x30, 0xfa, 0xdb, 0xa8, 0x82, 0x93, 0xa3, 0x88, 0x12, 0x79, 0x63, 0xa4, 0x56, 0xa8, 0xab, 0x46, 0x59, 0x27, 0x5d, 0xa3, 0xcf, 0x40, 0x55, 0xcc, 0xfd, 0xff, 0x3c, 0x1d, 0x7d, 0x66, 0xda, 0xef, 0x2e, 0x25, 0x81, 0xde, 0x57, 0xcf, 0xfb, 0x9c, 0x0, 0xfa, 0xf6, 0x81, 0x7a, 0xcd, 0xf3, 0x7e, 0x4f, 0x3d, 0xaf, 0x7e, 0x6, 0x84, 0x5e, 0x80, 0x6b, 0xab, 0xe5, 0x2f, 0xd3, 0x9c, 0xe6, 0xbe, 0x49, 0xaf, 0xb5, 0xb4, 0xe8, 0x31, 0x10, 0xde, 0x1, 0x2e, 0x6f, 0x5a, 0x9a, 0x7a, 0x0, 0x5c, 0xed, 0x2, 0xa3, 0xcf, 0xb6, 0xc2, 0x95, 0x86, 0x14, 0xa2, 0x15, 0xd4, 0x75, 0xe0, 0xe3, 0x2, 0x18, 0xca, 0x3, 0x91, 0x7b, 0x60, 0x60, 0xdd, 0x9f, 0x55, 0x73, 0x1f, 0xe7, 0x4f, 0x40, 0x6e, 0x9b, 0x9e, 0xe8, 0xe, 0x38, 0x3c, 0x2, 0x26, 0xa9, 0x3e, 0xbc, 0xf1, 0x7, 0x9c, 0x2f, 0x67, 0xdc, 0x46, 0x9a, 0x3c, 0x4e, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x12, 0x0, 0x0, 0xb, 0x12, 0x1, 0xd2, 0xdd, 0x7e, 0xfc, 0x0, 0x0, 0x1, 0x27, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0x9d, 0x93, 0x41, 0x4e, 0xc3, 0x30, 0x10, 0x45, 0xc7, 0xee, 0xd0, 0x82, 0x58, 0xd4, 0x6b, 0x28, 0xdc, 0x4, 0xc1, 0x92, 0x35, 0xa7, 0xe9, 0x11, 0x38, 0xd, 0x6b, 0x36, 0x2c, 0x10, 0x3b, 0xee, 0xc0, 0x6, 0x95, 0x1d, 0x6a, 0x83, 0x54, 0x4, 0xad, 0x1d, 0xf, 0x7f, 0xf0, 0x4, 0xb5, 0x52, 0x11, 0xe, 0x3f, 0x7a, 0x91, 0x93, 0x7c, 0xff, 0x78, 0x9c, 0x89, 0x23, 0x22, 0x6, 0x43, 0x30, 0x2, 0xfb, 0x36, 0x1e, 0x0, 0x4f, 0xdb, 0xca, 0xa0, 0x5, 0x6b, 0xf0, 0x9, 0x56, 0x3a, 0xee, 0x26, 0x1f, 0x82, 0x0, 0xc6, 0x36, 0xd6, 0x30, 0x67, 0xa8, 0xc4, 0xd0, 0x49, 0xef, 0xe0, 0xd, 0x34, 0x64, 0x6f, 0x57, 0x73, 0x38, 0x3f, 0xbb, 0xbc, 0x9a, 0x1c, 0x9f, 0x4e, 0x53, 0x4a, 0x21, 0xb, 0xed, 0x94, 0x47, 0x1c, 0x33, 0x37, 0xb3, 0x97, 0xe7, 0xeb, 0xfb, 0x87, 0xdb, 0x1b, 0xdc, 0x4a, 0x6c, 0xcb, 0x1e, 0x4f, 0x8e, 0x4e, 0xa6, 0x8b, 0xf9, 0x6b, 0x48, 0x31, 0xe1, 0x55, 0xbb, 0x13, 0x1c, 0xe, 0xde, 0xe3, 0xa0, 0x5e, 0x5c, 0xde, 0x81, 0xe5, 0x4f, 0x9, 0xeb, 0x18, 0x43, 0x8c, 0xf1, 0xd7, 0xc9, 0xa5, 0xe, 0x21, 0xf5, 0xa8, 0xd7, 0x4a, 0x1d, 0xb2, 0x6d, 0xd8, 0x28, 0xe7, 0x4c, 0x59, 0x32, 0xfd, 0x25, 0xd, 0x51, 0xaf, 0x95, 0x3e, 0x60, 0xdb, 0x6d, 0x27, 0x59, 0x1f, 0x8, 0xd5, 0x48, 0x8a, 0x4f, 0x37, 0xd8, 0x73, 0x57, 0x5e, 0x2b, 0x6d, 0xd5, 0xa, 0x54, 0xea, 0xed, 0xbe, 0x10, 0x6f, 0xa6, 0x8a, 0xf4, 0x5a, 0x1, 0x6d, 0x6, 0x88, 0x4e, 0xae, 0xe, 0x28, 0xbe, 0xef, 0x93, 0xb7, 0xe, 0x43, 0x68, 0xa2, 0x5a, 0x99, 0x57, 0x3, 0xb2, 0xb7, 0xf6, 0x5c, 0x51, 0xa6, 0x7a, 0x15, 0xaf, 0x76, 0x65, 0xcb, 0x5b, 0x8d, 0xe2, 0x1c, 0xf5, 0x15, 0xdb, 0x8f, 0xd1, 0xfc, 0x23, 0xe0, 0xa0, 0x6b, 0x24, 0xfd, 0xbb, 0x96, 0xa5, 0xd7, 0x7b, 0x5, 0xcc, 0xc1, 0x87, 0xee, 0xc1, 0x2, 0x3c, 0x81, 0xb, 0xa1, 0xba, 0x43, 0xbd, 0xe0, 0x11, 0xcc, 0xbe, 0x0, 0xbe, 0xe0, 0x95, 0x8, 0xaf, 0xb2, 0x52, 0x33, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char tab_disabled_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0x2e, 0x23, 0x0, 0x0, 0x2e, 0x23, 0x1, 0x78, 0xa5, 0x3f, 0x76, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0xa6, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x7c, 0xcd, 0xc5, 0x41, 0x4, 0x41, 0x10, 0x0, 0xc0, 0xea, 0xbd, 0xc1, 0x6d, 0xde, 0x47, 0x30, 0xe4, 0x40, 0x34, 0x1b, 0x2, 0xd1, 0x10, 0x1, 0x1a, 0xc, 0x4f, 0xdc, 0x6d, 0x1b, 0x77, 0xe6, 0xea, 0xd5, 0xde, 0xa1, 0x98, 0x36, 0x63, 0xd6, 0xb4, 0x91, 0xe, 0x30, 0x78, 0x74, 0xe7, 0xc6, 0xad, 0xbb, 0x97, 0xf6, 0x82, 0x6a, 0xc5, 0x82, 0x19, 0x21, 0x90, 0xd2, 0xad, 0x4b, 0xa7, 0x4e, 0x28, 0x66, 0xd4, 0xb5, 0xf5, 0xd5, 0xfe, 0xa1, 0xfa, 0xa1, 0x9c, 0x1c, 0x6c, 0xec, 0x6f, 0x7a, 0x28, 0x66, 0xad, 0x8c, 0xfb, 0xa3, 0xfa, 0x20, 0x7d, 0x9, 0xa5, 0x8e, 0x7b, 0xdb, 0x2e, 0x5e, 0x5f, 0xdc, 0xd7, 0x7b, 0x3f, 0xa5, 0x7b, 0xf7, 0xd5, 0x82, 0xe9, 0x62, 0x64, 0x66, 0x90, 0xfe, 0x1a, 0x98, 0x31, 0x2a, 0x3a, 0x91, 0x6, 0x7f, 0x25, 0xa1, 0x2b, 0x88, 0xe6, 0x85, 0xa0, 0x40, 0x73, 0x0, 0x5, 0x99, 0xf2, 0xff, 0x17, 0xf9, 0x79, 0x61, 0x98, 0x78, 0x21, 0x9a, 0x17, 0x82, 0xf2, 0x99, 0x34, 0x74, 0x13, 0xbb, 0x49, 0x87, 0xd0, 0x12, 0x4f, 0x3, 0x29, 0x20, 0x0, 0x0, 0xe, 0x38, 0x38, 0x83, 0xd2, 0xe8, 0x36, 0x36, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char tab_menu_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x36, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x40, 0x5, 0xa3, 0xe0, 0xc1, 0x7f, 0x54, 0x48, 0x3, 0x5, 0xf, 0xe3, 0x1e, 0x7c, 0x81, 0x4b, 0x7f, 0x7b, 0x98, 0x86, 0xc5, 0x15, 0xf7, 0x35, 0xee, 0x5f, 0x2, 0x4b, 0x5f, 0x7f, 0xac, 0x8b, 0xc3, 0xa1, 0x2f, 0xb8, 0x1f, 0xce, 0x7f, 0x38, 0xff, 0x5, 0x37, 0x75, 0xbd, 0xf, 0x0, 0x52, 0xd4, 0x48, 0xb8, 0x2d, 0x78, 0x5a, 0x91, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char tab_menu_hl_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x36, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x40, 0x5, 0xa3, 0xe0, 0xc1, 0x7f, 0x54, 0x48, 0x3, 0x5, 0xf, 0xe3, 0x1e, 0x7c, 0x81, 0x4b, 0x7f, 0x7b, 0x98, 0x86, 0xc5, 0x15, 0xf7, 0x35, 0xee, 0x5f, 0x2, 0x4b, 0x5f, 0x7f, 0xac, 0x8b, 0xc3, 0xa1, 0x2f, 0xb8, 0x1f, 0xce, 0x7f, 0x38, 0xff, 0x5, 0x37, 0x75, 0xbd, 0xf, 0x0, 0x52, 0xd4, 0x48, 0xb8, 0x2d, 0x78, 0x5a, 0x91, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char toggle_off_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x20, 0x8, 0x3, 0x0, 0x0, 0x0, 0x95, 0x43, 0x8e, 0xb6, 0x0, 0x0, 0x1, 0x7a, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x14, 0x17, 0x20, 0x20, 0x25, 0x24, 0x24, 0x28, 0x24, 0x24, 0x29, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x10, 0x13, 0x22, 0x22, 0x27, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x19, 0x19, 0x1c, 0x1a, 0x1a, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x11, 0x14, 0x12, 0x12, 0x14, 0x23, 0x23, 0x27, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x15, 0x15, 0x18, 0x20, 0x20, 0x25, 0x20, 0x20, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x24, 0x28, 0x0, 0x0, 0x0, 0x24, 0x24, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x24, 0x27, 0x15, 0x15, 0x18, 0x23, 0x23, 0x28, 0x12, 0x12, 0x14, 0x0, 0x0, 0x0, 0x1a, 0x1a, 0x1e, 0x0, 0x0, 0x0, 0x11, 0x11, 0x13, 0x22, 0x22, 0x26, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x24, 0x29, 0x25, 0x25, 0x2a, 0x24, 0x24, 0x28, 0x25, 0x25, 0x28, 0x25, 0x25, 0x29, 0x25, 0x25, 0x27, 0x2d, 0x26, 0x2c, 0x4d, 0x2b, 0x37, 0x63, 0x2f, 0x3f, 0x6e, 0x31, 0x43, 0x71, 0x32, 0x44, 0x6c, 0x31, 0x42, 0x51, 0x2c, 0x39, 0x47, 0x2a, 0x35, 0x66, 0x30, 0x40, 0x4d, 0x2b, 0x38, 0x32, 0x26, 0x2e, 0x26, 0x25, 0x2a, 0x2e, 0x25, 0x2c, 0x3c, 0x28, 0x31, 0x52, 0x2c, 0x39, 0x68, 0x30, 0x40, 0x27, 0x25, 0x2a, 0x50, 0x2c, 0x38, 0x5f, 0x2e, 0x3d, 0x35, 0x27, 0x2f, 0x38, 0x27, 0x30, 0x5e, 0x2e, 0x3d, 0x43, 0x2a, 0x34, 0x5f, 0x2f, 0x3e, 0x2f, 0x25, 0x2c, 0x44, 0x2a, 0x34, 0x2b, 0x26, 0x2c, 0x64, 0x2f, 0x3f, 0x36, 0x27, 0x30, 0x37, 0x27, 0x30, 0x66, 0x2f, 0x40, 0x2c, 0x26, 0x2c, 0x46, 0x2a, 0x35, 0x53, 0x2c, 0x39, 0x40, 0x40, 0x44, 0xad, 0xad, 0xaf, 0xff, 0xff, 0xff, 0xf2, 0xf2, 0xf2, 0x77, 0x77, 0x7a, 0x5b, 0x5b, 0x5f, 0x32, 0x32, 0x37, 0x5d, 0x2e, 0x3d, 0x3e, 0x29, 0x32, 0xc9, 0xc9, 0xca, 0xbb, 0xbb, 0xbd, 0x69, 0x69, 0x6c, 0x69, 0x30, 0x41, 0x2f, 0x26, 0x2d, 0x84, 0x84, 0x87, 0xd6, 0xd6, 0xd7, 0x92, 0x92, 0x94, 0xa0, 0xa0, 0xa2, 0x4e, 0x4e, 0x52, 0x48, 0x2b, 0x36, 0x2c, 0x26, 0x2b, 0x97, 0xb0, 0x86, 0xb4, 0x0, 0x0, 0x0, 0x41, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x1, 0x2, 0x3, 0x4, 0x9, 0xe, 0x13, 0x16, 0x18, 0x19, 0xa, 0x26, 0x36, 0x44, 0x4d, 0x52, 0x54, 0x55, 0x6, 0x12, 0x27, 0x43, 0x98, 0xe5, 0xfa, 0xfe, 0x8, 0x17, 0x35, 0x86, 0xf3, 0x7, 0x3a, 0xb4, 0xb9, 0xb, 0x28, 0x8a, 0x8b, 0xf6, 0x45, 0x5, 0x9b, 0xe6, 0xe6, 0x37, 0xf, 0xfb, 0x4c, 0xfe, 0x4e, 0x4f, 0x50, 0xfb, 0x9c, 0xf6, 0x8c, 0x3b, 0xbb, 0x3c, 0x87, 0xf3, 0x53, 0x14, 0xe5, 0x7c, 0xf3, 0x66, 0x0, 0x0, 0x2, 0x29, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xdd, 0x95, 0x3, 0x93, 0x24, 0x4b, 0x14, 0x85, 0x5f, 0xb9, 0xaa, 0x6d, 0x8e, 0x6d, 0xdb, 0x73, 0x2b, 0xb3, 0xe7, 0xad, 0x6d, 0xab, 0xdd, 0x63, 0xe3, 0xbf, 0x6f, 0x67, 0x65, 0xbb, 0xb4, 0xbb, 0x81, 0xc5, 0x97, 0x11, 0x27, 0x78, 0x4f, 0xea, 0xe2, 0xbf, 0x3f, 0x9, 0x86, 0xe5, 0x38, 0xde, 0x16, 0x8e, 0x63, 0x19, 0xc3, 0x70, 0x96, 0x17, 0x44, 0x49, 0x56, 0x1c, 0x36, 0x28, 0xb2, 0x24, 0xa, 0x3c, 0xab, 0xdf, 0x9d, 0x77, 0xca, 0x2e, 0xb7, 0xc7, 0xeb, 0xf3, 0x7, 0x2c, 0xf1, 0xfb, 0xbc, 0x1e, 0xb7, 0x4b, 0x76, 0xf2, 0x2d, 0xa7, 0x60, 0x83, 0xa1, 0x70, 0x24, 0x1a, 0x8b, 0x27, 0xb6, 0xc1, 0x86, 0xed, 0x44, 0x3c, 0x16, 0x8d, 0x84, 0x43, 0x41, 0xb6, 0x29, 0x3e, 0xd9, 0xd6, 0xde, 0xd1, 0xa9, 0x22, 0x84, 0x31, 0x6, 0xd, 0x4c, 0x40, 0x38, 0x85, 0xd, 0x4d, 0x3a, 0x3b, 0xda, 0xdb, 0x92, 0xd, 0xe, 0x4c, 0x97, 0xd2, 0xdd, 0xa3, 0xa2, 0x9d, 0xff, 0x6f, 0xdd, 0xbe, 0x43, 0xb9, 0x7b, 0x6f, 0x47, 0x73, 0x49, 0x21, 0x93, 0x73, 0xf4, 0x74, 0x2b, 0x5d, 0x4c, 0xfd, 0xfe, 0x92, 0xbb, 0x57, 0xc5, 0xf7, 0x1f, 0x3c, 0x7c, 0xf4, 0x18, 0x8, 0x8f, 0x9f, 0x3c, 0x7d, 0xf6, 0xfc, 0xfe, 0xb, 0xed, 0x24, 0x66, 0x37, 0xe9, 0x75, 0x4b, 0xb5, 0x77, 0x60, 0xfb, 0xfa, 0x7, 0x54, 0xfc, 0xf2, 0xd5, 0x6b, 0x68, 0xe0, 0xcd, 0xdb, 0x97, 0x2f, 0x2c, 0xdf, 0x62, 0xb0, 0xbf, 0xaf, 0x7a, 0x9, 0xbe, 0xcd, 0x33, 0x84, 0xde, 0xbd, 0x7f, 0x2, 0x4d, 0x7c, 0x78, 0xff, 0xf1, 0x31, 0x58, 0x30, 0x34, 0xdc, 0x36, 0x42, 0x8f, 0xc0, 0x8, 0xae, 0x51, 0xf4, 0xe9, 0xf3, 0x17, 0x68, 0xe1, 0xeb, 0xb7, 0x34, 0x58, 0x31, 0xea, 0x12, 0xa8, 0x1, 0x2b, 0xba, 0xc7, 0x50, 0xe6, 0x19, 0xe8, 0xc8, 0x66, 0x80, 0x92, 0xcb, 0x17, 0x8a, 0x25, 0xd8, 0x2d, 0x94, 0xd1, 0x64, 0xf, 0x8, 0xe3, 0x13, 0x93, 0xf4, 0xe, 0x9c, 0xe4, 0x89, 0xe3, 0xfd, 0x3, 0xd0, 0x71, 0xb0, 0xf, 0x94, 0xc3, 0xa3, 0xdc, 0x71, 0x21, 0xb7, 0x4b, 0x2, 0x35, 0xa1, 0x4c, 0xd, 0x4b, 0x1c, 0x35, 0x90, 0xa7, 0x67, 0xf0, 0xc9, 0x29, 0xe8, 0x38, 0x3d, 0xa9, 0x1c, 0x80, 0x4, 0x1d, 0x9d, 0xed, 0x9e, 0x13, 0x3, 0x22, 0x94, 0xed, 0x59, 0x99, 0xa7, 0x6, 0x6d, 0x73, 0x2a, 0xbe, 0x6d, 0xf0, 0x60, 0x8f, 0x6f, 0x13, 0x25, 0x41, 0x65, 0xb9, 0xc8, 0xef, 0x1e, 0x1e, 0x1e, 0xee, 0x69, 0x2, 0x94, 0xf9, 0xb6, 0x8a, 0x81, 0xec, 0x55, 0x2d, 0x4f, 0xb0, 0x47, 0x4e, 0x90, 0xbf, 0xdc, 0x25, 0x91, 0x44, 0x74, 0x27, 0x90, 0x3c, 0xb, 0xc8, 0xf2, 0xd, 0xce, 0xcf, 0x60, 0xaf, 0x58, 0xaa, 0x18, 0xe8, 0xdf, 0x80, 0x15, 0x27, 0x6c, 0x7e, 0x61, 0xb7, 0x78, 0x5e, 0xcc, 0x43, 0xab, 0x1, 0xfd, 0x5, 0x9a, 0x7, 0x8b, 0x36, 0x79, 0xb0, 0x77, 0x76, 0x5, 0x90, 0x2b, 0xed, 0x55, 0x84, 0xb2, 0x18, 0x16, 0x98, 0x5a, 0x26, 0x2e, 0xe1, 0x5f, 0xce, 0x44, 0x5a, 0xb, 0x83, 0x3f, 0x5f, 0xb, 0xcb, 0xb4, 0x16, 0xcc, 0xab, 0xf1, 0x9a, 0xc6, 0xdb, 0x57, 0x23, 0xed, 0x7, 0x2b, 0xab, 0x2a, 0xba, 0x69, 0xed, 0x7, 0xe6, 0x6c, 0xaf, 0xae, 0xd5, 0xfa, 0x1, 0xed, 0x48, 0x8a, 0x7b, 0x7d, 0x3, 0xa5, 0x10, 0x6d, 0x48, 0xb8, 0x2, 0x2a, 0x2f, 0x30, 0xa2, 0x73, 0xdd, 0xad, 0x24, 0x9b, 0x7b, 0x5a, 0x97, 0x14, 0xf6, 0x44, 0x63, 0x53, 0xdb, 0x60, 0xcb, 0xf6, 0x54, 0x2c, 0xea, 0x9, 0x4b, 0x5d, 0x6c, 0x6b, 0x57, 0xee, 0x93, 0x5d, 0x13, 0xc3, 0xb3, 0x9b, 0x1, 0x1b, 0x36, 0x67, 0x87, 0x27, 0x5c, 0x72, 0x1f, 0xcf, 0xe8, 0xa7, 0xca, 0x88, 0x30, 0xb9, 0xd5, 0x66, 0x3f, 0x17, 0xda, 0xb6, 0x26, 0x85, 0x11, 0x96, 0x31, 0x99, 0x4c, 0xfc, 0xf, 0x40, 0x27, 0xd3, 0xbf, 0xc4, 0x77, 0x82, 0xde, 0x40, 0xde, 0x4b, 0x3f, 0xe2, 0x98, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char toggle_off_disabled_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x20, 0x8, 0x3, 0x0, 0x0, 0x0, 0x95, 0x43, 0x8e, 0xb6, 0x0, 0x0, 0x0, 0xfc, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x14, 0x17, 0x20, 0x20, 0x25, 0x24, 0x24, 0x28, 0x24, 0x24, 0x29, 0x24, 0x24, 0x29, 0x25, 0x25, 0x2a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x10, 0x13, 0x22, 0x22, 0x27, 0x24, 0x24, 0x28, 0x25, 0x25, 0x28, 0x25, 0x25, 0x29, 0x25, 0x25, 0x27, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x19, 0x19, 0x1c, 0x2b, 0x26, 0x2c, 0x40, 0x40, 0x44, 0x4e, 0x4e, 0x52, 0x1a, 0x1a, 0x1d, 0x32, 0x32, 0x37, 0x2c, 0x26, 0x2c, 0x26, 0x25, 0x2a, 0x27, 0x25, 0x2a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x11, 0x14, 0x2f, 0x26, 0x2d, 0x12, 0x12, 0x14, 0x23, 0x23, 0x27, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x15, 0x15, 0x18, 0x20, 0x20, 0x25, 0x20, 0x20, 0x24, 0x5b, 0x5b, 0x5f, 0x84, 0x84, 0x87, 0x77, 0x77, 0x7a, 0x20, 0x20, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x69, 0x69, 0x6c, 0x24, 0x24, 0x28, 0x0, 0x0, 0x0, 0x24, 0x24, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x24, 0x27, 0x15, 0x15, 0x18, 0x23, 0x23, 0x28, 0x12, 0x12, 0x14, 0x0, 0x0, 0x0, 0x1a, 0x1a, 0x1e, 0x0, 0x0, 0x0, 0x11, 0x11, 0x13, 0x22, 0x22, 0x26, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x71, 0xb, 0x1b, 0xbb, 0x0, 0x0, 0x0, 0x54, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x1, 0x2, 0x3, 0x4, 0x9, 0xe, 0x13, 0x16, 0x18, 0x19, 0xa, 0x26, 0x36, 0x44, 0x4d, 0x52, 0x54, 0x55, 0x6, 0x12, 0x27, 0x43, 0x98, 0xe5, 0xfa, 0xfe, 0xff, 0xff, 0x8, 0x17, 0x35, 0x86, 0xf3, 0xff, 0xff, 0xff, 0xff, 0x7, 0x3a, 0xb4, 0xff, 0xff, 0xff, 0xb9, 0xff, 0xff, 0xff, 0xff, 0xb, 0x28, 0x8a, 0xff, 0x8b, 0xf6, 0x45, 0x5, 0x9b, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x37, 0xf, 0xff, 0xfb, 0x4c, 0xfe, 0x4e, 0x4f, 0x50, 0xfb, 0x9c, 0xf6, 0x8c, 0x3b, 0xbb, 0x3c, 0x87, 0xf3, 0x53, 0x14, 0xd4, 0x6d, 0x6c, 0xf9, 0x0, 0x0, 0x2, 0x3, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xdd, 0x55, 0x85, 0x9a, 0xe2, 0x30, 0x18, 0xbc, 0x7a, 0x8b, 0xbb, 0x7b, 0x2, 0xbb, 0x4d, 0x36, 0xb8, 0x3b, 0xeb, 0xae, 0xef, 0xff, 0x2e, 0x47, 0x48, 0x3f, 0xa0, 0x7a, 0xae, 0x83, 0x56, 0xfe, 0xe9, 0xfc, 0xfe, 0xe9, 0x6f, 0x2, 0xc7, 0xb, 0x82, 0xf8, 0x45, 0x8, 0x2, 0xcf, 0x39, 0x9a, 0xf3, 0xa2, 0x24, 0x2b, 0xaa, 0xe6, 0xfb, 0x2, 0x34, 0x55, 0x91, 0x25, 0x91, 0xb7, 0x3f, 0x5d, 0xf4, 0xab, 0x81, 0x60, 0x28, 0x1c, 0x89, 0xc6, 0x3c, 0x11, 0x8d, 0x84, 0x43, 0xc1, 0x80, 0xea, 0x17, 0x2d, 0x2a, 0xf8, 0x78, 0x22, 0x99, 0x4a, 0x67, 0xb2, 0xb9, 0x7c, 0xe1, 0xb, 0xc8, 0xe7, 0xb2, 0x99, 0x74, 0x2a, 0x99, 0x88, 0xf3, 0x26, 0xfb, 0x62, 0xa9, 0x5c, 0xa9, 0xd6, 0x0, 0x80, 0x10, 0xb2, 0xfb, 0x20, 0x5, 0x80, 0x75, 0xe8, 0x48, 0x52, 0xad, 0x94, 0x4b, 0xc5, 0x23, 0x6, 0xae, 0xa1, 0x9d, 0x9c, 0xd6, 0x80, 0x8e, 0xf0, 0x1e, 0x48, 0xdf, 0xb1, 0xd4, 0x81, 0x8b, 0x8e, 0xd3, 0x13, 0xad, 0xc1, 0x1d, 0xfc, 0x57, 0x82, 0x67, 0x35, 0x48, 0x30, 0x6a, 0xb6, 0x76, 0x97, 0x5b, 0x3a, 0x41, 0x98, 0xb4, 0x77, 0x4a, 0xdc, 0x3c, 0x39, 0xb, 0x2a, 0xfb, 0x38, 0xf0, 0x9d, 0x6e, 0xaf, 0x6, 0x11, 0xea, 0x1f, 0xdf, 0x41, 0x10, 0x6a, 0x7b, 0xc6, 0x62, 0xd0, 0xed, 0xf0, 0x6, 0x81, 0x58, 0xa, 0xd, 0x1, 0xa1, 0xa2, 0x8f, 0xa1, 0x23, 0xd2, 0xf2, 0x62, 0x18, 0x8e, 0x4a, 0x63, 0x26, 0x81, 0x93, 0x2, 0x13, 0xa0, 0xe3, 0xbe, 0xf5, 0xe, 0x82, 0x3d, 0x25, 0x14, 0x26, 0x1, 0x89, 0x11, 0xf0, 0x72, 0x70, 0xba, 0x15, 0x60, 0xbf, 0x3, 0x11, 0xe3, 0xcf, 0x6c, 0xbe, 0x58, 0xa2, 0x42, 0x7f, 0xb1, 0xc5, 0xee, 0x8b, 0x9d, 0x5f, 0xad, 0x37, 0xcc, 0x7, 0x41, 0x9, 0x65, 0x21, 0xbd, 0xd9, 0x8a, 0x3d, 0xe9, 0xf9, 0x7c, 0x46, 0x16, 0xb3, 0x3e, 0x35, 0xa4, 0x5f, 0x6, 0x2e, 0x46, 0x8a, 0xc0, 0x8, 0xd4, 0xcb, 0x2b, 0x88, 0x75, 0x3b, 0x81, 0x8e, 0xd, 0x1, 0xd4, 0x68, 0x8e, 0xfa, 0xe7, 0x94, 0xe0, 0x7c, 0x4f, 0x90, 0xbf, 0x56, 0x45, 0x46, 0x50, 0xba, 0xa9, 0x41, 0xec, 0x10, 0xb0, 0x96, 0x41, 0xd0, 0x3f, 0xdf, 0x7e, 0xe1, 0x79, 0xff, 0xfc, 0xfc, 0x9c, 0x6c, 0xbf, 0xf6, 0x14, 0xb7, 0x25, 0x83, 0x40, 0xd, 0xd7, 0x3c, 0x15, 0x90, 0x9d, 0x2, 0xec, 0xae, 0x40, 0x9, 0xdd, 0x1, 0xef, 0x18, 0xa0, 0x2, 0x59, 0xda, 0x5c, 0xd8, 0xc7, 0x80, 0x97, 0xd7, 0x5f, 0xc8, 0x42, 0x7f, 0x79, 0xbe, 0x9c, 0x17, 0x2c, 0x4, 0xfb, 0x2c, 0xd0, 0x3a, 0xb8, 0xff, 0x42, 0x1d, 0x10, 0x5a, 0x95, 0x33, 0x44, 0xd8, 0x97, 0x81, 0xfb, 0xa4, 0xc4, 0xed, 0x2b, 0xf1, 0x1, 0xfe, 0x40, 0x25, 0xd2, 0x5e, 0x18, 0x7c, 0x7b, 0x2f, 0x3c, 0xd2, 0x5e, 0xf8, 0x72, 0x37, 0x16, 0xbe, 0xdc, 0x8d, 0x6c, 0x1e, 0x3c, 0x3d, 0xd7, 0x40, 0xdb, 0x32, 0xf, 0xbc, 0xec, 0x9f, 0x5f, 0xf6, 0xf3, 0x80, 0x4d, 0x24, 0x2d, 0xf8, 0xfa, 0x6, 0xea, 0x80, 0xd, 0x24, 0x68, 0x0, 0x6c, 0x5f, 0x8e, 0xf6, 0xd5, 0xd7, 0xa0, 0x56, 0x34, 0xcf, 0xb4, 0x86, 0x92, 0xc, 0xa5, 0x33, 0x17, 0xf9, 0xc2, 0x17, 0x91, 0xbf, 0xc8, 0xa4, 0x43, 0x49, 0xa5, 0xc1, 0x5b, 0xa7, 0x72, 0x47, 0xd, 0xac, 0x47, 0xd7, 0xef, 0xb1, 0x2f, 0xe0, 0xfd, 0x7a, 0xb4, 0xe, 0xa8, 0x1d, 0x91, 0xb3, 0x6f, 0x95, 0xb1, 0xb4, 0xf9, 0x28, 0x7d, 0x79, 0x2f, 0x94, 0x3e, 0x36, 0xd2, 0x98, 0xe7, 0x5c, 0x36, 0x93, 0xf8, 0x15, 0xa0, 0x9b, 0xe9, 0xff, 0xc2, 0x67, 0x14, 0xf4, 0xa5, 0xb3, 0x35, 0x5e, 0x63, 0x97, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char toggle_off_disabled_mirrored_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x20, 0x8, 0x3, 0x0, 0x0, 0x0, 0x95, 0x43, 0x8e, 0xb6, 0x0, 0x0, 0x0, 0x9c, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xd, 0xd, 0xf, 0x1a, 0x1a, 0x1e, 0x20, 0x20, 0x24, 0x22, 0x22, 0x27, 0x24, 0x24, 0x29, 0x25, 0x25, 0x2a, 0x1d, 0x1d, 0x21, 0x11, 0x11, 0x14, 0x23, 0x23, 0x28, 0x2e, 0x2e, 0x2e, 0x46, 0x46, 0x46, 0x57, 0x57, 0x57, 0x60, 0x60, 0x60, 0x62, 0x62, 0x62, 0x5e, 0x5e, 0x5e, 0x4a, 0x4a, 0x4a, 0x12, 0x12, 0x15, 0x25, 0x27, 0x2d, 0x42, 0x42, 0x42, 0x59, 0x59, 0x59, 0x32, 0x32, 0x32, 0x25, 0x26, 0x2d, 0x25, 0x25, 0x2b, 0x25, 0x26, 0x2c, 0x39, 0x39, 0x39, 0x49, 0x49, 0x49, 0x5a, 0x5a, 0x5a, 0x48, 0x48, 0x48, 0x54, 0x54, 0x54, 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x1e, 0x1e, 0x22, 0x25, 0x26, 0x2b, 0x3f, 0x3f, 0x3f, 0xe, 0xe, 0x10, 0x2c, 0x2c, 0x2c, 0x58, 0x58, 0x58, 0x5d, 0x5d, 0x5f, 0x80, 0x80, 0x80, 0x79, 0x79, 0x79, 0x40, 0x40, 0x44, 0x32, 0x32, 0x37, 0x41, 0x41, 0x41, 0x1a, 0x1a, 0x1d, 0x6a, 0x6a, 0x6d, 0x52, 0x52, 0x52, 0x3a, 0x3a, 0x3a, 0x5b, 0x5b, 0x5b, 0x2f, 0x2f, 0x2f, 0x50, 0x50, 0x51, 0x13, 0x13, 0x15, 0x2b, 0xcd, 0x4, 0x96, 0x0, 0x0, 0x0, 0x1, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x40, 0xe6, 0xd8, 0x66, 0x0, 0x0, 0x1, 0x29, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xed, 0x94, 0xdb, 0x76, 0x83, 0x20, 0x10, 0x45, 0x8d, 0xe8, 0x24, 0x98, 0xda, 0x1a, 0x93, 0xda, 0x5b, 0xac, 0xb9, 0x50, 0x14, 0x52, 0x72, 0xfd, 0xff, 0x7f, 0xab, 0x68, 0x49, 0x28, 0x5a, 0x35, 0xf5, 0xa5, 0xf, 0x39, 0xf, 0xb3, 0x96, 0xe3, 0xda, 0x7, 0x98, 0x81, 0xb1, 0xac, 0x9b, 0xfe, 0x97, 0x6, 0x36, 0x72, 0x5c, 0x68, 0x91, 0xeb, 0x20, 0x7b, 0x50, 0xcf, 0xf, 0x5b, 0xe1, 0xb3, 0xc9, 0xb0, 0x6, 0x1f, 0xe1, 0x46, 0xc6, 0x1b, 0xdf, 0xf9, 0xf7, 0xa5, 0x1e, 0x2, 0xf, 0xf0, 0xc8, 0xe4, 0x27, 0x8d, 0xcb, 0x87, 0xd3, 0xd9, 0xf8, 0x31, 0x7a, 0x92, 0x7a, 0xf6, 0x5e, 0x5e, 0xdf, 0xa6, 0xa1, 0x3b, 0x31, 0xc, 0x1a, 0xd7, 0xf, 0xe7, 0xf1, 0xbb, 0xfe, 0x9d, 0xc4, 0xf3, 0x10, 0xff, 0xe4, 0x17, 0x4d, 0xfc, 0x72, 0x15, 0x7b, 0xc6, 0x81, 0xe2, 0xd5, 0x72, 0xa1, 0xf3, 0xeb, 0xc6, 0xf3, 0x93, 0x8f, 0xc4, 0x4c, 0x25, 0x33, 0x2, 0x6b, 0xcd, 0xc0, 0x56, 0x3f, 0x10, 0x4d, 0x33, 0x6, 0x24, 0xcd, 0x55, 0x4, 0x2e, 0x93, 0x9b, 0xa0, 0x6a, 0x1a, 0x6c, 0xe0, 0x53, 0x33, 0x40, 0x2a, 0x2f, 0x28, 0xe2, 0x29, 0x22, 0x12, 0x24, 0x25, 0x9d, 0x6b, 0xbb, 0xab, 0x1a, 0xec, 0xb6, 0x80, 0x34, 0x3, 0x47, 0x6d, 0x40, 0x42, 0x94, 0x11, 0x21, 0xd, 0x84, 0x32, 0xd8, 0x1f, 0xaa, 0x6, 0x87, 0x3d, 0xe8, 0x65, 0x54, 0x3d, 0x24, 0x22, 0xf, 0x47, 0x4a, 0x84, 0x10, 0xbc, 0x8, 0x45, 0xd6, 0x8f, 0xaa, 0x6, 0x91, 0xf, 0x50, 0xd3, 0x44, 0x5e, 0xec, 0xe0, 0x78, 0xfd, 0xe, 0x2e, 0x35, 0x60, 0xc0, 0x33, 0xf3, 0x8, 0x1d, 0x6a, 0x70, 0xee, 0x2, 0xc9, 0x44, 0x46, 0xc1, 0x30, 0xe8, 0xd0, 0x85, 0xcb, 0x3d, 0xe0, 0x4c, 0xd6, 0x92, 0xf1, 0xef, 0xd0, 0xf5, 0x1e, 0xf4, 0xbe, 0x89, 0xfd, 0xdf, 0x42, 0xff, 0xd7, 0x68, 0x9d, 0xae, 0x9b, 0x7, 0xa7, 0xba, 0x89, 0x4, 0x9d, 0x55, 0x37, 0x91, 0xca, 0x99, 0x88, 0xdb, 0x61, 0xfc, 0xeb, 0x4c, 0xbc, 0xe9, 0xaf, 0xfa, 0x2, 0xdc, 0x1a, 0x30, 0x60, 0x4e, 0xef, 0xb8, 0xbb, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char toggle_off_mirrored_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x20, 0x8, 0x3, 0x0, 0x0, 0x0, 0x95, 0x43, 0x8e, 0xb6, 0x0, 0x0, 0x1, 0xaa, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xd, 0xf, 0x1a, 0x1a, 0x1e, 0x20, 0x20, 0x24, 0x22, 0x22, 0x27, 0x24, 0x24, 0x29, 0x24, 0x24, 0x28, 0x20, 0x20, 0x25, 0x14, 0x14, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xa, 0xc, 0x1d, 0x1d, 0x21, 0x22, 0x22, 0x27, 0x10, 0x10, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x11, 0x14, 0x23, 0x23, 0x28, 0x19, 0x19, 0x1c, 0x12, 0x12, 0x15, 0x1a, 0x1a, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xb, 0xd, 0x23, 0x23, 0x28, 0x11, 0x11, 0x14, 0x1e, 0x1e, 0x22, 0x23, 0x23, 0x27, 0xe, 0xe, 0x10, 0x15, 0x15, 0x18, 0x1a, 0x1a, 0x1e, 0x20, 0x20, 0x25, 0x0, 0x0, 0x0, 0x24, 0x24, 0x28, 0x0, 0x0, 0x0, 0x20, 0x20, 0x24, 0x24, 0x24, 0x27, 0x0, 0x0, 0x0, 0xe, 0xe, 0x10, 0x15, 0x15, 0x18, 0x23, 0x23, 0x28, 0xb, 0xb, 0xd, 0x12, 0x12, 0x14, 0x0, 0x0, 0x0, 0x13, 0x13, 0x15, 0x1a, 0x1a, 0x1e, 0xb, 0xb, 0xc, 0x1d, 0x1d, 0x21, 0x22, 0x22, 0x26, 0x11, 0x11, 0x13, 0x24, 0x24, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x25, 0x25, 0x2a, 0x24, 0x24, 0x29, 0x25, 0x25, 0x28, 0x25, 0x25, 0x29, 0x24, 0x24, 0x28, 0x2d, 0x26, 0x2c, 0x51, 0x2c, 0x39, 0x6c, 0x31, 0x42, 0x71, 0x32, 0x44, 0x6e, 0x31, 0x43, 0x63, 0x2f, 0x3f, 0x4d, 0x2b, 0x37, 0x27, 0x25, 0x2a, 0x47, 0x2a, 0x35, 0x68, 0x30, 0x40, 0x52, 0x2c, 0x39, 0x3c, 0x28, 0x31, 0x2e, 0x25, 0x2c, 0x26, 0x25, 0x2a, 0x32, 0x26, 0x2e, 0x4d, 0x2b, 0x38, 0x66, 0x30, 0x40, 0x50, 0x2c, 0x38, 0x5e, 0x2e, 0x3d, 0x38, 0x27, 0x30, 0x35, 0x27, 0x2f, 0x5f, 0x2e, 0x3d, 0x44, 0x2a, 0x34, 0x5f, 0x2f, 0x3e, 0x2f, 0x25, 0x2c, 0x43, 0x2a, 0x34, 0x2c, 0x26, 0x2c, 0x66, 0x2f, 0x40, 0x37, 0x27, 0x30, 0x36, 0x27, 0x30, 0x64, 0x2f, 0x3f, 0x2b, 0x26, 0x2c, 0x40, 0x40, 0x44, 0xad, 0xad, 0xaf, 0xff, 0xff, 0xff, 0xf2, 0xf2, 0xf2, 0x77, 0x77, 0x7a, 0x5b, 0x5b, 0x5f, 0x32, 0x32, 0x37, 0x46, 0x2a, 0x35, 0x53, 0x2c, 0x39, 0xc9, 0xc9, 0xca, 0xbb, 0xbb, 0xbd, 0x69, 0x69, 0x6c, 0x5d, 0x2e, 0x3d, 0x3e, 0x29, 0x32, 0x84, 0x84, 0x87, 0xd6, 0xd6, 0xd7, 0x69, 0x30, 0x41, 0x2f, 0x26, 0x2d, 0x92, 0x92, 0x94, 0xa0, 0xa0, 0xa2, 0x4e, 0x4e, 0x52, 0x48, 0x2b, 0x36, 0x2c, 0x26, 0x2b, 0x25, 0x25, 0x27, 0xea, 0xac, 0x78, 0x5d, 0x0, 0x0, 0x0, 0x51, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x1, 0x2, 0x3, 0x4, 0x9, 0xe, 0x13, 0x16, 0x18, 0x19, 0xa, 0x26, 0x36, 0x44, 0x4d, 0x52, 0x54, 0x55, 0x6, 0x12, 0x27, 0x43, 0x80, 0xc5, 0xe7, 0xf5, 0xfe, 0xfa, 0xe5, 0x98, 0x8, 0x17, 0x35, 0x73, 0xd9, 0xf3, 0x86, 0x7, 0x3a, 0x96, 0xf9, 0xb4, 0x9a, 0xb9, 0xb, 0x28, 0x76, 0xfb, 0x8a, 0xde, 0xf6, 0x82, 0x9b, 0xc6, 0xe6, 0x4c, 0xfe, 0x4f, 0xe9, 0xfb, 0x37, 0x83, 0x9c, 0xf6, 0x77, 0x8b, 0x3b, 0x9c, 0xbb, 0x74, 0xda, 0xf3, 0x87, 0xfb, 0x45, 0x4e, 0x53, 0x5, 0xf, 0x14, 0xc7, 0x22, 0x44, 0x61, 0x0, 0x0, 0x2, 0x45, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xd5, 0x55, 0xe7, 0x5f, 0xd3, 0x40, 0x18, 0x26, 0x3b, 0x91, 0x24, 0x65, 0x95, 0xd, 0xd, 0x8e, 0x22, 0x6a, 0x71, 0x2b, 0x82, 0x75, 0xe1, 0x66, 0xa6, 0x97, 0xa0, 0x56, 0x45, 0xa4, 0x2a, 0x2e, 0xdc, 0x76, 0x25, 0x18, 0x84, 0x6, 0x9c, 0xff, 0xb3, 0xb9, 0x26, 0x17, 0xda, 0xa4, 0x49, 0xd4, 0x4f, 0xfa, 0x7c, 0xb8, 0xdf, 0xe5, 0xcd, 0xef, 0x79, 0xee, 0xbd, 0xf7, 0xde, 0xd1, 0xd4, 0xf4, 0xf, 0x1, 0xc3, 0x9, 0x82, 0x8c, 0x4, 0x41, 0xe0, 0x58, 0x43, 0x3a, 0x4e, 0x52, 0x34, 0xc3, 0x72, 0xbb, 0x22, 0xc0, 0xb1, 0xc, 0x4d, 0x91, 0xb8, 0xff, 0x74, 0xb2, 0x99, 0xe5, 0x5, 0x31, 0xd6, 0xd2, 0xda, 0x16, 0x8a, 0xd6, 0x96, 0x98, 0x28, 0xf0, 0x6c, 0x33, 0xe9, 0xf1, 0x2, 0x6f, 0xef, 0x88, 0x77, 0x76, 0x75, 0xf7, 0xf4, 0xf6, 0xc9, 0x11, 0xc8, 0xf4, 0xf5, 0xf, 0xc, 0x76, 0xc6, 0x3b, 0xda, 0xeb, 0x9c, 0xc0, 0x13, 0xd2, 0xd0, 0xee, 0x3d, 0x99, 0x0, 0xe, 0x50, 0x20, 0xec, 0xbd, 0xb5, 0x1, 0x40, 0xdd, 0xbb, 0x6f, 0x48, 0x4a, 0xd4, 0x28, 0x60, 0x49, 0x6e, 0x78, 0xff, 0x48, 0xe0, 0xa1, 0x90, 0xbb, 0x70, 0xeb, 0xf6, 0x1d, 0x1b, 0xd9, 0xbb, 0xf7, 0x16, 0x80, 0x7a, 0x60, 0x98, 0x4b, 0x62, 0x3b, 0xf7, 0x67, 0x84, 0x83, 0xa1, 0xbe, 0xdf, 0x5f, 0x7c, 0xb0, 0xf4, 0x70, 0x39, 0x57, 0xdd, 0xe7, 0x1e, 0x3d, 0x7e, 0xb2, 0xa8, 0xa8, 0x87, 0x4, 0xc6, 0x8d, 0x3, 0x9e, 0x1a, 0x3d, 0x7c, 0x24, 0x94, 0xbf, 0xf2, 0xf4, 0x59, 0xed, 0xf7, 0xf3, 0x17, 0x2b, 0x8a, 0x7a, 0x74, 0x34, 0x85, 0x2e, 0x41, 0x4a, 0xe2, 0xb1, 0x30, 0x7e, 0xee, 0xe5, 0xea, 0xab, 0x7a, 0xcb, 0xf2, 0xea, 0x6b, 0x70, 0x5c, 0x94, 0x48, 0xe7, 0x6, 0x14, 0x7f, 0x22, 0x34, 0xf0, 0x6f, 0xde, 0xbe, 0xf3, 0x9a, 0xde, 0x7f, 0xf8, 0x8, 0x4e, 0xf2, 0x94, 0x73, 0x3, 0x5a, 0x38, 0x85, 0x7e, 0xe4, 0xb, 0xc5, 0x52, 0x59, 0xd6, 0x8a, 0x16, 0xaa, 0x8b, 0xe, 0x8d, 0x6b, 0x9f, 0xfc, 0xa2, 0x4b, 0x6b, 0xe0, 0xb4, 0x40, 0xdb, 0x2, 0x4, 0x23, 0xf6, 0x20, 0xbb, 0xb1, 0x9e, 0xff, 0x5c, 0xcc, 0x6b, 0x90, 0xa8, 0xd9, 0x6c, 0xb, 0x1b, 0x9b, 0x7e, 0x81, 0xcd, 0xd, 0xa5, 0x5f, 0x64, 0x1c, 0x1, 0x76, 0xac, 0x17, 0x39, 0x0, 0x49, 0xeb, 0x15, 0xcd, 0x84, 0x2, 0x26, 0x12, 0xd8, 0xda, 0xf6, 0xb, 0x6c, 0x6f, 0x29, 0x67, 0xc6, 0x58, 0x47, 0x40, 0x1a, 0x47, 0x6f, 0xa8, 0x99, 0xd6, 0xf2, 0xa5, 0xa0, 0x19, 0x86, 0xa1, 0x57, 0x97, 0xaa, 0x35, 0x9b, 0x6b, 0x10, 0xd8, 0xac, 0xa2, 0x8e, 0x4b, 0xc8, 0x83, 0x18, 0x4a, 0x22, 0x1d, 0x7a, 0x50, 0xf8, 0xaa, 0x41, 0xa6, 0x66, 0x44, 0x78, 0xa0, 0xc6, 0x58, 0x37, 0x6, 0x13, 0xc8, 0x6e, 0x56, 0x64, 0xbd, 0x54, 0xf6, 0x8, 0x34, 0x8e, 0x1, 0x38, 0x8b, 0x62, 0x80, 0xd3, 0x69, 0xf7, 0x15, 0xb4, 0x92, 0x59, 0x2a, 0xc8, 0x1e, 0x81, 0xa0, 0x57, 0x48, 0xd3, 0x6e, 0x1e, 0x9c, 0x73, 0x7f, 0xe8, 0x95, 0x6f, 0x56, 0x2c, 0xcb, 0xba, 0xb3, 0x84, 0xe5, 0xc1, 0x79, 0x94, 0x7, 0x7f, 0x97, 0x89, 0xca, 0x5, 0x37, 0x13, 0x61, 0x2d, 0x5c, 0xfc, 0xf3, 0x5a, 0xb8, 0xb4, 0x53, 0xb, 0xbf, 0x51, 0x8d, 0xdf, 0x43, 0xab, 0x11, 0xf6, 0x83, 0xc9, 0xcb, 0xa1, 0x3e, 0xd4, 0xf7, 0x83, 0x1f, 0x40, 0xbd, 0x32, 0x59, 0xd3, 0xf, 0x60, 0x47, 0xe2, 0x84, 0xab, 0xd7, 0x82, 0xc8, 0x76, 0x47, 0x72, 0x9a, 0x92, 0xd5, 0x91, 0x7e, 0x82, 0xeb, 0x37, 0x4, 0x2e, 0x51, 0xdf, 0xd3, 0x92, 0x4c, 0x5c, 0xec, 0xea, 0x9e, 0x18, 0x91, 0x23, 0x91, 0xb9, 0x39, 0x30, 0x28, 0xc6, 0x99, 0xa4, 0xa7, 0x31, 0x63, 0x64, 0x8a, 0xe5, 0xd3, 0x53, 0xd3, 0x33, 0x6d, 0x11, 0x98, 0x99, 0x9e, 0x4a, 0xf3, 0x6c, 0x8a, 0xf4, 0xcd, 0x6, 0xc, 0x9f, 0xa5, 0xe6, 0xe6, 0xa5, 0xe8, 0xb9, 0x20, 0xcd, 0xcf, 0x51, 0xb3, 0x8d, 0x67, 0x8b, 0x35, 0x99, 0xa2, 0x7, 0x93, 0x35, 0x9a, 0x2, 0x26, 0xd3, 0xff, 0x8b, 0x5f, 0x3d, 0xdc, 0x7c, 0xb4, 0x8c, 0xb2, 0xd8, 0x5f, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char toggle_on_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x20, 0x8, 0x3, 0x0, 0x0, 0x0, 0x95, 0x43, 0x8e, 0xb6, 0x0, 0x0, 0x1, 0x74, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xd, 0xf, 0x1a, 0x1a, 0x1e, 0x20, 0x20, 0x24, 0x22, 0x22, 0x27, 0x24, 0x24, 0x29, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xa, 0xc, 0x1d, 0x1d, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x11, 0x14, 0x23, 0x23, 0x28, 0x12, 0x12, 0x15, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xb, 0xd, 0x23, 0x23, 0x28, 0xb, 0xb, 0xd, 0x1e, 0x1e, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0xe, 0x10, 0x1a, 0x1a, 0x1e, 0x1a, 0x1a, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x20, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0xe, 0x10, 0xb, 0xb, 0xd, 0x0, 0x0, 0x0, 0x13, 0x13, 0x15, 0x0, 0x0, 0x0, 0xb, 0xb, 0xc, 0x1d, 0x1d, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x25, 0x25, 0x2a, 0x24, 0x24, 0x29, 0x25, 0x2c, 0x36, 0x27, 0x49, 0x65, 0x29, 0x5d, 0x85, 0x2a, 0x66, 0x95, 0x2a, 0x68, 0x99, 0x29, 0x64, 0x92, 0x28, 0x4c, 0x6b, 0x25, 0x27, 0x2d, 0x27, 0x43, 0x5c, 0x29, 0x5f, 0x89, 0x27, 0x49, 0x66, 0x25, 0x30, 0x3e, 0x25, 0x26, 0x2d, 0x25, 0x25, 0x2b, 0x25, 0x26, 0x2c, 0x25, 0x2d, 0x38, 0x25, 0x3a, 0x4c, 0x27, 0x4d, 0x6b, 0x29, 0x60, 0x8c, 0x27, 0x44, 0x5c, 0x27, 0x4b, 0x69, 0x28, 0x59, 0x7f, 0x25, 0x34, 0x43, 0x25, 0x35, 0x45, 0x28, 0x58, 0x7f, 0x25, 0x26, 0x2b, 0x27, 0x40, 0x57, 0x27, 0x41, 0x57, 0x25, 0x2a, 0x33, 0x29, 0x5d, 0x87, 0x25, 0x34, 0x44, 0x25, 0x2b, 0x34, 0x40, 0x40, 0x44, 0xad, 0xad, 0xaf, 0xff, 0xff, 0xff, 0xf2, 0xf2, 0xf2, 0x77, 0x77, 0x7a, 0x5b, 0x5b, 0x5f, 0x4e, 0x4e, 0x52, 0xc9, 0xc9, 0xca, 0x27, 0x43, 0x5b, 0x27, 0x4d, 0x6c, 0x27, 0x4e, 0x6d, 0xbb, 0xbb, 0xbd, 0x69, 0x69, 0x6c, 0x28, 0x56, 0x7b, 0x26, 0x3b, 0x4e, 0x26, 0x3a, 0x4e, 0x32, 0x32, 0x37, 0x84, 0x84, 0x87, 0xd6, 0xd6, 0xd7, 0x29, 0x61, 0x8d, 0x25, 0x2e, 0x39, 0x92, 0x92, 0x94, 0xa0, 0xa0, 0xa2, 0xe4, 0xe4, 0xe5, 0x27, 0x44, 0x5d, 0xdd, 0xc9, 0xf2, 0x7e, 0x0, 0x0, 0x0, 0x41, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x1, 0x2, 0x3, 0x4, 0x9, 0xe, 0x13, 0x16, 0x18, 0x19, 0xa, 0x26, 0x36, 0x44, 0x4d, 0x52, 0x54, 0x55, 0x6, 0x12, 0x27, 0x43, 0x80, 0xc5, 0xe7, 0xf5, 0xfe, 0x8, 0x17, 0x35, 0x73, 0xd9, 0x7, 0x3a, 0x96, 0xf9, 0x9a, 0xb, 0x28, 0x76, 0xfb, 0x77, 0xde, 0x45, 0x5, 0x82, 0xc6, 0xc6, 0x37, 0xf, 0xe9, 0x4c, 0x4e, 0x4f, 0x50, 0x83, 0x78, 0x3b, 0x9c, 0x3c, 0x74, 0xda, 0x53, 0x14, 0x37, 0x21, 0x5a, 0x6c, 0x0, 0x0, 0x2, 0x4, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xdd, 0x95, 0x63, 0x83, 0xdc, 0x60, 0x10, 0xc7, 0x1b, 0x3c, 0xc1, 0xda, 0x3e, 0xdb, 0x36, 0xe7, 0x6c, 0xdb, 0xa, 0xcf, 0xc6, 0x7e, 0xf8, 0x2a, 0x6d, 0xb8, 0xac, 0x7b, 0xbf, 0xf7, 0xf3, 0x1f, 0xcf, 0x7c, 0xf8, 0x97, 0xc0, 0x70, 0x82, 0x20, 0xb3, 0x42, 0x10, 0x38, 0x96, 0xd2, 0x1c, 0x27, 0x11, 0x45, 0x33, 0xac, 0x2d, 0xb, 0x2c, 0x43, 0x53, 0x88, 0xc4, 0xad, 0xde, 0x49, 0x3b, 0xe3, 0x70, 0xba, 0xdc, 0x1e, 0xaf, 0x2f, 0x23, 0x5e, 0x8f, 0xdb, 0xe5, 0x74, 0x30, 0x76, 0xd2, 0x14, 0x5, 0xee, 0xf, 0x4, 0x43, 0xe1, 0x48, 0x34, 0x16, 0x87, 0x2c, 0xc4, 0x63, 0xd1, 0x48, 0x38, 0x14, 0xc, 0xf8, 0x71, 0x83, 0x7d, 0xa2, 0xa0, 0xb0, 0xa8, 0x78, 0x4, 0x72, 0x64, 0xa4, 0xb8, 0xa8, 0xb0, 0x20, 0xa1, 0x53, 0xc0, 0x4a, 0xd8, 0xd2, 0xb2, 0x72, 0xc8, 0xc4, 0xe8, 0xd8, 0xf8, 0xc4, 0xa4, 0xc2, 0xd4, 0xf4, 0x28, 0x94, 0x97, 0x95, 0xb2, 0x25, 0x98, 0x96, 0x3f, 0xed, 0xac, 0xc8, 0x18, 0xfb, 0xcc, 0xec, 0xdc, 0xfc, 0xc2, 0xe2, 0xd2, 0x17, 0x96, 0x57, 0x56, 0xd7, 0xd6, 0x37, 0x66, 0xe2, 0x15, 0x4e, 0x5a, 0xad, 0x3, 0x5e, 0x59, 0x55, 0x5d, 0x93, 0xd1, 0x7e, 0x73, 0x6b, 0x1b, 0x74, 0xec, 0xec, 0x6e, 0xce, 0xd4, 0xd4, 0x56, 0x55, 0x7e, 0x4f, 0x82, 0x2c, 0x70, 0xd5, 0x41, 0x6, 0xf6, 0xf6, 0xb7, 0x56, 0xc0, 0xc0, 0xca, 0xd6, 0xc1, 0x5e, 0x5d, 0x7d, 0x41, 0x83, 0x12, 0x2, 0x86, 0x1c, 0x8d, 0x90, 0x89, 0xc3, 0xa3, 0x63, 0x30, 0xb1, 0x33, 0x77, 0x2, 0x8d, 0xe, 0xa4, 0x8, 0xe0, 0x94, 0xb3, 0x9, 0x54, 0x4e, 0xcf, 0x38, 0x5e, 0x0, 0x91, 0x93, 0x40, 0x94, 0x41, 0xe1, 0xfc, 0x2, 0x2c, 0x5c, 0x9e, 0x43, 0x73, 0x4b, 0xab, 0x92, 0x3, 0x41, 0xbb, 0xa2, 0xa0, 0x22, 0x5f, 0x9d, 0x5e, 0x73, 0xa7, 0x22, 0x27, 0x6b, 0x2, 0x37, 0xb7, 0x60, 0xe1, 0xee, 0x6, 0xda, 0xea, 0x69, 0x42, 0x11, 0x60, 0xda, 0x63, 0x5a, 0x0, 0xdc, 0x3d, 0xc0, 0xd5, 0x83, 0xf8, 0xc8, 0x8b, 0xaa, 0xc0, 0xd3, 0x33, 0x58, 0x78, 0x7e, 0x82, 0xf2, 0xe, 0x86, 0x54, 0x4, 0xa, 0x3a, 0xb5, 0x1e, 0x8a, 0x8f, 0x0, 0xf0, 0x72, 0x26, 0xca, 0x2f, 0x8f, 0xaa, 0xc0, 0xc4, 0x22, 0x58, 0x58, 0x9c, 0x0, 0xe8, 0x2a, 0xf8, 0x26, 0xc0, 0xb8, 0xb5, 0x21, 0xba, 0xff, 0x12, 0xc1, 0xd9, 0xeb, 0x67, 0xe3, 0xb7, 0xb3, 0x9c, 0x23, 0xa0, 0x5d, 0x6d, 0xa0, 0xf2, 0xf8, 0x0, 0xf7, 0xbc, 0xf0, 0x59, 0x40, 0xe0, 0x72, 0xad, 0x1, 0x4e, 0xb5, 0xe8, 0xba, 0x20, 0xf2, 0x8f, 0xfc, 0xd9, 0xd7, 0x2, 0x3e, 0xe6, 0xda, 0x5, 0xc, 0x39, 0xba, 0x41, 0xe3, 0xfe, 0x41, 0x2, 0x38, 0x15, 0x0, 0x24, 0x21, 0xf3, 0x1c, 0x74, 0x7, 0x11, 0xf6, 0xd3, 0x93, 0xa8, 0xee, 0x42, 0x6d, 0xfe, 0xbb, 0xd0, 0xa3, 0xed, 0x42, 0xe, 0xdb, 0xb8, 0x61, 0xdc, 0xc6, 0xa4, 0xba, 0x8d, 0xea, 0x3d, 0xe8, 0xed, 0xab, 0xc9, 0xe7, 0x1e, 0xd4, 0xf4, 0xf5, 0xab, 0xf7, 0x40, 0xb9, 0x48, 0xac, 0x73, 0x60, 0x10, 0x72, 0x66, 0x70, 0xc0, 0xc9, 0x26, 0x8c, 0x37, 0xad, 0x84, 0xe, 0xba, 0xc2, 0x91, 0xb6, 0x72, 0xc8, 0x4a, 0x79, 0x5b, 0x24, 0xec, 0xa, 0xd2, 0x25, 0xb8, 0xf9, 0x2a, 0x57, 0x32, 0x8e, 0x96, 0xfa, 0x8e, 0x21, 0x5f, 0x16, 0x86, 0x3a, 0xea, 0x5b, 0x1c, 0x4c, 0x25, 0x89, 0x59, 0xbf, 0x4a, 0x3, 0x6a, 0x1d, 0x2e, 0xc8, 0xfe, 0x17, 0xa, 0x86, 0x5b, 0x51, 0x3, 0x8e, 0xa5, 0xf9, 0x4c, 0x64, 0xe, 0x68, 0x9f, 0xe9, 0xbd, 0xf0, 0x9, 0xb7, 0x71, 0x36, 0xc6, 0x9b, 0x3d, 0x7f, 0x21, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char toggle_on_disabled_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x20, 0x8, 0x3, 0x0, 0x0, 0x0, 0x95, 0x43, 0x8e, 0xb6, 0x0, 0x0, 0x1, 0x53, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xd, 0xf, 0x1a, 0x1a, 0x1e, 0x20, 0x20, 0x24, 0x22, 0x22, 0x27, 0x24, 0x24, 0x29, 0x25, 0x25, 0x2a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xa, 0xc, 0x1d, 0x1d, 0x21, 0x24, 0x24, 0x29, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x11, 0x14, 0x23, 0x23, 0x28, 0x2e, 0x2e, 0x2e, 0x46, 0x46, 0x46, 0x57, 0x57, 0x57, 0x60, 0x60, 0x60, 0x62, 0x62, 0x62, 0x5e, 0x5e, 0x5e, 0x4a, 0x4a, 0x4a, 0x12, 0x12, 0x15, 0x25, 0x27, 0x2d, 0x42, 0x42, 0x42, 0x59, 0x59, 0x59, 0x32, 0x32, 0x32, 0x25, 0x26, 0x2d, 0x25, 0x25, 0x2b, 0x25, 0x26, 0x2c, 0x39, 0x39, 0x39, 0x49, 0x49, 0x49, 0x5a, 0x5a, 0x5a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xb, 0xd, 0x23, 0x23, 0x28, 0x48, 0x48, 0x48, 0x54, 0x54, 0x54, 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0xb, 0xb, 0xd, 0x1e, 0x1e, 0x22, 0x25, 0x26, 0x2b, 0x3f, 0x3f, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0xe, 0x10, 0x2c, 0x2c, 0x2c, 0x58, 0x58, 0x58, 0x1a, 0x1a, 0x1e, 0x40, 0x40, 0x44, 0x56, 0x56, 0x58, 0x80, 0x80, 0x80, 0x79, 0x79, 0x79, 0x3c, 0x3c, 0x3d, 0x2e, 0x2e, 0x30, 0x27, 0x27, 0x29, 0x64, 0x64, 0x66, 0x41, 0x41, 0x41, 0x1a, 0x1a, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5d, 0x5d, 0x5f, 0x34, 0x34, 0x36, 0x52, 0x52, 0x52, 0x3a, 0x3a, 0x3a, 0x20, 0x20, 0x24, 0x0, 0x0, 0x0, 0x32, 0x32, 0x37, 0x42, 0x42, 0x44, 0x6a, 0x6a, 0x6d, 0x5b, 0x5b, 0x5b, 0x2f, 0x2f, 0x2f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x49, 0x4a, 0x0, 0x0, 0x0, 0x50, 0x50, 0x51, 0x70, 0x70, 0x74, 0xe, 0xe, 0x10, 0xb, 0xb, 0xd, 0x0, 0x0, 0x0, 0x13, 0x13, 0x15, 0x0, 0x0, 0x0, 0xb, 0xb, 0xc, 0x1d, 0x1d, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbd, 0xb, 0x85, 0x35, 0x0, 0x0, 0x0, 0x71, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x1, 0x2, 0x3, 0x4, 0x9, 0xe, 0x13, 0x16, 0x18, 0x19, 0xa, 0x26, 0x36, 0x44, 0x4d, 0x52, 0x54, 0x55, 0x6, 0x12, 0x27, 0x43, 0x80, 0xc5, 0xe7, 0xf5, 0xfe, 0xff, 0x8, 0x17, 0x35, 0x73, 0xd9, 0xff, 0x7, 0x3a, 0x96, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb, 0x28, 0x76, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x77, 0xde, 0xff, 0xff, 0x45, 0x5, 0x82, 0xff, 0xff, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc6, 0x37, 0xf, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x4c, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4e, 0x4f, 0xff, 0x50, 0xff, 0xff, 0x83, 0x78, 0x3b, 0x9c, 0x3c, 0x74, 0xda, 0x53, 0x14, 0x49, 0x96, 0x6e, 0xf, 0x0, 0x0, 0x1, 0xfa, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x62, 0x18, 0x5e, 0x0, 0xd0, 0x5c, 0x39, 0x28, 0x49, 0x12, 0xc0, 0x60, 0xb8, 0xda, 0xdd, 0xcb, 0x31, 0x33, 0xb6, 0x6d, 0xdb, 0x5e, 0xdb, 0xd6, 0xfb, 0x17, 0x4e, 0x7d, 0x37, 0xe6, 0xf9, 0x2b, 0x23, 0x7f, 0x9c, 0x20, 0x28, 0x86, 0xe1, 0xb, 0xc1, 0x30, 0x14, 0x99, 0x6a, 0x8e, 0xe2, 0x4, 0x49, 0xd1, 0xcc, 0xda, 0x2, 0x18, 0x9a, 0x22, 0x9, 0x1c, 0x9d, 0xf4, 0x8e, 0xaf, 0xd3, 0x1b, 0x9b, 0x5b, 0xdb, 0x1c, 0x2e, 0x6f, 0x2e, 0x5c, 0xce, 0xf6, 0xd6, 0xe6, 0x6, 0xbd, 0x8e, 0x8f, 0x45, 0x81, 0xf2, 0x5, 0x42, 0x91, 0x58, 0x22, 0x95, 0xc9, 0x61, 0x1, 0x72, 0x99, 0x54, 0x22, 0x16, 0x9, 0x5, 0x7c, 0x74, 0xc4, 0x5e, 0xa1, 0x54, 0xa9, 0x35, 0x5a, 0x58, 0x12, 0xad, 0x46, 0xad, 0x52, 0x2a, 0x86, 0x14, 0x10, 0x1d, 0xa3, 0x37, 0x18, 0x61, 0x1e, 0x26, 0xb3, 0xc5, 0x6a, 0x63, 0xb1, 0x3b, 0x4c, 0x60, 0x34, 0xe8, 0x19, 0x1d, 0x32, 0xc8, 0x9f, 0xda, 0x74, 0xce, 0x8d, 0xdd, 0xe5, 0xf6, 0x98, 0xbd, 0x3e, 0xff, 0x57, 0x2, 0xa6, 0x60, 0x28, 0xec, 0x76, 0xc9, 0x9d, 0x9b, 0x54, 0xbf, 0xe, 0x68, 0x24, 0x1a, 0x8b, 0xcf, 0xb5, 0x4f, 0x24, 0x53, 0x30, 0x44, 0x3a, 0x99, 0x70, 0xc5, 0x33, 0xd1, 0xc8, 0x8f, 0x24, 0x70, 0xe5, 0x56, 0x16, 0xe6, 0x90, 0xcb, 0x27, 0x4d, 0x63, 0x9, 0x25, 0xf3, 0xb9, 0x6c, 0x41, 0x59, 0x64, 0x43, 0x40, 0x88, 0x8d, 0x12, 0xcc, 0xa3, 0x5c, 0x49, 0xc3, 0x18, 0x69, 0x4f, 0x19, 0x4a, 0x1b, 0x4, 0x2b, 0x80, 0x92, 0x9b, 0x55, 0xe8, 0x53, 0xab, 0x37, 0x9a, 0x2d, 0x68, 0x37, 0x3a, 0xd0, 0xee, 0x2, 0x4b, 0xcf, 0x1, 0x13, 0x38, 0x7a, 0xb0, 0xb3, 0xbb, 0xc7, 0xe6, 0x80, 0x51, 0x5b, 0x52, 0xe8, 0xd3, 0xdd, 0xaf, 0x1d, 0x34, 0x6a, 0xed, 0x46, 0x77, 0x20, 0x70, 0x78, 0x4, 0x13, 0x1c, 0x1d, 0xc2, 0x71, 0x81, 0xc2, 0x58, 0x1, 0xfa, 0x44, 0x36, 0x8, 0xa0, 0x71, 0xa, 0xb0, 0x7f, 0xd6, 0x3e, 0x6f, 0xb6, 0xfb, 0x2, 0x17, 0x97, 0x30, 0xc1, 0xe5, 0x5, 0x18, 0xaf, 0x68, 0x9c, 0x15, 0x50, 0x5e, 0xf, 0x7a, 0xd8, 0x3e, 0x7, 0x80, 0x9b, 0x7a, 0xbb, 0x7b, 0x73, 0xde, 0x17, 0xb0, 0xfa, 0x60, 0x2, 0x9f, 0x15, 0xe0, 0x56, 0xf9, 0x5d, 0x80, 0xde, 0x1e, 0xc, 0xd1, 0xe9, 0xd7, 0x8, 0xea, 0x77, 0xed, 0x2e, 0xdc, 0xd7, 0x97, 0x8e, 0x80, 0xda, 0x3a, 0x86, 0x3e, 0xe7, 0x67, 0x70, 0xda, 0x6c, 0xb5, 0xbb, 0xd0, 0x6a, 0x2c, 0x5b, 0x3, 0x94, 0xdc, 0xad, 0x42, 0x9f, 0x76, 0xf3, 0xbc, 0x59, 0x87, 0xaf, 0xe1, 0x9f, 0x2f, 0xd5, 0x5, 0x76, 0xe, 0x1e, 0x60, 0xc0, 0xe9, 0x59, 0x7, 0xa0, 0xd6, 0x2, 0xe8, 0xb4, 0xe6, 0xcf, 0xc1, 0x83, 0x90, 0x40, 0x7e, 0x79, 0x12, 0xfb, 0xbb, 0x90, 0x59, 0x7d, 0x17, 0x1e, 0xd9, 0x5d, 0xf8, 0xd5, 0x6d, 0xec, 0xdf, 0x83, 0xa7, 0xe7, 0xf8, 0x2a, 0xf7, 0x20, 0xfe, 0xfc, 0xc2, 0xde, 0x83, 0xfe, 0x45, 0x62, 0x36, 0x5f, 0xdf, 0x60, 0x69, 0xde, 0x5e, 0x37, 0x19, 0xc5, 0xe8, 0x4d, 0xd3, 0x51, 0xc2, 0x2d, 0xb1, 0xe4, 0xd8, 0x8, 0xb, 0x31, 0x1e, 0x4b, 0xc4, 0x5b, 0x42, 0x4a, 0x87, 0x8e, 0x5f, 0xe5, 0x8, 0xbd, 0xb1, 0x5b, 0xb8, 0x7a, 0xe7, 0x2d, 0xe0, 0xfd, 0xaa, 0xb0, 0xbb, 0x41, 0x47, 0x70, 0x64, 0xf2, 0xab, 0x14, 0x89, 0xbd, 0xf, 0xe5, 0xe2, 0xbf, 0xa0, 0xfc, 0xd8, 0x23, 0x8a, 0x28, 0x32, 0xe3, 0x33, 0xe1, 0x4b, 0xc0, 0x7e, 0xa6, 0xff, 0x87, 0xcf, 0xb, 0x94, 0xb9, 0x37, 0x3c, 0xc6, 0xd8, 0xcd, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char toggle_on_disabled_mirrored_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x20, 0x8, 0x3, 0x0, 0x0, 0x0, 0x95, 0x43, 0x8e, 0xb6, 0x0, 0x0, 0x0, 0x69, 0x50, 0x4c, 0x54, 0x45, 0x93, 0x7f, 0x2b, 0x14, 0x14, 0x17, 0x20, 0x20, 0x25, 0x24, 0x24, 0x28, 0x24, 0x24, 0x29, 0x25, 0x25, 0x2a, 0x10, 0x10, 0x13, 0x22, 0x22, 0x27, 0x25, 0x25, 0x28, 0x25, 0x25, 0x29, 0x25, 0x25, 0x27, 0x19, 0x19, 0x1c, 0x2b, 0x26, 0x2c, 0x40, 0x40, 0x44, 0x4e, 0x4e, 0x52, 0x1a, 0x1a, 0x1d, 0x32, 0x32, 0x37, 0x2c, 0x26, 0x2c, 0x26, 0x25, 0x2a, 0x27, 0x25, 0x2a, 0x11, 0x11, 0x14, 0x2f, 0x26, 0x2d, 0x12, 0x12, 0x14, 0x23, 0x23, 0x27, 0x15, 0x15, 0x18, 0x5b, 0x5b, 0x5f, 0x84, 0x84, 0x87, 0x77, 0x77, 0x7a, 0x69, 0x69, 0x6c, 0x20, 0x20, 0x24, 0x24, 0x24, 0x27, 0x23, 0x23, 0x28, 0x1a, 0x1a, 0x1e, 0x11, 0x11, 0x13, 0x22, 0x22, 0x26, 0xd7, 0x77, 0xc6, 0x92, 0x0, 0x0, 0x0, 0x1, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x40, 0xe6, 0xd8, 0x66, 0x0, 0x0, 0x1, 0x35, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xed, 0x94, 0xd1, 0x72, 0x83, 0x20, 0x10, 0x45, 0x4d, 0x90, 0xb8, 0x18, 0x96, 0x6c, 0xb5, 0x24, 0x41, 0x68, 0x9b, 0xf4, 0xff, 0x3f, 0xb2, 0x84, 0xb4, 0x8a, 0xa, 0x3a, 0x9d, 0x74, 0xa6, 0x2f, 0xb9, 0xbe, 0x38, 0xca, 0x3d, 0x5c, 0x16, 0xd8, 0xa2, 0x78, 0xea, 0x2f, 0xb5, 0xd9, 0xb2, 0xb2, 0xe4, 0x2b, 0x2a, 0x4b, 0xb6, 0xdd, 0x24, 0xed, 0xbb, 0x8a, 0x1, 0x8, 0x21, 0xee, 0xe3, 0xc4, 0x4d, 0x20, 0x6a, 0x91, 0x84, 0x54, 0xbb, 0xb9, 0x7f, 0xcf, 0x40, 0xa2, 0xea, 0x85, 0x32, 0x50, 0x6a, 0xc8, 0xe4, 0xd8, 0x4f, 0xfd, 0x7, 0x26, 0x48, 0xe1, 0x4b, 0x13, 0x7e, 0x37, 0x92, 0x50, 0x51, 0x1b, 0x92, 0xe4, 0x56, 0x72, 0x18, 0xfb, 0x5f, 0x99, 0x40, 0xd4, 0xf1, 0x8, 0x42, 0x6c, 0x17, 0x6b, 0x71, 0x1c, 0x1, 0x4e, 0x40, 0x21, 0x74, 0x24, 0x89, 0xd4, 0x2c, 0x11, 0x4e, 0xb1, 0xff, 0xc, 0x52, 0xe9, 0xe9, 0x8, 0x52, 0x8b, 0x11, 0xf8, 0x39, 0x2, 0x6c, 0x7d, 0x80, 0xf9, 0x8, 0xa4, 0xe1, 0xd5, 0x74, 0x16, 0xb9, 0xee, 0x5a, 0xae, 0xdd, 0xcf, 0xb7, 0xb7, 0x8, 0xe0, 0x2b, 0x40, 0x73, 0x40, 0x4, 0x75, 0x6, 0xa9, 0x43, 0xdd, 0xb9, 0x8, 0xc0, 0x46, 0x0, 0x25, 0xe7, 0x0, 0xa9, 0xfa, 0x0, 0x9d, 0xe7, 0x1b, 0xd4, 0xce, 0xea, 0x1, 0x50, 0x8e, 0x1, 0x89, 0x82, 0x35, 0x3d, 0x20, 0xb8, 0x94, 0xd1, 0x4e, 0xb9, 0x1, 0xc0, 0x7f, 0x91, 0x80, 0x42, 0x2, 0xe5, 0xcd, 0xd6, 0x24, 0x13, 0xbc, 0xc3, 0x5a, 0xd, 0x90, 0x93, 0xf5, 0x4b, 0xf0, 0x8b, 0x49, 0xd6, 0x60, 0x75, 0x17, 0xb4, 0x75, 0xd6, 0x84, 0x95, 0xb8, 0xe4, 0x2e, 0xac, 0x9f, 0x3, 0xba, 0x9d, 0x4b, 0xf4, 0xb3, 0xb4, 0xfd, 0x4c, 0xf1, 0x39, 0x28, 0x3e, 0xc4, 0x63, 0x27, 0xb1, 0x38, 0x3e, 0x7a, 0x17, 0xb2, 0xb7, 0x31, 0xeb, 0x9f, 0xdc, 0xc6, 0xa2, 0xb8, 0x30, 0x68, 0xa7, 0xfd, 0x60, 0xc1, 0x7f, 0x99, 0x77, 0x94, 0xeb, 0x27, 0xd4, 0x70, 0x6f, 0x48, 0xe2, 0x5b, 0xe0, 0x9f, 0xa4, 0xbf, 0xba, 0x66, 0x7b, 0x22, 0x5f, 0x55, 0xb6, 0x27, 0x3e, 0xf5, 0x8f, 0xfa, 0x2, 0xa0, 0x14, 0x20, 0xeb, 0xde, 0xb1, 0x8c, 0x34, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char toggle_on_mirrored_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x20, 0x8, 0x3, 0x0, 0x0, 0x0, 0x95, 0x43, 0x8e, 0xb6, 0x0, 0x0, 0x1, 0x9b, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xd, 0xf, 0x1a, 0x1a, 0x1e, 0x20, 0x20, 0x24, 0x22, 0x22, 0x27, 0x24, 0x24, 0x29, 0x24, 0x24, 0x28, 0x20, 0x20, 0x25, 0x14, 0x14, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xa, 0xc, 0x1d, 0x1d, 0x21, 0x22, 0x22, 0x27, 0x10, 0x10, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x11, 0x14, 0x23, 0x23, 0x28, 0x19, 0x19, 0x1c, 0x12, 0x12, 0x15, 0x1a, 0x1a, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xb, 0xd, 0x23, 0x23, 0x28, 0x12, 0x12, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x1e, 0x22, 0x23, 0x23, 0x27, 0xe, 0xe, 0x10, 0x15, 0x15, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0x1a, 0x1d, 0x20, 0x20, 0x24, 0x20, 0x20, 0x24, 0x24, 0x24, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0xe, 0x10, 0x15, 0x15, 0x18, 0xb, 0xb, 0xd, 0x12, 0x12, 0x14, 0x0, 0x0, 0x0, 0x13, 0x13, 0x15, 0x1a, 0x1a, 0x1e, 0xb, 0xb, 0xc, 0x1d, 0x1d, 0x21, 0x11, 0x11, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x25, 0x25, 0x2a, 0x24, 0x24, 0x29, 0x25, 0x25, 0x29, 0x25, 0x25, 0x27, 0x25, 0x2c, 0x36, 0x28, 0x4c, 0x6b, 0x29, 0x64, 0x92, 0x2a, 0x68, 0x99, 0x2a, 0x66, 0x95, 0x29, 0x5d, 0x85, 0x27, 0x49, 0x65, 0x25, 0x25, 0x28, 0x25, 0x27, 0x2d, 0x27, 0x44, 0x5c, 0x29, 0x60, 0x8c, 0x27, 0x4d, 0x6b, 0x25, 0x3a, 0x4c, 0x25, 0x2d, 0x38, 0x25, 0x26, 0x2c, 0x25, 0x25, 0x2b, 0x25, 0x26, 0x2d, 0x25, 0x30, 0x3e, 0x27, 0x49, 0x66, 0x29, 0x5f, 0x89, 0x27, 0x43, 0x5c, 0x27, 0x4b, 0x69, 0x28, 0x58, 0x7f, 0x25, 0x35, 0x45, 0x25, 0x34, 0x43, 0x28, 0x59, 0x7f, 0x25, 0x26, 0x2b, 0x27, 0x41, 0x57, 0x27, 0x40, 0x57, 0x25, 0x2b, 0x34, 0x25, 0x34, 0x44, 0x29, 0x5d, 0x87, 0x25, 0x2a, 0x33, 0x27, 0x43, 0x5b, 0x27, 0x4e, 0x6d, 0x27, 0x4d, 0x6c, 0x40, 0x40, 0x44, 0xad, 0xad, 0xaf, 0xff, 0xff, 0xff, 0xf2, 0xf2, 0xf2, 0x77, 0x77, 0x7a, 0x5b, 0x5b, 0x5f, 0x4e, 0x4e, 0x52, 0xc9, 0xc9, 0xca, 0x28, 0x56, 0x7b, 0x26, 0x3a, 0x4e, 0x26, 0x3b, 0x4e, 0xbb, 0xbb, 0xbd, 0x69, 0x69, 0x6c, 0x29, 0x61, 0x8d, 0x25, 0x2e, 0x39, 0x32, 0x32, 0x37, 0x84, 0x84, 0x87, 0xd6, 0xd6, 0xd7, 0x92, 0x92, 0x94, 0xa0, 0xa0, 0xa2, 0x27, 0x44, 0x5d, 0xa6, 0xa2, 0x25, 0x5b, 0x0, 0x0, 0x0, 0x4c, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x1, 0x2, 0x3, 0x4, 0x9, 0xe, 0x13, 0x16, 0x18, 0x19, 0xa, 0x26, 0x36, 0x44, 0x4d, 0x52, 0x54, 0x55, 0x6, 0x12, 0x27, 0x43, 0x80, 0xc5, 0xe7, 0xf5, 0xfe, 0xfa, 0xe5, 0x98, 0x8, 0x17, 0x35, 0x73, 0xd9, 0xf3, 0x86, 0x7, 0x3a, 0x96, 0xf9, 0xb4, 0x9a, 0xb9, 0xb, 0x28, 0x77, 0xfb, 0x8b, 0x5, 0x45, 0xde, 0xf6, 0x82, 0x9b, 0xf, 0x37, 0xc6, 0xe6, 0xe9, 0xfb, 0x4e, 0x50, 0x83, 0x9c, 0x78, 0x8c, 0x3c, 0x9c, 0xbb, 0x74, 0xda, 0x87, 0x53, 0x14, 0xd0, 0x92, 0x4e, 0x2c, 0x0, 0x0, 0x2, 0x35, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0x63, 0x60, 0x18, 0x44, 0x80, 0x91, 0x89, 0x99, 0x99, 0x85, 0x20, 0x60, 0x66, 0x66, 0x62, 0xc4, 0xaa, 0x9d, 0x89, 0x85, 0x95, 0x8d, 0x9d, 0x83, 0x93, 0x8b, 0x0, 0xe0, 0xe4, 0x60, 0x67, 0x63, 0x65, 0x61, 0xc2, 0xb4, 0x9d, 0x85, 0x9b, 0x83, 0x87, 0x97, 0x8f, 0x5f, 0x40, 0x50, 0x8, 0x2f, 0x10, 0x14, 0xe0, 0xe7, 0xe3, 0xe5, 0xe1, 0xe0, 0x66, 0x41, 0x73, 0x5, 0x93, 0xb0, 0x88, 0xa8, 0x98, 0xb8, 0x84, 0xa4, 0x94, 0xb4, 0xf, 0x1, 0xe0, 0x2b, 0x2d, 0x23, 0x2b, 0x27, 0x26, 0x2a, 0x22, 0x8c, 0xe2, 0x8, 0x26, 0x79, 0x5, 0x45, 0x25, 0x65, 0x5f, 0xc, 0xd5, 0x7e, 0xfe, 0x7e, 0x58, 0xd, 0x51, 0x51, 0x55, 0x54, 0x90, 0x47, 0x32, 0x81, 0x51, 0x8d, 0x53, 0x5d, 0x43, 0xd3, 0x27, 0x20, 0x30, 0x28, 0x18, 0x2, 0x42, 0x42, 0xc3, 0x2, 0x20, 0x6, 0x84, 0xe3, 0x70, 0x87, 0x96, 0x3a, 0xa7, 0x1a, 0x23, 0xc2, 0xff, 0xec, 0xbc, 0xda, 0xd2, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 0x20, 0x90, 0x90, 0x98, 0x94, 0x9c, 0x12, 0x1, 0x36, 0x2, 0x97, 0x4f, 0x74, 0x78, 0xd9, 0xe1, 0xe1, 0xc0, 0xa4, 0xab, 0xa7, 0x6f, 0x10, 0x91, 0x9a, 0x96, 0x8e, 0xac, 0x22, 0x23, 0x33, 0x35, 0x2, 0x6f, 0x58, 0x18, 0xea, 0xe9, 0x42, 0x3d, 0xc1, 0x68, 0xa4, 0x60, 0x6c, 0x92, 0x95, 0x9d, 0x19, 0x8b, 0xaa, 0x22, 0x36, 0x33, 0x27, 0xb, 0x9f, 0x9, 0xa6, 0xc6, 0xa, 0x46, 0x10, 0x27, 0x30, 0xb1, 0xf2, 0x98, 0xf9, 0xe4, 0x26, 0xa7, 0xa3, 0xab, 0xc8, 0xcb, 0x2f, 0xc0, 0x1b, 0x1f, 0xe6, 0x3c, 0xac, 0x10, 0x3, 0x58, 0x2c, 0x2c, 0xad, 0x7c, 0xa, 0x8b, 0x30, 0x55, 0x14, 0x17, 0xc2, 0x99, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x3e, 0x95, 0x65, 0x55, 0x3e, 0x95, 0xd5, 0x30, 0x31, 0x6b, 0x4b, 0xb, 0x88, 0x1f, 0x84, 0xd9, 0x8d, 0x6d, 0x7c, 0x6a, 0x6a, 0x31, 0xd, 0xa8, 0xab, 0x81, 0x33, 0xab, 0xeb, 0x4b, 0x1a, 0xca, 0x4a, 0x2a, 0xcb, 0xaa, 0x91, 0xc, 0xb0, 0x35, 0x66, 0x67, 0x6, 0x1b, 0xa0, 0xc6, 0x61, 0xa7, 0xe9, 0xd3, 0xd8, 0x84, 0x69, 0x40, 0x53, 0x23, 0xdc, 0x1, 0x65, 0xcd, 0x3e, 0x3e, 0xf5, 0x2d, 0x95, 0xad, 0xe5, 0x95, 0x8, 0x3, 0x7c, 0xed, 0x38, 0x58, 0x20, 0x6, 0x28, 0xd8, 0xfb, 0xf8, 0x84, 0x24, 0x60, 0x1a, 0x90, 0x10, 0x2, 0x63, 0x55, 0xb6, 0x2, 0x89, 0xb6, 0xd2, 0xca, 0xea, 0xb6, 0x56, 0x84, 0x1, 0x3e, 0xf6, 0xa, 0x2c, 0xc4, 0xba, 0xa0, 0x19, 0xe4, 0x82, 0xd2, 0x76, 0xa0, 0xe6, 0xf2, 0x52, 0x4c, 0x17, 0x10, 0x13, 0x6, 0xad, 0x2d, 0x3e, 0xcd, 0xe5, 0x15, 0x40, 0x3, 0x2a, 0xca, 0x30, 0xc3, 0x80, 0x98, 0x58, 0xa8, 0x2c, 0x6f, 0x2d, 0x2f, 0x5, 0x7, 0x60, 0x2b, 0x66, 0x2c, 0x30, 0xb1, 0x8a, 0x3a, 0x10, 0x4c, 0x7, 0xcd, 0x2d, 0x55, 0xc0, 0xb0, 0xac, 0xf0, 0xf1, 0xa9, 0xaa, 0x80, 0x9, 0x39, 0x8a, 0x42, 0xd3, 0x1, 0xc5, 0x29, 0x11, 0x94, 0x17, 0x9c, 0x48, 0xcf, 0xb, 0xce, 0xf0, 0xbc, 0x0, 0xcb, 0x8d, 0x1d, 0xa8, 0xb9, 0x31, 0x12, 0xbf, 0x7e, 0xe4, 0xdc, 0x8, 0x2a, 0xf, 0x5c, 0x5c, 0xd, 0xb0, 0x94, 0x7, 0xb8, 0xf5, 0xbb, 0xb9, 0x20, 0x95, 0x7, 0xa0, 0x12, 0x89, 0x93, 0xd7, 0xdd, 0x3, 0x53, 0x9d, 0x5f, 0x38, 0xf6, 0xf2, 0x40, 0xc5, 0x93, 0x97, 0x53, 0x1e, 0xb5, 0x4c, 0x53, 0x63, 0x17, 0xe5, 0x13, 0x97, 0xb0, 0xd1, 0xf4, 0x21, 0x8, 0x7c, 0x6d, 0x65, 0xe5, 0xf8, 0x44, 0xd9, 0xd5, 0xd0, 0xa, 0x66, 0x46, 0x16, 0x5d, 0xe, 0x1e, 0x4b, 0x63, 0x3b, 0x2f, 0x21, 0x2, 0xc0, 0xcb, 0xce, 0xd8, 0x92, 0x87, 0x43, 0x97, 0x5, 0xa3, 0x6e, 0x60, 0x64, 0x32, 0x62, 0xb5, 0xf0, 0x56, 0x20, 0x5c, 0x2f, 0x28, 0x78, 0x5b, 0xb0, 0x1a, 0x61, 0xaf, 0x5b, 0x80, 0x35, 0x13, 0xe1, 0x8a, 0x9, 0x58, 0x35, 0xe1, 0xa8, 0x99, 0x86, 0x2e, 0x0, 0x0, 0x69, 0x2c, 0x6b, 0xc2, 0xf1, 0x2f, 0x53, 0x53, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char tooltip_bg_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2d, 0x2c, 0x2f, 0x48, 0x46, 0x4a, 0xdd, 0xdd, 0xdd, 0x4c, 0x4a, 0x4e, 0x48, 0x46, 0x4a, 0x40, 0x3e, 0x42, 0xbc, 0x3, 0x4f, 0xe9, 0x0, 0x0, 0x0, 0xd, 0x74, 0x52, 0x4e, 0x53, 0xa, 0x1a, 0x26, 0x29, 0x2a, 0x48, 0x65, 0x6d, 0x6e, 0x66, 0xf5, 0xfe, 0xcc, 0xff, 0xb7, 0x4a, 0xbe, 0x0, 0x0, 0x0, 0x38, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0x54, 0x76, 0x1, 0x2, 0x23, 0x1, 0x6, 0xd1, 0xf4, 0xe, 0x20, 0x28, 0xb, 0x64, 0xd0, 0x5c, 0x7d, 0x17, 0x8, 0x76, 0x4d, 0x62, 0x70, 0x7f, 0x7f, 0x6, 0x8, 0xfe, 0x95, 0x30, 0x78, 0xdc, 0x1, 0x31, 0xce, 0xb6, 0x50, 0xc8, 0x80, 0x1b, 0x8, 0xb7, 0x2, 0x6e, 0x29, 0xdc, 0x19, 0x0, 0xcf, 0x24, 0x4d, 0xb3, 0xd0, 0x4d, 0xb9, 0x40, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char tree_bg_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0xa, 0x4, 0x3, 0x0, 0x0, 0x0, 0x7f, 0x1c, 0xd2, 0x8e, 0x0, 0x0, 0x0, 0x2a, 0x50, 0x4c, 0x54, 0x45, 0x17, 0x16, 0x1a, 0x1d, 0x1c, 0x21, 0x20, 0x1e, 0x24, 0x21, 0x1f, 0x25, 0x1d, 0x1c, 0x21, 0x20, 0x1e, 0x24, 0x1d, 0x1c, 0x21, 0x1d, 0x1c, 0x21, 0x24, 0x22, 0x29, 0x28, 0x26, 0x2d, 0x28, 0x26, 0x2e, 0x2b, 0x2a, 0x31, 0x2c, 0x2a, 0x32, 0xff, 0xff, 0xff, 0xb9, 0x11, 0x56, 0x3e, 0x0, 0x0, 0x0, 0x8, 0x74, 0x52, 0x4e, 0x53, 0x6f, 0xef, 0xf7, 0xf7, 0xf0, 0xf9, 0xf1, 0xee, 0xcf, 0x21, 0xd2, 0xdf, 0x0, 0x0, 0x0, 0x2d, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x54, 0x36, 0x36, 0x12, 0x60, 0xf0, 0x98, 0xb5, 0x6a, 0x65, 0xb, 0x43, 0xe4, 0x9e, 0x33, 0xa7, 0xa7, 0x32, 0x58, 0x9d, 0x39, 0x73, 0x66, 0x31, 0x16, 0x12, 0x22, 0xb, 0x52, 0xd9, 0xc6, 0xc0, 0x2, 0xd4, 0x55, 0x0, 0x0, 0xc, 0x14, 0x1a, 0x90, 0x55, 0x1a, 0xec, 0xdb, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char tree_bg_disabled_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0xa, 0x8, 0x4, 0x0, 0x0, 0x0, 0x27, 0x3b, 0x7, 0x36, 0x0, 0x0, 0x0, 0x4e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x94, 0xc8, 0x67, 0x6b, 0x60, 0xe6, 0x60, 0x64, 0x80, 0x80, 0xff, 0xc, 0x7f, 0x7f, 0xfc, 0x6a, 0x60, 0x94, 0xfb, 0xc0, 0xce, 0xcf, 0xc2, 0x80, 0x10, 0xfc, 0xc3, 0xf0, 0xf3, 0x23, 0xa3, 0xe2, 0x4f, 0xe, 0x36, 0x54, 0xc1, 0x1f, 0xbf, 0x18, 0x95, 0xbe, 0x73, 0x70, 0xb0, 0x30, 0xc0, 0x1, 0x48, 0xf0, 0x7, 0x85, 0x82, 0x58, 0x2d, 0xc2, 0xe6, 0xa4, 0x4f, 0x20, 0xc7, 0x37, 0x32, 0xb3, 0x23, 0x39, 0xfe, 0xfb, 0xaf, 0x46, 0x0, 0xee, 0x2a, 0x2f, 0xce, 0x4c, 0x47, 0x66, 0xf6, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char tree_title_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x1, 0x3, 0x0, 0x0, 0x0, 0x25, 0x3d, 0x6d, 0x22, 0x0, 0x0, 0x0, 0x6, 0x50, 0x4c, 0x54, 0x45, 0x25, 0x23, 0x25, 0x4c, 0x4a, 0x4e, 0x1, 0xf9, 0x98, 0x2e, 0x0, 0x0, 0x0, 0xb, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x11, 0x0, 0x0, 0x0, 0x30, 0x0, 0x1, 0x6e, 0xa6, 0xf, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char tree_title_pressed_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x1, 0x3, 0x0, 0x0, 0x0, 0x25, 0x3d, 0x6d, 0x22, 0x0, 0x0, 0x0, 0x6, 0x50, 0x4c, 0x54, 0x45, 0x36, 0x34, 0x36, 0x4c, 0x4a, 0x4e, 0x14, 0xd7, 0x5b, 0xf8, 0x0, 0x0, 0x0, 0xb, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x11, 0x0, 0x0, 0x0, 0x30, 0x0, 0x1, 0x6e, 0xa6, 0xf, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char unchecked_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x33, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x38, 0x37, 0x40, 0x20, 0x20, 0x24, 0x20, 0x20, 0x24, 0x38, 0x36, 0x40, 0x20, 0x20, 0x25, 0x1e, 0x1e, 0x22, 0x1f, 0x1f, 0x23, 0x20, 0x20, 0x24, 0x22, 0x22, 0x27, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2a, 0x23, 0xc3, 0x49, 0x39, 0x0, 0x0, 0x0, 0xb, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x7, 0x27, 0x50, 0x66, 0x68, 0xb4, 0xfa, 0xfb, 0xb4, 0xfa, 0xa4, 0x7f, 0xe1, 0x5a, 0x0, 0x0, 0x0, 0x4f, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xb5, 0xcf, 0x45, 0x2, 0x80, 0x40, 0x8, 0x0, 0x40, 0x97, 0x66, 0xfb, 0xff, 0x9f, 0xb5, 0xdb, 0xb3, 0x73, 0xa4, 0x19, 0xbe, 0x2, 0x20, 0xf1, 0x8a, 0x10, 0xc2, 0x1c, 0x0, 0xd1, 0x94, 0x57, 0x49, 0x5, 0xe6, 0x0, 0x6a, 0xa9, 0x6d, 0x55, 0x8b, 0xe2, 0x1c, 0xa0, 0x54, 0xfb, 0xae, 0x26, 0x9a, 0x3, 0x9c, 0xdb, 0x11, 0x68, 0x99, 0xff, 0xa, 0x7c, 0xd6, 0xde, 0xf, 0x33, 0x9c, 0x3, 0xe0, 0x76, 0x9c, 0x1e, 0x1d, 0xbe, 0xcf, 0x7d, 0x4c, 0x93, 0xe2, 0x8, 0xa4, 0x66, 0x3c, 0xec, 0xed, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char unchecked_disabled_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x33, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x6a, 0x69, 0x70, 0x6a, 0x68, 0x70, 0x58, 0x58, 0x5c, 0x58, 0x58, 0x5b, 0x58, 0x58, 0x5b, 0x5c, 0x5c, 0x5f, 0x5a, 0x5a, 0x5e, 0x59, 0x59, 0x5d, 0x58, 0x58, 0x5b, 0x57, 0x57, 0x5a, 0x56, 0x56, 0x59, 0x27, 0xa1, 0xa6, 0x53, 0x0, 0x0, 0x0, 0xb, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x7, 0x27, 0x50, 0x66, 0x68, 0xb4, 0xb4, 0xfa, 0xfa, 0xfb, 0xc7, 0x8b, 0xf6, 0x7e, 0x0, 0x0, 0x0, 0x52, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5e, 0xb5, 0xcf, 0x31, 0x12, 0xc0, 0x20, 0x8, 0x44, 0xd1, 0x15, 0x50, 0x83, 0x11, 0xe5, 0xfe, 0xa7, 0xcd, 0xe8, 0xc4, 0x22, 0xf4, 0x79, 0xe5, 0x36, 0x7c, 0x80, 0x8, 0x89, 0x58, 0xf2, 0x26, 0x4c, 0x9, 0x0, 0x15, 0xf5, 0xb9, 0xb9, 0x16, 0x2, 0xc0, 0x3a, 0xac, 0x6f, 0x36, 0x94, 0x1, 0x88, 0xdb, 0xfd, 0x32, 0x17, 0x0, 0x79, 0xf6, 0x33, 0xf4, 0x99, 0xff, 0x1a, 0xe2, 0xd9, 0x4f, 0x58, 0x5b, 0x61, 0x54, 0xdb, 0x49, 0xbf, 0xea, 0x4a, 0x8f, 0xcf, 0x45, 0xf, 0x4, 0x40, 0x7, 0x90, 0xb0, 0x7b, 0x47, 0x4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char updown_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0x81, 0x83, 0xf6, 0xf6, 0x0, 0x0, 0x0, 0x57, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x8d, 0x4e, 0xb5, 0x1, 0xc0, 0x30, 0xc, 0xf3, 0x15, 0xfe, 0xff, 0x96, 0x64, 0xa, 0x6c, 0xca, 0x56, 0xd2, 0x25, 0x65, 0xe6, 0xc8, 0x8b, 0x49, 0x20, 0x79, 0x28, 0x95, 0x81, 0xa1, 0xd4, 0x7d, 0x4, 0xbb, 0xa1, 0x50, 0xea, 0x3c, 0xa6, 0x71, 0x98, 0x96, 0x69, 0x58, 0x31, 0xcc, 0xb7, 0xe5, 0x2f, 0x48, 0x63, 0x26, 0xf6, 0xa2, 0xd4, 0x18, 0xf9, 0x7, 0x2d, 0xe3, 0x46, 0x89, 0xb4, 0xd2, 0xf8, 0xa3, 0x68, 0xe3, 0xd7, 0x14, 0x20, 0xe6, 0xc3, 0x3d, 0xd8, 0xca, 0x5e, 0x94, 0x32, 0xd0, 0x3, 0x91, 0xba, 0x5f, 0x1b, 0x4a, 0x9b, 0x12, 0x62, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char vseparator_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x2, 0x3, 0x0, 0x0, 0x0, 0xb9, 0x61, 0x56, 0x18, 0x0, 0x0, 0x0, 0x9, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x73, 0x9b, 0xaa, 0xce, 0xdc, 0xe1, 0xeb, 0x64, 0x9a, 0x78, 0x0, 0x0, 0x0, 0x3, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xb3, 0xb3, 0x67, 0xf6, 0xdb, 0x93, 0x0, 0x0, 0x0, 0xf, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x80, 0x83, 0xac, 0x95, 0xc, 0x48, 0x0, 0x0, 0xe, 0x79, 0x1, 0x14, 0x17, 0x9a, 0x55, 0x26, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char vslider_bg_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x51, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x34, 0x33, 0x3a, 0x2d, 0x2c, 0x32, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x3f, 0x3e, 0x49, 0x2a, 0x29, 0x2f, 0x20, 0x20, 0x24, 0x3f, 0x3e, 0x49, 0x3f, 0x3e, 0x49, 0x1f, 0x1f, 0x24, 0x40, 0x3e, 0x4a, 0x20, 0x20, 0x24, 0x34, 0x33, 0x3a, 0x20, 0x20, 0x25, 0x22, 0x22, 0x27, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2a, 0x1e, 0x1e, 0x23, 0x23, 0x23, 0x27, 0x2d, 0x2c, 0x32, 0x1f, 0x1f, 0x23, 0x30, 0x7, 0x9c, 0xfe, 0x0, 0x0, 0x0, 0x13, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x4, 0x1a, 0x40, 0x5d, 0x19, 0x28, 0x96, 0xf0, 0xfd, 0x94, 0x95, 0xfc, 0x93, 0xfc, 0xc0, 0x0, 0xb4, 0xa, 0x5f, 0x0, 0x0, 0x0, 0x5f, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x2c, 0xc8, 0x83, 0x11, 0x0, 0x30, 0x0, 0xc0, 0xc0, 0xda, 0xf6, 0xfe, 0x8b, 0xd6, 0x39, 0xe6, 0xc1, 0xe, 0x12, 0xca, 0x38, 0x67, 0x82, 0xc0, 0x73, 0xe7, 0xa5, 0xd2, 0xc6, 0x68, 0x2b, 0xbf, 0x40, 0xe1, 0x7c, 0x2e, 0x25, 0xfb, 0x20, 0x3e, 0x30, 0x9d, 0x6b, 0x6b, 0x35, 0x6b, 0xf6, 0x81, 0x9b, 0xd2, 0x76, 0x25, 0xf2, 0x7, 0x28, 0xf5, 0x71, 0x60, 0xf4, 0x84, 0x2e, 0xe0, 0x35, 0x49, 0x29, 0x51, 0x90, 0x80, 0xa8, 0x94, 0x24, 0x33, 0x19, 0x2, 0x18, 0x86, 0xa2, 0x5b, 0x8b, 0xe9, 0x30, 0x4c, 0xa7, 0x63, 0x7a, 0xe, 0xc3, 0xfb, 0x0, 0x89, 0x5c, 0xa, 0x6b, 0x4f, 0x78, 0xac, 0x83, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char vslider_grabber_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0xbc, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xa0, 0x17, 0x60, 0x66, 0xe0, 0x65, 0x90, 0x61, 0x50, 0x67, 0xd0, 0x60, 0x50, 0x62, 0x10, 0x67, 0xe0, 0x2, 0xf2, 0x19, 0x51, 0xa5, 0xc5, 0xd2, 0xf2, 0x3a, 0xf, 0xce, 0x78, 0x3f, 0xed, 0x43, 0xff, 0xed, 0xc6, 0xf5, 0x41, 0xa9, 0x8a, 0x86, 0xc, 0x22, 0xc, 0xac, 0x8, 0x5, 0xbc, 0x69, 0x79, 0x93, 0x5e, 0xf4, 0xfd, 0x6f, 0x7, 0xc2, 0xae, 0xff, 0xfd, 0xff, 0xa7, 0xfd, 0xe9, 0x7f, 0x50, 0x31, 0x87, 0x47, 0x87, 0x81, 0x1b, 0x66, 0x8e, 0x4c, 0xe7, 0xc1, 0xbe, 0xff, 0x2d, 0xff, 0x9b, 0xa1, 0xb0, 0xf5, 0x7f, 0xe7, 0xff, 0xc9, 0xff, 0x27, 0xdc, 0xb6, 0xf0, 0x7, 0x9a, 0xc3, 0x2, 0x52, 0xa0, 0x3e, 0xe3, 0x7d, 0x3b, 0x54, 0x12, 0xa1, 0xa8, 0xe7, 0xff, 0x9c, 0x2f, 0x45, 0xc5, 0xc, 0xdc, 0xf8, 0x14, 0x7c, 0xaf, 0xaa, 0x65, 0xe0, 0xc1, 0x69, 0xc5, 0xc4, 0x3b, 0xe, 0xa1, 0xc, 0x62, 0xc, 0x2c, 0x68, 0x8e, 0xec, 0xf8, 0xdf, 0xfb, 0x7f, 0xda, 0xbf, 0x89, 0xf, 0x4a, 0xa6, 0xf2, 0xe8, 0x0, 0x75, 0x33, 0xa2, 0x79, 0x73, 0xea, 0x87, 0xbe, 0x7b, 0xbd, 0x47, 0x7d, 0x53, 0x58, 0x34, 0x18, 0x84, 0x19, 0x58, 0xb1, 0x7, 0x94, 0xa, 0x83, 0x14, 0x50, 0x27, 0x13, 0x3, 0x3d, 0x1, 0x0, 0x79, 0xc3, 0x79, 0x54, 0x19, 0x56, 0x3b, 0x28, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char vslider_grabber_disabled_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0xb4, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xa0, 0x17, 0x60, 0x66, 0xe0, 0x65, 0x90, 0x61, 0x50, 0x67, 0xd0, 0x60, 0x50, 0x62, 0x10, 0x67, 0xe0, 0x2, 0xf2, 0x19, 0x51, 0xa5, 0xc5, 0x8c, 0xf3, 0x5c, 0xf, 0xfa, 0xbc, 0xf7, 0xfe, 0xe0, 0x71, 0xdb, 0x71, 0xbd, 0x66, 0xaa, 0xa0, 0x21, 0x83, 0x8, 0x3, 0x2b, 0x42, 0x1, 0xaf, 0x71, 0x9e, 0xe7, 0xb, 0xf7, 0xff, 0x2e, 0x40, 0xe8, 0xfa, 0xdf, 0xe3, 0xbf, 0xf7, 0x1f, 0x8f, 0x7, 0x36, 0x73, 0xd8, 0x74, 0x18, 0xb8, 0x61, 0xe6, 0xc8, 0xb8, 0x1e, 0x74, 0xff, 0xef, 0x4, 0x87, 0xce, 0x40, 0x65, 0x5e, 0xff, 0x3d, 0x6e, 0xcb, 0xf8, 0x3, 0xcd, 0x61, 0x1, 0x29, 0x50, 0xf7, 0x79, 0xef, 0x2, 0x95, 0x44, 0x28, 0x72, 0xfb, 0xef, 0xf7, 0xc5, 0xb2, 0x98, 0x81, 0x1b, 0x9f, 0x82, 0xef, 0xb6, 0xb5, 0xc, 0x3c, 0x38, 0xad, 0xf0, 0xbc, 0xa3, 0x10, 0xca, 0x20, 0xc6, 0xc0, 0x82, 0xec, 0x48, 0x30, 0x74, 0xff, 0xef, 0xfd, 0xcf, 0xf3, 0x81, 0xd5, 0x54, 0x36, 0x1d, 0xa0, 0x6e, 0x46, 0xc, 0x6f, 0xba, 0xdf, 0x73, 0x3f, 0xaa, 0x9e, 0xc2, 0xa4, 0xc1, 0x20, 0xcc, 0xc0, 0x8a, 0x3d, 0xa0, 0x54, 0x18, 0xa4, 0x80, 0x3a, 0x99, 0x18, 0xe8, 0x9, 0x0, 0xf1, 0x9, 0x63, 0x9b, 0x53, 0x7f, 0x6d, 0x9b, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char vslider_grabber_hl_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x6c, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x5b, 0xa6, 0xa5, 0x61, 0xb3, 0xbc, 0x63, 0xb7, 0xc8, 0x65, 0xbb, 0xca, 0x60, 0xaf, 0xb1, 0x55, 0x9b, 0x9a, 0x60, 0xb2, 0xbd, 0x5e, 0xb1, 0xcd, 0x61, 0xb3, 0xc2, 0x62, 0xb4, 0xbd, 0x68, 0xc0, 0xcf, 0x68, 0xc1, 0xcf, 0x63, 0xb7, 0xbf, 0x52, 0x96, 0x95, 0x62, 0xb3, 0xbf, 0x5e, 0xb0, 0xcd, 0x63, 0xb4, 0xb6, 0x60, 0xb1, 0xbc, 0x63, 0xb7, 0xc7, 0x55, 0xa3, 0xc8, 0x4f, 0x98, 0xc4, 0x4b, 0x93, 0xc2, 0x4c, 0x94, 0xc2, 0x54, 0xa2, 0xc8, 0x5a, 0xab, 0xcb, 0x4e, 0x97, 0xc4, 0x49, 0x8f, 0xc0, 0x47, 0x8c, 0xbf, 0x48, 0x8e, 0xc0, 0x52, 0x9e, 0xc6, 0x51, 0x9d, 0xc6, 0x5a, 0xac, 0xcc, 0x53, 0x9f, 0xc7, 0x4d, 0x96, 0xc3, 0x4b, 0x92, 0xc2, 0x7f, 0xcb, 0x5d, 0x16, 0x0, 0x0, 0x0, 0x1, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x40, 0xe6, 0xd8, 0x66, 0x0, 0x0, 0x0, 0x47, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xa0, 0x16, 0x60, 0x65, 0x61, 0x66, 0x62, 0x44, 0xe2, 0x73, 0x4a, 0x88, 0x8b, 0x89, 0x8a, 0x70, 0xb0, 0xb3, 0xc1, 0xe4, 0x25, 0x64, 0x65, 0x80, 0x40, 0x5a, 0x4a, 0x92, 0xb, 0x22, 0xc0, 0x22, 0x2e, 0x3, 0x1, 0xd2, 0x72, 0xdc, 0x68, 0x2, 0xf2, 0x3c, 0xa8, 0x5a, 0x14, 0x78, 0x11, 0x86, 0x2a, 0x2b, 0x29, 0xa, 0xf0, 0xf3, 0x21, 0x59, 0x2b, 0x2c, 0x24, 0xc8, 0x40, 0x3d, 0x0, 0x0, 0x19, 0x8b, 0x5, 0xfc, 0x96, 0x5c, 0x15, 0x3b, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char vslider_tick_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x4, 0x4, 0x3, 0x0, 0x0, 0x0, 0x75, 0x9a, 0xa2, 0xdf, 0x0, 0x0, 0x0, 0x1b, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x81, 0xa2, 0xad, 0x8c, 0xac, 0xb8, 0x38, 0x55, 0x5f, 0x82, 0x82, 0x82, 0x8d, 0x8d, 0x8d, 0x98, 0x98, 0x98, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x7c, 0xda, 0x48, 0x6d, 0x0, 0x0, 0x0, 0x9, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x79, 0x79, 0x79, 0x31, 0x1c, 0x18, 0xed, 0xfe, 0x2b, 0x0, 0x0, 0x0, 0x1c, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x80, 0x3, 0xd7, 0x44, 0x5, 0x6, 0x6, 0xe6, 0x92, 0x30, 0x86, 0xf2, 0x62, 0x3, 0x20, 0xa3, 0xbd, 0x1c, 0x2e, 0x3, 0x0, 0x3f, 0xce, 0x3, 0xaf, 0xed, 0xed, 0x7c, 0x2f, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char vsplit_bg_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x1, 0x3, 0x0, 0x0, 0x0, 0xfe, 0xc1, 0x2c, 0xc8, 0x0, 0x0, 0x0, 0x6, 0x50, 0x4c, 0x54, 0x45, 0x27, 0x27, 0x29, 0xff, 0xff, 0xff, 0x11, 0xab, 0xb9, 0xf3, 0x0, 0x0, 0x0, 0xa, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x40, 0x3, 0x0, 0x0, 0x10, 0x0, 0x1, 0xb3, 0xac, 0xe2, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char vsplitter_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0x6c, 0x9, 0xa6, 0x3, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x76, 0x93, 0xcd, 0x38, 0x0, 0x0, 0x0, 0x18, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xa0, 0x1c, 0x2c, 0x48, 0xa5, 0xc, 0x33, 0xa4, 0x5a, 0x53, 0x86, 0x29, 0x7, 0xa3, 0x61, 0x0, 0x0, 0x18, 0x61, 0x34, 0xa1, 0xba, 0xa4, 0x4d, 0xe, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char window_resizer_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x1e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x18, 0xbc, 0xe0, 0x45, 0x3f, 0x1, 0xe9, 0xec, 0xfe, 0x81, 0x94, 0x86, 0xb1, 0x70, 0x48, 0x23, 0x58, 0x84, 0xa4, 0x7, 0x15, 0x0, 0x0, 0xed, 0x9f, 0x18, 0xe8, 0xcd, 0x91, 0xd8, 0xe, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const unsigned char window_resizer_mirrored_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x1, 0x6f, 0x72, 0x4e, 0x54, 0x1, 0xcf, 0xa2, 0x77, 0x9a, 0x0, 0x0, 0x0, 0x27, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0x60, 0x18, 0x44, 0xe0, 0x45, 0x3f, 0x76, 0x71, 0x26, 0x18, 0xa3, 0x19, 0xa7, 0x12, 0x38, 0xc8, 0xee, 0xa7, 0xb1, 0x12, 0x98, 0x4, 0x4e, 0x25, 0x8, 0x9, 0x4a, 0x94, 0xc, 0x10, 0x0, 0x0, 0x9d, 0x84, 0x18, 0x73, 0x33, 0x1c, 0x96, 0xd6, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -// shaders block diff --git a/scene/resources/default_theme/toggle_off.png b/scene/resources/default_theme/toggle_off.png Binary files differdeleted file mode 100644 index 64b51c8c9d..0000000000 --- a/scene/resources/default_theme/toggle_off.png +++ /dev/null diff --git a/scene/resources/default_theme/toggle_off.svg b/scene/resources/default_theme/toggle_off.svg new file mode 100644 index 0000000000..95ec679cbe --- /dev/null +++ b/scene/resources/default_theme/toggle_off.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 32 15.999999" width="32" xmlns="http://www.w3.org/2000/svg"><g fill-opacity=".5" stroke-width=".999997"><rect fill="#1a1a1a" height="14" rx="7.000001" width="30" x="1" y="1"/><circle cx="8" cy="8" fill="#fff" r="5"/></g></svg> diff --git a/scene/resources/default_theme/toggle_off_disabled.png b/scene/resources/default_theme/toggle_off_disabled.png Binary files differdeleted file mode 100644 index 250cd29b66..0000000000 --- a/scene/resources/default_theme/toggle_off_disabled.png +++ /dev/null diff --git a/scene/resources/default_theme/toggle_off_disabled.svg b/scene/resources/default_theme/toggle_off_disabled.svg new file mode 100644 index 0000000000..c86a678768 --- /dev/null +++ b/scene/resources/default_theme/toggle_off_disabled.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 32 15.999999" width="32" xmlns="http://www.w3.org/2000/svg"><g fill-opacity=".25" stroke-width=".999997"><rect fill="#1a1a1a" height="14" rx="7.000001" width="30" x="1" y="1"/><circle cx="8" cy="8" fill="#fff" r="5"/></g></svg> diff --git a/scene/resources/default_theme/toggle_off_disabled_mirrored.png b/scene/resources/default_theme/toggle_off_disabled_mirrored.png Binary files differdeleted file mode 100644 index 799b63c098..0000000000 --- a/scene/resources/default_theme/toggle_off_disabled_mirrored.png +++ /dev/null diff --git a/scene/resources/default_theme/toggle_off_disabled_mirrored.svg b/scene/resources/default_theme/toggle_off_disabled_mirrored.svg new file mode 100644 index 0000000000..0182dd738e --- /dev/null +++ b/scene/resources/default_theme/toggle_off_disabled_mirrored.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 32 15.999999" width="32" xmlns="http://www.w3.org/2000/svg"><g fill-opacity=".25" stroke-width=".999997" transform="scale(-1 1)"><rect fill="#1a1a1a" height="14" rx="7.000001" width="30" x="-31" y="1"/><circle cx="-24" cy="8" fill="#fff" r="5"/></g></svg> diff --git a/scene/resources/default_theme/toggle_off_mirrored.png b/scene/resources/default_theme/toggle_off_mirrored.png Binary files differdeleted file mode 100644 index 3487605d58..0000000000 --- a/scene/resources/default_theme/toggle_off_mirrored.png +++ /dev/null diff --git a/scene/resources/default_theme/toggle_off_mirrored.svg b/scene/resources/default_theme/toggle_off_mirrored.svg new file mode 100644 index 0000000000..f61517a4ae --- /dev/null +++ b/scene/resources/default_theme/toggle_off_mirrored.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 32 15.999999" width="32" xmlns="http://www.w3.org/2000/svg"><g fill-opacity=".5" stroke-width=".999997" transform="scale(-1 1)"><rect fill="#1a1a1a" height="14" rx="7.000001" width="30" x="-31" y="1"/><circle cx="-24" cy="8" fill="#fff" r="5"/></g></svg> diff --git a/scene/resources/default_theme/toggle_on.png b/scene/resources/default_theme/toggle_on.png Binary files differdeleted file mode 100644 index f0c699c181..0000000000 --- a/scene/resources/default_theme/toggle_on.png +++ /dev/null diff --git a/scene/resources/default_theme/toggle_on.svg b/scene/resources/default_theme/toggle_on.svg new file mode 100644 index 0000000000..7e02602792 --- /dev/null +++ b/scene/resources/default_theme/toggle_on.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 32 15.999999" width="32" xmlns="http://www.w3.org/2000/svg"><g stroke-width=".999997" transform="scale(-1 1)"><rect fill="#fff" fill-opacity=".75" height="14" rx="7.000001" width="30" x="-31" y="1"/><circle cx="-24" cy="8" fill="#1a1a1a" r="5"/></g></svg> diff --git a/scene/resources/default_theme/toggle_on_disabled.png b/scene/resources/default_theme/toggle_on_disabled.png Binary files differdeleted file mode 100644 index b1dacbaf32..0000000000 --- a/scene/resources/default_theme/toggle_on_disabled.png +++ /dev/null diff --git a/scene/resources/default_theme/toggle_on_disabled.svg b/scene/resources/default_theme/toggle_on_disabled.svg new file mode 100644 index 0000000000..72ce5bb9b2 --- /dev/null +++ b/scene/resources/default_theme/toggle_on_disabled.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 32 15.999999" width="32" xmlns="http://www.w3.org/2000/svg"><g stroke-width=".999997" transform="scale(-1 1)"><rect fill="#fff" fill-opacity=".37" height="14" rx="7.000001" width="30" x="-31" y="1"/><circle cx="-24" cy="8" fill="#1a1a1a" fill-opacity=".5" r="5"/></g></svg> diff --git a/scene/resources/default_theme/toggle_on_disabled_mirrored.png b/scene/resources/default_theme/toggle_on_disabled_mirrored.png Binary files differdeleted file mode 100644 index 0758babd4f..0000000000 --- a/scene/resources/default_theme/toggle_on_disabled_mirrored.png +++ /dev/null diff --git a/scene/resources/default_theme/toggle_on_disabled_mirrored.svg b/scene/resources/default_theme/toggle_on_disabled_mirrored.svg new file mode 100644 index 0000000000..340a386def --- /dev/null +++ b/scene/resources/default_theme/toggle_on_disabled_mirrored.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 32 15.999999" width="32" xmlns="http://www.w3.org/2000/svg"><g stroke-width=".999997"><rect fill="#fff" fill-opacity=".37" height="14" rx="7.000001" width="30" x="1" y="1"/><circle cx="8" cy="8" fill="#1a1a1a" fill-opacity=".5" r="5"/></g></svg> diff --git a/scene/resources/default_theme/toggle_on_mirrored.png b/scene/resources/default_theme/toggle_on_mirrored.png Binary files differdeleted file mode 100644 index 3fd953c8e2..0000000000 --- a/scene/resources/default_theme/toggle_on_mirrored.png +++ /dev/null diff --git a/scene/resources/default_theme/toggle_on_mirrored.svg b/scene/resources/default_theme/toggle_on_mirrored.svg new file mode 100644 index 0000000000..fbc6be2af9 --- /dev/null +++ b/scene/resources/default_theme/toggle_on_mirrored.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 32 15.999999" width="32" xmlns="http://www.w3.org/2000/svg"><g stroke-width=".999997"><rect fill="#fff" fill-opacity=".75" height="14" rx="7.000001" width="30" x="1" y="1"/><circle cx="8" cy="8" fill="#1a1a1a" r="5"/></g></svg> diff --git a/scene/resources/default_theme/tooltip_bg.png b/scene/resources/default_theme/tooltip_bg.png Binary files differdeleted file mode 100644 index 07b7d942ca..0000000000 --- a/scene/resources/default_theme/tooltip_bg.png +++ /dev/null diff --git a/scene/resources/default_theme/tree_bg.png b/scene/resources/default_theme/tree_bg.png Binary files differdeleted file mode 100644 index 2b0c506f34..0000000000 --- a/scene/resources/default_theme/tree_bg.png +++ /dev/null diff --git a/scene/resources/default_theme/tree_bg_disabled.png b/scene/resources/default_theme/tree_bg_disabled.png Binary files differdeleted file mode 100644 index 69d78febd9..0000000000 --- a/scene/resources/default_theme/tree_bg_disabled.png +++ /dev/null diff --git a/scene/resources/default_theme/tree_title.png b/scene/resources/default_theme/tree_title.png Binary files differdeleted file mode 100644 index e5f3f49695..0000000000 --- a/scene/resources/default_theme/tree_title.png +++ /dev/null diff --git a/scene/resources/default_theme/tree_title_pressed.png b/scene/resources/default_theme/tree_title_pressed.png Binary files differdeleted file mode 100644 index 35e2bb3008..0000000000 --- a/scene/resources/default_theme/tree_title_pressed.png +++ /dev/null diff --git a/scene/resources/default_theme/unchecked.png b/scene/resources/default_theme/unchecked.png Binary files differdeleted file mode 100644 index 8c818af755..0000000000 --- a/scene/resources/default_theme/unchecked.png +++ /dev/null diff --git a/scene/resources/default_theme/unchecked.svg b/scene/resources/default_theme/unchecked.svg new file mode 100644 index 0000000000..f475108f44 --- /dev/null +++ b/scene/resources/default_theme/unchecked.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.3333333 1c-1.2887 0-2.3333333 1.0446683-2.3333333 2.3333333v9.3333337c0 1.2887 1.0446683 2.333333 2.3333333 2.333333h9.3333337c1.2887 0 2.333333-1.044668 2.333333-2.333333v-9.3333337c0-1.2887-1.044668-2.3333333-2.333333-2.3333333z" fill="#1a1a1a" fill-opacity=".5" stroke-width="1.16667"/></svg> diff --git a/scene/resources/default_theme/unchecked_disabled.png b/scene/resources/default_theme/unchecked_disabled.png Binary files differdeleted file mode 100644 index bef9316f58..0000000000 --- a/scene/resources/default_theme/unchecked_disabled.png +++ /dev/null diff --git a/scene/resources/default_theme/unchecked_disabled.svg b/scene/resources/default_theme/unchecked_disabled.svg new file mode 100644 index 0000000000..195b85e37f --- /dev/null +++ b/scene/resources/default_theme/unchecked_disabled.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.3333333 1c-1.2887 0-2.3333333 1.0446683-2.3333333 2.3333333v9.3333337c0 1.2887 1.0446683 2.333333 2.3333333 2.333333h9.3333337c1.2887 0 2.333333-1.044668 2.333333-2.333333v-9.3333337c0-1.2887-1.044668-2.3333333-2.333333-2.3333333z" fill="#1a1a1a" fill-opacity=".25" stroke-width="1.16667"/></svg> diff --git a/scene/resources/default_theme/updown.png b/scene/resources/default_theme/updown.png Binary files differdeleted file mode 100644 index 56f81921e8..0000000000 --- a/scene/resources/default_theme/updown.png +++ /dev/null diff --git a/scene/resources/default_theme/updown.svg b/scene/resources/default_theme/updown.svg new file mode 100644 index 0000000000..d6a630740f --- /dev/null +++ b/scene/resources/default_theme/updown.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#fff" stroke-opacity=".75" stroke-width="2"><path d="m4 6 4-3.5 4 3.5"/><path d="m12 10-4 3.5-4-3.5"/></g></svg> diff --git a/scene/resources/default_theme/visibility_visible.svg b/scene/resources/default_theme/visibility_visible.svg new file mode 100644 index 0000000000..ac1af8db0a --- /dev/null +++ b/scene/resources/default_theme/visibility_visible.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2c-2.557 0-5.791 1.948-6.955 5.705-.057.186-.059.384-.006.57 1.124 3.936 4.461 5.725 6.961 5.725s5.836-1.789 6.961-5.725c.052-.18.052-.372 0-.552-1.1-3.788-4.407-5.723-6.961-5.723zm0 2c2.194 0 4 1.806 4 4s-1.806 4-4 4-4-1.806-4-4 1.806-4 4-4zm0 2c-1.097 0-2 .903-2 2s.903 2 2 2 2-.903 2-2-.903-2-2-2z" fill="#b2b2b2"/></svg> diff --git a/scene/resources/default_theme/vseparator.png b/scene/resources/default_theme/vseparator.png Binary files differdeleted file mode 100644 index 51e79f3ac5..0000000000 --- a/scene/resources/default_theme/vseparator.png +++ /dev/null diff --git a/scene/resources/default_theme/vslider_bg.png b/scene/resources/default_theme/vslider_bg.png Binary files differdeleted file mode 100644 index ba3244e3e5..0000000000 --- a/scene/resources/default_theme/vslider_bg.png +++ /dev/null diff --git a/scene/resources/default_theme/vslider_grabber.png b/scene/resources/default_theme/vslider_grabber.png Binary files differdeleted file mode 100644 index 6c6bf93e68..0000000000 --- a/scene/resources/default_theme/vslider_grabber.png +++ /dev/null diff --git a/scene/resources/default_theme/vslider_grabber_disabled.png b/scene/resources/default_theme/vslider_grabber_disabled.png Binary files differdeleted file mode 100644 index 49cced5055..0000000000 --- a/scene/resources/default_theme/vslider_grabber_disabled.png +++ /dev/null diff --git a/scene/resources/default_theme/vslider_grabber_hl.png b/scene/resources/default_theme/vslider_grabber_hl.png Binary files differdeleted file mode 100644 index 28774fdbf8..0000000000 --- a/scene/resources/default_theme/vslider_grabber_hl.png +++ /dev/null diff --git a/scene/resources/default_theme/vslider_tick.png b/scene/resources/default_theme/vslider_tick.png Binary files differdeleted file mode 100644 index bde788b563..0000000000 --- a/scene/resources/default_theme/vslider_tick.png +++ /dev/null diff --git a/scene/resources/default_theme/vslider_tick.svg b/scene/resources/default_theme/vslider_tick.svg new file mode 100644 index 0000000000..1365d36aca --- /dev/null +++ b/scene/resources/default_theme/vslider_tick.svg @@ -0,0 +1 @@ +<svg height="4" viewBox="0 0 16 3.9999998" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m-3 0h2v16h-2z" fill="#fff" fill-opacity=".25" stroke-width=".285079" transform="rotate(-90)"/></svg> diff --git a/scene/resources/default_theme/vsplit_bg.png b/scene/resources/default_theme/vsplit_bg.png Binary files differdeleted file mode 100644 index a5749f6d5c..0000000000 --- a/scene/resources/default_theme/vsplit_bg.png +++ /dev/null diff --git a/scene/resources/default_theme/vsplitter.png b/scene/resources/default_theme/vsplitter.png Binary files differdeleted file mode 100644 index dde1f390df..0000000000 --- a/scene/resources/default_theme/vsplitter.png +++ /dev/null diff --git a/scene/resources/default_theme/vsplitter.svg b/scene/resources/default_theme/vsplitter.svg new file mode 100644 index 0000000000..c46d785925 --- /dev/null +++ b/scene/resources/default_theme/vsplitter.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" viewBox="0 0 48 8" xmlns="http://www.w3.org/2000/svg"><path d="m4 4h40" fill="none" stroke="#808080" stroke-opacity=".65" stroke-width="1.7"/></svg> diff --git a/scene/resources/default_theme/window_resizer.png b/scene/resources/default_theme/window_resizer.png Binary files differdeleted file mode 100644 index b06e6f5366..0000000000 --- a/scene/resources/default_theme/window_resizer.png +++ /dev/null diff --git a/scene/resources/default_theme/window_resizer_mirrored.png b/scene/resources/default_theme/window_resizer_mirrored.png Binary files differdeleted file mode 100644 index bbce5f1406..0000000000 --- a/scene/resources/default_theme/window_resizer_mirrored.png +++ /dev/null diff --git a/scene/resources/default_theme/zoom_less.svg b/scene/resources/default_theme/zoom_less.svg new file mode 100644 index 0000000000..a438f7f683 --- /dev/null +++ b/scene/resources/default_theme/zoom_less.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" fill="#b2b2b2" fill-opacity=".65" r="8"/><circle cx="8" cy="8" fill="#fefffe" r="7"/><path d="m4 7h8v2h-8z" fill="#010001"/></svg> diff --git a/scene/resources/default_theme/zoom_more.svg b/scene/resources/default_theme/zoom_more.svg new file mode 100644 index 0000000000..192e0ed907 --- /dev/null +++ b/scene/resources/default_theme/zoom_more.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" fill="#b2b2b2" fill-opacity=".65" r="8"/><circle cx="8" cy="8" fill="#fefffe" r="7"/><path d="m7 4h2v3h3v2h-3v3h-2v-3h-3v-2h3z" fill="#010001"/></svg> diff --git a/scene/resources/default_theme/zoom_reset.svg b/scene/resources/default_theme/zoom_reset.svg new file mode 100644 index 0000000000..427214cda2 --- /dev/null +++ b/scene/resources/default_theme/zoom_reset.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" fill="#b2b2b2" fill-opacity=".65" r="8"/><circle cx="8" cy="8" fill="#fefffe" r="7"/><path d="m8.016 4.002h.029c.548 0 .999.45 1 .998v7h-2v-5.131l-1.445.963-1.11-1.664 3-2c.156-.103.338-.161.526-.166z" fill="#010001"/></svg> diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 7e71ad8986..0afe040f33 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -496,13 +496,13 @@ bool Environment::is_sdfgi_enabled() const { return sdfgi_enabled; } -void Environment::set_sdfgi_cascades(SDFGICascades p_cascades) { - ERR_FAIL_INDEX(p_cascades, SDFGI_CASCADES_8 + 1); +void Environment::set_sdfgi_cascades(int p_cascades) { + ERR_FAIL_COND_MSG(p_cascades < 1 || p_cascades > 8, "Invalid number of SDFGI cascades (must be between 1 and 8)."); sdfgi_cascades = p_cascades; _update_sdfgi(); } -Environment::SDFGICascades Environment::get_sdfgi_cascades() const { +int Environment::get_sdfgi_cascades() const { return sdfgi_cascades; } @@ -517,9 +517,7 @@ float Environment::get_sdfgi_min_cell_size() const { void Environment::set_sdfgi_max_distance(float p_distance) { p_distance /= 64.0; - int cc[3] = { 4, 6, 8 }; - int cascades = cc[sdfgi_cascades]; - for (int i = 0; i < cascades; i++) { + for (int i = 0; i < sdfgi_cascades; i++) { p_distance *= 0.5; //halve for each cascade } sdfgi_min_cell_size = p_distance; @@ -529,9 +527,7 @@ void Environment::set_sdfgi_max_distance(float p_distance) { float Environment::get_sdfgi_max_distance() const { float md = sdfgi_min_cell_size; md *= 64.0; - int cc[3] = { 4, 6, 8 }; - int cascades = cc[sdfgi_cascades]; - for (int i = 0; i < cascades; i++) { + for (int i = 0; i < sdfgi_cascades; i++) { md *= 2.0; } return md; @@ -612,7 +608,7 @@ void Environment::_update_sdfgi() { RS::get_singleton()->environment_set_sdfgi( environment, sdfgi_enabled, - RS::EnvironmentSDFGICascades(sdfgi_cascades), + sdfgi_cascades, sdfgi_min_cell_size, RS::EnvironmentSDFGIYScale(sdfgi_y_scale), sdfgi_use_occlusion, @@ -1303,7 +1299,7 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_use_occlusion"), "set_sdfgi_use_occlusion", "is_sdfgi_using_occlusion"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_read_sky_light"), "set_sdfgi_read_sky_light", "is_sdfgi_reading_sky_light"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_bounce_feedback", PROPERTY_HINT_RANGE, "0,1.99,0.01"), "set_sdfgi_bounce_feedback", "get_sdfgi_bounce_feedback"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "sdfgi_cascades", PROPERTY_HINT_ENUM, "4 Cascades,6 Cascades,8 Cascades"), "set_sdfgi_cascades", "get_sdfgi_cascades"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "sdfgi_cascades", PROPERTY_HINT_RANGE, "1,8,1"), "set_sdfgi_cascades", "get_sdfgi_cascades"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_min_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_sdfgi_min_cell_size", "get_sdfgi_min_cell_size"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_cascade0_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater"), "set_sdfgi_cascade0_distance", "get_sdfgi_cascade0_distance"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_max_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater"), "set_sdfgi_max_distance", "get_sdfgi_max_distance"); @@ -1480,10 +1476,6 @@ void Environment::_bind_methods() { BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_REPLACE); BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_MIX); - BIND_ENUM_CONSTANT(SDFGI_CASCADES_4); - BIND_ENUM_CONSTANT(SDFGI_CASCADES_6); - BIND_ENUM_CONSTANT(SDFGI_CASCADES_8); - BIND_ENUM_CONSTANT(SDFGI_Y_SCALE_DISABLED); BIND_ENUM_CONSTANT(SDFGI_Y_SCALE_75_PERCENT); BIND_ENUM_CONSTANT(SDFGI_Y_SCALE_50_PERCENT); diff --git a/scene/resources/environment.h b/scene/resources/environment.h index 98e755c336..3f05315013 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -70,12 +70,6 @@ public: TONE_MAPPER_ACES, }; - enum SDFGICascades { - SDFGI_CASCADES_4, - SDFGI_CASCADES_6, - SDFGI_CASCADES_8, - }; - enum SDFGIYScale { SDFGI_Y_SCALE_DISABLED, SDFGI_Y_SCALE_75_PERCENT, @@ -153,7 +147,7 @@ private: // SDFGI bool sdfgi_enabled = false; - SDFGICascades sdfgi_cascades = SDFGI_CASCADES_6; + int sdfgi_cascades = 6; float sdfgi_min_cell_size = 0.2; SDFGIYScale sdfgi_y_scale = SDFGI_Y_SCALE_DISABLED; bool sdfgi_use_occlusion = false; @@ -320,8 +314,8 @@ public: // SDFGI void set_sdfgi_enabled(bool p_enabled); bool is_sdfgi_enabled() const; - void set_sdfgi_cascades(SDFGICascades p_cascades); - SDFGICascades get_sdfgi_cascades() const; + void set_sdfgi_cascades(int p_cascades); + int get_sdfgi_cascades() const; void set_sdfgi_min_cell_size(float p_size); float get_sdfgi_min_cell_size() const; void set_sdfgi_max_distance(float p_distance); @@ -433,7 +427,6 @@ VARIANT_ENUM_CAST(Environment::BGMode) VARIANT_ENUM_CAST(Environment::AmbientSource) VARIANT_ENUM_CAST(Environment::ReflectionSource) VARIANT_ENUM_CAST(Environment::ToneMapper) -VARIANT_ENUM_CAST(Environment::SDFGICascades) VARIANT_ENUM_CAST(Environment::SDFGIYScale) VARIANT_ENUM_CAST(Environment::GlowBlendMode) diff --git a/scene/resources/immediate_mesh.cpp b/scene/resources/immediate_mesh.cpp index b9469803a0..28afef8638 100644 --- a/scene/resources/immediate_mesh.cpp +++ b/scene/resources/immediate_mesh.cpp @@ -382,7 +382,7 @@ AABB ImmediateMesh::get_aabb() const { if (i == 0) { aabb = surfaces[i].aabb; } else { - aabb.merge(surfaces[i].aabb); + aabb = aabb.merge(surfaces[i].aabb); } } return aabb; diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 402e67a0f1..f9a4eba978 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -175,14 +175,12 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { #endif } } else { - Object *obj = nullptr; + //node belongs to this scene and must be created + Object *obj = ClassDB::instantiate(snames[n.type]); - if (ClassDB::is_class_enabled(snames[n.type])) { - //node belongs to this scene and must be created - obj = ClassDB::instantiate(snames[n.type]); - } + node = Object::cast_to<Node>(obj); - if (!Object::cast_to<Node>(obj)) { + if (!node) { if (obj) { memdelete(obj); obj = nullptr; @@ -203,9 +201,9 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { if (!obj) { obj = memnew(Node); } - } - node = Object::cast_to<Node>(obj); + node = Object::cast_to<Node>(obj); + } } if (node) { diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index cc7322476f..0677d9c1a8 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -30,7 +30,6 @@ #include "surface_tool.h" -#define _VERTEX_SNAP 0.0001 #define EQ_VERTEX_DIST 0.00001 SurfaceTool::OptimizeVertexCacheFunc SurfaceTool::optimize_vertex_cache_func = nullptr; diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index ece1ba1972..4bc62e7617 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -231,8 +231,8 @@ String VisualShaderNode::get_warning(Shader::Mode p_mode, VisualShader::Type p_t return String(); } -String VisualShaderNode::get_input_port_default_hint(int p_port) const { - return ""; +bool VisualShaderNode::is_input_port_default(int p_port, Shader::Mode p_mode) const { + return false; } void VisualShaderNode::_bind_methods() { @@ -2312,7 +2312,6 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR, "object_position", "OBJECT_POSITION" }, { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR, "uvw", "UVW" }, { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR, "extents", "EXTENTS" }, - { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_SCALAR, "sdf", "SDF" }, { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, @@ -3402,7 +3401,6 @@ bool VisualShaderNodeGroupBase::is_valid_port_name(const String &p_name) const { } void VisualShaderNodeGroupBase::add_input_port(int p_id, int p_type, const String &p_name) { - ERR_FAIL_COND(has_input_port(p_id)); ERR_FAIL_INDEX(p_type, int(PORT_TYPE_MAX)); ERR_FAIL_COND(!is_valid_port_name(p_name)); @@ -3478,7 +3476,6 @@ bool VisualShaderNodeGroupBase::has_input_port(int p_id) const { } void VisualShaderNodeGroupBase::add_output_port(int p_id, int p_type, const String &p_name) { - ERR_FAIL_COND(has_output_port(p_id)); ERR_FAIL_INDEX(p_type, int(PORT_TYPE_MAX)); ERR_FAIL_COND(!is_valid_port_name(p_name)); diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 066c18e3bc..acb33efd30 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -240,7 +240,7 @@ public: virtual PortType get_output_port_type(int p_port) const = 0; virtual String get_output_port_name(int p_port) const = 0; - virtual String get_input_port_default_hint(int p_port) const; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const; void set_output_port_for_preview(int p_index); int get_output_port_for_preview() const; diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index b61e3f5d14..0cfa9f31f7 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -487,11 +487,13 @@ bool VisualShaderNodeTexture::is_output_port_expandable(int p_port) const { return false; } -String VisualShaderNodeTexture::get_input_port_default_hint(int p_port) const { - if (p_port == 0) { - return "default"; +bool VisualShaderNodeTexture::is_input_port_default(int p_port, Shader::Mode p_mode) const { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + if (p_port == 0) { + return true; + } } - return ""; + return false; } Vector<VisualShader::DefaultTextureParam> VisualShaderNodeTexture::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { @@ -526,7 +528,7 @@ String VisualShaderNodeTexture::generate_global(Shader::Mode p_mode, VisualShade String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String default_uv; - if (p_mode != Shader::MODE_PARTICLES && p_mode != Shader::MODE_SKY) { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { default_uv = "UV.xy"; } else { default_uv = "vec2(0.0)"; @@ -1052,16 +1054,18 @@ bool VisualShaderNodeSample3D::is_output_port_expandable(int p_port) const { return false; } -String VisualShaderNodeSample3D::get_input_port_default_hint(int p_port) const { - if (p_port == 0) { - return "default"; +bool VisualShaderNodeSample3D::is_input_port_default(int p_port, Shader::Mode p_mode) const { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + if (p_port == 0) { + return true; + } } - return ""; + return false; } String VisualShaderNodeSample3D::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String default_uv; - if (p_mode != Shader::MODE_PARTICLES && p_mode != Shader::MODE_SKY) { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { default_uv = "vec3(UV, 0.0)"; } else { default_uv = "vec3(0.0)"; @@ -1346,7 +1350,7 @@ String VisualShaderNodeCubemap::generate_global(Shader::Mode p_mode, VisualShade String VisualShaderNodeCubemap::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String default_uv; - if (p_mode != Shader::MODE_PARTICLES && p_mode != Shader::MODE_SKY) { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { default_uv = "vec3(UV, 0.0)"; } else { default_uv = "vec3(0.0)"; @@ -1393,11 +1397,13 @@ String VisualShaderNodeCubemap::generate_code(Shader::Mode p_mode, VisualShader: return code; } -String VisualShaderNodeCubemap::get_input_port_default_hint(int p_port) const { - if (p_port == 0) { - return "default"; +bool VisualShaderNodeCubemap::is_input_port_default(int p_port, Shader::Mode p_mode) const { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + if (p_port == 0) { + return true; + } } - return ""; + return false; } void VisualShaderNodeCubemap::set_source(Source p_source) { @@ -2781,11 +2787,13 @@ String VisualShaderNodeUVFunc::get_input_port_name(int p_port) const { return ""; } -String VisualShaderNodeUVFunc::get_input_port_default_hint(int p_port) const { - if (p_port == 0) { - return "UV"; +bool VisualShaderNodeUVFunc::is_input_port_default(int p_port, Shader::Mode p_mode) const { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + if (p_port == 0) { + return true; + } } - return ""; + return false; } int VisualShaderNodeUVFunc::get_output_port_count() const { @@ -2809,7 +2817,11 @@ String VisualShaderNodeUVFunc::generate_code(Shader::Mode p_mode, VisualShader:: String uv; if (p_input_vars[0].is_empty()) { - uv = "vec3(UV.xy, 0.0)"; + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + uv = "vec3(UV.xy, 0.0)"; + } else { + uv = "vec3(0.0)"; + } } else { uv = vformat("%s", p_input_vars[0]); } @@ -4966,7 +4978,7 @@ bool VisualShaderNodeTextureUniform::is_code_generated() const { String VisualShaderNodeTextureUniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String default_uv; - if (p_mode != Shader::MODE_PARTICLES && p_mode != Shader::MODE_SKY) { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { default_uv = "UV.xy"; } else { default_uv = "vec2(0.0)"; @@ -5112,11 +5124,13 @@ void VisualShaderNodeTextureUniform::_bind_methods() { BIND_ENUM_CONSTANT(REPEAT_MAX); } -String VisualShaderNodeTextureUniform::get_input_port_default_hint(int p_port) const { - if (p_port == 0) { - return "default"; +bool VisualShaderNodeTextureUniform::is_input_port_default(int p_port, Shader::Mode p_mode) const { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + if (p_port == 0) { + return true; + } } - return ""; + return false; } bool VisualShaderNodeTextureUniform::is_qualifier_supported(Qualifier p_qual) const { @@ -5224,13 +5238,13 @@ String VisualShaderNodeTextureUniformTriplanar::generate_code(Shader::Mode p_mod return code; } -String VisualShaderNodeTextureUniformTriplanar::get_input_port_default_hint(int p_port) const { +bool VisualShaderNodeTextureUniformTriplanar::is_input_port_default(int p_port, Shader::Mode p_mode) const { if (p_port == 0) { - return "default"; + return true; } else if (p_port == 1) { - return "default"; + return true; } - return ""; + return false; } VisualShaderNodeTextureUniformTriplanar::VisualShaderNodeTextureUniformTriplanar() { @@ -5266,8 +5280,8 @@ String VisualShaderNodeTexture2DArrayUniform::get_input_port_name(int p_port) co return ""; } -String VisualShaderNodeTexture2DArrayUniform::get_input_port_default_hint(int p_port) const { - return ""; +bool VisualShaderNodeTexture2DArrayUniform::is_input_port_default(int p_port, Shader::Mode p_mode) const { + return false; } String VisualShaderNodeTexture2DArrayUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { @@ -5339,8 +5353,8 @@ String VisualShaderNodeTexture3DUniform::get_input_port_name(int p_port) const { return ""; } -String VisualShaderNodeTexture3DUniform::get_input_port_default_hint(int p_port) const { - return ""; +bool VisualShaderNodeTexture3DUniform::is_input_port_default(int p_port, Shader::Mode p_mode) const { + return false; } String VisualShaderNodeTexture3DUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { @@ -5412,8 +5426,8 @@ String VisualShaderNodeCubemapUniform::get_input_port_name(int p_port) const { return ""; } -String VisualShaderNodeCubemapUniform::get_input_port_default_hint(int p_port) const { - return ""; +bool VisualShaderNodeCubemapUniform::is_input_port_default(int p_port, Shader::Mode p_mode) const { + return false; } String VisualShaderNodeCubemapUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { @@ -5738,12 +5752,20 @@ String VisualShaderNodeFresnel::generate_code(Shader::Mode p_mode, VisualShader: String normal; String view; if (p_input_vars[0].is_empty()) { - normal = "NORMAL"; + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + normal = "NORMAL"; + } else { + normal = "vec3(0.0)"; + } } else { normal = p_input_vars[0]; } if (p_input_vars[1].is_empty()) { - view = "VIEW"; + if (p_mode == Shader::MODE_SPATIAL) { + view = "VIEW"; + } else { + view = "vec3(0.0)"; + } } else { view = p_input_vars[1]; } @@ -5759,13 +5781,17 @@ String VisualShaderNodeFresnel::generate_code(Shader::Mode p_mode, VisualShader: } } -String VisualShaderNodeFresnel::get_input_port_default_hint(int p_port) const { +bool VisualShaderNodeFresnel::is_input_port_default(int p_port, Shader::Mode p_mode) const { if (p_port == 0) { - return "default"; + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + return true; + } } else if (p_port == 1) { - return "default"; + if (p_mode == Shader::MODE_SPATIAL) { + return true; + } } - return ""; + return false; } VisualShaderNodeFresnel::VisualShaderNodeFresnel() { diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index f1dda634f1..bf5777a3fb 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -280,7 +280,7 @@ public: virtual String get_output_port_name(int p_port) const override; virtual bool is_output_port_expandable(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; @@ -392,7 +392,7 @@ public: virtual int get_input_port_count() const override; virtual PortType get_input_port_type(int p_port) const override; virtual String get_input_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual int get_output_port_count() const override; virtual PortType get_output_port_type(int p_port) const override; @@ -488,7 +488,7 @@ public: virtual int get_input_port_count() const override; virtual PortType get_input_port_type(int p_port) const override; virtual String get_input_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual int get_output_port_count() const override; virtual PortType get_output_port_type(int p_port) const override; @@ -1103,7 +1103,7 @@ public: virtual int get_input_port_count() const override; virtual PortType get_input_port_type(int p_port) const override; virtual String get_input_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual int get_output_port_count() const override; virtual PortType get_output_port_type(int p_port) const override; @@ -1986,7 +1986,7 @@ public: virtual int get_input_port_count() const override; virtual PortType get_input_port_type(int p_port) const override; virtual String get_input_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual int get_output_port_count() const override; virtual PortType get_output_port_type(int p_port) const override; @@ -2036,7 +2036,7 @@ public: virtual PortType get_input_port_type(int p_port) const override; virtual String get_input_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; virtual String generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; @@ -2061,7 +2061,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; @@ -2084,7 +2084,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; @@ -2107,7 +2107,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; @@ -2200,7 +2200,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual bool is_generate_input_var(int p_port) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; diff --git a/scene/resources/visual_shader_particle_nodes.cpp b/scene/resources/visual_shader_particle_nodes.cpp index c970b9c08b..fbac92a06d 100644 --- a/scene/resources/visual_shader_particle_nodes.cpp +++ b/scene/resources/visual_shader_particle_nodes.cpp @@ -1448,22 +1448,22 @@ bool VisualShaderNodeParticleEmit::is_generate_input_var(int p_port) const { return true; } -String VisualShaderNodeParticleEmit::get_input_port_default_hint(int p_port) const { +bool VisualShaderNodeParticleEmit::is_input_port_default(int p_port, Shader::Mode p_mode) const { switch (p_port) { case 1: - return "default"; + return true; case 2: - return "default"; + return true; case 3: - return "default"; + return true; case 4: - return "default"; + return true; case 5: - return "default"; + return true; case 6: - return "default"; + return true; } - return String(); + return false; } String VisualShaderNodeParticleEmit::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { diff --git a/scene/resources/visual_shader_particle_nodes.h b/scene/resources/visual_shader_particle_nodes.h index add6928841..ce0d896c01 100644 --- a/scene/resources/visual_shader_particle_nodes.h +++ b/scene/resources/visual_shader_particle_nodes.h @@ -342,7 +342,7 @@ public: virtual bool is_show_prop_names() const override; virtual bool is_generate_input_var(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeParticleEmit(); diff --git a/scene/resources/visual_shader_sdf_nodes.cpp b/scene/resources/visual_shader_sdf_nodes.cpp index 1b43fda4c5..6654e2319b 100644 --- a/scene/resources/visual_shader_sdf_nodes.cpp +++ b/scene/resources/visual_shader_sdf_nodes.cpp @@ -97,11 +97,11 @@ String VisualShaderNodeScreenUVToSDF::get_output_port_name(int p_port) const { return ""; } -String VisualShaderNodeScreenUVToSDF::get_input_port_default_hint(int p_port) const { +bool VisualShaderNodeScreenUVToSDF::is_input_port_default(int p_port, Shader::Mode p_mode) const { if (p_port == 0) { - return "default"; + return true; } - return ""; + return false; } String VisualShaderNodeScreenUVToSDF::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { diff --git a/scene/resources/visual_shader_sdf_nodes.h b/scene/resources/visual_shader_sdf_nodes.h index d2d1dde4ea..7c1f695423 100644 --- a/scene/resources/visual_shader_sdf_nodes.h +++ b/scene/resources/visual_shader_sdf_nodes.h @@ -66,7 +66,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeScreenUVToSDF(); diff --git a/servers/display_server.cpp b/servers/display_server.cpp index e9f15ab535..d4ff42bc34 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -139,10 +139,6 @@ void DisplayServer::mouse_warp_to_position(const Point2i &p_to) { WARN_PRINT("Mouse warping is not supported by this display server."); } -Point2i DisplayServer::mouse_get_absolute_position() const { - ERR_FAIL_V_MSG(Point2i(), "Mouse is not supported by this display server."); -} - Point2i DisplayServer::mouse_get_position() const { ERR_FAIL_V_MSG(Point2i(), "Mouse is not supported by this display server."); } @@ -159,6 +155,10 @@ String DisplayServer::clipboard_get() const { ERR_FAIL_V_MSG(String(), "Clipboard is not supported by this display server."); } +bool DisplayServer::clipboard_has() const { + return !clipboard_get().is_empty(); +} + void DisplayServer::clipboard_set_primary(const String &p_text) { WARN_PRINT("Primary clipboard is not supported by this display server."); } @@ -359,11 +359,11 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("mouse_warp_to_position", "position"), &DisplayServer::mouse_warp_to_position); ClassDB::bind_method(D_METHOD("mouse_get_position"), &DisplayServer::mouse_get_position); - ClassDB::bind_method(D_METHOD("mouse_get_absolute_position"), &DisplayServer::mouse_get_absolute_position); ClassDB::bind_method(D_METHOD("mouse_get_button_state"), &DisplayServer::mouse_get_button_state); ClassDB::bind_method(D_METHOD("clipboard_set", "clipboard"), &DisplayServer::clipboard_set); ClassDB::bind_method(D_METHOD("clipboard_get"), &DisplayServer::clipboard_get); + ClassDB::bind_method(D_METHOD("clipboard_has"), &DisplayServer::clipboard_has); ClassDB::bind_method(D_METHOD("clipboard_set_primary", "clipboard_primary"), &DisplayServer::clipboard_set_primary); ClassDB::bind_method(D_METHOD("clipboard_get_primary"), &DisplayServer::clipboard_get_primary); diff --git a/servers/display_server.h b/servers/display_server.h index d896572b88..0c2bc5dd3a 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -156,11 +156,11 @@ public: virtual void mouse_warp_to_position(const Point2i &p_to); virtual Point2i mouse_get_position() const; - virtual Point2i mouse_get_absolute_position() const; virtual MouseButton mouse_get_button_state() const; virtual void clipboard_set(const String &p_text); virtual String clipboard_get() const; + virtual bool clipboard_has() const; virtual void clipboard_set_primary(const String &p_text); virtual String clipboard_get_primary() const; diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp index 26fa470233..666e773c1c 100644 --- a/servers/physics_3d/godot_shape_3d.cpp +++ b/servers/physics_3d/godot_shape_3d.cpp @@ -52,11 +52,11 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.0002 -#define _FACE_IS_VALID_SUPPORT_THRESHOLD 0.9998 +constexpr double edge_support_threshold = 0.0002; +constexpr double face_support_threshold = 0.9998; -#define _CYLINDER_EDGE_IS_VALID_SUPPORT_THRESHOLD 0.002 -#define _CYLINDER_FACE_IS_VALID_SUPPORT_THRESHOLD 0.999 +constexpr double cylinder_edge_support_threshold = 0.002; +constexpr double cylinder_face_support_threshold = 0.999; void GodotShape3D::configure(const AABB &p_aabb) { aabb = p_aabb; @@ -184,7 +184,7 @@ Vector3 GodotSeparationRayShape3D::get_support(const Vector3 &p_normal) const { } void GodotSeparationRayShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { - if (Math::abs(p_normal.z) < _EDGE_IS_VALID_SUPPORT_THRESHOLD) { + if (Math::abs(p_normal.z) < edge_support_threshold) { r_amount = 2; r_type = FEATURE_EDGE; r_supports[0] = Vector3(0, 0, 0); @@ -335,7 +335,7 @@ void GodotBoxShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 * Vector3 axis; axis[i] = 1.0; real_t dot = p_normal.dot(axis); - if (Math::abs(dot) > _FACE_IS_VALID_SUPPORT_THRESHOLD) { + if (Math::abs(dot) > face_support_threshold) { //Vector3 axis_b; bool neg = dot < 0; @@ -376,7 +376,7 @@ void GodotBoxShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 * Vector3 axis; axis[i] = 1.0; - if (Math::abs(p_normal.dot(axis)) < _EDGE_IS_VALID_SUPPORT_THRESHOLD) { + if (Math::abs(p_normal.dot(axis)) < edge_support_threshold) { r_amount = 2; r_type = FEATURE_EDGE; @@ -522,7 +522,7 @@ void GodotCapsuleShape3D::get_supports(const Vector3 &p_normal, int p_max, Vecto real_t d = n.y; - if (Math::abs(d) < _EDGE_IS_VALID_SUPPORT_THRESHOLD) { + if (Math::abs(d) < edge_support_threshold) { // make it flat n.y = 0.0; n.normalize(); @@ -703,7 +703,7 @@ Vector3 GodotCylinderShape3D::get_support(const Vector3 &p_normal) const { void GodotCylinderShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { real_t d = p_normal.y; - if (Math::abs(d) > _CYLINDER_FACE_IS_VALID_SUPPORT_THRESHOLD) { + if (Math::abs(d) > cylinder_face_support_threshold) { real_t h = (d > 0) ? height : -height; Vector3 n = p_normal; @@ -718,7 +718,7 @@ void GodotCylinderShape3D::get_supports(const Vector3 &p_normal, int p_max, Vect r_supports[1].x += radius; r_supports[2] = n; r_supports[2].z += radius; - } else if (Math::abs(d) < _CYLINDER_EDGE_IS_VALID_SUPPORT_THRESHOLD) { + } else if (Math::abs(d) < cylinder_edge_support_threshold) { // make it flat Vector3 n = p_normal; n.y = 0.0; @@ -911,7 +911,7 @@ void GodotConvexPolygonShape3D::get_supports(const Vector3 &p_normal, int p_max, } for (int i = 0; i < fc; i++) { - if (faces[i].plane.normal.dot(p_normal) > _FACE_IS_VALID_SUPPORT_THRESHOLD) { + if (faces[i].plane.normal.dot(p_normal) > face_support_threshold) { int ic = faces[i].indices.size(); const int *ind = faces[i].indices.ptr(); @@ -940,7 +940,7 @@ void GodotConvexPolygonShape3D::get_supports(const Vector3 &p_normal, int p_max, for (int i = 0; i < ec; i++) { real_t dot = (vertices[edges[i].a] - vertices[edges[i].b]).normalized().dot(p_normal); dot = ABS(dot); - if (dot < _EDGE_IS_VALID_SUPPORT_THRESHOLD && (edges[i].a == vtx || edges[i].b == vtx)) { + if (dot < edge_support_threshold && (edges[i].a == vtx || edges[i].b == vtx)) { r_amount = 2; r_type = FEATURE_EDGE; r_supports[0] = vertices[edges[i].a]; @@ -1140,7 +1140,7 @@ void GodotFaceShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 Vector3 n = p_normal; /** TEST FACE AS SUPPORT **/ - if (Math::abs(normal.dot(n)) > _FACE_IS_VALID_SUPPORT_THRESHOLD) { + if (Math::abs(normal.dot(n)) > face_support_threshold) { r_amount = 3; r_type = FEATURE_FACE; for (int i = 0; i < 3; i++) { @@ -1174,7 +1174,7 @@ void GodotFaceShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 // check if edge is valid as a support real_t dot = (vertex[i] - vertex[nx]).normalized().dot(n); dot = ABS(dot); - if (dot < _EDGE_IS_VALID_SUPPORT_THRESHOLD) { + if (dot < edge_support_threshold) { r_amount = 2; r_type = FEATURE_EDGE; r_supports[0] = vertex[i]; diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h index f02a01c97d..83da8388e4 100644 --- a/servers/rendering/rasterizer_dummy.h +++ b/servers/rendering/rasterizer_dummy.h @@ -120,7 +120,7 @@ public: void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override {} void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {} - void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {} + void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {} void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {} void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {} diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index a27ea75017..7987a98b0e 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -463,7 +463,6 @@ SceneShaderForwardClustered::MaterialData::~MaterialData() { RendererStorageRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) { MaterialData *material_data = memnew(MaterialData); material_data->shader_data = p_shader; - material_data->last_frame = false; //update will happen later anyway so do nothing. return material_data; } diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index 8e7bbad63e..33049fad9c 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -189,7 +189,6 @@ public: } struct MaterialData : public RendererStorageRD::MaterialData { - uint64_t last_frame; ShaderData *shader_data; RID uniform_set; uint64_t last_pass = 0; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 1613a307ec..0b99948063 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -452,7 +452,6 @@ SceneShaderForwardMobile::MaterialData::~MaterialData() { RendererStorageRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) { MaterialData *material_data = memnew(MaterialData); material_data->shader_data = p_shader; - material_data->last_frame = false; //update will happen later anyway so do nothing. return material_data; } diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index c136afd9f3..92db15e3b0 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -163,7 +163,6 @@ public: } struct MaterialData : public RendererStorageRD::MaterialData { - uint64_t last_frame; ShaderData *shader_data; RID uniform_set; uint64_t last_pass = 0; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 7e188926e0..0f3daef371 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -1377,14 +1377,6 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p if (md->shader_data->uses_time) { time_used = true; } - if (md->last_frame != RendererCompositorRD::singleton->get_frame_number()) { - md->last_frame = RendererCompositorRD::singleton->get_frame_number(); - if (!RD::get_singleton()->uniform_set_is_valid(md->uniform_set)) { - // uniform set may be gone because a dependency was erased. In this case, it will happen - // if a texture is deleted, so just re-create it. - storage->material_force_update_textures(material, RendererStorageRD::SHADER_TYPE_2D); - } - } } } @@ -2240,7 +2232,6 @@ RendererCanvasRenderRD::MaterialData::~MaterialData() { RendererStorageRD::MaterialData *RendererCanvasRenderRD::_create_material_func(ShaderData *p_shader) { MaterialData *material_data = memnew(MaterialData); material_data->shader_data = p_shader; - material_data->last_frame = false; //update will happen later anyway so do nothing. return material_data; } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index b409264c9a..84f64b6fda 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -200,7 +200,6 @@ class RendererCanvasRenderRD : public RendererCanvasRender { } struct MaterialData : public RendererStorageRD::MaterialData { - uint64_t last_frame; ShaderData *shader_data; RID uniform_set; diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp index 7ea117ef33..0d0d7513d0 100644 --- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp @@ -68,7 +68,7 @@ void RendererSceneEnvironmentRD::set_glow(bool p_enable, Vector<float> p_levels, glow_hdr_luminance_cap = p_hdr_luminance_cap; } -void RendererSceneEnvironmentRD::set_sdfgi(bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) { +void RendererSceneEnvironmentRD::set_sdfgi(bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) { sdfgi_enabled = p_enable; sdfgi_cascades = p_cascades; sdfgi_min_cell_size = p_min_cell_size; diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h index 9e36a61870..629d224b49 100644 --- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h @@ -133,7 +133,7 @@ public: /// SDFGI bool sdfgi_enabled = false; - RS::EnvironmentSDFGICascades sdfgi_cascades; + int sdfgi_cascades = 6; float sdfgi_min_cell_size = 0.2; bool sdfgi_use_occlusion = false; float sdfgi_bounce_feedback = 0.0; @@ -155,7 +155,7 @@ public: void set_ambient_light(const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source); void set_tonemap(RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale); void set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap); - void set_sdfgi(bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias); + void set_sdfgi(bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias); void set_fog(bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective); void set_volumetric_fog(bool p_enable, float p_density, const Color &p_scatterin, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject); void set_ssr(bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance); diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp index 73cb088f6a..3069b1c379 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp @@ -42,14 +42,13 @@ const Vector3i RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFF void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, RendererSceneGIRD *p_gi) { storage = p_gi->storage; gi = p_gi; - cascade_mode = p_env->sdfgi_cascades; + num_cascades = p_env->sdfgi_cascades; min_cell_size = p_env->sdfgi_min_cell_size; uses_occlusion = p_env->sdfgi_use_occlusion; y_scale_mode = p_env->sdfgi_y_scale; static const float y_scale[3] = { 1.0, 1.5, 2.0 }; y_mult = y_scale[y_scale_mode]; - static const int cascasde_size[3] = { 4, 6, 8 }; - cascades.resize(cascasde_size[cascade_mode]); + cascades.resize(num_cascades); probe_axis_count = SDFGI::PROBE_DIVISOR + 1; solid_cell_ratio = gi->sdfgi_solid_cell_ratio; solid_cell_count = uint32_t(float(cascade_size * cascade_size * cascade_size) * solid_cell_ratio); @@ -716,7 +715,10 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 13; RID parent_average; - if (i < cascades.size() - 1) { + if (cascades.size() == 1) { + // If there is only one SDFGI cascade, we can't use the previous cascade for blending. + parent_average = cascades[i].lightprobe_average_tex; + } else if (i < cascades.size() - 1) { parent_average = cascades[i + 1].lightprobe_average_tex; } else { parent_average = cascades[i - 1].lightprobe_average_tex; //to use something, but it won't be used diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h index a407199d0a..5e55262798 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h @@ -495,7 +495,7 @@ public: float solid_cell_ratio = 0; uint32_t solid_cell_count = 0; - RS::EnvironmentSDFGICascades cascade_mode; + int num_cascades = 6; float min_cell_size = 0; uint32_t probe_axis_count = 0; //amount of probes per axis, this is an odd number because it encloses endpoints diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index f6d58cb094..deaf613836 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -65,7 +65,7 @@ void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment static const uint32_t history_frames_to_converge[RS::ENV_SDFGI_CONVERGE_MAX] = { 5, 10, 15, 20, 25, 30 }; uint32_t requested_history_size = history_frames_to_converge[gi.sdfgi_frames_to_converge]; - if (rb->sdfgi && (rb->sdfgi->cascade_mode != env->sdfgi_cascades || rb->sdfgi->min_cell_size != env->sdfgi_min_cell_size || requested_history_size != rb->sdfgi->history_size || rb->sdfgi->uses_occlusion != env->sdfgi_use_occlusion || rb->sdfgi->y_scale_mode != env->sdfgi_y_scale)) { + if (rb->sdfgi && (rb->sdfgi->num_cascades != env->sdfgi_cascades || rb->sdfgi->min_cell_size != env->sdfgi_min_cell_size || requested_history_size != rb->sdfgi->history_size || rb->sdfgi->uses_occlusion != env->sdfgi_use_occlusion || rb->sdfgi->y_scale_mode != env->sdfgi_y_scale)) { //configuration changed, erase rb->sdfgi->erase(); memdelete(rb->sdfgi); @@ -303,7 +303,7 @@ void RendererSceneRenderRD::environment_glow_set_use_high_quality(bool p_enable) glow_high_quality = p_enable; } -void RendererSceneRenderRD::environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) { +void RendererSceneRenderRD::environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) { RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env); ERR_FAIL_COND(!env); @@ -514,7 +514,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba ambient_color_sky_mix = env->ambient_sky_contribution; const float ambient_energy = env->ambient_light_energy; ambient_color = env->ambient_light; - ambient_color.to_linear(); + ambient_color = ambient_color.to_linear(); ambient_color.r *= ambient_energy; ambient_color.g *= ambient_energy; ambient_color.b *= ambient_energy; @@ -533,7 +533,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba } else { const float bg_energy = env->bg_energy; Color panorama_color = ((environment_background == RS::ENV_BG_CLEAR_COLOR) ? storage->get_default_clear_color() : env->bg_color); - panorama_color.to_linear(); + panorama_color = panorama_color.to_linear(); panorama_color.r *= bg_energy; panorama_color.g *= bg_energy; panorama_color.b *= bg_energy; @@ -1132,11 +1132,11 @@ bool RendererSceneRenderRD::_shadow_atlas_find_omni_shadows(ShadowAtlas *shadow_ return false; } -bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) { +bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) { ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas); ERR_FAIL_COND_V(!shadow_atlas, false); - LightInstance *li = light_instance_owner.get_or_null(p_light_intance); + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); ERR_FAIL_COND_V(!li, false); if (shadow_atlas->size == 0 || shadow_atlas->smallest_subdiv == 0) { @@ -1185,8 +1185,8 @@ bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_i bool should_realloc = false; bool should_redraw = false; - if (shadow_atlas->shadow_owners.has(p_light_intance)) { - old_key = shadow_atlas->shadow_owners[p_light_intance]; + if (shadow_atlas->shadow_owners.has(p_light_instance)) { + old_key = shadow_atlas->shadow_owners[p_light_instance]; old_quadrant = (old_key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; old_shadow = old_key & ShadowAtlas::SHADOW_INDEX_MASK; @@ -1230,7 +1230,7 @@ bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_i ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow]; _shadow_atlas_invalidate_shadow(sh, p_atlas, shadow_atlas, new_quadrant, new_shadow); - sh->owner = p_light_intance; + sh->owner = p_light_instance; sh->alloc_tick = tick; sh->version = p_light_version; @@ -1241,7 +1241,7 @@ bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_i ShadowAtlas::Quadrant::Shadow *extra_sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_omni_shadow]; _shadow_atlas_invalidate_shadow(extra_sh, p_atlas, shadow_atlas, new_quadrant, new_omni_shadow); - extra_sh->owner = p_light_intance; + extra_sh->owner = p_light_instance; extra_sh->alloc_tick = tick; extra_sh->version = p_light_version; } @@ -1249,7 +1249,7 @@ bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_i li->shadow_atlases.insert(p_atlas); //update it in map - shadow_atlas->shadow_owners[p_light_intance] = new_key; + shadow_atlas->shadow_owners[p_light_instance] = new_key; //make it dirty, as it should redraw anyway return true; } @@ -1270,10 +1270,10 @@ void RendererSceneRenderRD::_shadow_atlas_invalidate_shadow(RendererSceneRenderR omni_shadow->owner = RID(); } + p_shadow_atlas->shadow_owners.erase(p_shadow->owner); p_shadow->version = 0; p_shadow->owner = RID(); sli->shadow_atlases.erase(p_atlas); - p_shadow_atlas->shadow_owners.erase(p_shadow->owner); } } @@ -2636,8 +2636,12 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS) { if (p_shadow_atlas.is_valid()) { RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas); - Size2 rtsize = storage->render_target_get_size(rb->render_target); + if (shadow_atlas_texture.is_null()) { + shadow_atlas_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + } + + Size2 rtsize = storage->render_target_get_size(rb->render_target); effects->copy_to_fb_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true); } } @@ -3993,7 +3997,6 @@ RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) { FogMaterialData *material_data = memnew(FogMaterialData); material_data->shader_data = p_shader; - material_data->last_frame = false; //update will happen later anyway so do nothing. return material_data; } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 6432ca99f0..592618ae05 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -942,7 +942,6 @@ private: }; struct FogMaterialData : public RendererStorageRD::MaterialData { - uint64_t last_frame; FogShaderData *shader_data; RID uniform_set; bool uniform_set_updated; @@ -984,7 +983,7 @@ public: virtual RID shadow_atlas_create() override; virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = false) override; virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override; - virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override; + virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) override; _FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_intance) { ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); ERR_FAIL_COND_V(!atlas, false); @@ -1093,7 +1092,7 @@ public: bool environment_is_ssr_enabled(RID p_env) const; bool environment_is_sdfgi_enabled(RID p_env) const; - virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override; + virtual void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override; virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override; virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override; virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override; diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index f0419b7907..856ea5e74d 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -750,7 +750,6 @@ RendererStorageRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() { RendererStorageRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) { SkyMaterialData *material_data = memnew(SkyMaterialData); material_data->shader_data = p_shader; - material_data->last_frame = false; //update will happen later anyway so do nothing. return material_data; } diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h index 46d376e667..d81a415c2d 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h @@ -228,7 +228,6 @@ public: } sky_shader; struct SkyMaterialData : public RendererStorageRD::MaterialData { - uint64_t last_frame; SkyShaderData *shader_data; RID uniform_set; bool uniform_set_updated; diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 19075fab86..2e63ac57d9 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -2962,24 +2962,19 @@ bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<St return true; } -void RendererStorageRD::_material_uniform_set_erased(const RID &p_set, void *p_material) { +void RendererStorageRD::_material_uniform_set_erased(void *p_material) { RID rid = *(RID *)p_material; Material *material = base_singleton->material_owner.get_or_null(rid); if (material) { + if (material->data) { + // Uniform set may be gone because a dependency was erased. This happens + // if a texture is deleted, so re-create it. + base_singleton->_material_queue_update(material, false, true); + } material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); } } -void RendererStorageRD::material_force_update_textures(RID p_material, ShaderType p_shader_type) { - Material *material = material_owner.get_or_null(p_material); - if (material->shader_type != p_shader_type) { - return; - } - if (material->data) { - material->data->update_parameters(material->params, false, true); - } -} - void RendererStorageRD::_update_queued_materials() { while (material_update_list.first()) { Material *material = material_update_list.first()->self(); @@ -5882,8 +5877,6 @@ RendererStorageRD::ShaderData *RendererStorageRD::_create_particles_shader_func( } bool RendererStorageRD::ParticlesMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - uniform_set_updated = true; - return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, base_singleton->particles_shader.shader.version_get_shader(shader_data->version, 0), 3); } @@ -5894,7 +5887,6 @@ RendererStorageRD::ParticlesMaterialData::~ParticlesMaterialData() { RendererStorageRD::MaterialData *RendererStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) { ParticlesMaterialData *material_data = memnew(ParticlesMaterialData); material_data->shader_data = p_shader; - material_data->last_frame = false; //update will happen later anyway so do nothing. return material_data; } diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index 8c04274c3f..43bbcf6520 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -177,7 +177,7 @@ public: Vector<RID> texture_cache; }; typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *); - static void _material_uniform_set_erased(const RID &p_set, void *p_material); + static void _material_uniform_set_erased(void *p_material); enum DefaultRDTexture { DEFAULT_RD_TEXTURE_WHITE, @@ -910,10 +910,8 @@ private: } struct ParticlesMaterialData : public MaterialData { - uint64_t last_frame = 0; ParticlesShaderData *shader_data = nullptr; RID uniform_set; - bool uniform_set_updated = false; virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} @@ -1448,7 +1446,6 @@ public: void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters); void material_update_dependency(RID p_material, DependencyTracker *p_instance); - void material_force_update_textures(RID p_material, ShaderType p_shader_type); void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function); diff --git a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl index fdc7729338..52787bb204 100644 --- a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl @@ -1,6 +1,6 @@ #define LIGHT_BAKE_DISABLED 0 -#define LIGHT_BAKE_DYNAMIC 1 -#define LIGHT_BAKE_STATIC 2 +#define LIGHT_BAKE_STATIC 1 +#define LIGHT_BAKE_DYNAMIC 2 struct LightData { //this structure needs to be as packed as possible highp vec3 position; diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h index 20ca49cd71..426d22f83e 100644 --- a/servers/rendering/renderer_scene.h +++ b/servers/rendering/renderer_scene.h @@ -149,7 +149,7 @@ public: virtual void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) = 0; virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0; - virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0; + virtual void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0; virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0; virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0; diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index 071d88233f..1e770ef66c 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -1127,7 +1127,7 @@ public: PASS2(environment_set_volumetric_fog_volume_size, int, int) PASS1(environment_set_volumetric_fog_filter_active, bool) - PASS11(environment_set_sdfgi, RID, bool, RS::EnvironmentSDFGICascades, float, RS::EnvironmentSDFGIYScale, bool, float, bool, float, float, float) + PASS11(environment_set_sdfgi, RID, bool, int, float, RS::EnvironmentSDFGIYScale, bool, float, bool, float, float, float) PASS1(environment_set_sdfgi_ray_count, RS::EnvironmentSDFGIRayCount) PASS1(environment_set_sdfgi_frames_to_converge, RS::EnvironmentSDFGIFramesToConverge) PASS1(environment_set_sdfgi_frames_to_update_light, RS::EnvironmentSDFGIFramesToUpdateLight) diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index f99d34d292..c34a46d166 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -140,7 +140,7 @@ public: virtual void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) = 0; virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0; - virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0; + virtual void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0; virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0; virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0; diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 46fb3c8537..6fc5d0b3e8 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -451,7 +451,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("compute_list_add_barrier", "compute_list"), &RenderingDevice::compute_list_add_barrier); ClassDB::bind_method(D_METHOD("compute_list_end", "post_barrier"), &RenderingDevice::compute_list_end, DEFVAL(BARRIER_MASK_ALL)); - ClassDB::bind_method(D_METHOD("free", "rid"), &RenderingDevice::free); + ClassDB::bind_method(D_METHOD("free_rid", "rid"), &RenderingDevice::free); ClassDB::bind_method(D_METHOD("capture_timestamp", "name"), &RenderingDevice::capture_timestamp); ClassDB::bind_method(D_METHOD("get_captured_timestamps_count"), &RenderingDevice::get_captured_timestamps_count); diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 3e74741de0..655a32a805 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -742,7 +742,7 @@ public: virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set) = 0; virtual bool uniform_set_is_valid(RID p_uniform_set) = 0; - typedef void (*UniformSetInvalidatedCallback)(const RID &, void *); + typedef void (*UniformSetInvalidatedCallback)(void *); virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata) = 0; virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0; diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index ead49f053c..54fd897a77 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -259,7 +259,6 @@ public: command_queue.push(RSG::storage, &RendererStorage::mesh_initialize, mesh); command_queue.push(RSG::storage, &RendererStorage::mesh_set_blend_shape_count, mesh, p_blend_shape_count); for (int i = 0; i < p_surfaces.size(); i++) { - RSG::storage->mesh_add_surface(mesh, p_surfaces[i]); command_queue.push(RSG::storage, &RendererStorage::mesh_add_surface, mesh, p_surfaces[i]); } } @@ -643,7 +642,7 @@ public: FUNC2(environment_set_volumetric_fog_volume_size, int, int) FUNC1(environment_set_volumetric_fog_filter_active, bool) - FUNC11(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, float, bool, float, float, float) + FUNC11(environment_set_sdfgi, RID, bool, int, float, EnvironmentSDFGIYScale, bool, float, bool, float, float, float) FUNC1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount) FUNC1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge) FUNC1(environment_set_sdfgi_frames_to_update_light, EnvironmentSDFGIFramesToUpdateLight) diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index bb6cfd7b03..f16f66544a 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -2742,13 +2742,13 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI //stage based function const StageFunctionInfo &sf = p_function_info.stage_functions[name]; if (argcount != sf.arguments.size()) { - _set_error(vformat("Invalid number of arguments when calling stage function '%s', which expects %d arguments.", String(name), sf.arguments.size())); + _set_error(vformat(RTR("Invalid number of arguments when calling stage function '%s', which expects %d arguments."), String(name), sf.arguments.size())); return false; } //validate arguments for (int i = 0; i < argcount; i++) { if (args[i] != sf.arguments[i].type) { - _set_error(vformat("Invalid argument type when calling stage function '%s', type expected is '%s'.", String(name), String(get_datatype_name(sf.arguments[i].type)))); + _set_error(vformat(RTR("Invalid argument type when calling stage function '%s', type expected is '%s'."), String(name), get_datatype_name(sf.arguments[i].type))); return false; } } @@ -2852,7 +2852,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI } } if (error) { - _set_error(vformat("Expected integer constant within %s..%s range.", min, max)); + _set_error(vformat(RTR("Expected integer constant within [%d..%d] range."), min, max)); return false; } } @@ -2871,7 +2871,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI } if (arg_idx < argcount) { if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE && p_func->arguments[arg_idx + 1]->type != Node::TYPE_MEMBER && p_func->arguments[arg_idx + 1]->type != Node::TYPE_ARRAY) { - _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member."); + _set_error(vformat(RTR("Argument %d of function '%s' is not a variable, array, or member."), arg_idx + 1, String(name))); return false; } @@ -2895,7 +2895,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI fail = true; } else { if (shader->varyings.has(varname)) { - _set_error(vformat("Varyings cannot be passed for '%s' parameter!", "out")); + _set_error(vformat(RTR("Varyings cannot be passed for the '%s' parameter."), "out")); return false; } if (p_function_info.built_ins.has(varname)) { @@ -2908,7 +2908,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI } } if (fail) { - _set_error(vformat("Constant value cannot be passed for '%s' parameter!", "out")); + _set_error(vformat(RTR("A constant value cannot be passed for the '%s' parameter."), "out")); return false; } @@ -2921,7 +2921,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI n = static_cast<const MemberNode *>(n)->owner; } if (n->type != Node::TYPE_VARIABLE && n->type != Node::TYPE_ARRAY) { - _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member."); + _set_error(vformat(RTR("Argument %d of function '%s' is not a variable, array, or member."), arg_idx + 1, String(name))); return false; } if (n->type == Node::TYPE_VARIABLE) { @@ -2951,7 +2951,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI } if (!valid) { - _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable, array or member."); + _set_error(vformat(RTR("Argument %d of function '%s' can only take a local variable, array, or member."), arg_idx + 1, String(name))); return false; } } @@ -2998,16 +2998,15 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI arglist += get_datatype_name(builtin_func_defs[builtin_idx].args[i]); } - String err = "Built-in function \"" + String(name) + "(" + arglist + ")\" is supported only on high-end platform!"; - _set_error(err); + _set_error(vformat(RTR("Built-in function \"%s(%s)\" is only supported on high-end platforms."), String(name), arglist)); return false; } if (failed_builtin) { - String err = "Invalid arguments for built-in function: " + String(name) + "("; + String arg_list; for (int i = 0; i < argcount; i++) { if (i > 0) { - err += ","; + arg_list += ","; } String arg_name; @@ -3021,10 +3020,9 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI arg_name += itos(args3[i]); arg_name += "]"; } - err += arg_name; + arg_list += arg_name; } - err += ")"; - _set_error(err); + _set_error(vformat(RTR("Invalid arguments for the built-in function: \"%s(%s)\"."), String(name), arg_list)); return false; } @@ -3041,7 +3039,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI } if (name == exclude_function) { - _set_error("Recursion is not allowed"); + _set_error(RTR("Recursion is not allowed.")); return false; } @@ -3054,7 +3052,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI } if (!shader->functions[i].callable) { - _set_error("Function '" + String(name) + " can't be called from source code."); + _set_error(vformat(RTR("Function '%s' can't be called from source code."), String(name))); return false; } @@ -3113,7 +3111,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI arg_name += "]"; } - _set_error(vformat("Invalid argument for \"%s(%s)\" function: argument %s should be %s but is %s.", String(name), arg_list, j + 1, func_arg_name, arg_name)); + _set_error(vformat(RTR("Invalid argument for \"%s(%s)\" function: argument %d should be %s but is %s."), String(name), arg_list, j + 1, func_arg_name, arg_name)); fail = true; break; } @@ -3150,9 +3148,9 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI } if (last_arg_count > args.size()) { - _set_error(vformat("Too few arguments for \"%s(%s)\" call. Expected at least %s but received %s.", String(name), arg_list, last_arg_count, args.size())); + _set_error(vformat(RTR("Too few arguments for \"%s(%s)\" call. Expected at least %d but received %d."), String(name), arg_list, last_arg_count, args.size())); } else if (last_arg_count < args.size()) { - _set_error(vformat("Too many arguments for \"%s(%s)\" call. Expected at most %s but received %s.", String(name), arg_list, last_arg_count, args.size())); + _set_error(vformat(RTR("Too many arguments for \"%s(%s)\" call. Expected at most %d but received %d."), String(name), arg_list, last_arg_count, args.size())); } return false; @@ -3190,7 +3188,7 @@ bool ShaderLanguage::_compare_datatypes(DataType p_datatype_a, String p_datatype type_name2 += "]"; } - _set_error("Invalid assignment of '" + type_name2 + "' to '" + type_name + "'"); + _set_error(vformat(RTR("Invalid assignment of '%s' to '%s'."), type_name2, type_name)); } return result; } @@ -3235,7 +3233,7 @@ bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Functio return true; } else if (tk.type != TK_COMMA) { // something is broken - _set_error("Expected ',' or ')' after argument"); + _set_error(RTR("Expected ',' or ')' after argument.")); return false; } } @@ -4247,14 +4245,14 @@ bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringNam ERR_FAIL_INDEX_V(p_argument, shader->functions[i].function->arguments.size(), false); FunctionNode::Argument *arg = &shader->functions[i].function->arguments.write[p_argument]; if (arg->tex_builtin_check) { - _set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using both built-ins and uniform textures, this is not supported (use either one or the other)."); + _set_error(vformat(RTR("Sampler argument %d of function '%s' called more than once using both built-ins and uniform textures, this is not supported (use either one or the other)."), p_argument, String(p_name))); return false; } else if (arg->tex_argument_check) { //was checked, verify that filter and repeat are the same if (arg->tex_argument_filter == p_filter && arg->tex_argument_repeat == p_repeat) { return true; } else { - _set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using textures that differ in either filter or repeat setting."); + _set_error(vformat(RTR("Sampler argument %d of function '%s' called more than once using textures that differ in either filter or repeat setting."), p_argument, String(p_name))); return false; } } else { @@ -4281,14 +4279,14 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa ERR_FAIL_INDEX_V(p_argument, shader->functions[i].function->arguments.size(), false); FunctionNode::Argument *arg = &shader->functions[i].function->arguments.write[p_argument]; if (arg->tex_argument_check) { - _set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using both built-ins and uniform textures, this is not supported (use either one or the other)."); + _set_error(vformat(RTR("Sampler argument %d of function '%s' called more than once using both built-ins and uniform textures, this is not supported (use either one or the other)."), p_argument, String(p_name))); return false; } else if (arg->tex_builtin_check) { //was checked, verify that the built-in is the same if (arg->tex_builtin == p_builtin) { return true; } else { - _set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using different built-ins. Only calling with the same built-in is supported."); + _set_error(vformat(RTR("Sampler argument %d of function '%s' called more than once using different built-ins. Only calling with the same built-in is supported."), p_argument, String(p_name))); return false; } } else { @@ -4318,7 +4316,7 @@ Error ShaderLanguage::_parse_array_size(BlockNode *p_block, const FunctionInfo & error = true; } if (error) { - _set_error("Array size is already defined!"); + _set_error(vformat(RTR("Array size is already defined."))); return ERR_PARSE_ERROR; } @@ -4327,7 +4325,7 @@ Error ShaderLanguage::_parse_array_size(BlockNode *p_block, const FunctionInfo & if (tk.type == TK_BRACKET_CLOSE) { if (p_forbid_unknown_size) { - _set_error("Unknown array size is forbidden in that context!"); + _set_error(vformat(RTR("Unknown array size is forbidden in that context."))); return ERR_PARSE_ERROR; } if (r_unknown_size != nullptr) { @@ -4364,7 +4362,7 @@ Error ShaderLanguage::_parse_array_size(BlockNode *p_block, const FunctionInfo & } } } else if (n->type == Node::TYPE_OPERATOR) { - _set_error("Array size expressions are not yet implemented."); + _set_error(vformat(RTR("Array size expressions are not supported."))); return ERR_PARSE_ERROR; } if (r_size_expression != nullptr) { @@ -4376,13 +4374,13 @@ Error ShaderLanguage::_parse_array_size(BlockNode *p_block, const FunctionInfo & } if (array_size <= 0) { - _set_error("Expected single integer constant > 0"); + _set_error(RTR("Expected a positive integer constant.")); return ERR_PARSE_ERROR; } tk = _get_token(); if (tk.type != TK_BRACKET_CLOSE) { - _set_error("Expected ']'"); + _set_expected_error("]"); return ERR_PARSE_ERROR; } @@ -4409,7 +4407,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc struct_name = tk.text; } else { if (!is_token_variable_datatype(tk.type)) { - _set_error("Invalid data type for array"); + _set_error(RTR("Invalid data type for the array.")); return nullptr; } type = get_token_datatype(tk.type); @@ -4422,7 +4420,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc } tk = _get_token(); } else { - _set_error("Expected '['"); + _set_expected_error("["); return nullptr; } } @@ -4460,20 +4458,20 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc break; } else { if (auto_size) { - _set_error("Expected '}' or ','"); + _set_expected_error("}", ","); } else { - _set_error("Expected ')' or ','"); + _set_expected_error(")", ","); } return nullptr; } idx++; } if (!auto_size && !undefined_size && an->initializer.size() != array_size) { - _set_error("Array size mismatch"); + _set_error(RTR("Array size mismatch.")); return nullptr; } } else { - _set_error("Expected array initialization!"); + _set_error(RTR("Expected array initialization.")); return nullptr; } @@ -4503,7 +4501,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc Node *n = _parse_and_reduce_expression(p_block, p_function_info); if (!n) { - _set_error("Invalid data type for array"); + _set_error(RTR("Invalid data type for the array.")); return nullptr; } @@ -4526,30 +4524,32 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc } tk = _get_token(); } else { - _set_error("Expected '['"); + _set_expected_error("["); return nullptr; } if (type != p_type || struct_name != p_struct_name || array_size != p_array_size) { - String error_str = "Cannot convert from '"; + String from; if (type == TYPE_STRUCT) { - error_str += struct_name; + from += struct_name; } else { - error_str += get_datatype_name(type); + from += get_datatype_name(type); } - error_str += "["; - error_str += itos(array_size); - error_str += "]'"; - error_str += " to '"; + from += "["; + from += itos(array_size); + from += "]'"; + + String to; if (type == TYPE_STRUCT) { - error_str += p_struct_name; + to += p_struct_name; } else { - error_str += get_datatype_name(p_type); + to += get_datatype_name(p_type); } - error_str += "["; - error_str += itos(p_array_size); - error_str += "]'"; - _set_error(error_str); + to += "["; + to += itos(p_array_size); + to += "]'"; + + _set_error(vformat(RTR("Cannot convert from '%s' to '%s'."), from, to)); return nullptr; } } @@ -4580,19 +4580,19 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc break; } else { if (auto_size) { - _set_error("Expected '}' or ','"); + _set_expected_error("}", ","); } else { - _set_error("Expected ')' or ','"); + _set_expected_error(")", ","); } return nullptr; } } if (an->initializer.size() != p_array_size) { - _set_error("Array size mismatch"); + _set_error(RTR("Array size mismatch.")); return nullptr; } } else { - _set_error("Expected array initialization!"); + _set_error(RTR("Expected array initialization.")); return nullptr; } @@ -4623,7 +4623,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons tk = _get_token(); if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_error("Expected ')' in expression"); + _set_error(RTR("Expected ')' in expression.")); return nullptr; } @@ -4671,7 +4671,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } else if (tk.type == TK_TYPE_VOID) { //make sure void is not used in expression - _set_error("Void value not allowed in Expression"); + _set_error(RTR("Void value not allowed in expression.")); return nullptr; } else if (is_token_nonvoid_datatype(tk.type) || tk.type == TK_CURLY_BRACKET_OPEN) { if (tk.type == TK_CURLY_BRACKET_OPEN) { @@ -4700,7 +4700,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expr = _parse_array_constructor(p_block, p_function_info); } else { if (tk.type != TK_PARENTHESIS_OPEN) { - _set_error("Expected '(' after type name"); + _set_error(RTR("Expected '(' after the type name.")); return nullptr; } //basic type constructor @@ -4733,7 +4733,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } if (!_validate_function_call(p_block, p_function_info, func, &func->return_cache, &func->struct_name)) { - _set_error("No matching constructor found for: '" + String(funcname->name) + "'"); + _set_error(vformat(RTR("No matching constructor found for: '%s'."), String(funcname->name))); return nullptr; } @@ -4790,7 +4790,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (i + 1 < pstruct->members.size()) { tk = _get_token(); if (tk.type != TK_COMMA) { - _set_error("Expected ','"); + _set_expected_error(","); return nullptr; } } @@ -4798,7 +4798,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } tk = _get_token(); if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_error("Expected ')'"); + _set_expected_error(")"); return nullptr; } @@ -4822,7 +4822,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons ShaderLanguage::BlockNode *bnode = p_block; while (bnode) { if (bnode->variables.has(name)) { - _set_error("Expected function name"); + _set_error(RTR("Expected a function name.")); return nullptr; } bnode = bnode->parent_block; @@ -4859,7 +4859,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } if (!_validate_function_call(p_block, p_function_info, func, &func->return_cache, &func->struct_name)) { - _set_error("No matching function found for: '" + String(funcname->name) + "'"); + _set_error(vformat(RTR("No matching function found for: '%s'."), String(funcname->name))); return nullptr; } completion_class = TAG_GLOBAL; // reset sub-class @@ -4912,7 +4912,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (shader->varyings.has(varname)) { switch (shader->varyings[varname].stage) { case ShaderNode::Varying::STAGE_UNKNOWN: { - _set_error(vformat("Varying '%s' must be assigned in the vertex or fragment function first!", varname)); + _set_error(vformat(RTR("Varying '%s' must be assigned in the vertex or fragment function first."), varname)); return nullptr; } case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT: @@ -4938,7 +4938,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } if (error) { - _set_error(vformat("Varying '%s' cannot be passed for the '%s' parameter in that context!", varname, _get_qualifier_str(arg_qual))); + _set_error(vformat(RTR("Varying '%s' cannot be passed for the '%s' parameter in that context."), varname, _get_qualifier_str(arg_qual))); return nullptr; } } @@ -4985,7 +4985,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } if (error) { - _set_error(vformat("Constant value cannot be passed for '%s' parameter!", _get_qualifier_str(arg_qual))); + _set_error(vformat(RTR("A constant value cannot be passed for '%s' parameter."), _get_qualifier_str(arg_qual))); return nullptr; } } @@ -5067,12 +5067,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons idx++; } if (!found) { - _set_error("Unknown identifier in expression: " + String(identifier)); + _set_error(vformat(RTR("Unknown identifier in expression: '%s'."), String(identifier))); return nullptr; } } else { if (!_find_identifier(p_block, false, p_function_info, identifier, &data_type, &ident_type, &is_const, &array_size, &struct_name)) { - _set_error("Unknown identifier in expression: " + String(identifier)); + _set_error(vformat(RTR("Unknown identifier in expression: '%s'."), String(identifier))); return nullptr; } if (ident_type == IDENTIFIER_VARYING) { @@ -5114,7 +5114,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } if (ident_type == IDENTIFIER_FUNCTION) { - _set_error("Can't use function as identifier: " + String(identifier)); + _set_error(vformat(RTR("Can't use function as identifier: '%s'."), String(identifier))); return nullptr; } if (is_const) { @@ -5136,7 +5136,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (tk.type == TK_OP_ASSIGN) { if (is_const) { - _set_error("Constants cannot be modified."); + _set_error(RTR("Constants cannot be modified.")); return nullptr; } assign_expression = _parse_array_constructor(p_block, p_function_info, data_type, struct_name, array_size); @@ -5159,7 +5159,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } if (index_expression->get_array_size() != 0 || (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT)) { - _set_error("Only integer expressions are allowed for indexing."); + _set_error(RTR("Only integer expressions are allowed for indexing.")); return nullptr; } @@ -5169,7 +5169,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (!cnode->values.is_empty()) { int value = cnode->values[0].sint; if (value < 0 || value >= array_size) { - _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1)); + _set_error(vformat(RTR("Index [%d] out of range [%d..%d]."), value, 0, array_size - 1)); return nullptr; } } @@ -5178,7 +5178,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons tk = _get_token(); if (tk.type != TK_BRACKET_CLOSE) { - _set_error("Expected ']'"); + _set_expected_error("]"); return nullptr; } } else { @@ -5208,9 +5208,15 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons #ifdef DEBUG_ENABLED if (check_warnings) { StringName func_name; + BlockNode *b = p_block; - if (p_block && p_block->parent_function) { - func_name = p_block->parent_function->name; + while (b) { + if (b->parent_function) { + func_name = b->parent_function->name; + break; + } else { + b = b->parent_block; + } } _parse_used_identifier(identifier, ident_type, func_name); @@ -5247,12 +5253,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons continue; } else { if (tk.type != TK_SEMICOLON) { - _set_error("Expected expression, found: " + get_token_text(tk)); + _set_error(vformat(RTR("Expected expression, found: '%s'."), get_token_text(tk))); return nullptr; } else { #ifdef DEBUG_ENABLED if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) { - _add_line_warning(ShaderWarning::FORMATTING_ERROR, "Empty statement. Remove ';' to fix this warning."); + _add_line_warning(ShaderWarning::FORMATTING_ERROR, RTR("Empty statement. Remove ';' to fix this warning.")); } #endif // DEBUG_ENABLED _set_tkpos(prepos); @@ -5299,7 +5305,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } if (identifier == StringName()) { - _set_error("Expected identifier as member"); + _set_error(RTR("Expected an identifier as a member.")); return nullptr; } String ident = identifier; @@ -5544,12 +5550,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } if (mix_error) { - _set_error("Cannot combine symbols from different sets in expression ." + ident); + _set_error(vformat(RTR("Cannot combine symbols from different sets in expression '.%s'."), ident)); return nullptr; } if (!ok) { - _set_error("Invalid member for " + (dt == TYPE_STRUCT ? st : get_datatype_name(dt)) + " expression: ." + ident); + _set_error(vformat(RTR("Invalid member for '%s' expression: '.%s'."), (dt == TYPE_STRUCT ? st : get_datatype_name(dt)), ident)); return nullptr; } @@ -5569,7 +5575,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons tk = _get_token(); if (tk.type == TK_OP_ASSIGN) { if (last_type == IDENTIFIER_CONSTANT) { - _set_error("Constants cannot be modified."); + _set_error(RTR("Constants cannot be modified.")); return nullptr; } Node *assign_expression = _parse_array_constructor(p_block, p_function_info, member_type, member_struct_name, array_size); @@ -5594,7 +5600,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } if (index_expression->get_array_size() != 0 || (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT)) { - _set_error("Only integer expressions are allowed for indexing."); + _set_error(RTR("Only integer expressions are allowed for indexing.")); return nullptr; } @@ -5604,7 +5610,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (!cnode->values.is_empty()) { int value = cnode->values[0].sint; if (value < 0 || value >= array_size) { - _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1)); + _set_error(vformat(RTR("Index [%d] out of range [%d..%d]."), value, 0, array_size - 1)); return nullptr; } } @@ -5613,7 +5619,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons tk = _get_token(); if (tk.type != TK_BRACKET_CLOSE) { - _set_error("Expected ']'"); + _set_expected_error("]"); return nullptr; } mn->index_expression = index_expression; @@ -5640,7 +5646,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } if (index->get_array_size() != 0 || (index->get_datatype() != TYPE_INT && index->get_datatype() != TYPE_UINT)) { - _set_error("Only integer expressions are allowed for indexing."); + _set_error(RTR("Only integer expressions are allowed for indexing.")); return nullptr; } @@ -5651,7 +5657,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (index->type == Node::TYPE_CONSTANT) { uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint; if (index_constant >= (uint32_t)expr->get_array_size()) { - _set_error(vformat("Index [%s] out of range [%s..%s]", index_constant, 0, expr->get_array_size() - 1)); + _set_error(vformat(RTR("Index [%d] out of range [%d..%d]."), index_constant, 0, expr->get_array_size() - 1)); return nullptr; } } @@ -5669,7 +5675,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (index->type == Node::TYPE_CONSTANT) { uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint; if (index_constant >= 2) { - _set_error("Index out of range (0-1)"); + _set_error(vformat(RTR("Index [%d] out of range [%d..%d]."), index_constant, 0, 1)); return nullptr; } } @@ -5703,7 +5709,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (index->type == Node::TYPE_CONSTANT) { uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint; if (index_constant >= 3) { - _set_error("Index out of range (0-2)"); + _set_error(vformat(RTR("Index [%d] out of range [%d..%d]."), index_constant, 0, 2)); return nullptr; } } @@ -5736,7 +5742,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (index->type == Node::TYPE_CONSTANT) { uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint; if (index_constant >= 4) { - _set_error("Index out of range (0-3)"); + _set_error(vformat(RTR("Index [%d] out of range [%d..%d]."), index_constant, 0, 3)); return nullptr; } } @@ -5762,7 +5768,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } break; default: { - _set_error("Object of type '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' can't be indexed"); + _set_error(vformat(RTR("An object of type '%s' can't be indexed."), (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())))); return nullptr; } } @@ -5777,7 +5783,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons tk = _get_token(); if (tk.type != TK_BRACKET_CLOSE) { - _set_error("Expected ']' after indexing expression"); + _set_expected_error("]"); return nullptr; } @@ -5787,12 +5793,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons op->arguments.push_back(expr); if (!_validate_operator(op, &op->return_cache, &op->return_array_size)) { - _set_error("Invalid base type for increment/decrement operator"); + _set_error(RTR("Invalid base type for increment/decrement operator.")); return nullptr; } if (!_validate_assign(expr, p_function_info)) { - _set_error("Invalid use of increment/decrement operator in constant expression."); + _set_error(RTR("Invalid use of increment/decrement operator in a constant expression.")); return nullptr; } expr = op; @@ -5909,7 +5915,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons o.op = OP_SELECT_ELSE; break; default: { - _set_error("Invalid token for operator: " + get_token_text(tk)); + _set_error(vformat(RTR("Invalid token for the operator: '%s'."), get_token_text(tk))); return nullptr; } } @@ -6088,7 +6094,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expr_pos++; if (expr_pos == expression.size()) { //can happen.. - _set_error("Unexpected end of expression..."); + _set_error(RTR("Unexpected end of expression.")); return nullptr; } } @@ -6098,7 +6104,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons OperatorNode *op = alloc_node<OperatorNode>(); op->op = expression[i].op; if ((op->op == OP_INCREMENT || op->op == OP_DECREMENT) && !_validate_assign(expression[i + 1].node, p_function_info)) { - _set_error("Can't use increment/decrement operator in constant expression."); + _set_error(RTR("Can't use increment/decrement operator in a constant expression.")); return nullptr; } op->arguments.push_back(expression[i + 1].node); @@ -6110,7 +6116,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons String at; for (int j = 0; j < op->arguments.size(); j++) { if (j > 0) { - at += " and "; + at += ", "; } at += get_datatype_name(op->arguments[j]->get_datatype()); if (!op->arguments[j]->is_indexed() && op->arguments[j]->get_array_size() > 0) { @@ -6119,7 +6125,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons at += "]"; } } - _set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at); + _set_error(vformat(RTR("Invalid arguments to unary operator '%s': %s."), get_operator_text(op->op), at)); return nullptr; } expression.remove_at(i + 1); @@ -6127,12 +6133,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } else if (is_ternary) { if (next_op < 1 || next_op >= (expression.size() - 1)) { - _set_error("Parser bug..."); + _set_parsing_error(); ERR_FAIL_V(nullptr); } if (next_op + 2 >= expression.size() || !expression[next_op + 2].is_op || expression[next_op + 2].op != OP_SELECT_ELSE) { - _set_error("Missing matching ':' for select operator"); + _set_error(RTR("Missing matching ':' for select operator.")); return nullptr; } @@ -6148,7 +6154,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons String at; for (int i = 0; i < op->arguments.size(); i++) { if (i > 0) { - at += " and "; + at += ", "; } at += get_datatype_name(op->arguments[i]->get_datatype()); if (!op->arguments[i]->is_indexed() && op->arguments[i]->get_array_size() > 0) { @@ -6157,7 +6163,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons at += "]"; } } - _set_error("Invalid argument to ternary ?: operator: " + at); + _set_error(vformat(RTR("Invalid argument to ternary operator: '%s'."), at)); return nullptr; } @@ -6167,7 +6173,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } else { if (next_op < 1 || next_op >= (expression.size() - 1)) { - _set_error("Parser bug..."); + _set_parsing_error(); ERR_FAIL_V(nullptr); } @@ -6175,7 +6181,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons op->op = expression[next_op].op; if (expression[next_op - 1].is_op) { - _set_error("Parser bug..."); + _set_parsing_error(); ERR_FAIL_V(nullptr); } @@ -6193,7 +6199,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons // can be followed by a unary op in a valid combination, // due to how precedence works, unaries will always disappear first - _set_error("Parser bug..."); + _set_parsing_error(); } op->arguments.push_back(expression[next_op - 1].node); //expression goes as left @@ -6206,7 +6212,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons String at; for (int i = 0; i < op->arguments.size(); i++) { if (i > 0) { - at += " and "; + at += ", "; } if (op->arguments[i]->get_datatype() == TYPE_STRUCT) { at += op->arguments[i]->get_datatype_name(); @@ -6219,7 +6225,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons at += "]"; } } - _set_error("Invalid arguments to operator '" + get_operator_text(op->op) + "' :" + at); + _set_error(vformat(RTR("Invalid arguments to operator '%s': '%s'."), get_operator_text(op->op), at)); return nullptr; } @@ -6359,7 +6365,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_SWITCH) { if (tk.type != TK_CF_CASE && tk.type != TK_CF_DEFAULT && tk.type != TK_CURLY_BRACKET_CLOSE) { - _set_error("Switch may contains only case and default blocks"); + _set_error(vformat(RTR("A switch may only contain '%s' and '%s' blocks."), "case", "default")); return ERR_PARSE_ERROR; } } @@ -6368,7 +6374,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (tk.type == TK_CURLY_BRACKET_CLOSE) { //end of block if (p_just_one) { - _set_error("Unexpected '}'"); + _set_expected_error("}"); return ERR_PARSE_ERROR; } @@ -6406,18 +6412,18 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun is_struct = shader->structs.has(tk.text); // check again. } if (is_struct && precision != PRECISION_DEFAULT) { - _set_error("Precision modifier cannot be used on structs."); + _set_error(RTR("The precision modifier cannot be used on structs.")); return ERR_PARSE_ERROR; } if (!is_token_nonvoid_datatype(tk.type)) { - _set_error("Expected datatype after precision"); + _set_error(RTR("Expected variable type after precision modifier.")); return ERR_PARSE_ERROR; } } if (!is_struct) { if (!is_token_variable_datatype(tk.type)) { - _set_error("Invalid data type for variable (samplers not allowed)"); + _set_error(RTR("Invalid variable type (samplers are not allowed).")); return ERR_PARSE_ERROR; } } @@ -6452,7 +6458,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun first = false; if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) { - _set_error("Expected identifier or '[' after datatype."); + _set_error(RTR("Expected an identifier or '[' after type.")); return ERR_PARSE_ERROR; } @@ -6469,7 +6475,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } if (tk.type != TK_IDENTIFIER) { - _set_error("Expected identifier!"); + _set_error(RTR("Expected an identifier.")); return ERR_PARSE_ERROR; } @@ -6477,7 +6483,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun ShaderLanguage::IdentifierType itype; if (_find_identifier(p_block, true, p_function_info, name, (ShaderLanguage::DataType *)nullptr, &itype)) { if (itype != IDENTIFIER_FUNCTION) { - _set_error("Redefinition of '" + String(name) + "'"); + _set_redefinition_error(String(name)); return ERR_PARSE_ERROR; } } @@ -6509,7 +6515,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (tk.type == TK_BRACKET_OPEN) { if (RenderingServer::get_singleton()->is_low_end() && is_const) { - _set_error("Local const arrays are supported only on high-end platform!"); + _set_error(RTR("Local const arrays are only supported on high-end platforms.")); return ERR_PARSE_ERROR; } @@ -6529,7 +6535,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (tk.type == TK_OP_ASSIGN) { if (RenderingServer::get_singleton()->is_low_end()) { - _set_error("Array initialization is supported only on high-end platform!"); + _set_error(RTR("Array initialization is only supported on high-end platforms.")); return ERR_PARSE_ERROR; } @@ -6541,7 +6547,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun Node *n = _parse_and_reduce_expression(p_block, p_function_info); if (!n) { - _set_error("Expected correct array initializer!"); + _set_error(RTR("Expected array initializer.")); return ERR_PARSE_ERROR; } else { if (unknown_size) { @@ -6561,7 +6567,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } else { if (tk.type != TK_CURLY_BRACKET_OPEN) { if (unknown_size) { - _set_error("Expected '{'"); + _set_expected_error("{"); return ERR_PARSE_ERROR; } @@ -6572,11 +6578,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun precision2 = get_token_precision(tk.type); tk = _get_token(); if (shader->structs.has(tk.text)) { - _set_error("Precision modifier cannot be used on structs."); + _set_error(RTR("The precision modifier cannot be used on structs.")); return ERR_PARSE_ERROR; } if (!is_token_nonvoid_datatype(tk.type)) { - _set_error("Expected datatype after precision"); + _set_error(RTR("Expected data type after precision modifier.")); return ERR_PARSE_ERROR; } } @@ -6589,7 +6595,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun struct_name2 = tk.text; } else { if (!is_token_variable_datatype(tk.type)) { - _set_error("Invalid data type for array"); + _set_error(RTR("Invalid data type for the array.")); return ERR_PARSE_ERROR; } type2 = get_token_datatype(tk.type); @@ -6609,38 +6615,40 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } tk = _get_token(); } else { - _set_error("Expected '['"); + _set_expected_error("["); return ERR_PARSE_ERROR; } if (precision != precision2 || type != type2 || struct_name != struct_name2 || var.array_size != array_size2) { - String error_str = "Cannot convert from '"; + String from; if (precision2 != PRECISION_DEFAULT) { - error_str += get_precision_name(precision2); - error_str += " "; + from += get_precision_name(precision2); + from += " "; } if (type2 == TYPE_STRUCT) { - error_str += struct_name2; + from += struct_name2; } else { - error_str += get_datatype_name(type2); + from += get_datatype_name(type2); } - error_str += "["; - error_str += itos(array_size2); - error_str += "]'"; - error_str += " to '"; + from += "["; + from += itos(array_size2); + from += "]'"; + + String to; if (precision != PRECISION_DEFAULT) { - error_str += get_precision_name(precision); - error_str += " "; + to += get_precision_name(precision); + to += " "; } if (type == TYPE_STRUCT) { - error_str += struct_name; + to += struct_name; } else { - error_str += get_datatype_name(type); + to += get_datatype_name(type); } - error_str += "["; - error_str += itos(var.array_size); - error_str += "]'"; - _set_error(error_str); + to += "["; + to += itos(var.array_size); + to += "]'"; + + _set_error(vformat(RTR("Cannot convert from '%s' to '%s'."), from, to)); return ERR_PARSE_ERROR; } } @@ -6649,13 +6657,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (unknown_size) { if (!curly) { - _set_error("Expected '{'"); + _set_expected_error("{"); return ERR_PARSE_ERROR; } } else { if (full_def) { if (curly) { - _set_error("Expected '('"); + _set_expected_error("("); return ERR_PARSE_ERROR; } } @@ -6669,7 +6677,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } if (is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) { - _set_error("Expected constant expression"); + _set_error(RTR("Expected a constant expression.")); return ERR_PARSE_ERROR; } @@ -6689,9 +6697,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun break; } else { if (curly) { - _set_error("Expected '}' or ','"); + _set_expected_error("}", ","); } else { - _set_error("Expected ')' or ','"); + _set_expected_error(")", ","); } return ERR_PARSE_ERROR; } @@ -6700,7 +6708,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun decl.size = decl.initializer.size(); var.array_size = decl.initializer.size(); } else if (decl.initializer.size() != var.array_size) { - _set_error("Array size mismatch"); + _set_error(RTR("Array size mismatch.")); return ERR_PARSE_ERROR; } tk = _get_token(); @@ -6708,11 +6716,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } } else { if (unknown_size) { - _set_error("Expected array initialization"); + _set_error(RTR("Expected array initialization.")); return ERR_PARSE_ERROR; } if (is_const) { - _set_error("Expected initialization of constant"); + _set_error(RTR("Expected initialization of constant.")); return ERR_PARSE_ERROR; } } @@ -6728,7 +6736,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun OperatorNode *op = ((OperatorNode *)n); for (int i = 1; i < op->arguments.size(); i++) { if (!_check_node_constness(op->arguments[i])) { - _set_error("Expected constant expression for argument '" + itos(i - 1) + "' of function call after '='"); + _set_error(vformat(RTR("Expected constant expression for argument %d of function call after '='."), i - 1)); return ERR_PARSE_ERROR; } } @@ -6749,7 +6757,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun tk = _get_token(); } else { if (is_const) { - _set_error("Expected initialization of constant"); + _set_error(RTR("Expected initialization of constant.")); return ERR_PARSE_ERROR; } } @@ -6763,13 +6771,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (tk.type == TK_COMMA) { if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR) { - _set_error("Multiple declarations in 'for' loop are not implemented yet."); + _set_error(vformat("Multiple declarations in '%s' loop are not supported.", "for")); return ERR_PARSE_ERROR; } } else if (tk.type == TK_SEMICOLON) { break; } else { - _set_error("Expected ',' or ';' after variable"); + _set_expected_error(",", ";"); return ERR_PARSE_ERROR; } } while (tk.type == TK_COMMA); //another variable @@ -6787,7 +6795,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun //if () {} tk = _get_token(); if (tk.type != TK_PARENTHESIS_OPEN) { - _set_error("Expected '(' after if"); + _set_expected_after_error("(", "if"); return ERR_PARSE_ERROR; } @@ -6799,13 +6807,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } if (n->get_datatype() != TYPE_BOOL) { - _set_error("Expected boolean expression"); + _set_error(RTR("Expected a boolean expression.")); return ERR_PARSE_ERROR; } tk = _get_token(); if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_error("Expected ')' after expression"); + _set_expected_error(")"); return ERR_PARSE_ERROR; } @@ -6835,14 +6843,14 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } } else if (tk.type == TK_CF_SWITCH) { if (RenderingServer::get_singleton()->is_low_end()) { - _set_error("\"switch\" operator is supported only on high-end platform!"); + _set_error(vformat(RTR("The '%s' operator is only supported on high-end platforms."), "switch")); return ERR_PARSE_ERROR; } // switch() {} tk = _get_token(); if (tk.type != TK_PARENTHESIS_OPEN) { - _set_error("Expected '(' after switch"); + _set_expected_after_error("(", "switch"); return ERR_PARSE_ERROR; } ControlFlowNode *cf = alloc_node<ControlFlowNode>(); @@ -6852,17 +6860,17 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return ERR_PARSE_ERROR; } if (n->get_datatype() != TYPE_INT) { - _set_error("Expected integer expression"); + _set_error(RTR("Expected an integer expression.")); return ERR_PARSE_ERROR; } tk = _get_token(); if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_error("Expected ')' after expression"); + _set_expected_error(")"); return ERR_PARSE_ERROR; } tk = _get_token(); if (tk.type != TK_CURLY_BRACKET_OPEN) { - _set_error("Expected '{' after switch statement"); + _set_expected_after_error("{", "switch"); return ERR_PARSE_ERROR; } BlockNode *switch_block = alloc_node<BlockNode>(); @@ -6883,10 +6891,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (tk.type == TK_CF_CASE || tk.type == TK_CF_DEFAULT) { if (prev_type == TK_CF_DEFAULT) { if (tk.type == TK_CF_CASE) { - _set_error("Cases must be defined before default case."); + _set_error(RTR("Cases must be defined before default case.")); return ERR_PARSE_ERROR; } else if (prev_type == TK_CF_DEFAULT) { - _set_error("Default case must be defined only once."); + _set_error(RTR("Default case must be defined only once.")); return ERR_PARSE_ERROR; } } @@ -6905,7 +6913,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return ERR_PARSE_ERROR; } if (constants.has(cn->values[0].sint)) { - _set_error("Duplicated case label: '" + itos(cn->values[0].sint) + "'"); + _set_error(vformat(RTR("Duplicated case label: %d."), cn->values[0].sint)); return ERR_PARSE_ERROR; } constants.insert(cn->values[0].sint); @@ -6917,7 +6925,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun ConstantNode::Value v; _find_identifier(p_block, false, p_function_info, vn->name, nullptr, nullptr, nullptr, nullptr, nullptr, &v); if (constants.has(v.sint)) { - _set_error("Duplicated case label: '" + itos(v.sint) + "'"); + _set_error(vformat(RTR("Duplicated case label: %d."), v.sint)); return ERR_PARSE_ERROR; } constants.insert(v.sint); @@ -6944,7 +6952,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } if (!p_block || (p_block->block_type != BlockNode::BLOCK_TYPE_SWITCH)) { - _set_error("case must be placed within switch block"); + _set_error(vformat(RTR("'%s' must be placed within a '%s' block."), "case", "switch")); return ERR_PARSE_ERROR; } @@ -6973,7 +6981,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } } if (!correct_constant_expression) { - _set_error("Expected integer constant"); + _set_error(RTR("Expected an integer constant.")); return ERR_PARSE_ERROR; } @@ -6997,7 +7005,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun tk = _get_token(); if (tk.type != TK_COLON) { - _set_error("Expected ':'"); + _set_expected_error(":"); return ERR_PARSE_ERROR; } @@ -7025,14 +7033,14 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } if (!p_block || (p_block->block_type != BlockNode::BLOCK_TYPE_SWITCH)) { - _set_error("default must be placed within switch block"); + _set_error(vformat(RTR("'%s' must be placed within a '%s' block."), "default", "switch")); return ERR_PARSE_ERROR; } tk = _get_token(); if (tk.type != TK_COLON) { - _set_error("Expected ':'"); + _set_expected_error(":"); return ERR_PARSE_ERROR; } @@ -7069,14 +7077,14 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun tk = _get_token(); if (tk.type != TK_CF_WHILE) { - _set_error("Expected while after do"); + _set_expected_after_error("while", "do"); return ERR_PARSE_ERROR; } } tk = _get_token(); if (tk.type != TK_PARENTHESIS_OPEN) { - _set_error("Expected '(' after while"); + _set_expected_after_error("(", "while"); return ERR_PARSE_ERROR; } @@ -7093,7 +7101,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun tk = _get_token(); if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_error("Expected ')' after expression"); + _set_expected_error(")"); return ERR_PARSE_ERROR; } if (!is_do) { @@ -7114,7 +7122,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun tk = _get_token(); if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';'"); + _set_expected_error(";"); return ERR_PARSE_ERROR; } } @@ -7122,7 +7130,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun // for() {} tk = _get_token(); if (tk.type != TK_PARENTHESIS_OPEN) { - _set_error("Expected '(' after for"); + _set_expected_after_error("(", "for"); return ERR_PARSE_ERROR; } @@ -7144,13 +7152,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } if (n->get_datatype() != TYPE_BOOL) { - _set_error("Middle expression is expected to be boolean."); + _set_error(RTR("The middle expression is expected to be boolean.")); return ERR_PARSE_ERROR; } tk = _get_token(); if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';' after middle expression"); + _set_expected_error(";"); return ERR_PARSE_ERROR; } @@ -7165,7 +7173,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun tk = _get_token(); if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_error("Expected ')' after third expression"); + _set_expected_error(")"); return ERR_PARSE_ERROR; } @@ -7188,12 +7196,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } if (!b) { - _set_error("Bug"); + _set_parsing_error(); return ERR_BUG; } if (b && b->parent_function && p_function_info.main_function) { - _set_error(vformat("Using 'return' in '%s' processor function results in undefined behavior!", b->parent_function->name)); + _set_error(vformat(RTR("Using '%s' in the '%s' processor function is incorrect."), "return", b->parent_function->name)); return ERR_PARSE_ERROR; } @@ -7212,7 +7220,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (tk.type == TK_SEMICOLON) { //all is good if (b->parent_function->return_type != TYPE_VOID) { - _set_error("Expected return with an expression of type '" + (!return_struct_name.is_empty() ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'"); + _set_error(vformat(RTR("Expected '%s' with an expression of type '%s'."), "return", (!return_struct_name.is_empty() ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string)); return ERR_PARSE_ERROR; } } else { @@ -7224,13 +7232,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } if (b->parent_function->return_type != expr->get_datatype() || b->parent_function->return_array_size != expr->get_array_size() || return_struct_name != expr->get_datatype_name()) { - _set_error("Expected return with an expression of type '" + (!return_struct_name.is_empty() ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'"); + _set_error(vformat(RTR("Expected return with an expression of type '%s'."), (!return_struct_name.is_empty() ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string)); return ERR_PARSE_ERROR; } tk = _get_token(); if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';' after return expression"); + _set_expected_after_error(";", "return"); return ERR_PARSE_ERROR; } @@ -7253,12 +7261,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun b = b->parent_block; } if (!b) { - _set_error("Bug"); + _set_parsing_error(); return ERR_BUG; } if (!b->parent_function->can_discard) { - _set_error("Use of 'discard' is not allowed here."); + _set_error(vformat(RTR("Use of '%s' is not allowed here."), "discard")); return ERR_PARSE_ERROR; } @@ -7268,14 +7276,14 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun pos = _get_tkpos(); tk = _get_token(); if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';' after discard"); + _set_expected_after_error(";", "discard"); return ERR_PARSE_ERROR; } p_block->statements.push_back(flow); } else if (tk.type == TK_CF_BREAK) { if (!p_can_break) { - _set_error("'break' is not allowed outside of a loop or 'switch' statement"); + _set_error(vformat(RTR("'%s' is not allowed outside of a loop or '%s' statement."), "break", "switch")); return ERR_PARSE_ERROR; } @@ -7285,7 +7293,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun pos = _get_tkpos(); tk = _get_token(); if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';' after break"); + _set_expected_after_error(";", "break"); return ERR_PARSE_ERROR; } @@ -7301,7 +7309,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } else if (tk.type == TK_CF_CONTINUE) { if (!p_can_continue) { - _set_error("'continue' is not allowed outside of a loop"); + _set_error(vformat(RTR("'%s' is not allowed outside of a loop."), "continue")); return ERR_PARSE_ERROR; } @@ -7312,7 +7320,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun tk = _get_token(); if (tk.type != TK_SEMICOLON) { //all is good - _set_error("Expected ';' after continue"); + _set_expected_after_error(";", "continue"); return ERR_PARSE_ERROR; } @@ -7329,7 +7337,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun tk = _get_token(); if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';' after statement"); + _set_expected_error(";"); return ERR_PARSE_ERROR; } } @@ -7390,7 +7398,7 @@ Error ShaderLanguage::_validate_datatype(DataType p_type) { } if (invalid_type) { - _set_error(vformat("\"%s\" type is supported only on high-end platform!", get_datatype_name(p_type))); + _set_error(vformat(RTR("The \"%s\" type is only supported on high-end platforms."), get_datatype_name(p_type))); return ERR_UNAVAILABLE; } } @@ -7402,7 +7410,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct TkPos prev_pos; if (tk.type != TK_SHADER_TYPE) { - _set_error("Expected 'shader_type' at the beginning of shader. Valid types are: " + _get_shader_type_list(p_shader_types)); + _set_error(vformat(RTR("Expected '%s' at the beginning of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types))); return ERR_PARSE_ERROR; } @@ -7410,11 +7418,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct _get_completable_identifier(nullptr, COMPLETION_SHADER_TYPE, shader_type_identifier); if (shader_type_identifier == StringName()) { - _set_error("Expected identifier after 'shader_type', indicating type of shader. Valid types are: " + _get_shader_type_list(p_shader_types)); + _set_error(vformat(RTR("Expected an identifier after '%s', indicating the type of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types))); return ERR_PARSE_ERROR; } if (!p_shader_types.has(shader_type_identifier)) { - _set_error("Invalid shader type. Valid types are: " + _get_shader_type_list(p_shader_types)); + _set_error(vformat(RTR("Invalid shader type. Valid types are: %s"), _get_shader_type_list(p_shader_types))); return ERR_PARSE_ERROR; } prev_pos = _get_tkpos(); @@ -7422,7 +7430,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (tk.type != TK_SEMICOLON) { _set_tkpos(prev_pos); - _set_error("Expected ';' after 'shader_type <type>'."); + _set_expected_after_error(";", "shader_type " + String(shader_type_identifier)); return ERR_PARSE_ERROR; } @@ -7462,14 +7470,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct _get_completable_identifier(nullptr, COMPLETION_RENDER_MODE, mode); if (mode == StringName()) { - _set_error("Expected identifier for render mode"); + _set_error(RTR("Expected an identifier for render mode.")); return ERR_PARSE_ERROR; } const String smode = String(mode); if (shader->render_modes.find(mode) != -1) { - _set_error(vformat("Duplicated render mode: '%s'.", smode)); + _set_error(vformat(RTR("Duplicated render mode: '%s'."), smode)); return ERR_PARSE_ERROR; } @@ -7485,7 +7493,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct found = true; if (defined_modes.has(name)) { - _set_error(vformat("Redefinition of render mode: '%s'. The %s mode has already been set to '%s'.", smode, name, defined_modes[name])); + _set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name])); return ERR_PARSE_ERROR; } defined_modes.insert(name, smode); @@ -7499,7 +7507,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (!found) { - _set_error(vformat("Invalid render mode: '%s'.", smode)); + _set_error(vformat(RTR("Invalid render mode: '%s'."), smode)); return ERR_PARSE_ERROR; } @@ -7511,7 +7519,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else if (tk.type == TK_SEMICOLON) { break; //done } else { - _set_error("Unexpected token: " + get_token_text(tk)); + _set_error(vformat(RTR("Unexpected token: '%s'."), get_token_text(tk))); return ERR_PARSE_ERROR; } } @@ -7524,16 +7532,16 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (tk.type == TK_IDENTIFIER) { st.name = tk.text; if (shader->constants.has(st.name) || shader->structs.has(st.name)) { - _set_error("Redefinition of '" + String(st.name) + "'"); + _set_redefinition_error(String(st.name)); return ERR_PARSE_ERROR; } tk = _get_token(); if (tk.type != TK_CURLY_BRACKET_OPEN) { - _set_error("Expected '{'"); + _set_expected_error("{"); return ERR_PARSE_ERROR; } } else { - _set_error("Expected struct identifier!"); + _set_error(RTR("Expected a struct identifier.")); return ERR_PARSE_ERROR; } @@ -7553,7 +7561,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct DataPrecision precision = DataPrecision::PRECISION_DEFAULT; if (tk.type == TK_STRUCT) { - _set_error("nested structs are not allowed!"); + _set_error(RTR("Nested structs are not allowed.")); return ERR_PARSE_ERROR; } @@ -7572,22 +7580,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct #endif // DEBUG_ENABLED struct_dt = true; if (use_precision) { - _set_error("Precision modifier cannot be used on structs."); + _set_error(RTR("The precision modifier cannot be used on structs.")); return ERR_PARSE_ERROR; } } if (!is_token_datatype(tk.type) && !struct_dt) { - _set_error("Expected datatype."); + _set_error(RTR("Expected data type.")); return ERR_PARSE_ERROR; } else { type = struct_dt ? TYPE_STRUCT : get_token_datatype(tk.type); - if (is_sampler_type(type)) { - _set_error("sampler datatype not allowed here"); - return ERR_PARSE_ERROR; - } else if (type == TYPE_VOID) { - _set_error("void datatype not allowed here"); + if (type == TYPE_VOID || is_sampler_type(type)) { + _set_error(vformat(RTR("A '%s' data type is not allowed here."), get_datatype_name(type))); return ERR_PARSE_ERROR; } @@ -7602,7 +7607,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct first = false; if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) { - _set_error("Expected identifier or '['."); + _set_error(RTR("Expected an identifier or '['.")); return ERR_PARSE_ERROR; } @@ -7617,7 +7622,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (tk.type != TK_IDENTIFIER) { - _set_error("Expected identifier!"); + _set_error(RTR("Expected an identifier.")); return ERR_PARSE_ERROR; } @@ -7629,7 +7634,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct member->array_size = array_size; if (member_names.has(member->name)) { - _set_error("Redefinition of '" + String(member->name) + "'"); + _set_redefinition_error(String(member->name)); return ERR_PARSE_ERROR; } member_names.insert(member->name); @@ -7648,7 +7653,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (tk.type != TK_SEMICOLON && tk.type != TK_COMMA) { - _set_error("Expected ',' or ';' after struct member."); + _set_expected_error(",", ";"); return ERR_PARSE_ERROR; } @@ -7658,13 +7663,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } } if (member_count == 0) { - _set_error("Empty structs are not allowed!"); + _set_error(RTR("Empty structs are not allowed.")); return ERR_PARSE_ERROR; } tk = _get_token(); if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';'"); + _set_expected_error(";"); return ERR_PARSE_ERROR; } shader->structs[st.name] = st; @@ -7678,7 +7683,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct case TK_GLOBAL: { tk = _get_token(); if (tk.type != TK_UNIFORM) { - _set_error("Expected 'uniform' after 'global'"); + _set_expected_after_error("uniform", "global"); return ERR_PARSE_ERROR; } uniform_scope = ShaderNode::Uniform::SCOPE_GLOBAL; @@ -7688,7 +7693,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) { tk = _get_token(); if (tk.type != TK_UNIFORM) { - _set_error("Expected 'uniform' after 'instance'"); + _set_expected_after_error("uniform", "instance"); return ERR_PARSE_ERROR; } uniform_scope = ShaderNode::Uniform::SCOPE_INSTANCE; @@ -7701,7 +7706,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (!uniform) { if (shader_type_identifier == "particles" || shader_type_identifier == "sky" || shader_type_identifier == "fog") { - _set_error(vformat("Varyings cannot be used in '%s' shaders!", shader_type_identifier)); + _set_error(vformat(RTR("Varyings cannot be used in '%s' shaders."), shader_type_identifier)); return ERR_PARSE_ERROR; } } @@ -7716,7 +7721,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (is_token_interpolation(tk.type)) { if (uniform) { - _set_error("Interpolation qualifiers are not supported for uniforms!"); + _set_error(RTR("Interpolation qualifiers are not supported for uniforms.")); return ERR_PARSE_ERROR; } interpolation = get_token_interpolation(tk.type); @@ -7732,38 +7737,38 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (shader->structs.has(tk.text)) { if (uniform) { if (precision_defined) { - _set_error("Precision modifier cannot be used on structs."); + _set_error(RTR("The precision modifier cannot be used on structs.")); return ERR_PARSE_ERROR; } - _set_error("struct datatype is not yet supported for uniforms!"); + _set_error(vformat(RTR("The '%s' data type is not supported for uniforms."), "struct")); return ERR_PARSE_ERROR; } else { - _set_error("struct datatype not allowed here"); + _set_error(vformat(RTR("The '%s' data type not allowed here."), "struct")); return ERR_PARSE_ERROR; } } if (!is_token_datatype(tk.type)) { - _set_error("Expected datatype. "); + _set_error(RTR("Expected data type.")); return ERR_PARSE_ERROR; } type = get_token_datatype(tk.type); if (type == TYPE_VOID) { - _set_error("void datatype not allowed here"); + _set_error(vformat(RTR("The '%s' data type is not allowed here."), "void")); return ERR_PARSE_ERROR; } if (!uniform && (type < TYPE_FLOAT || type > TYPE_MAT4)) { - _set_error("Invalid type for varying, only float,vec2,vec3,vec4,mat2,mat3,mat4 or array of these types allowed."); + _set_error(RTR("Invalid type for varying, only 'float', 'vec2', 'vec3', 'vec4', 'mat2', 'mat3', 'mat4', or arrays of these types are allowed.")); return ERR_PARSE_ERROR; } tk = _get_token(); if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) { - _set_error("Expected identifier or '['."); + _set_error(RTR("Expected an identifier or '['.")); return ERR_PARSE_ERROR; } @@ -7776,7 +7781,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (tk.type != TK_IDENTIFIER) { - _set_error("Expected identifier!"); + _set_error(RTR("Expected an identifier.")); return ERR_PARSE_ERROR; } @@ -7784,12 +7789,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct name = tk.text; if (_find_identifier(nullptr, false, constants, name)) { - _set_error("Redefinition of '" + String(name) + "'"); + _set_redefinition_error(String(name)); return ERR_PARSE_ERROR; } if (has_builtin(p_functions, name)) { - _set_error("Redefinition of '" + String(name) + "'"); + _set_redefinition_error(String(name)); return ERR_PARSE_ERROR; } @@ -7798,12 +7803,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct //validate global uniform DataType gvtype = global_var_get_type_func(name); if (gvtype == TYPE_MAX) { - _set_error("Global uniform '" + String(name) + "' does not exist. Create it in Project Settings."); + _set_error(vformat(RTR("Global uniform '%s' does not exist. Create it in Project Settings."), String(name))); return ERR_PARSE_ERROR; } if (type != gvtype) { - _set_error("Global uniform '" + String(name) + "' must be of type '" + get_datatype_name(gvtype) + "'."); + _set_error(vformat(RTR("Global uniform '%s' must be of type '%s'."), String(name), get_datatype_name(gvtype))); return ERR_PARSE_ERROR; } } @@ -7825,7 +7830,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (is_sampler_type(type)) { if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE) { - _set_error("Uniforms with 'instance' qualifiers can't be of sampler type."); + _set_error(vformat(RTR("Uniforms with '%s' qualifiers can't be of sampler type.", "instance"))); return ERR_PARSE_ERROR; } uniform2.texture_order = texture_uniforms++; @@ -7841,7 +7846,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } } else { if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE && (type == TYPE_MAT2 || type == TYPE_MAT3 || type == TYPE_MAT4)) { - _set_error("Uniforms with 'instance' qualifiers can't be of matrix type."); + _set_error(vformat(RTR("Uniforms with '%s' qualifier can't be of matrix type.", "instance"))); return ERR_PARSE_ERROR; } uniform2.texture_order = -1; @@ -7870,11 +7875,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (uniform2.array_size > 0) { if (uniform_scope == ShaderNode::Uniform::SCOPE_GLOBAL) { - _set_error("'SCOPE_GLOBAL' qualifier is not yet supported for uniform array!"); + _set_error(vformat(RTR("The '%s' qualifier is not supported for uniform arrays."), "SCOPE_GLOBAL")); return ERR_PARSE_ERROR; } if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE) { - _set_error("'SCOPE_INSTANCE' qualifier is not yet supported for uniform array!"); + _set_error(vformat(RTR("The '%s' qualifier is not supported for uniform arrays."), "SCOPE_INSTANCE")); return ERR_PARSE_ERROR; } } @@ -7892,13 +7897,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct completion_line = tk.line; if (!is_token_hint(tk.type)) { - _set_error("Expected valid type hint after ':'."); + _set_error(RTR("Expected valid type hint after ':'.")); return ERR_PARSE_ERROR; } if (uniform2.array_size > 0) { if (tk.type != TK_HINT_COLOR) { - _set_error("This hint is not yet supported for uniform arrays!"); + _set_error(RTR("This hint is not supported for uniform arrays.")); return ERR_PARSE_ERROR; } } @@ -7929,20 +7934,20 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct uniform2.hint = ShaderNode::Uniform::HINT_BLACK_ALBEDO; } else if (tk.type == TK_HINT_COLOR) { if (type != TYPE_VEC4) { - _set_error("Color hint is for vec4 only"); + _set_error(vformat(RTR("Color hint is for '%s' only."), "vec4")); return ERR_PARSE_ERROR; } uniform2.hint = ShaderNode::Uniform::HINT_COLOR; } else if (tk.type == TK_HINT_RANGE) { uniform2.hint = ShaderNode::Uniform::HINT_RANGE; if (type != TYPE_FLOAT && type != TYPE_INT) { - _set_error("Range hint is for float and int only"); + _set_error(vformat(RTR("Range hint is for '%s' and '%s' only."), "float", "int")); return ERR_PARSE_ERROR; } tk = _get_token(); if (tk.type != TK_PARENTHESIS_OPEN) { - _set_error("Expected '(' after hint_range"); + _set_expected_after_error("(", "hint_range"); return ERR_PARSE_ERROR; } @@ -7956,7 +7961,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (tk.type != TK_FLOAT_CONSTANT && !tk.is_integer_constant()) { - _set_error("Expected integer constant"); + _set_error(RTR("Expected an integer constant.")); return ERR_PARSE_ERROR; } @@ -7966,7 +7971,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type != TK_COMMA) { - _set_error("Expected ',' after integer constant"); + _set_error(RTR("Expected ',' after integer constant.")); return ERR_PARSE_ERROR; } @@ -7980,7 +7985,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (tk.type != TK_FLOAT_CONSTANT && !tk.is_integer_constant()) { - _set_error("Expected integer constant after ','"); + _set_error(RTR("Expected an integer constant after ','.")); return ERR_PARSE_ERROR; } @@ -7993,7 +7998,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type != TK_FLOAT_CONSTANT && !tk.is_integer_constant()) { - _set_error("Expected integer constant after ','"); + _set_error(RTR("Expected an integer constant after ','.")); return ERR_PARSE_ERROR; } @@ -8008,44 +8013,44 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_error("Expected ')'"); + _set_expected_error(")"); return ERR_PARSE_ERROR; } } else if (tk.type == TK_HINT_INSTANCE_INDEX) { if (custom_instance_index != -1) { - _set_error("Can only specify 'instance_index' once."); + _set_error(vformat(RTR("Can only specify '%s' once."), "instance_index")); return ERR_PARSE_ERROR; } tk = _get_token(); if (tk.type != TK_PARENTHESIS_OPEN) { - _set_error("Expected '(' after 'instance_index'"); + _set_expected_after_error("(", "instance_index"); return ERR_PARSE_ERROR; } tk = _get_token(); if (tk.type == TK_OP_SUB) { - _set_error("The instance index can't be negative."); + _set_error(RTR("The instance index can't be negative.")); return ERR_PARSE_ERROR; } if (!tk.is_integer_constant()) { - _set_error("Expected integer constant"); + _set_error(RTR("Expected an integer constant.")); return ERR_PARSE_ERROR; } custom_instance_index = tk.constant; if (custom_instance_index >= MAX_INSTANCE_UNIFORM_INDICES) { - _set_error("Allowed instance uniform indices are 0-" + itos(MAX_INSTANCE_UNIFORM_INDICES - 1)); + _set_error(vformat(RTR("Allowed instance uniform indices must be within [0..%d] range."), MAX_INSTANCE_UNIFORM_INDICES - 1)); return ERR_PARSE_ERROR; } tk = _get_token(); if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_error("Expected ')'"); + _set_expected_error(")"); return ERR_PARSE_ERROR; } } else if (tk.type == TK_FILTER_LINEAR) { @@ -8067,7 +8072,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (uniform2.hint != ShaderNode::Uniform::HINT_RANGE && uniform2.hint != ShaderNode::Uniform::HINT_NONE && uniform2.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) { - _set_error("This hint is only for sampler types"); + _set_error(RTR("This hint is only for sampler types.")); return ERR_PARSE_ERROR; } @@ -8082,7 +8087,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else { uniform2.instance_index = instance_index++; if (instance_index > MAX_INSTANCE_UNIFORM_INDICES) { - _set_error("Too many 'instance' uniforms in shader, maximum supported is " + itos(MAX_INSTANCE_UNIFORM_INDICES)); + _set_error(vformat(RTR("Too many '%s' uniforms in shader, maximum supported is %d."), "instance", MAX_INSTANCE_UNIFORM_INDICES)); return ERR_PARSE_ERROR; } } @@ -8092,7 +8097,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (tk.type == TK_OP_ASSIGN) { if (uniform2.array_size > 0) { - _set_error("Setting default value to a uniform array is not yet supported!"); + _set_error(RTR("Setting default values to uniform arrays is not supported.")); return ERR_PARSE_ERROR; } @@ -8101,7 +8106,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } if (expr->type != Node::TYPE_CONSTANT) { - _set_error("Expected constant expression after '='"); + _set_error(RTR("Expected constant expression after '='.")); return ERR_PARSE_ERROR; } @@ -8110,7 +8115,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct uniform2.default_value.resize(cn->values.size()); if (!convert_constant(cn, uniform2.type, uniform2.default_value.ptrw())) { - _set_error("Can't convert constant to " + get_datatype_name(uniform2.type)); + _set_error(vformat(RTR("Can't convert constant to '%s'."), get_datatype_name(uniform2.type))); return ERR_PARSE_ERROR; } tk = _get_token(); @@ -8127,7 +8132,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL; if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';'"); + _set_expected_error(";"); return ERR_PARSE_ERROR; } @@ -8143,9 +8148,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type != TK_SEMICOLON && tk.type != TK_BRACKET_OPEN) { if (array_size == 0) { - _set_error("Expected ';' or '['"); + _set_expected_error(";", "["); } else { - _set_error("Expected ';'"); + _set_expected_error(";"); } return ERR_PARSE_ERROR; } @@ -8168,7 +8173,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } break; case TK_SHADER_TYPE: { - _set_error("Shader type is already defined."); + _set_error(RTR("Shader type is already defined.")); return ERR_PARSE_ERROR; } break; default: { @@ -8194,19 +8199,23 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (shader->structs.has(tk.text)) { if (precision != PRECISION_DEFAULT) { - _set_error("Precision modifier cannot be used on structs."); + _set_error(RTR("The precision modifier cannot be used on structs.")); return ERR_PARSE_ERROR; } is_struct = true; struct_name = tk.text; } else { if (!is_token_datatype(tk.type)) { - _set_error("Expected constant, function, uniform or varying"); + _set_error(RTR("Expected constant, function, uniform or varying.")); return ERR_PARSE_ERROR; } if (!is_token_variable_datatype(tk.type)) { - _set_error("Invalid data type for constants or function return (samplers not allowed)"); + if (is_constant) { + _set_error(RTR("Invalid constant type (samplers are not allowed).")); + } else { + _set_error(RTR("Invalid function type (samplers are not allowed).")); + } return ERR_PARSE_ERROR; } } @@ -8224,7 +8233,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (tk.type == TK_BRACKET_OPEN) { if (is_constant && RenderingServer::get_singleton()->is_low_end()) { - _set_error("Global const arrays are only supported on high-end platform!"); + _set_error(RTR("Global constant arrays are only supported on high-end platforms.")); return ERR_PARSE_ERROR; } Error error = _parse_array_size(nullptr, constants, !is_constant, nullptr, &array_size, &unknown_size); @@ -8241,22 +8250,22 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (name == StringName()) { if (is_constant) { - _set_error("Expected identifier or '[' after datatype."); + _set_error(RTR("Expected an identifier or '[' after type.")); } else { - _set_error("Expected function name after datatype."); + _set_error(RTR("Expected a function name after type.")); } return ERR_PARSE_ERROR; } if (shader->structs.has(name) || _find_identifier(nullptr, false, constants, name) || has_builtin(p_functions, name)) { - _set_error("Redefinition of '" + String(name) + "'"); + _set_redefinition_error(String(name)); return ERR_PARSE_ERROR; } tk = _get_token(); if (tk.type != TK_PARENTHESIS_OPEN) { if (type == TYPE_VOID) { - _set_error("Expected '(' after function identifier"); + _set_error(RTR("Expected '(' after function identifier.")); return ERR_PARSE_ERROR; } @@ -8272,7 +8281,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (tk.type == TK_BRACKET_OPEN) { if (RenderingServer::get_singleton()->is_low_end()) { - _set_error("Global const arrays are only supported on high-end platform!"); + _set_error(RTR("Global const arrays are only supported on high-end platforms.")); return ERR_PARSE_ERROR; } Error error = _parse_array_size(nullptr, constants, false, nullptr, &constant.array_size, &unknown_size); @@ -8284,7 +8293,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (tk.type == TK_OP_ASSIGN) { if (!is_constant) { - _set_error("Expected 'const' keyword before constant definition"); + _set_error(vformat(RTR("Global non-constant variables are not supported. Expected '%s' keyword before constant definition."), "const")); return ERR_PARSE_ERROR; } @@ -8299,7 +8308,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (tk.type != TK_CURLY_BRACKET_OPEN) { if (unknown_size) { - _set_error("Expected '{'"); + _set_expected_error("{"); return ERR_PARSE_ERROR; } @@ -8310,7 +8319,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct precision2 = get_token_precision(tk.type); tk = _get_token(); if (!is_token_nonvoid_datatype(tk.type)) { - _set_error("Expected datatype after precision"); + _set_error(RTR("Expected data type after precision modifier.")); return ERR_PARSE_ERROR; } } @@ -8323,7 +8332,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct struct_name2 = tk.text; } else { if (!is_token_variable_datatype(tk.type)) { - _set_error("Invalid data type for array"); + _set_error(RTR("Invalid data type for the array.")); return ERR_PARSE_ERROR; } type2 = get_token_datatype(tk.type); @@ -8343,38 +8352,40 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } tk = _get_token(); } else { - _set_error("Expected '["); + _set_expected_error("["); return ERR_PARSE_ERROR; } if (constant.precision != precision2 || constant.type != type2 || struct_name != struct_name2 || constant.array_size != array_size2) { - String error_str = "Cannot convert from '"; + String from; if (type2 == TYPE_STRUCT) { - error_str += struct_name2; + from += struct_name2; } else { if (precision2 != PRECISION_DEFAULT) { - error_str += get_precision_name(precision2); - error_str += " "; + from += get_precision_name(precision2); + from += " "; } - error_str += get_datatype_name(type2); + from += get_datatype_name(type2); } - error_str += "["; - error_str += itos(array_size2); - error_str += "]'"; - error_str += " to '"; + from += "["; + from += itos(array_size2); + from += "]'"; + + String to; if (type == TYPE_STRUCT) { - error_str += struct_name; + to += struct_name; } else { if (precision != PRECISION_DEFAULT) { - error_str += get_precision_name(precision); - error_str += " "; + to += get_precision_name(precision); + to += " "; } - error_str += get_datatype_name(type); + to += get_datatype_name(type); } - error_str += "["; - error_str += itos(constant.array_size); - error_str += "]'"; - _set_error(error_str); + to += "["; + to += itos(constant.array_size); + to += "]'"; + + _set_error(vformat(RTR("Cannot convert from '%s' to '%s'."), from, to)); return ERR_PARSE_ERROR; } } @@ -8383,13 +8394,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (unknown_size) { if (!curly) { - _set_error("Expected '{'"); + _set_expected_error("{"); return ERR_PARSE_ERROR; } } else { if (full_def) { if (curly) { - _set_error("Expected '('"); + _set_expected_error("("); return ERR_PARSE_ERROR; } } @@ -8403,7 +8414,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) { - _set_error("Expected constant expression"); + _set_error(RTR("Expected constant expression.")); return ERR_PARSE_ERROR; } @@ -8423,9 +8434,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct break; } else { if (curly) { - _set_error("Expected '}' or ','"); + _set_expected_error("}", ","); } else { - _set_error("Expected ')' or ','"); + _set_expected_error(")", ","); } return ERR_PARSE_ERROR; } @@ -8434,7 +8445,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct decl.size = decl.initializer.size(); constant.array_size = decl.initializer.size(); } else if (decl.initializer.size() != constant.array_size) { - _set_error("Array size mismatch"); + _set_error(RTR("Array size mismatch.")); return ERR_PARSE_ERROR; } } @@ -8462,7 +8473,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct OperatorNode *op = ((OperatorNode *)expr); for (int i = 1; i < op->arguments.size(); i++) { if (!_check_node_constness(op->arguments[i])) { - _set_error("Expected constant expression for argument '" + itos(i - 1) + "' of function call after '='"); + _set_error(vformat(RTR("Expected constant expression for argument %d of function call after '='."), i - 1)); return ERR_PARSE_ERROR; } } @@ -8477,10 +8488,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); } else { if (constant.array_size > 0 || unknown_size) { - _set_error("Expected array initialization"); + _set_error(RTR("Expected array initialization.")); return ERR_PARSE_ERROR; } else { - _set_error("Expected initialization of constant"); + _set_error(RTR("Expected initialization of constant.")); return ERR_PARSE_ERROR; } } @@ -8496,18 +8507,18 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (tk.type == TK_COMMA) { tk = _get_token(); if (tk.type != TK_IDENTIFIER) { - _set_error("Expected identifier after type"); + _set_error(RTR("Expected an identifier after type.")); return ERR_PARSE_ERROR; } name = tk.text; if (_find_identifier(nullptr, false, constants, name)) { - _set_error("Redefinition of '" + String(name) + "'"); + _set_redefinition_error(String(name)); return ERR_PARSE_ERROR; } if (has_builtin(p_functions, name)) { - _set_error("Redefinition of '" + String(name) + "'"); + _set_redefinition_error(String(name)); return ERR_PARSE_ERROR; } @@ -8521,7 +8532,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else if (tk.type == TK_SEMICOLON) { break; } else { - _set_error("Expected ',' or ';' after constant"); + _set_expected_error(",", ";"); return ERR_PARSE_ERROR; } } @@ -8548,7 +8559,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct for (int i = 0; i < shader->functions.size(); i++) { if (!shader->functions[i].callable && shader->functions[i].name == name) { - _set_error("Redefinition of '" + String(name) + "'"); + _set_redefinition_error(String(name)); return ERR_PARSE_ERROR; } } @@ -8603,14 +8614,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); } else if (tk.type == TK_ARG_OUT) { if (is_const) { - _set_error("'out' qualifier cannot be used within a function parameter declared with 'const'."); + _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "out", "const")); return ERR_PARSE_ERROR; } qualifier = ARGUMENT_QUALIFIER_OUT; tk = _get_token(); } else if (tk.type == TK_ARG_INOUT) { if (is_const) { - _set_error("'inout' qualifier cannot be used within a function parameter declared with 'const'."); + _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "inout", "const")); return ERR_PARSE_ERROR; } qualifier = ARGUMENT_QUALIFIER_INOUT; @@ -8641,19 +8652,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } #endif // DEBUG_ENABLED if (use_precision) { - _set_error("Precision modifier cannot be used on structs."); + _set_error(RTR("The precision modifier cannot be used on structs.")); return ERR_PARSE_ERROR; } } if (!is_struct && !is_token_datatype(tk.type)) { - _set_error("Expected a valid datatype for argument"); + _set_error(RTR("Expected a valid data type for argument.")); return ERR_PARSE_ERROR; } if (qualifier == ARGUMENT_QUALIFIER_OUT || qualifier == ARGUMENT_QUALIFIER_INOUT) { if (is_sampler_type(get_token_datatype(tk.type))) { - _set_error("Opaque types cannot be output parameters."); + _set_error(RTR("Opaque types cannot be output parameters.")); return ERR_PARSE_ERROR; } } @@ -8666,7 +8677,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } if (ptype == TYPE_VOID) { - _set_error("void not allowed in argument"); + _set_error(RTR("Void type not allowed as argument.")); return ERR_PARSE_ERROR; } } @@ -8681,7 +8692,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); } if (tk.type != TK_IDENTIFIER) { - _set_error("Expected identifier for argument name"); + _set_error(RTR("Expected an identifier for argument name.")); return ERR_PARSE_ERROR; } @@ -8690,13 +8701,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct ShaderLanguage::IdentifierType itype; if (_find_identifier(func_node->body, false, builtins, pname, (ShaderLanguage::DataType *)nullptr, &itype)) { if (itype != IDENTIFIER_FUNCTION) { - _set_error("Redefinition of '" + String(pname) + "'"); + _set_redefinition_error(String(pname)); return ERR_PARSE_ERROR; } } if (has_builtin(p_functions, pname)) { - _set_error("Redefinition of '" + String(pname) + "'"); + _set_redefinition_error(String(pname)); return ERR_PARSE_ERROR; } @@ -8728,7 +8739,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); //do none and go on } else if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_error("Expected ',' or ')' after identifier"); + _set_expected_error(",", ")"); return ERR_PARSE_ERROR; } } @@ -8736,11 +8747,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (p_functions.has(name)) { //if one of the core functions, make sure they are of the correct form if (func_node->arguments.size() > 0) { - _set_error("Function '" + String(name) + "' expects no arguments."); + _set_error(vformat(RTR("Function '%s' expects no arguments."), String(name))); return ERR_PARSE_ERROR; } if (func_node->return_type != TYPE_VOID) { - _set_error("Function '" + String(name) + "' must be of void return type."); + _set_error(vformat(RTR("Function '%s' must be of '%s' return type."), String(name), "void")); return ERR_PARSE_ERROR; } } @@ -8748,7 +8759,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct //all good let's parse inside the function! tk = _get_token(); if (tk.type != TK_CURLY_BRACKET_OPEN) { - _set_error("Expected '{' to begin function"); + _set_error(RTR("Expected a '{' to begin function.")); return ERR_PARSE_ERROR; } @@ -8762,7 +8773,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (func_node->return_type != DataType::TYPE_VOID) { BlockNode *block = func_node->body; if (_find_last_flow_op_in_block(block, FlowOperation::FLOW_OP_RETURN) != OK) { - _set_error("Expected at least one return statement in a non-void function."); + _set_error(vformat(RTR("Expected at least one '%s' statement in a non-void function."), "return")); return ERR_PARSE_ERROR; } } @@ -8775,7 +8786,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct #ifdef DEBUG_ENABLED if (check_device_limit_warnings && uniform_buffer_exceeded_line != -1) { - _add_warning(ShaderWarning::DEVICE_LIMIT_EXCEEDED, uniform_buffer_exceeded_line, "uniform buffer", { uniform_buffer_size, max_uniform_buffer_size }); + _add_warning(ShaderWarning::DEVICE_LIMIT_EXCEEDED, uniform_buffer_exceeded_line, RTR("uniform buffer"), { uniform_buffer_size, max_uniform_buffer_size }); } #endif // DEBUG_ENABLED return OK; @@ -9049,6 +9060,19 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ } break; case COMPLETION_MAIN_FUNCTION: { for (const KeyValue<StringName, FunctionInfo> &E : p_info.functions) { + if (!E.value.main_function) { + continue; + } + bool found = false; + for (int i = 0; i < shader->functions.size(); i++) { + if (shader->functions[i].name == E.key) { + found = true; + break; + } + } + if (found) { + continue; + } ScriptCodeCompletionOption option(E.key, ScriptCodeCompletionOption::KIND_FUNCTION); r_options->push_back(option); } diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index c619934182..1307eeac2b 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -945,6 +945,26 @@ private: error_str = p_str; } + void _set_expected_error(const String &p_what) { + _set_error(vformat(RTR("Expected a '%s'."), p_what)); + } + + void _set_expected_error(const String &p_first, const String p_second) { + _set_error(vformat(RTR("Expected a '%s' or '%s'."), p_first, p_second)); + } + + void _set_expected_after_error(const String &p_what, const String &p_after) { + _set_error(vformat(RTR("Expected a '%s' after '%s'."), p_what, p_after)); + } + + void _set_redefinition_error(const String &p_what) { + _set_error(vformat(RTR("Redefinition of '%s'."), p_what)); + } + + void _set_parsing_error() { + _set_error("Parser bug."); + } + static const char *token_names[TK_MAX]; Token _make_token(TokenType p_type, const StringName &p_text = StringName()); diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index 9ae60c14cb..b8bb211a7a 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -435,7 +435,6 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["OBJECT_POSITION"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["UVW"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["EXTENTS"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["SDF"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["DENSITY"] = ShaderLanguage::TYPE_FLOAT; diff --git a/servers/rendering/shader_warnings.cpp b/servers/rendering/shader_warnings.cpp index f2e74c4d78..639b9bd165 100644 --- a/servers/rendering/shader_warnings.cpp +++ b/servers/rendering/shader_warnings.cpp @@ -48,23 +48,23 @@ const StringName &ShaderWarning::get_subject() const { String ShaderWarning::get_message() const { switch (code) { case FLOAT_COMPARISON: - return vformat("Direct floating-point comparison (this may not evaluate to `true` as you expect). Instead, use `abs(a - b) < 0.0001` for an approximate but predictable comparison."); + return vformat(RTR("Direct floating-point comparison (this may not evaluate to `true` as you expect). Instead, use `abs(a - b) < 0.0001` for an approximate but predictable comparison.")); case UNUSED_CONSTANT: - return vformat("The const '%s' is declared but never used.", subject); + return vformat(RTR("The const '%s' is declared but never used."), subject); case UNUSED_FUNCTION: - return vformat("The function '%s' is declared but never used.", subject); + return vformat(RTR("The function '%s' is declared but never used."), subject); case UNUSED_STRUCT: - return vformat("The struct '%s' is declared but never used.", subject); + return vformat(RTR("The struct '%s' is declared but never used."), subject); case UNUSED_UNIFORM: - return vformat("The uniform '%s' is declared but never used.", subject); + return vformat(RTR("The uniform '%s' is declared but never used."), subject); case UNUSED_VARYING: - return vformat("The varying '%s' is declared but never used.", subject); + return vformat(RTR("The varying '%s' is declared but never used."), subject); case UNUSED_LOCAL_VARIABLE: - return vformat("The local variable '%s' is declared but never used.", subject); + return vformat(RTR("The local variable '%s' is declared but never used."), subject); case FORMATTING_ERROR: return subject; case DEVICE_LIMIT_EXCEEDED: - return vformat("The total size of the %s for this shader on this device has been exceeded (%s/%s). The shader may not work correctly.", subject, (int)extra_args[0], (int)extra_args[1]); + return vformat(RTR("The total size of the %s for this shader on this device has been exceeded (%d/%d). The shader may not work correctly."), subject, (int)extra_args[0], (int)extra_args[1]); default: break; } diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 020c850f46..84e54eab22 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -1927,8 +1927,8 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(LIGHT_PARAM_MAX); BIND_ENUM_CONSTANT(LIGHT_BAKE_DISABLED); - BIND_ENUM_CONSTANT(LIGHT_BAKE_DYNAMIC); BIND_ENUM_CONSTANT(LIGHT_BAKE_STATIC); + BIND_ENUM_CONSTANT(LIGHT_BAKE_DYNAMIC); BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_DUAL_PARABOLOID); BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_CUBE); @@ -2388,10 +2388,6 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(ENV_SSIL_QUALITY_HIGH); BIND_ENUM_CONSTANT(ENV_SSIL_QUALITY_ULTRA); - BIND_ENUM_CONSTANT(ENV_SDFGI_CASCADES_4); - BIND_ENUM_CONSTANT(ENV_SDFGI_CASCADES_6); - BIND_ENUM_CONSTANT(ENV_SDFGI_CASCADES_8); - BIND_ENUM_CONSTANT(ENV_SDFGI_Y_SCALE_DISABLED); BIND_ENUM_CONSTANT(ENV_SDFGI_Y_SCALE_75_PERCENT); BIND_ENUM_CONSTANT(ENV_SDFGI_Y_SCALE_50_PERCENT); @@ -2775,13 +2771,14 @@ void RenderingServer::mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry const Geometry3D::MeshData::Face &f = p_mesh_data.faces[i]; for (int j = 2; j < f.indices.size(); j++) { -#define _ADD_VERTEX(m_idx) \ - vertices.push_back(p_mesh_data.vertices[f.indices[m_idx]]); \ - normals.push_back(f.plane.normal); + vertices.push_back(p_mesh_data.vertices[f.indices[0]]); + normals.push_back(f.plane.normal); + + vertices.push_back(p_mesh_data.vertices[f.indices[j - 1]]); + normals.push_back(f.plane.normal); - _ADD_VERTEX(0); - _ADD_VERTEX(j - 1); - _ADD_VERTEX(j); + vertices.push_back(p_mesh_data.vertices[f.indices[j]]); + normals.push_back(f.plane.normal); } } diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 5dbec04665..b067db3d27 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -447,8 +447,8 @@ public: enum LightBakeMode { LIGHT_BAKE_DISABLED, - LIGHT_BAKE_DYNAMIC, LIGHT_BAKE_STATIC, + LIGHT_BAKE_DYNAMIC, }; virtual void light_set_bake_mode(RID p_light, LightBakeMode p_bake_mode) = 0; @@ -1041,19 +1041,13 @@ public: virtual void environment_set_ssil_quality(EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0; - enum EnvironmentSDFGICascades { - ENV_SDFGI_CASCADES_4, - ENV_SDFGI_CASCADES_6, - ENV_SDFGI_CASCADES_8, - }; - enum EnvironmentSDFGIYScale { ENV_SDFGI_Y_SCALE_DISABLED, ENV_SDFGI_Y_SCALE_75_PERCENT, ENV_SDFGI_Y_SCALE_50_PERCENT }; - virtual void environment_set_sdfgi(RID p_env, bool p_enable, EnvironmentSDFGICascades p_cascades, float p_min_cell_size, EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0; + virtual void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0; enum EnvironmentSDFGIRayCount { ENV_SDFGI_RAY_COUNT_4, @@ -1608,7 +1602,6 @@ VARIANT_ENUM_CAST(RenderingServer::EnvironmentToneMapper); VARIANT_ENUM_CAST(RenderingServer::EnvironmentSSRRoughnessQuality); VARIANT_ENUM_CAST(RenderingServer::EnvironmentSSAOQuality); VARIANT_ENUM_CAST(RenderingServer::EnvironmentSSILQuality); -VARIANT_ENUM_CAST(RenderingServer::EnvironmentSDFGICascades); VARIANT_ENUM_CAST(RenderingServer::EnvironmentSDFGIFramesToConverge); VARIANT_ENUM_CAST(RenderingServer::EnvironmentSDFGIRayCount); VARIANT_ENUM_CAST(RenderingServer::EnvironmentSDFGIFramesToUpdateLight); diff --git a/servers/xr/xr_pose.cpp b/servers/xr/xr_pose.cpp index 0862fefef5..400f13b9c2 100644 --- a/servers/xr/xr_pose.cpp +++ b/servers/xr/xr_pose.cpp @@ -33,6 +33,10 @@ #include "servers/xr_server.h" void XRPose::_bind_methods() { + BIND_ENUM_CONSTANT(XR_TRACKING_CONFIDENCE_NONE); + BIND_ENUM_CONSTANT(XR_TRACKING_CONFIDENCE_LOW); + BIND_ENUM_CONSTANT(XR_TRACKING_CONFIDENCE_HIGH); + ClassDB::bind_method(D_METHOD("set_has_tracking_data", "has_tracking_data"), &XRPose::set_has_tracking_data); ClassDB::bind_method(D_METHOD("get_has_tracking_data"), &XRPose::get_has_tracking_data); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "has_tracking_data"), "set_has_tracking_data", "get_has_tracking_data"); @@ -53,6 +57,10 @@ void XRPose::_bind_methods() { ClassDB::bind_method(D_METHOD("set_angular_velocity", "velocity"), &XRPose::set_angular_velocity); ClassDB::bind_method(D_METHOD("get_angular_velocity"), &XRPose::get_angular_velocity); ADD_PROPERTY(PropertyInfo(Variant::STRING, "angular_velocity"), "set_angular_velocity", "get_angular_velocity"); + + ClassDB::bind_method(D_METHOD("set_tracking_confidence", "tracking_confidence"), &XRPose::set_tracking_confidence); + ClassDB::bind_method(D_METHOD("get_tracking_confidence"), &XRPose::get_tracking_confidence); + ADD_PROPERTY(PropertyInfo(Variant::INT, "tracking_confidence"), "set_tracking_confidence", "get_tracking_confidence"); } void XRPose::set_has_tracking_data(const bool p_has_tracking_data) { @@ -108,3 +116,11 @@ void XRPose::set_angular_velocity(const Vector3 p_velocity) { Vector3 XRPose::get_angular_velocity() const { return angular_velocity; } + +void XRPose::set_tracking_confidence(const XRPose::TrackingConfidence p_tracking_confidence) { + tracking_confidence = p_tracking_confidence; +} + +XRPose::TrackingConfidence XRPose::get_tracking_confidence() const { + return tracking_confidence; +} diff --git a/servers/xr/xr_pose.h b/servers/xr/xr_pose.h index 8c1fc63360..f306c22390 100644 --- a/servers/xr/xr_pose.h +++ b/servers/xr/xr_pose.h @@ -37,12 +37,20 @@ class XRPose : public RefCounted { GDCLASS(XRPose, RefCounted); public: + // TrackingConfidence gives an indication of how reliable our transform data is. + enum TrackingConfidence { + XR_TRACKING_CONFIDENCE_NONE, // No tracking information is available for this pose. + XR_TRACKING_CONFIDENCE_LOW, // Tracking information may be inaccurate or estimated. + XR_TRACKING_CONFIDENCE_HIGH // Tracking information is deemed accurate and up to date. + }; + private: bool has_tracking_data = false; StringName name; Transform3D transform; Vector3 linear_velocity; Vector3 angular_velocity; + TrackingConfidence tracking_confidence = XR_TRACKING_CONFIDENCE_NONE; protected: static void _bind_methods(); @@ -63,6 +71,11 @@ public: void set_angular_velocity(const Vector3 p_velocity); Vector3 get_angular_velocity() const; + + void set_tracking_confidence(const TrackingConfidence p_tracking_confidence); + TrackingConfidence get_tracking_confidence() const; }; +VARIANT_ENUM_CAST(XRPose::TrackingConfidence); + #endif diff --git a/servers/xr/xr_positional_tracker.cpp b/servers/xr/xr_positional_tracker.cpp index 74907a5675..62e011654e 100644 --- a/servers/xr/xr_positional_tracker.cpp +++ b/servers/xr/xr_positional_tracker.cpp @@ -56,7 +56,7 @@ void XRPositionalTracker::_bind_methods() { ClassDB::bind_method(D_METHOD("has_pose", "name"), &XRPositionalTracker::has_pose); ClassDB::bind_method(D_METHOD("get_pose", "name"), &XRPositionalTracker::get_pose); ClassDB::bind_method(D_METHOD("invalidate_pose", "name"), &XRPositionalTracker::invalidate_pose); - ClassDB::bind_method(D_METHOD("set_pose", "name", "transform", "linear_velocity", "angular_velocity"), &XRPositionalTracker::set_pose); + ClassDB::bind_method(D_METHOD("set_pose", "name", "transform", "linear_velocity", "angular_velocity", "tracking_confidence"), &XRPositionalTracker::set_pose); ADD_SIGNAL(MethodInfo("pose_changed", PropertyInfo(Variant::OBJECT, "pose", PROPERTY_HINT_RESOURCE_TYPE, "XRPose"))); ClassDB::bind_method(D_METHOD("get_input", "name"), &XRPositionalTracker::get_input); @@ -137,7 +137,7 @@ void XRPositionalTracker::invalidate_pose(const StringName &p_action_name) { } } -void XRPositionalTracker::set_pose(const StringName &p_action_name, const Transform3D &p_transform, const Vector3 &p_linear_velocity, const Vector3 &p_angular_velocity) { +void XRPositionalTracker::set_pose(const StringName &p_action_name, const Transform3D &p_transform, const Vector3 &p_linear_velocity, const Vector3 &p_angular_velocity, const XRPose::TrackingConfidence p_tracking_confidence) { Ref<XRPose> new_pose; new_pose.instantiate(); @@ -146,6 +146,7 @@ void XRPositionalTracker::set_pose(const StringName &p_action_name, const Transf new_pose->set_transform(p_transform); new_pose->set_linear_velocity(p_linear_velocity); new_pose->set_angular_velocity(p_angular_velocity); + new_pose->set_tracking_confidence(p_tracking_confidence); poses[p_action_name] = new_pose; emit_signal("pose_changed", new_pose); diff --git a/servers/xr/xr_positional_tracker.h b/servers/xr/xr_positional_tracker.h index 2bcbf2c018..2f358cbb21 100644 --- a/servers/xr/xr_positional_tracker.h +++ b/servers/xr/xr_positional_tracker.h @@ -82,7 +82,7 @@ public: bool has_pose(const StringName &p_action_name) const; Ref<XRPose> get_pose(const StringName &p_action_name) const; void invalidate_pose(const StringName &p_action_name); - void set_pose(const StringName &p_action_name, const Transform3D &p_transform, const Vector3 &p_linear_velocity, const Vector3 &p_angular_velocity); + void set_pose(const StringName &p_action_name, const Transform3D &p_transform, const Vector3 &p_linear_velocity, const Vector3 &p_angular_velocity, const XRPose::TrackingConfidence p_tracking_confidence = XRPose::XR_TRACKING_CONFIDENCE_HIGH); Variant get_input(const StringName &p_action_name) const; void set_input(const StringName &p_action_name, const Variant &p_value); diff --git a/tests/core/variant/test_dictionary.h b/tests/core/variant/test_dictionary.h index 79d53fa64e..729035919d 100644 --- a/tests/core/variant/test_dictionary.h +++ b/tests/core/variant/test_dictionary.h @@ -196,7 +196,7 @@ TEST_CASE("[Dictionary] Duplicate dictionary") { Dictionary shallow_d = d.duplicate(false); CHECK_MESSAGE(shallow_d.id() != d.id(), "Should create a new array"); CHECK_MESSAGE(Dictionary(shallow_d[1]).id() == Dictionary(d[1]).id(), "Should keep nested dictionary"); - CHECK_MESSAGE(Array(shallow_d[2]).id() == Array(d[2]).id(), "Should keep nested array"); + CHECK_MESSAGE(Array(shallow_d[k2]).id() == Array(d[k2]).id(), "Should keep nested array"); CHECK_EQ(shallow_d, d); shallow_d[0] = 0; CHECK_NE(shallow_d, d); diff --git a/tests/scene/test_code_edit.h b/tests/scene/test_code_edit.h index be6e796da8..84e71150c7 100644 --- a/tests/scene/test_code_edit.h +++ b/tests/scene/test_code_edit.h @@ -2812,7 +2812,7 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { } SUBCASE("[CodeEdit] autocomplete request") { - SIGNAL_WATCH(code_edit, "request_code_completion"); + SIGNAL_WATCH(code_edit, "code_completion_requested"); code_edit->set_code_completion_enabled(true); Array signal_args; @@ -2820,13 +2820,13 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { /* Force request. */ code_edit->request_code_completion(); - SIGNAL_CHECK_FALSE("request_code_completion"); + SIGNAL_CHECK_FALSE("code_completion_requested"); code_edit->request_code_completion(true); - SIGNAL_CHECK("request_code_completion", signal_args); + SIGNAL_CHECK("code_completion_requested", signal_args); /* Manual request should force. */ SEND_GUI_ACTION(code_edit, "ui_text_completion_query"); - SIGNAL_CHECK("request_code_completion", signal_args); + SIGNAL_CHECK("code_completion_requested", signal_args); /* Insert prefix. */ TypedArray<String> completion_prefixes; @@ -2835,12 +2835,12 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { code_edit->insert_text_at_caret("."); code_edit->request_code_completion(); - SIGNAL_CHECK("request_code_completion", signal_args); + SIGNAL_CHECK("code_completion_requested", signal_args); /* Should work with space too. */ code_edit->insert_text_at_caret(" "); code_edit->request_code_completion(); - SIGNAL_CHECK("request_code_completion", signal_args); + SIGNAL_CHECK("code_completion_requested", signal_args); /* Should work when complete ends with prefix. */ code_edit->clear(); @@ -2849,9 +2849,9 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { code_edit->update_code_completion_options(); code_edit->confirm_code_completion(); CHECK(code_edit->get_line(0) == "test."); - SIGNAL_CHECK("request_code_completion", signal_args); + SIGNAL_CHECK("code_completion_requested", signal_args); - SIGNAL_UNWATCH(code_edit, "request_code_completion"); + SIGNAL_UNWATCH(code_edit, "code_completion_requested"); } SUBCASE("[CodeEdit] autocomplete completion") { @@ -3158,7 +3158,7 @@ TEST_CASE("[SceneTree][CodeEdit] symbol lookup") { code_edit->set_text("this is some text"); Point2 caret_pos = code_edit->get_caret_draw_pos(); - caret_pos.x += 55; + caret_pos.x += 58; SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MouseButton::NONE, MouseButton::NONE); CHECK(code_edit->get_text_for_symbol_lookup() == "this is s" + String::chr(0xFFFF) + "ome text"); @@ -3248,6 +3248,55 @@ TEST_CASE("[SceneTree][CodeEdit] Backspace delete") { memdelete(code_edit); } +TEST_CASE("[SceneTree][CodeEdit] New Line") { + CodeEdit *code_edit = memnew(CodeEdit); + SceneTree::get_singleton()->get_root()->add_child(code_edit); + + /* Add a new line. */ + code_edit->set_text(""); + code_edit->insert_text_at_caret("test new line"); + code_edit->set_caret_line(0); + code_edit->set_caret_column(13); + SEND_GUI_ACTION(code_edit, "ui_text_newline"); + CHECK(code_edit->get_line(0) == "test new line"); + CHECK(code_edit->get_line(1) == ""); + + /* Split line with new line. */ + code_edit->set_text(""); + code_edit->insert_text_at_caret("test new line"); + code_edit->set_caret_line(0); + code_edit->set_caret_column(5); + SEND_GUI_ACTION(code_edit, "ui_text_newline"); + CHECK(code_edit->get_line(0) == "test "); + CHECK(code_edit->get_line(1) == "new line"); + + /* Delete selection and split with new line. */ + code_edit->set_text(""); + code_edit->insert_text_at_caret("test new line"); + code_edit->select(0, 0, 0, 5); + SEND_GUI_ACTION(code_edit, "ui_text_newline"); + CHECK(code_edit->get_line(0) == ""); + CHECK(code_edit->get_line(1) == "new line"); + + /* Blank new line below with selection should not split. */ + code_edit->set_text(""); + code_edit->insert_text_at_caret("test new line"); + code_edit->select(0, 0, 0, 5); + SEND_GUI_ACTION(code_edit, "ui_text_newline_blank"); + CHECK(code_edit->get_line(0) == "test new line"); + CHECK(code_edit->get_line(1) == ""); + + /* Blank new line above with selection should not split. */ + code_edit->set_text(""); + code_edit->insert_text_at_caret("test new line"); + code_edit->select(0, 0, 0, 5); + SEND_GUI_ACTION(code_edit, "ui_text_newline_above"); + CHECK(code_edit->get_line(0) == ""); + CHECK(code_edit->get_line(1) == "test new line"); + + memdelete(code_edit); +} + } // namespace TestCodeEdit #endif // TEST_CODE_EDIT_H diff --git a/tests/test_main.cpp b/tests/test_main.cpp index 3826c03cad..0190fa5184 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -203,7 +203,7 @@ struct GodotTestCaseListener : public doctest::IReporter { memnew(InputMap); InputMap::get_singleton()->load_default(); - make_default_theme(false, Ref<Font>()); + make_default_theme(1.0, Ref<Font>()); memnew(SceneTree); SceneTree::get_singleton()->initialize(); diff --git a/thirdparty/README.md b/thirdparty/README.md index 2cb5458952..6333a0fe87 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -138,10 +138,10 @@ Files extracted from upstream source: * License: OFL-1.1 * Comment: Use UI font variant if available, because it has tight vertical metrics and good for UI. -- `Hack_Regular.ttf`: - * Upstream: https://github.com/source-foundry/Hack - * Version: 3.003 (2018) - * License: MIT + Bitstream Vera License +- `JetBrainsMono_Regular.ttf`: + * Upstream: https://github.com/JetBrains/JetBrainsMono + * Version: 2.242 + * License: OFL-1.1 - `DroidSans*.ttf`: * Upstream: https://android.googlesource.com/platform/frameworks/base/+/master/data/fonts/ * Version: ? (pre-2014 commit when DroidSansJapanese.ttf was obsoleted) @@ -152,6 +152,7 @@ Files extracted from upstream source: * License: Apache 2.0 + ## freetype - Upstream: https://www.freetype.org diff --git a/thirdparty/fonts/Hack_Regular.ttf b/thirdparty/fonts/Hack_Regular.ttf Binary files differdeleted file mode 100644 index 92a90cb06e..0000000000 --- a/thirdparty/fonts/Hack_Regular.ttf +++ /dev/null diff --git a/thirdparty/fonts/JetBrainsMono_Regular.ttf b/thirdparty/fonts/JetBrainsMono_Regular.ttf Binary files differnew file mode 100644 index 0000000000..8da8aa4051 --- /dev/null +++ b/thirdparty/fonts/JetBrainsMono_Regular.ttf diff --git a/thirdparty/fonts/LICENSE.JetBrainsMono.txt b/thirdparty/fonts/LICENSE.JetBrainsMono.txt new file mode 100644 index 0000000000..e5f5dd62fc --- /dev/null +++ b/thirdparty/fonts/LICENSE.JetBrainsMono.txt @@ -0,0 +1,93 @@ +Copyright 2020, The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/thirdparty/fonts/LICENSE_Hack.md b/thirdparty/fonts/LICENSE_Hack.md deleted file mode 100644 index 08927e504f..0000000000 --- a/thirdparty/fonts/LICENSE_Hack.md +++ /dev/null @@ -1,45 +0,0 @@ -The work in the Hack project is Copyright 2018 Source Foundry Authors and licensed under the MIT License - -The work in the DejaVu project was committed to the public domain. - -Bitstream Vera Sans Mono Copyright 2003 Bitstream Inc. and licensed under the Bitstream Vera License with Reserved Font Names "Bitstream" and "Vera" - -### MIT License - -Copyright (c) 2018 Source Foundry Authors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -### BITSTREAM VERA LICENSE - -Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: - -The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. - -The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". - -This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. - -The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. - -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. - -Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org. diff --git a/thirdparty/thorvg/patches/thorvg-pr1166-vs2017-minmax.patch b/thirdparty/thorvg/patches/thorvg-pr1166-vs2017-minmax.patch new file mode 100644 index 0000000000..0b045bd05a --- /dev/null +++ b/thirdparty/thorvg/patches/thorvg-pr1166-vs2017-minmax.patch @@ -0,0 +1,49 @@ +diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp +index 78537e7726..c75e73760e 100644 +--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp ++++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp +@@ -23,6 +23,7 @@ + #include "tvgSwCommon.h" + #include "tvgTaskScheduler.h" + #include "tvgSwRenderer.h" ++#include "tvgMath.h" + + /************************************************************************/ + /* Internal Class Implementation */ +@@ -594,10 +595,10 @@ void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, + task->surface = surface; + task->mpool = mpool; + task->flags = flags; +- task->bbox.min.x = max(static_cast<SwCoord>(0), static_cast<SwCoord>(vport.x)); +- task->bbox.min.y = max(static_cast<SwCoord>(0), static_cast<SwCoord>(vport.y)); +- task->bbox.max.x = min(static_cast<SwCoord>(surface->w), static_cast<SwCoord>(vport.x + vport.w)); +- task->bbox.max.y = min(static_cast<SwCoord>(surface->h), static_cast<SwCoord>(vport.y + vport.h)); ++ task->bbox.min.x = mathMax(static_cast<SwCoord>(0), static_cast<SwCoord>(vport.x)); ++ task->bbox.min.y = mathMax(static_cast<SwCoord>(0), static_cast<SwCoord>(vport.y)); ++ task->bbox.max.x = mathMin(static_cast<SwCoord>(surface->w), static_cast<SwCoord>(vport.x + vport.w)); ++ task->bbox.max.y = mathMin(static_cast<SwCoord>(surface->h), static_cast<SwCoord>(vport.y + vport.h)); + + if (!task->pushed) { + task->pushed = true; +diff --git a/thirdparty/thorvg/src/lib/tvgMath.h b/thirdparty/thorvg/src/lib/tvgMath.h +index 9e5c915fc3..94b4fe1cf1 100644 +--- a/thirdparty/thorvg/src/lib/tvgMath.h ++++ b/thirdparty/thorvg/src/lib/tvgMath.h +@@ -29,6 +29,10 @@ + #include "tvgCommon.h" + + ++#define mathMin(x, y) (((x) < (y)) ? (x) : (y)) ++#define mathMax(x, y) (((x) > (y)) ? (x) : (y)) ++ ++ + static inline bool mathZero(float a) + { + return (fabsf(a) < FLT_EPSILON) ? true : false; +@@ -154,4 +158,4 @@ static inline Matrix mathMultiply(const Matrix* lhs, const Matrix* rhs) + } + + +-#endif //_TVG_MATH_H_ +\ No newline at end of file ++#endif //_TVG_MATH_H_ diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp index 78537e7726..c75e73760e 100644 --- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp @@ -23,6 +23,7 @@ #include "tvgSwCommon.h" #include "tvgTaskScheduler.h" #include "tvgSwRenderer.h" +#include "tvgMath.h" /************************************************************************/ /* Internal Class Implementation */ @@ -594,10 +595,10 @@ void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, task->surface = surface; task->mpool = mpool; task->flags = flags; - task->bbox.min.x = max(static_cast<SwCoord>(0), static_cast<SwCoord>(vport.x)); - task->bbox.min.y = max(static_cast<SwCoord>(0), static_cast<SwCoord>(vport.y)); - task->bbox.max.x = min(static_cast<SwCoord>(surface->w), static_cast<SwCoord>(vport.x + vport.w)); - task->bbox.max.y = min(static_cast<SwCoord>(surface->h), static_cast<SwCoord>(vport.y + vport.h)); + task->bbox.min.x = mathMax(static_cast<SwCoord>(0), static_cast<SwCoord>(vport.x)); + task->bbox.min.y = mathMax(static_cast<SwCoord>(0), static_cast<SwCoord>(vport.y)); + task->bbox.max.x = mathMin(static_cast<SwCoord>(surface->w), static_cast<SwCoord>(vport.x + vport.w)); + task->bbox.max.y = mathMin(static_cast<SwCoord>(surface->h), static_cast<SwCoord>(vport.y + vport.h)); if (!task->pushed) { task->pushed = true; diff --git a/thirdparty/thorvg/src/lib/tvgMath.h b/thirdparty/thorvg/src/lib/tvgMath.h index 9e5c915fc3..94b4fe1cf1 100644 --- a/thirdparty/thorvg/src/lib/tvgMath.h +++ b/thirdparty/thorvg/src/lib/tvgMath.h @@ -29,6 +29,10 @@ #include "tvgCommon.h" +#define mathMin(x, y) (((x) < (y)) ? (x) : (y)) +#define mathMax(x, y) (((x) > (y)) ? (x) : (y)) + + static inline bool mathZero(float a) { return (fabsf(a) < FLT_EPSILON) ? true : false; @@ -154,4 +158,4 @@ static inline Matrix mathMultiply(const Matrix* lhs, const Matrix* rhs) } -#endif //_TVG_MATH_H_
\ No newline at end of file +#endif //_TVG_MATH_H_ diff --git a/version.py b/version.py index 66cb145528..f9aa1dd0f4 100644 --- a/version.py +++ b/version.py @@ -3,7 +3,7 @@ name = "Godot Engine" major = 4 minor = 0 patch = 0 -status = "dev" +status = "alpha" module_config = "" year = 2022 website = "https://godotengine.org" |