diff options
44 files changed, 588 insertions, 201 deletions
@@ -17,25 +17,24 @@ generous deed immortalized in the next stable release of Godot Engine. ## Gold sponsors Gamblify <https://www.gamblify.com> - Image Campus <https://www.imagecampus.edu.ar> ## Mini sponsors Alan Beauchamp + Aleksandar Kordic Anandarup Mallik Andrew Dunai Brandon Lamb + Christian Chipont Christian Uldall Pedersen Christoph Woinke - Connor Hill Denis Malyavin Edward Flick GameDev.net GameDev.tv Hein-Pieter van Braam Jacob McKenney - Javary Games - Jay Sistar + Javary Co. Justin Arnold Kyle Szklenski Leonard Meagher @@ -44,15 +43,13 @@ generous deed immortalized in the next stable release of Godot Engine. Mike King Neal Gompa (Conan Kudo) Patrick Aarstad - "Rainway " Slobodan Milnovic - StarFlare Software Stephan Lanfermann Stephen Telford Steve - TigerJ VilliHaukka Xananax + Y8.com Zashi ## Gold donors @@ -77,12 +74,14 @@ generous deed immortalized in the next stable release of Godot Engine. Andreas Schüle Asher Glick Austen McRae + Brian van der Stel + Carlo Cabanilla Daniel James David Giardi - David Graham Edward E Florian Breisch Gero + Javier Roman Jay Horton Jon Smith Jon Woodward @@ -107,12 +106,12 @@ generous deed immortalized in the next stable release of Godot Engine. William Wold Wyatt Goodin + Alex Khayrullin Chris Goddard Chris Serino Christian Padilla Conrad Curry Craig Smith - Daniel Egger Dean Harmon Ian Richard Kunert Ivan Trombley @@ -135,17 +134,18 @@ generous deed immortalized in the next stable release of Godot Engine. Wojciech Chojnacki Xavier PATRICELLI + Adam Neumann Alessandra Pereyra + Alexander J Maynard Alexey Dyadchenko Andrew Bowen Asdf - Benjamin W Flint + Ben Botwin Carlos de Sousa Marques Chris Petrich Christian Leth Jeppesen Christoph Schröder Cody Parker - ComicSads D Daniel Daniel Eichler @@ -163,6 +163,8 @@ generous deed immortalized in the next stable release of Godot Engine. Guilherme Felipe de C. G. da Silva Heath Hayes Hysteria + Idzard Kwadijk + Jared White Jose Malheiro Joshua Flores Juan T Chen @@ -173,7 +175,6 @@ generous deed immortalized in the next stable release of Godot Engine. Leandro Voltolino Maarten Elings Malcolm Peralty - Marius Kamm Markus Fehr Markus Wiesner Martin Eigel @@ -184,6 +185,7 @@ generous deed immortalized in the next stable release of Godot Engine. M H Nick Nikitin Oliver Dick + Paolo Munoz Paul Hocker Paul Von Zimmerman Pete Goodwin @@ -197,7 +199,6 @@ generous deed immortalized in the next stable release of Godot Engine. Urho WytRabbit Xavier Fumado Beltran - yuanzhe zhou ## Silver donors @@ -208,6 +209,7 @@ generous deed immortalized in the next stable release of Godot Engine. Adam Nakonieczny Adam Smeltzer Adisibio + Agustinus Arya Aidan O'Flannagain Alder Stefano Alessandro Senese @@ -231,21 +233,23 @@ generous deed immortalized in the next stable release of Godot Engine. Benedikt Ben Phelan Ben Vercammen + Ben Woodley + Berbank Bernd Jänichen Black Block Blair Allen Bobby CC Wong Boyquotes - Branwen Zak + Branwyn Tylwyth Bryan Stevenson - Carl Winder Carwyn Edwards Chris Brown Chris Chapin + Chris Gonzales Christian Baune Christian Winter Christoffer Sundbom - Christopher Fisher + Christopher Schmitt Chris Wilson Clay Heaton Cobaltum @@ -262,7 +266,6 @@ generous deed immortalized in the next stable release of Godot Engine. Dominik Wetzel Duobix Edward Herbert - E.G. Egon Elbre Ellen Marie Dash Elmeri '- Duy Kevin Nguyen @@ -271,30 +274,33 @@ generous deed immortalized in the next stable release of Godot Engine. Eric Martini Eric McCarthy Eric Williams - Fabian Lökes + Evan Rose Felix Kollmann fengjiongmax - Foomf + Flaredown G3Dev sàrl Gary Hulst Gerrit Großkopf gmmath Grant Clarke Greg Olson - Greg Pennefather + Greg P Guldoman Heribert Hirth Hiroshi Naruo HMan Hunter Jones + Hylpher ialex32x Igor Buzatovic Iiari + IndustrialRobot Isaac Morton Jaime Ruiz-Borau Vizárraga Jako Danar James A F Manley Jax + Jed Jeff Hungerford Jeff Nyte Jeremy Kahn @@ -302,6 +308,7 @@ generous deed immortalized in the next stable release of Godot Engine. Joe Alden Joel Fivat Joel Setterberg + Johannes Eichler Johannes Wuensch Jonas Rudlang Jonas Yamazaki @@ -316,6 +323,7 @@ generous deed immortalized in the next stable release of Godot Engine. Juan Negrier Judd Julian Murgia + Kasier Bald0 KC Chan kickmaniac Kiyohiro Kawamura (kyorohiro) @@ -324,22 +332,24 @@ generous deed immortalized in the next stable release of Godot Engine. KsyTek Games Kuan Cheang kycho + Lavik1988 Levi Lindsey Linus Lind Lundgren Lionel Gaillard Luis Moraes + LunaticInAHat + Lurkars Macil - magodev Major Haul Malcolm Malik Ahmed + Malik Nejer + Marcus Richter Markus Michael Egger Martin Holas Matthew Little Maxwell medecau - Menno Finlay-Smits - Mertcan Mermerkaya mhilbrunner Michael Dürwald Michael Gringauz @@ -347,9 +357,9 @@ generous deed immortalized in the next stable release of Godot Engine. Mikael Olsson Mikayla Hutchinson Mike Cunningham + mlevin cantu MoM Moritz Laass - Moritz Weissenberger MuffinManKen Natrim nee @@ -360,6 +370,7 @@ generous deed immortalized in the next stable release of Godot Engine. Nicolas SAN AGUSTIN Nithin Jino NZ + Omar Delarosa Oscar Norlander Pan Ip Patrick Forringer @@ -370,30 +381,30 @@ generous deed immortalized in the next stable release of Godot Engine. Philip O. Staiger Pierre-Igor Berthet Pietro Vertechi - Piotr Kaczmarski Pitsanu Tongprasin Poryg + Rafa Laguna + Rafal Wyszomirski Raphael Leroux - Red Hara Rémi Verschelde Ricardo Alcantara - Rob Crowle Robert Farr (Larington) Robert Hernandez Rodrigo Loli - Roger Burgess Roger Smith Roland Rząsa Roman Tinkov Ryan Groom Ryan Hentz Saad Khoudmi - Samdze + Samuele Zolfanelli + Sanka.X Sasori Olkof Scott D. Yelich Sebastian Michailidis Shane Sicienski Shane Spoor + Simon Ledam Simon Wenner SK Sootstone @@ -408,13 +419,18 @@ generous deed immortalized in the next stable release of Godot Engine. Tim Drumheller Tim Gudex Timo Schmidt + Timothy B. MacDonald + Tobbun Tom Larrow Torsten Crass Travis O'Brien + Trent Skinner Tryggve Sollid - Tyler Strafos + Turgut Temucin + Tyler Stafos UltyX Vaiktorg + Valeria Viana Gusmao Veodok Victor Vigilant Watch diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index ce2054db36..891fb7b0ca 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -346,6 +346,12 @@ Error HTTPClient::poll() { } else { // We are already handshaking, which means we can use your already active SSL connection ssl = static_cast<Ref<StreamPeerSSL> >(connection); + if (ssl.is_null()) { + close(); + status = STATUS_SSL_HANDSHAKE_ERROR; + return ERR_CANT_CONNECT; + } + ssl->poll(); // Try to finish the handshake } diff --git a/core/list.h b/core/list.h index 103a82a31d..d1b528562d 100644 --- a/core/list.h +++ b/core/list.h @@ -602,9 +602,6 @@ public: Element *next = current->next_ptr; - //disconnect - current->next_ptr = NULL; - if (from != current) { current->prev_ptr = NULL; diff --git a/doc/classes/@GDScript.xml b/doc/classes/@GDScript.xml index 553fd4d629..b6de5dbf62 100644 --- a/doc/classes/@GDScript.xml +++ b/doc/classes/@GDScript.xml @@ -92,13 +92,13 @@ <argument index="0" name="condition" type="bool"> </argument> <description> - Assert that the [code]condition[/code] is [code]true[/code] . If the [code]condition[/code] is [code]false[/code] a fatal error is generated and the program is halted. Useful for debugging to make sure a value is always [code]true[/code]. + Asserts that the [code]condition[/code] is [code]true[/code] . If the [code]condition[/code] is [code]false[/code], an error is generated and the program is halted until you resume it. Only executes in debug builds, or when running the game from the editor. Use it for debugging purposes, to make sure a statement is [code]true[/code] during development. [codeblock] - # Speed should always be between 0 and 20 + # Imagine we always want speed to be between 0 and 20 speed = -10 - assert(speed < 20) # Is true and program continues - assert(speed >= 0) # Is false and program stops - assert(speed >= 0 && speed < 20) # Or combined + assert(speed < 20) # True, the program will continue + assert(speed >= 0) # False, the program will stop + assert(speed >= 0 && speed < 20) # You can also combine the two conditional statements in one check [/codeblock] </description> </method> diff --git a/doc/classes/InputEventKey.xml b/doc/classes/InputEventKey.xml index 86a1362230..53b1f74bd4 100644 --- a/doc/classes/InputEventKey.xml +++ b/doc/classes/InputEventKey.xml @@ -29,7 +29,7 @@ Key scancode, one of the [enum KeyList] constants. </member> <member name="unicode" type="int" setter="set_unicode" getter="get_unicode"> - Key unicode identifier when relevant. + Key unicode identifier when relevant. Unicode identifiers for the composite characters and complex scripts may not be available unless IME input mode is active. See [method OS.set_ime_active] for more information. </member> </members> <constants> diff --git a/doc/classes/MultiMeshInstance2D.xml b/doc/classes/MultiMeshInstance2D.xml new file mode 100644 index 0000000000..0bf243ee24 --- /dev/null +++ b/doc/classes/MultiMeshInstance2D.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="MultiMeshInstance2D" inherits="Node2D" category="Core" version="3.2"> + <brief_description> + Node that instances a [MultiMesh] in 2D. + </brief_description> + <description> + [MultiMeshInstance2D] is a specialized node to instance a [MultiMesh] resource in 2D. + Usage is the same as [MultiMeshInstance]. + </description> + <tutorials> + </tutorials> + <methods> + </methods> + <members> + <member name="multimesh" type="MultiMesh" setter="set_multimesh" getter="get_multimesh"> + The [MultiMesh] that will be drawn by the [MultiMeshInstance2D]. + </member> + <member name="normal_map" type="Texture" setter="set_normal_map" getter="get_normal_map"> + The normal map that will be used if using the default [CanvasItemMaterial]. + </member> + <member name="texture" type="Texture" setter="set_texture" getter="get_texture"> + The [Texture] that will be used if using the default [CanvasItemMaterial]. Can be accessed as [code]TEXTURE[/code] in CanvasItem shader. + </member> + </members> + <constants> + </constants> +</class> diff --git a/doc/classes/Navigation.xml b/doc/classes/Navigation.xml index 3690c1d682..f0ae3fef99 100644 --- a/doc/classes/Navigation.xml +++ b/doc/classes/Navigation.xml @@ -59,7 +59,7 @@ <argument index="2" name="optimize" type="bool" default="true"> </argument> <description> - Returns the path between two given points. Points are in local coordinate space. If [code]optimize[/code] is [code]true[/code] (the default), the agent properties associated with each [NavigationMesh] (raidus, height, etc.) are considered in the path calculation, otherwise they are ignored. + Returns the path between two given points. Points are in local coordinate space. If [code]optimize[/code] is [code]true[/code] (the default), the agent properties associated with each [NavigationMesh] (radius, height, etc.) are considered in the path calculation, otherwise they are ignored. </description> </method> <method name="navmesh_add"> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index dd0fcd63e7..f7cd6c3e83 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -221,14 +221,16 @@ <return type="Vector2"> </return> <description> - Returns IME selection range. + Returns IME cursor position (currently edited portion of the string) relative to the characters in the composition string. + [code]NOTIFICATION_OS_IME_UPDATE[/code] is sent to the application to notify it of changes to the IME cursor position. </description> </method> <method name="get_ime_text" qualifiers="const"> <return type="String"> </return> <description> - Returns IME intermediate text. + Returns IME intermediate composition string. + [code]NOTIFICATION_OS_IME_UPDATE[/code] is sent to the application to notify it of changes to the IME composition string. </description> </method> <method name="get_latin_keyboard_variant" qualifiers="const"> @@ -710,6 +712,9 @@ </argument> <description> Sets whether IME input mode should be enabled. + If active IME handles key events before the application and creates an composition string and suggestion list. + Application can retrieve the composition status by using [method get_ime_selection] and [method get_ime_text] functions. + Completed composition string is committed when input is finished. </description> </method> <method name="set_ime_position"> diff --git a/doc/classes/Particles.xml b/doc/classes/Particles.xml index 0023fce97d..7820c63ad7 100644 --- a/doc/classes/Particles.xml +++ b/doc/classes/Particles.xml @@ -15,13 +15,14 @@ <return type="AABB"> </return> <description> + Returns the bounding box that contains all the particles that are active in the current frame. </description> </method> <method name="restart"> <return type="void"> </return> <description> - Restarts the particle emmission, clearing existing particles. + Restarts the particle emission, clearing existing particles. </description> </method> </methods> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 5bcd39a8d6..460db5e792 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -723,7 +723,7 @@ Shaders have a time variable that constantly increases. At some point, it needs to be rolled back to zero to avoid precision errors on shader animations. This setting specifies when (in seconds). </member> <member name="rendering/quality/2d/gles2_use_nvidia_rect_flicker_workaround" type="bool" setter="" getter=""> - Some NVIDIA GPU drivers have a bug which produces flickering issues for the [code]draw_rect[/code] method, especially as used in [TileMap]. Refer to [url=https://github.com/godotengine/godot/issues/9913][/url] for details. + Some NVIDIA GPU drivers have a bug which produces flickering issues for the [code]draw_rect[/code] method, especially as used in [TileMap]. Refer to [url=https://github.com/godotengine/godot/issues/9913]GitHub issue 9913[/url] for details. If [code]true[/code], this option enables a "safe" code path for such NVIDIA GPUs at the cost of performance. This option only impacts the GLES2 rendering backend (so the bug stays if you use GLES3), and only desktop platforms. </member> <member name="rendering/quality/2d/use_pixel_snap" type="bool" setter="" getter=""> diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py index c3e15b2f9a..454c71d3c7 100755 --- a/doc/tools/makerst.py +++ b/doc/tools/makerst.py @@ -478,24 +478,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S f.write(make_heading('Tutorials', '-')) for t in class_def.tutorials: link = t.strip() - match = GODOT_DOCS_PATTERN.search(link) - if match: - groups = match.groups() - if match.lastindex == 2: - # Doc reference with fragment identifier: emit direct link to section with reference to page, for example: - # `#calling-javascript-from-script in Exporting For Web` - f.write("- `" + groups[1] + " <../" + groups[0] + ".html" + groups[1] + ">`_ in :doc:`../" + groups[0] + "`\n\n") - # Commented out alternative: Instead just emit: - # `Subsection in Exporting For Web` - # f.write("- `Subsection <../" + groups[0] + ".html" + groups[1] + ">`_ in :doc:`../" + groups[0] + "`\n\n") - elif match.lastindex == 1: - # Doc reference, for example: - # `Math` - f.write("- :doc:`../" + groups[0] + "`\n\n") - else: - # External link, for example: - # `http://enet.bespin.org/usergroup0.html` - f.write("- `" + link + " <" + link + ">`_\n\n") + f.write("- " + make_url(link) + "\n\n") # Property descriptions if len(class_def.properties) > 0: @@ -802,15 +785,16 @@ def rstize_text(text, state): # type: (str, State) -> str tag_text = "" # '![](' + cmd[6:] + ')' elif cmd.find('url=') == 0: url_link = cmd[4:] - tag_text = ':ref:`' + tag_text = '`' tag_depth += 1 - url_has_name = False inside_url = True + url_has_name = False elif cmd == '/url': - tag_text = ('' if url_has_name else url_link) + '<' + url_link + ">`" + tag_text = ('' if url_has_name else url_link) + " <" + url_link + ">`_" tag_depth -= 1 escape_post = True inside_url = False + url_has_name = False elif cmd == 'center': tag_depth += 1 tag_text = '' @@ -996,5 +980,26 @@ def make_heading(title, underline): # type: (str, str) -> str return title + '\n' + (underline * len(title)) + "\n\n" +def make_url(link): # type: (str) -> str + match = GODOT_DOCS_PATTERN.search(link) + if match: + groups = match.groups() + if match.lastindex == 2: + # Doc reference with fragment identifier: emit direct link to section with reference to page, for example: + # `#calling-javascript-from-script in Exporting For Web` + return "`" + groups[1] + " <../" + groups[0] + ".html" + groups[1] + ">`_ in :doc:`../" + groups[0] + "`" + # Commented out alternative: Instead just emit: + # `Subsection in Exporting For Web` + # return "`Subsection <../" + groups[0] + ".html" + groups[1] + ">`__ in :doc:`../" + groups[0] + "`" + elif match.lastindex == 1: + # Doc reference, for example: + # `Math` + return ":doc:`../" + groups[0] + "`" + else: + # External link, for example: + # `http://enet.bespin.org/usergroup0.html` + return "`" + link + " <" + link + ">`_" + + if __name__ == '__main__': main() diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index ee722e9d6c..b82186162d 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -1081,6 +1081,8 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur } else { glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 3, buffer + color_ofs); } + } else { + glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 3, 1.0, 1.0, 1.0, 1.0); } if (multi_mesh->custom_data_floats) { diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index 7dce784f52..0818942b0a 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -112,7 +112,12 @@ void main() { #ifdef USE_INSTANCING mat4 extra_matrix_instance = extra_matrix * transpose(mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0))); color *= instance_color; + +#ifdef USE_INSTANCE_CUSTOM vec4 instance_custom = instance_custom_data; +#else + vec4 instance_custom = vec4(0.0); +#endif #else mat4 extra_matrix_instance = extra_matrix; diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 0d1e7ee4a1..a46b31c92e 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -117,7 +117,12 @@ void main() { #ifdef USE_INSTANCING mat4 extra_matrix_instance = extra_matrix * transpose(mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0))); color *= instance_color; + +#ifdef USE_INSTANCE_CUSTOM vec4 instance_custom = instance_custom_data; +#else + vec4 instance_custom = vec4(0.0); +#endif #else mat4 extra_matrix_instance = extra_matrix; diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index bde73e9268..cc9e2c12e8 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -725,7 +725,7 @@ bool OrphanResourcesDialog::_fill_owners(EditorFileSystemDirectory *efsd, HashMa int ds = efsd->get_file_deps(i).size(); ti->set_text(1, itos(ds)); if (ds) { - ti->add_button(1, get_icon("GuiVisibilityVisible", "EditorIcons")); + ti->add_button(1, get_icon("GuiVisibilityVisible", "EditorIcons"), -1, false, TTR("Show Dependencies")); } ti->set_metadata(0, path); has_children = true; diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index f61a831015..38f30df169 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -560,6 +560,7 @@ void EditorData::move_edited_scene_index(int p_idx, int p_to_idx) { ERR_FAIL_INDEX(p_to_idx, edited_scene.size()); SWAP(edited_scene.write[p_idx], edited_scene.write[p_to_idx]); } + void EditorData::remove_scene(int p_idx) { ERR_FAIL_INDEX(p_idx, edited_scene.size()); if (edited_scene[p_idx].root) { diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 3d198dec67..1a293adb4b 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -1253,6 +1253,12 @@ void EditorFileDialog::_favorite_toggled(bool p_toggle) { _update_favorites(); } +void EditorFileDialog::_favorite_pressed() { + + favorite->set_pressed(!favorite->is_pressed()); + _favorite_toggled(favorite->is_pressed()); +} + void EditorFileDialog::_recent_selected(int p_idx) { Vector<String> recentd = EditorSettings::get_singleton()->get_recent_dirs(); @@ -1376,6 +1382,7 @@ void EditorFileDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("_go_up"), &EditorFileDialog::_go_up); ClassDB::bind_method(D_METHOD("_favorite_toggled"), &EditorFileDialog::_favorite_toggled); + ClassDB::bind_method(D_METHOD("_favorite_pressed"), &EditorFileDialog::_favorite_pressed); ClassDB::bind_method(D_METHOD("_favorite_selected"), &EditorFileDialog::_favorite_selected); ClassDB::bind_method(D_METHOD("_favorite_move_up"), &EditorFileDialog::_favorite_move_up); ClassDB::bind_method(D_METHOD("_favorite_move_down"), &EditorFileDialog::_favorite_move_down); @@ -1519,7 +1526,7 @@ EditorFileDialog::EditorFileDialog() { favorite->set_flat(true); favorite->set_toggle_mode(true); favorite->set_tooltip(TTR("(Un)favorite current folder.")); - favorite->connect("toggled", this, "_favorite_toggled"); + favorite->connect("pressed", this, "_favorite_pressed"); pathhb->add_child(favorite); Ref<ButtonGroup> view_mode_group; diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h index edaccac51d..529aaa71de 100644 --- a/editor/editor_file_dialog.h +++ b/editor/editor_file_dialog.h @@ -151,6 +151,7 @@ private: void _update_favorites(); void _favorite_toggled(bool p_toggle); + void _favorite_pressed(); void _favorite_selected(int p_idx); void _favorite_move_up(); void _favorite_move_down(); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 43c8ef60aa..969e1affd7 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -523,6 +523,7 @@ void EditorNode::_fs_changed() { void EditorNode::_resources_reimported(const Vector<String> &p_resources) { List<String> scenes; //will load later + int current_tab = scene_tabs->get_current_tab(); for (int i = 0; i < p_resources.size(); i++) { String file_type = ResourceLoader::get_resource_type(p_resources[i]); @@ -545,6 +546,8 @@ void EditorNode::_resources_reimported(const Vector<String> &p_resources) { for (List<String>::Element *E = scenes.front(); E; E = E->next()) { reload_scene(E->get()); } + + scene_tabs->set_current_tab(current_tab); } void EditorNode::_sources_changed(bool p_exist) { @@ -1214,6 +1217,17 @@ void EditorNode::save_all_scenes() { _save_all_scenes(); } +void EditorNode::save_scene_list(Vector<String> p_scene_filenames) { + + for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { + Node *scene = editor_data.get_edited_scene_root(i); + + if (scene && (p_scene_filenames.find(scene->get_filename()) >= 0)) { + _save_scene(scene->get_filename(), i); + } + } +} + void EditorNode::restart_editor() { exiting = true; @@ -2859,7 +2873,7 @@ bool EditorNode::is_addon_plugin_enabled(const String &p_addon) const { return plugin_addons.has(p_addon); } -void EditorNode::_remove_edited_scene() { +void EditorNode::_remove_edited_scene(bool p_change_tab) { int new_index = editor_data.get_edited_scene(); int old_index = new_index; @@ -2875,18 +2889,19 @@ void EditorNode::_remove_edited_scene() { if (editor_data.get_scene_path(old_index) != String()) { ScriptEditor::get_singleton()->close_builtin_scripts_from_scene(editor_data.get_scene_path(old_index)); } - _scene_tab_changed(new_index); + + if (p_change_tab) _scene_tab_changed(new_index); editor_data.remove_scene(old_index); editor_data.get_undo_redo().clear_history(false); _update_title(); _update_scene_tabs(); } -void EditorNode::_remove_scene(int index) { +void EditorNode::_remove_scene(int index, bool p_change_tab) { if (editor_data.get_edited_scene() == index) { //Scene to remove is current scene - _remove_edited_scene(); + _remove_edited_scene(p_change_tab); } else { //Scene to remove is not active scene editor_data.remove_scene(index); @@ -4182,6 +4197,14 @@ bool EditorNode::ensure_main_scene(bool p_from_native) { return true; } +int EditorNode::get_current_tab() { + return scene_tabs->get_current_tab(); +} + +void EditorNode::set_current_tab(int p_tab) { + scene_tabs->set_current_tab(p_tab); +} + void EditorNode::_update_layouts_menu() { editor_layouts->clear(); @@ -4809,8 +4832,7 @@ void EditorNode::reload_scene(const String &p_path) { if (scene_idx == -1) { if (get_edited_scene()) { - //scene is not open, so at it might be instanced, just refresh, set tab to itself and it will reload - set_current_scene(current_tab); + //scene is not open, so at it might be instanced. We'll refresh the whole scene later. editor_data.get_undo_redo().clear_history(); } return; @@ -4820,17 +4842,19 @@ void EditorNode::reload_scene(const String &p_path) { editor_data.apply_changes_in_editors(); _set_scene_metadata(p_path); } + //remove scene - _remove_scene(scene_idx); - //reload scene + _remove_scene(scene_idx, false); + //reload scene load_scene(p_path, true, false, true, true); + //adjust index so tab is back a the previous position editor_data.move_edited_scene_to_index(scene_idx); get_undo_redo()->clear_history(); + //recover the tab scene_tabs->set_current_tab(current_tab); - _scene_tab_changed(current_tab); } int EditorNode::plugin_init_callback_count = 0; diff --git a/editor/editor_node.h b/editor/editor_node.h index ea988cb134..f3bc95c409 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -525,8 +525,8 @@ private: static void _editor_file_dialog_unregister(EditorFileDialog *p_dialog); void _cleanup_scene(); - void _remove_edited_scene(); - void _remove_scene(int index); + void _remove_edited_scene(bool p_change_tab = true); + void _remove_scene(int index, bool p_change_tab = true); bool _find_and_save_resource(RES p_res, Map<RES, bool> &processed, int32_t flags); bool _find_and_save_edited_subresources(Object *obj, Map<RES, bool> &processed, int32_t flags); void _save_edited_subresources(Node *scene, Map<RES, bool> &processed, int32_t flags); @@ -644,6 +644,12 @@ protected: void _notification(int p_what); static void _bind_methods(); +protected: + friend class FileSystemDock; + + int get_current_tab(); + void set_current_tab(int p_tab); + public: bool call_build(); @@ -815,6 +821,7 @@ public: void remove_tool_menu_item(const String &p_name); void save_all_scenes(); + void save_scene_list(Vector<String> p_scene_filenames); void restart_editor(); void dim_editor(bool p_dimming); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 6a4d9fea0c..ee88b558c8 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -1203,6 +1203,21 @@ void FileSystemDock::_update_favorites_list_after_move(const Map<String, String> EditorSettings::get_singleton()->set_favorites(new_favorites); } +void FileSystemDock::_save_scenes_after_move(const Map<String, String> &p_renames) const { + Vector<String> remaps; + _find_remaps(EditorFileSystem::get_singleton()->get_filesystem(), p_renames, remaps); + Vector<String> new_filenames; + + for (int i = 0; i < remaps.size(); ++i) { + String file = p_renames.has(remaps[i]) ? p_renames[remaps[i]] : remaps[i]; + if (ResourceLoader::get_resource_type(file) == "PackedScene") { + new_filenames.push_back(file); + } + } + + editor->save_scene_list(new_filenames); +} + void FileSystemDock::_make_dir_confirm() { String dir_name = make_dir_dialog_text->get_text().strip_edges(); @@ -1281,14 +1296,21 @@ void FileSystemDock::_rename_operation_confirm() { Map<String, String> file_renames; Map<String, String> folder_renames; _try_move_item(to_rename, new_path, file_renames, folder_renames); + + int current_tab = editor->get_current_tab(); + _update_dependencies_after_move(file_renames); _update_resource_paths_after_move(file_renames); _update_project_settings_after_move(file_renames); _update_favorites_list_after_move(file_renames, folder_renames); - //Rescan everything + editor->set_current_tab(current_tab); + print_verbose("FileSystem: calling rescan."); _rescan(); + + print_verbose("FileSystem: saving moved scenes."); + _save_scenes_after_move(file_renames); } void FileSystemDock::_duplicate_operation_confirm() { @@ -1384,13 +1406,20 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool overw } if (is_moved) { + int current_tab = editor->get_current_tab(); + _update_dependencies_after_move(file_renames); _update_resource_paths_after_move(file_renames); _update_project_settings_after_move(file_renames); _update_favorites_list_after_move(file_renames, folder_renames); + editor->set_current_tab(current_tab); + print_verbose("FileSystem: calling rescan."); _rescan(); + + print_verbose("FileSystem: saving moved scenes."); + _save_scenes_after_move(file_renames); } } diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 978235b328..46eaf71a8a 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -202,6 +202,7 @@ private: void _try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const; void _update_dependencies_after_move(const Map<String, String> &p_renames) const; void _update_resource_paths_after_move(const Map<String, String> &p_renames) const; + void _save_scenes_after_move(const Map<String, String> &p_renames) const; void _update_favorites_list_after_move(const Map<String, String> &p_files_renames, const Map<String, String> &p_folders_renames) const; void _update_project_settings_after_move(const Map<String, String> &p_folders_renames) const; diff --git a/editor/icons/icon_multi_mesh_instance_2d.svg b/editor/icons/icon_multi_mesh_instance_2d.svg new file mode 100644 index 0000000000..07202ac659 --- /dev/null +++ b/editor/icons/icon_multi_mesh_instance_2d.svg @@ -0,0 +1,4 @@ +<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"> +<rect x="-1" y="-1" width="582" height="402" fill="none"/> +<path d="m3 1c-1.1046 0-2 0.89543-2 2 5.6e-4 0.71397 0.38169 1.3735 1 1.7305v6.541c-0.61771 0.35664-0.99874 1.0152-1 1.7285 0 1.1046 0.89543 2 2 2 0.71397-5.6e-4 1.3735-0.38169 1.7305-1h1.2695v-2h-1.2715c-0.17478-0.30301-0.42598-0.55488-0.72852-0.73047v-5.8555l3.5859 3.5859h1.4141v-1.4141l-3.5859-3.5859h5.8574c0.17532 0.30158 0.42647 0.55205 0.72852 0.72656v1.2734h2v-1.2695c0.61831-0.35698 0.99944-1.0165 1-1.7305 0-1.1046-0.89543-2-2-2-0.71397 5.6e-4 -1.3735 0.38169-1.7305 1h-6.541c-0.35664-0.61771-1.0152-0.99874-1.7285-1zm8 7v3h-3v2h3v3h2v-3h3v-2h-3v-3h-2z" fill="#a5b7f3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/> +</svg> diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 0dfb53b34a..a0774ac696 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -733,6 +733,7 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PoolByt image_data = cached_data; file->close(); + memdelete(file); } } @@ -807,6 +808,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons if (file) { file->store_line(new_etag); file->close(); + memdelete(file); } int len = p_data.size(); @@ -816,6 +818,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons file->store_32(len); file->store_buffer(r.ptr(), len); file->close(); + memdelete(file); } break; @@ -855,6 +858,7 @@ void EditorAssetLibrary::_update_image_queue() { if (file) { headers.push_back("If-None-Match: " + file->get_line()); file->close(); + memdelete(file); } } diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 4ef2d17128..3f513de30f 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -299,9 +299,13 @@ void TileMapEditor::_set_cell(const Point2i &p_pos, Vector<int> p_values, bool p Vector2 position; int current = manual_palette->get_current(); if (current != -1) { - position = manual_palette->get_item_metadata(current); + if (tool != TOOL_PASTING) { + position = manual_palette->get_item_metadata(current); + } else { + position = p_autotile_coord; + } } else { - // if there is no manual tile selected, that either means that + // If there is no manual tile selected, that either means that // autotiling is enabled, or the given tile is not autotiling. Either // way, the coordinate of the tile does not matter, so assigning it to // the coordinate of the existing tile works fine. @@ -309,7 +313,7 @@ void TileMapEditor::_set_cell(const Point2i &p_pos, Vector<int> p_values, bool p } if (p_value == prev_val && p_flip_h == prev_flip_h && p_flip_v == prev_flip_v && p_transpose == prev_transpose && prev_position == position) - return; //check that it's actually different + return; // Check that it's actually different. for (int y = p_pos.y - 1; y <= p_pos.y + 1; y++) { for (int x = p_pos.x - 1; x <= p_pos.x + 1; x++) { @@ -322,21 +326,19 @@ void TileMapEditor::_set_cell(const Point2i &p_pos, Vector<int> p_values, bool p node->_set_celld(p_pos, _create_cell_dictionary(p_value, p_flip_h, p_flip_v, p_transpose, p_autotile_coord)); + if (tool == TOOL_PASTING) + return; + if (manual_autotile || (p_value != -1 && node->get_tileset()->tile_get_tile_mode(p_value) == TileSet::ATLAS_TILE)) { if (current != -1) { node->set_cell_autotile_coord(p_pos.x, p_pos.y, position); - - } else if (tool != TOOL_PASTING && node->get_tileset()->tile_get_tile_mode(p_value) == TileSet::ATLAS_TILE && priority_atlastile) { - - // BIND_CENTER is used to indicate that bitmask should not update for this tile cell + } else if (node->get_tileset()->tile_get_tile_mode(p_value) == TileSet::ATLAS_TILE && priority_atlastile) { + // BIND_CENTER is used to indicate that bitmask should not update for this tile cell. node->get_tileset()->autotile_set_bitmask(p_value, Vector2(p_pos.x, p_pos.y), TileSet::BIND_CENTER); node->update_cell_bitmask(p_pos.x, p_pos.y); } } else { - // manually placing tiles should not update bitmasks - if (tool != TOOL_PASTING) { - node->update_bitmask_area(Point2(p_pos)); - } + node->update_bitmask_area(Point2(p_pos)); } } @@ -396,6 +398,8 @@ void TileMapEditor::_update_palette() { // Update the palette Vector<int> selected = get_selected_tiles(); + int selected_single = palette->get_current(); + int selected_manual = manual_palette->get_current(); palette->clear(); manual_palette->clear(); manual_palette->hide(); @@ -503,7 +507,7 @@ void TileMapEditor::_update_palette() { if (selected.get(0) != TileMap::INVALID_CELL) { set_selected_tiles(selected); sel_tile = selected.get(Math::rand() % selected.size()); - } else { + } else if (palette->get_item_count() > 0) { palette->select(0); } @@ -545,9 +549,10 @@ void TileMapEditor::_update_palette() { if (manual_palette->get_item_count() > 0) { // Only show the manual palette if at least tile exists in it - int selected2 = manual_palette->get_current(); - if (selected2 == -1) selected2 = 0; - manual_palette->set_current(selected2); + if (selected_manual == -1 || selected_single != palette->get_current()) + selected_manual = 0; + if (selected_manual < manual_palette->get_item_count()) + manual_palette->set_current(selected_manual); manual_palette->show(); } @@ -759,15 +764,15 @@ void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p Rect2 r = node->get_tileset()->tile_get_region(p_cell); if (node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::AUTO_TILE || node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::ATLAS_TILE) { Vector2 offset; - int selected = manual_palette->get_current(); - if ((manual_autotile || (node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::ATLAS_TILE && !priority_atlastile)) && selected != -1) { - offset = manual_palette->get_item_metadata(selected); - } else { - if (tool != TOOL_PASTING) { - offset = node->get_tileset()->autotile_get_icon_coordinate(p_cell); + if (tool != TOOL_PASTING) { + int selected = manual_palette->get_current(); + if ((manual_autotile || (node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::ATLAS_TILE && !priority_atlastile)) && selected != -1) { + offset = manual_palette->get_item_metadata(selected); } else { - offset = p_autotile_coord; + offset = node->get_tileset()->autotile_get_icon_coordinate(p_cell); } + } else { + offset = p_autotile_coord; } int spacing = node->get_tileset()->autotile_get_spacing(p_cell); @@ -810,10 +815,11 @@ void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p Color modulate = node->get_tileset()->tile_get_modulate(p_cell); modulate.a = 0.5; - if (r.has_no_area()) + if (r.has_no_area()) { p_viewport->draw_texture_rect(t, rect, false, modulate, p_transpose); - else + } else { p_viewport->draw_texture_rect_region(t, rect, r, modulate, p_transpose); + } } void TileMapEditor::_draw_fill_preview(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Point2i p_autotile_coord, const Transform2D &p_xform) { @@ -848,7 +854,6 @@ void TileMapEditor::_update_copydata() { TileData tcd; tcd.cell = node->get_cell(j, i); - if (tcd.cell != TileMap::INVALID_CELL) { tcd.pos = Point2i(j, i); tcd.flip_h = node->is_cell_x_flipped(j, i); @@ -1980,31 +1985,31 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { p->connect("id_pressed", this, "_menu_option"); rotate_left_button = memnew(ToolButton); - rotate_left_button->set_tooltip(TTR("Rotate left")); + rotate_left_button->set_tooltip(TTR("Rotate Left")); rotate_left_button->set_focus_mode(FOCUS_NONE); rotate_left_button->connect("pressed", this, "_rotate", varray(-1)); tool_hb->add_child(rotate_left_button); rotate_right_button = memnew(ToolButton); - rotate_right_button->set_tooltip(TTR("Rotate right")); + rotate_right_button->set_tooltip(TTR("Rotate Right")); rotate_right_button->set_focus_mode(FOCUS_NONE); rotate_right_button->connect("pressed", this, "_rotate", varray(1)); tool_hb->add_child(rotate_right_button); flip_horizontal_button = memnew(ToolButton); - flip_horizontal_button->set_tooltip(TTR("Flip horizontally")); + flip_horizontal_button->set_tooltip(TTR("Flip Horizontally")); flip_horizontal_button->set_focus_mode(FOCUS_NONE); flip_horizontal_button->connect("pressed", this, "_flip_horizontal"); tool_hb->add_child(flip_horizontal_button); flip_vertical_button = memnew(ToolButton); - flip_vertical_button->set_tooltip(TTR("Flip vertically")); + flip_vertical_button->set_tooltip(TTR("Flip Vertically")); flip_vertical_button->set_focus_mode(FOCUS_NONE); flip_vertical_button->connect("pressed", this, "_flip_vertical"); tool_hb->add_child(flip_vertical_button); clear_transform_button = memnew(ToolButton); - clear_transform_button->set_tooltip(TTR("Clear transform")); + clear_transform_button->set_tooltip(TTR("Clear Transform")); clear_transform_button->set_focus_mode(FOCUS_NONE); clear_transform_button->connect("pressed", this, "_clear_transform"); tool_hb->add_child(clear_transform_button); diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index 621ab039f4..c3b62810f1 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -1025,7 +1025,9 @@ void ScriptEditorDebugger::_performance_draw() { int pi = which[i]; Color c = get_color("accent_color", "Editor"); float h = (float)which[i] / (float)(perf_items.size()); - c.set_hsv(Math::fmod(h + 0.4, 0.9), c.get_s() * 0.9, c.get_v() * 1.4); + // Use a darker color on light backgrounds for better visibility + float value_multiplier = EditorSettings::get_singleton()->is_dark_theme() ? 1.4 : 0.55; + c.set_hsv(Math::fmod(h + 0.4, 0.9), c.get_s() * 0.9, c.get_v() * value_multiplier); c.a = 0.6; perf_draw->draw_string(graph_font, r.position + Point2(0, graph_font->get_ascent()), perf_items[pi]->get_text(0), c, r.size.x); @@ -1045,9 +1047,8 @@ void ScriptEditorDebugger::_performance_draw() { float h2 = E->get()[pi] / m; h2 = (1.0 - h2) * r.size.y; - c.a = 0.7; if (E != perf_history.front()) - perf_draw->draw_line(r.position + Point2(from, h2), r.position + Point2(from + spacing, prev), c, 2.0); + perf_draw->draw_line(r.position + Point2(from, h2), r.position + Point2(from + spacing, prev), c, Math::round(EDSCALE), true); prev = h2; E = E->next(); from -= spacing; diff --git a/modules/mono/SCsub b/modules/mono/SCsub index 341d57f3e4..6c3ecee272 100644 --- a/modules/mono/SCsub +++ b/modules/mono/SCsub @@ -20,11 +20,6 @@ if env['tools']: 'glue/cs_glue_version.gen.h' ) -vars = Variables() -vars.Add(BoolVariable('mono_glue', 'Build with the mono glue sources', True)) -vars.Add(BoolVariable('xbuild_fallback', 'If MSBuild is not found, fallback to xbuild', False)) -vars.Update(env_mono) - # Glue sources if env_mono['mono_glue']: env_mono.Append(CPPDEFINES=['MONO_GLUE_ENABLED']) diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py index 2bce3ed376..c549640d61 100644 --- a/modules/mono/build_scripts/mono_configure.py +++ b/modules/mono/build_scripts/mono_configure.py @@ -47,14 +47,6 @@ def copy_file(src_dir, dst_dir, name): def configure(env, env_mono): - from SCons.Script import BoolVariable, PathVariable, Variables - - envvars = Variables() - envvars.Add(PathVariable('mono_prefix', 'Path to the mono installation directory for the target platform and architecture', '', PathVariable.PathAccept)) - envvars.Add(BoolVariable('mono_static', 'Statically link mono', False)) - envvars.Add(BoolVariable('copy_mono_root', 'Make a copy of the mono installation directory to bundle with the editor', False)) - envvars.Update(env) - bits = env['bits'] is_android = env['platform'] == 'android' diff --git a/modules/mono/build_scripts/patches/fix-mono-android-pthread_mutexattr_setprotocol.diff b/modules/mono/build_scripts/patches/fix-mono-android-pthread_mutexattr_setprotocol.diff deleted file mode 100644 index 21cb1a0cf8..0000000000 --- a/modules/mono/build_scripts/patches/fix-mono-android-pthread_mutexattr_setprotocol.diff +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/mono/utils/mono-os-mutex.h b/mono/utils/mono-os-mutex.h -index e8039bf4094..ee39c0330b3 100644 ---- a/mono/utils/mono-os-mutex.h -+++ b/mono/utils/mono-os-mutex.h -@@ -57,7 +57,7 @@ mono_os_mutex_init_type (mono_mutex_t *mutex, int type) - if (G_UNLIKELY (res != 0)) - g_error ("%s: pthread_mutexattr_settype failed with \"%s\" (%d)", __func__, g_strerror (res), res); - --#ifdef PTHREAD_PRIO_INHERIT -+#if defined(PTHREAD_PRIO_INHERIT) && __ANDROID_API__ >= 28 - /* use PTHREAD_PRIO_INHERIT if possible */ - res = pthread_mutexattr_setprotocol (&attr, PTHREAD_PRIO_INHERIT); - if (G_UNLIKELY (res != 0 && res != ENOTSUP)) diff --git a/modules/mono/config.py b/modules/mono/config.py index 3b2e96765e..9adf4ee6e5 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -8,6 +8,16 @@ def configure(env): env.use_ptrcall = True env.add_module_version_string('mono') + from SCons.Script import BoolVariable, PathVariable, Variables + + envvars = Variables() + envvars.Add(PathVariable('mono_prefix', 'Path to the mono installation directory for the target platform and architecture', '', PathVariable.PathAccept)) + envvars.Add(BoolVariable('mono_static', 'Statically link mono', False)) + envvars.Add(BoolVariable('mono_glue', 'Build with the mono glue sources', True)) + envvars.Add(BoolVariable('copy_mono_root', 'Make a copy of the mono installation directory to bundle with the editor', False)) + envvars.Add(BoolVariable('xbuild_fallback', 'If MSBuild is not found, fallback to xbuild', False)) + envvars.Update(env) + def get_doc_classes(): return [ diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index 212966af11..eed230ba89 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -60,6 +60,7 @@ public: unsigned int osx_state; bool pressed; bool echo; + bool raw; uint32_t scancode; uint32_t unicode; }; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 113c6636f0..567d24de3e 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -392,7 +392,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt @interface GodotContentView : NSView <NSTextInputClient> { NSTrackingArea *trackingArea; NSMutableAttributedString *markedText; - bool imeMode; + bool imeInputEventInProgress; } - (void)cancelComposition; - (BOOL)wantsUpdateLayer; @@ -418,7 +418,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt - (id)init { self = [super init]; trackingArea = nil; - imeMode = false; + imeInputEventInProgress = false; [self updateTrackingAreas]; [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]]; markedText = [[NSMutableAttributedString alloc] init]; @@ -452,7 +452,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; [markedText initWithString:aString]; } if (OS_OSX::singleton->im_active) { - imeMode = true; + imeInputEventInProgress = true; OS_OSX::singleton->im_text.parse_utf8([[markedText mutableString] UTF8String]); OS_OSX::singleton->im_selection = Point2(selectedRange.location, selectedRange.length); @@ -467,7 +467,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; } - (void)unmarkText { - imeMode = false; + imeInputEventInProgress = false; [[markedText mutableString] setString:@""]; if (OS_OSX::singleton->im_active) { OS_OSX::singleton->im_text = String(); @@ -540,6 +540,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; ke.osx_state = [event modifierFlags]; ke.pressed = true; ke.echo = false; + ke.raw = false; // IME input event ke.scancode = 0; ke.unicode = codepoint; @@ -1045,29 +1046,52 @@ static int remapKey(unsigned int key) { - (void)keyDown:(NSEvent *)event { - //disable raw input in IME mode - if (!imeMode) { - OS_OSX::KeyEvent ke; + // Ignore all input if IME input is in progress + if (!imeInputEventInProgress) { + NSString *characters = [event characters]; + NSUInteger length = [characters length]; - ke.osx_state = [event modifierFlags]; - ke.pressed = true; - ke.echo = [event isARepeat]; - ke.scancode = remapKey([event keyCode]); - ke.unicode = 0; + if (!OS_OSX::singleton->im_active && length > 0 && keycode_has_unicode(remapKey([event keyCode]))) { + // Fallback unicode character handler used if IME is not active + for (NSUInteger i = 0; i < length; i++) { + OS_OSX::KeyEvent ke; - push_to_key_event_buffer(ke); + ke.osx_state = [event modifierFlags]; + ke.pressed = true; + ke.echo = [event isARepeat]; + ke.scancode = remapKey([event keyCode]); + ke.raw = true; + ke.unicode = [characters characterAtIndex:i]; + + push_to_key_event_buffer(ke); + } + } else { + OS_OSX::KeyEvent ke; + + ke.osx_state = [event modifierFlags]; + ke.pressed = true; + ke.echo = [event isARepeat]; + ke.scancode = remapKey([event keyCode]); + ke.raw = false; + ke.unicode = 0; + + push_to_key_event_buffer(ke); + } } - if (OS_OSX::singleton->im_active == true) + // Pass events to IME handler + if (OS_OSX::singleton->im_active) [self interpretKeyEvents:[NSArray arrayWithObject:event]]; } - (void)flagsChanged:(NSEvent *)event { - if (!imeMode) { + // Ignore all input if IME input is in progress + if (!imeInputEventInProgress) { OS_OSX::KeyEvent ke; ke.echo = false; + ke.raw = true; int key = [event keyCode]; int mod = [event modifierFlags]; @@ -1114,17 +1138,37 @@ static int remapKey(unsigned int key) { - (void)keyUp:(NSEvent *)event { - if (!imeMode) { + // Ignore all input if IME input is in progress + if (!imeInputEventInProgress) { + NSString *characters = [event characters]; + NSUInteger length = [characters length]; - OS_OSX::KeyEvent ke; + // Fallback unicode character handler used if IME is not active + if (!OS_OSX::singleton->im_active && length > 0 && keycode_has_unicode(remapKey([event keyCode]))) { + for (NSUInteger i = 0; i < length; i++) { + OS_OSX::KeyEvent ke; - ke.osx_state = [event modifierFlags]; - ke.pressed = false; - ke.echo = false; - ke.scancode = remapKey([event keyCode]); - ke.unicode = 0; + ke.osx_state = [event modifierFlags]; + ke.pressed = false; + ke.echo = [event isARepeat]; + ke.scancode = remapKey([event keyCode]); + ke.raw = true; + ke.unicode = [characters characterAtIndex:i]; - push_to_key_event_buffer(ke); + push_to_key_event_buffer(ke); + } + } else { + OS_OSX::KeyEvent ke; + + ke.osx_state = [event modifierFlags]; + ke.pressed = false; + ke.echo = [event isARepeat]; + ke.scancode = remapKey([event keyCode]); + ke.raw = true; + ke.unicode = 0; + + push_to_key_event_buffer(ke); + } } } @@ -2612,30 +2656,44 @@ void OS_OSX::process_key_events() { const KeyEvent &ke = key_event_buffer[i]; - if ((i == 0 && ke.scancode == 0) || (i > 0 && key_event_buffer[i - 1].scancode == 0)) { + if (ke.raw) { + // Non IME input - no composite characters, pass events as is k.instance(); get_key_modifier_state(ke.osx_state, k); k->set_pressed(ke.pressed); k->set_echo(ke.echo); - k->set_scancode(0); + k->set_scancode(ke.scancode); k->set_unicode(ke.unicode); push_input(k); - } - if (ke.scancode != 0) { - k.instance(); + } else { + // IME input + if ((i == 0 && ke.scancode == 0) || (i > 0 && key_event_buffer[i - 1].scancode == 0)) { + k.instance(); - get_key_modifier_state(ke.osx_state, k); - k->set_pressed(ke.pressed); - k->set_echo(ke.echo); - k->set_scancode(ke.scancode); + get_key_modifier_state(ke.osx_state, k); + k->set_pressed(ke.pressed); + k->set_echo(ke.echo); + k->set_scancode(0); + k->set_unicode(ke.unicode); - if (i + 1 < key_event_pos && key_event_buffer[i + 1].scancode == 0) { - k->set_unicode(key_event_buffer[i + 1].unicode); + push_input(k); } + if (ke.scancode != 0) { + k.instance(); - push_input(k); + get_key_modifier_state(ke.osx_state, k); + k->set_pressed(ke.pressed); + k->set_echo(ke.echo); + k->set_scancode(ke.scancode); + + if (i + 1 < key_event_pos && key_event_buffer[i + 1].scancode == 0) { + k->set_unicode(key_event_buffer[i + 1].unicode); + } + + push_input(k); + } } } diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp index cdcad33f6d..ec43a4c26f 100644 --- a/platform/uwp/export/export.cpp +++ b/platform/uwp/export/export.cpp @@ -241,7 +241,6 @@ void AppxPackager::make_block_map() { tmp_file->close(); memdelete(tmp_file); - tmp_file = NULL; } String AppxPackager::content_type(String p_extension) { @@ -291,7 +290,6 @@ void AppxPackager::make_content_types() { tmp_file->close(); memdelete(tmp_file); - tmp_file = NULL; } Vector<uint8_t> AppxPackager::make_file_header(FileMeta p_file_meta) { @@ -606,7 +604,6 @@ void AppxPackager::finish() { blockmap_file->close(); memdelete(blockmap_file); - blockmap_file = NULL; // Add content types EditorNode::progress_task_step("export", "Setting content types...", 5); @@ -622,7 +619,6 @@ void AppxPackager::finish() { types_file->close(); memdelete(types_file); - types_file = NULL; // Pre-process central directory before signing for (int i = 0; i < file_metadata.size(); i++) { diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 311b42be22..494ae41220 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -1017,12 +1017,12 @@ void OS_X11::set_wm_fullscreen(bool p_enabled) { XFree(xsh); } - if (!p_enabled && !get_borderless_window()) { - // put decorations back if the window wasn't suppoesed to be borderless + if (!p_enabled) { + // put back or remove decorations according to the last set borderless state Hints hints; Atom property; hints.flags = 2; - hints.decorations = 1; + hints.decorations = current_videomode.borderless_window ? 0 : 1; property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5); } @@ -1531,7 +1531,7 @@ bool OS_X11::is_window_always_on_top() const { void OS_X11::set_borderless_window(bool p_borderless) { - if (current_videomode.borderless_window == p_borderless) + if (get_borderless_window() == p_borderless) return; if (!p_borderless && layered_window) @@ -1551,7 +1551,24 @@ void OS_X11::set_borderless_window(bool p_borderless) { } bool OS_X11::get_borderless_window() { - return current_videomode.borderless_window; + + bool borderless = current_videomode.borderless_window; + Atom prop = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); + if (prop != None) { + + Atom type; + int format; + unsigned long len; + unsigned long remaining; + unsigned char *data = NULL; + if (XGetWindowProperty(x11_display, x11_window, prop, 0, sizeof(Hints), False, AnyPropertyType, &type, &format, &len, &remaining, &data) == Success) { + if (data && (format == 32) && (len >= 5)) { + borderless = !((Hints *)data)->decorations; + } + XFree(data); + } + } + return borderless; } void OS_X11::request_attention() { diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index 25ad6bd5c9..075b0e6252 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -646,6 +646,7 @@ void AnimatedSprite::_reset_timeout() { void AnimatedSprite::set_animation(const StringName &p_animation) { ERR_EXPLAIN(vformat("There is no animation with name '%s'.", p_animation)); + ERR_FAIL_COND(frames == NULL) ERR_FAIL_COND(frames->get_animation_names().find(p_animation) == -1); if (animation == p_animation) diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp index ba06b3ebff..e116d404d6 100644 --- a/scene/2d/line_2d.cpp +++ b/scene/2d/line_2d.cpp @@ -105,6 +105,7 @@ void Line2D::set_point_position(int i, Vector2 pos) { } Vector2 Line2D::get_point_position(int i) const { + ERR_FAIL_INDEX_V(i, _points.size(), Vector2()) return _points.get(i); } diff --git a/scene/2d/multimesh_instance_2d.cpp b/scene/2d/multimesh_instance_2d.cpp new file mode 100644 index 0000000000..ca75302163 --- /dev/null +++ b/scene/2d/multimesh_instance_2d.cpp @@ -0,0 +1,111 @@ +/*************************************************************************/ +/* multimesh_instance_2d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 "multimesh_instance_2d.h" + +void MultiMeshInstance2D::_notification(int p_what) { + + if (p_what == NOTIFICATION_DRAW) { + if (multimesh.is_valid()) { + draw_multimesh(multimesh, texture, normal_map); + } + } +} + +void MultiMeshInstance2D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_multimesh", "multimesh"), &MultiMeshInstance2D::set_multimesh); + ClassDB::bind_method(D_METHOD("get_multimesh"), &MultiMeshInstance2D::get_multimesh); + + ClassDB::bind_method(D_METHOD("set_texture", "texture"), &MultiMeshInstance2D::set_texture); + ClassDB::bind_method(D_METHOD("get_texture"), &MultiMeshInstance2D::get_texture); + + ClassDB::bind_method(D_METHOD("set_normal_map", "normal_map"), &MultiMeshInstance2D::set_normal_map); + ClassDB::bind_method(D_METHOD("get_normal_map"), &MultiMeshInstance2D::get_normal_map); + + ADD_SIGNAL(MethodInfo("texture_changed")); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multimesh", PROPERTY_HINT_RESOURCE_TYPE, "MultiMesh"), "set_multimesh", "get_multimesh"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_normal_map", "get_normal_map"); +} + +void MultiMeshInstance2D::set_multimesh(const Ref<MultiMesh> &p_multimesh) { + + multimesh = p_multimesh; + update(); +} + +Ref<MultiMesh> MultiMeshInstance2D::get_multimesh() const { + + return multimesh; +} + +void MultiMeshInstance2D::set_texture(const Ref<Texture> &p_texture) { + + if (p_texture == texture) + return; + texture = p_texture; + update(); + emit_signal("texture_changed"); + _change_notify("texture"); +} + +Ref<Texture> MultiMeshInstance2D::get_texture() const { + + return texture; +} + +void MultiMeshInstance2D::set_normal_map(const Ref<Texture> &p_texture) { + + normal_map = p_texture; + update(); +} + +Ref<Texture> MultiMeshInstance2D::get_normal_map() const { + + return normal_map; +} + +Rect2 MultiMeshInstance2D::_edit_get_rect() const { + + if (multimesh.is_valid()) { + AABB aabb = multimesh->get_aabb(); + return Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); + } + + return Node2D::_edit_get_rect(); +} + +MultiMeshInstance2D::MultiMeshInstance2D() { +} + +MultiMeshInstance2D::~MultiMeshInstance2D() { +} diff --git a/scene/2d/multimesh_instance_2d.h b/scene/2d/multimesh_instance_2d.h new file mode 100644 index 0000000000..3795497183 --- /dev/null +++ b/scene/2d/multimesh_instance_2d.h @@ -0,0 +1,65 @@ +/*************************************************************************/ +/* multimesh_instance_2d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 MULTIMESH_INSTANCE_2D_H +#define MULTIMESH_INSTANCE_2D_H + +#include "scene/2d/node_2d.h" +#include "scene/resources/multimesh.h" + +class MultiMeshInstance2D : public Node2D { + GDCLASS(MultiMeshInstance2D, Node2D); + + Ref<MultiMesh> multimesh; + + Ref<Texture> texture; + Ref<Texture> normal_map; + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_multimesh(const Ref<MultiMesh> &p_multimesh); + Ref<MultiMesh> get_multimesh() const; + + void set_texture(const Ref<Texture> &p_texture); + Ref<Texture> get_texture() const; + + void set_normal_map(const Ref<Texture> &p_texture); + Ref<Texture> get_normal_map() const; + + virtual Rect2 _edit_get_rect() const; + + MultiMeshInstance2D(); + ~MultiMeshInstance2D(); +}; + +#endif // MULTIMESH_INSTANCE_2D_H diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index e8692d56d2..6463ee5ad5 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -159,9 +159,7 @@ void GraphNode::_resort() { fit_child_in_rect(c, r); cache_y.push_back(vofs + size.y * 0.5); - if (vofs > 0) - vofs += sep; - vofs += size.y; + vofs += size.y + sep; } update(); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index cc966efee9..58bdde1ffd 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -44,7 +44,7 @@ static bool _is_text_char(CharType c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'; + return !is_symbol(c); } void LineEdit::_gui_input(Ref<InputEvent> p_event) { diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 3117d8c59f..6203b15992 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -50,7 +50,7 @@ inline bool _is_symbol(CharType c) { static bool _is_text_char(CharType c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'; + return !is_symbol(c); } static bool _is_whitespace(CharType c) { diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 474eb51860..2007ae2669 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -3532,14 +3532,14 @@ TreeItem *Tree::_search_item_text(TreeItem *p_at, const String &p_find, int *r_c TreeItem *Tree::search_item_text(const String &p_find, int *r_col, bool p_selectable) { - TreeItem *from = get_selected()->get_next_visible(); + TreeItem *from = get_selected(); - if (!root) + if (!from) from = root; if (!from) return NULL; - return _search_item_text(from, p_find, r_col, p_selectable); + return _search_item_text(from->get_next_visible(true), p_find, r_col, p_selectable); } void Tree::_do_incr_search(const String &p_add) { diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 8e6e8e2a53..5e4cf9c2ee 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -48,6 +48,7 @@ #include "scene/2d/light_occluder_2d.h" #include "scene/2d/line_2d.h" #include "scene/2d/mesh_instance_2d.h" +#include "scene/2d/multimesh_instance_2d.h" #include "scene/2d/navigation_2d.h" #include "scene/2d/parallax_background.h" #include "scene/2d/parallax_layer.h" @@ -543,6 +544,7 @@ void register_scene_types() { ClassDB::register_class<Position2D>(); ClassDB::register_class<Line2D>(); ClassDB::register_class<MeshInstance2D>(); + ClassDB::register_class<MultiMeshInstance2D>(); ClassDB::register_virtual_class<CollisionObject2D>(); ClassDB::register_virtual_class<PhysicsBody2D>(); ClassDB::register_class<StaticBody2D>(); @@ -587,9 +589,13 @@ void register_scene_types() { SceneTree::add_idle_callback(ParticlesMaterial::flush_changes); ParticlesMaterial::init_shaders(); -#ifndef _3D_DISABLED ClassDB::register_virtual_class<Mesh>(); ClassDB::register_class<ArrayMesh>(); + ClassDB::register_class<MultiMesh>(); + ClassDB::register_class<SurfaceTool>(); + ClassDB::register_class<MeshDataTool>(); + +#ifndef _3D_DISABLED ClassDB::register_virtual_class<PrimitiveMesh>(); ClassDB::register_class<CapsuleMesh>(); ClassDB::register_class<CubeMesh>(); @@ -603,7 +609,6 @@ void register_scene_types() { SceneTree::add_idle_callback(SpatialMaterial::flush_changes); SpatialMaterial::init_shaders(); - ClassDB::register_class<MultiMesh>(); ClassDB::register_class<MeshLibrary>(); OS::get_singleton()->yield(); //may take time to init @@ -619,9 +624,6 @@ void register_scene_types() { ClassDB::register_class<ConvexPolygonShape>(); ClassDB::register_class<ConcavePolygonShape>(); - ClassDB::register_class<SurfaceTool>(); - ClassDB::register_class<MeshDataTool>(); - OS::get_singleton()->yield(); //may take time to init ClassDB::register_class<SpatialVelocityTracker>(); diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index bdb6c78782..e8359e3dfe 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -582,14 +582,14 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // GraphNode - Ref<StyleBoxTexture> graphsb = make_stylebox(graph_node_png, 6, 24, 6, 5, 16, 24, 16, 5); - Ref<StyleBoxTexture> graphsbcomment = make_stylebox(graph_node_comment_png, 6, 24, 6, 5, 16, 24, 16, 5); - Ref<StyleBoxTexture> graphsbcommentselected = make_stylebox(graph_node_comment_focus_png, 6, 24, 6, 5, 16, 24, 16, 5); - Ref<StyleBoxTexture> graphsbselected = make_stylebox(graph_node_selected_png, 6, 24, 6, 5, 16, 24, 16, 5); + 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, 5); - Ref<StyleBoxTexture> graph_position = make_stylebox(graph_node_position_png, 6, 24, 6, 5, 16, 24, 16, 5); + 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(MARGIN_LEFT,10); //graphsb->set_expand_margin_size(MARGIN_RIGHT,10); |