From a6b75da78c4bfdceddfac100adfc1f5d6ff86400 Mon Sep 17 00:00:00 2001 From: smix8 <52464204+smix8@users.noreply.github.com> Date: Sat, 6 Aug 2022 21:39:38 +0200 Subject: [PATCH 01/16] Fix TileMap error msg when optional navigation node is not set Fixes TileMap error msg spam when bake_navigation=true but the optional and depr navigation node is not set. (cherry picked from commit 30d4555c6572746e5fc7aecc5272aa8ff0d47d55) --- scene/2d/tile_map.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 4113ab68243..8b7f1dc6801 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -157,7 +157,11 @@ void TileMap::_update_quadrant_transform() { Transform2D nav_rel; if (bake_navigation) { - nav_rel = get_relative_transform_to_parent(navigation); + if (navigation) { + nav_rel = get_relative_transform_to_parent(navigation); + } else { + nav_rel = get_transform(); + } } for (Map::Element *E = quadrant_map.front(); E; E = E->next()) { @@ -339,7 +343,11 @@ void TileMap::update_dirty_quadrants() { Vector2 tofs = get_cell_draw_offset(); Transform2D nav_rel; if (bake_navigation) { - nav_rel = get_relative_transform_to_parent(navigation); + if (navigation) { + nav_rel = get_relative_transform_to_parent(navigation); + } else { + nav_rel = get_transform(); + } } Vector2 qofs; From 2ed3818277fd7e966ce82df8cdff765a36bc2844 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Fri, 5 Aug 2022 09:54:46 +0200 Subject: [PATCH 02/16] Improve `range_lerp()` and related methods documentation (cherry picked from commit bd19c9a95cacb3a5ff3ed0f14e3290313c78f9a0) --- doc/classes/Curve.xml | 1 + doc/classes/Gradient.xml | 3 ++- modules/gdscript/doc_classes/@GDScript.xml | 11 ++++++----- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/doc/classes/Curve.xml b/doc/classes/Curve.xml index 3d94f8a8c1d..bfe2756cece 100644 --- a/doc/classes/Curve.xml +++ b/doc/classes/Curve.xml @@ -5,6 +5,7 @@ A curve that can be saved and re-used for other objects. By default, it ranges between [code]0[/code] and [code]1[/code] on the Y axis and positions points relative to the [code]0.5[/code] Y position. + See also [Gradient] which is designed for color interpolation. See also [Curve2D] and [Curve3D]. diff --git a/doc/classes/Gradient.xml b/doc/classes/Gradient.xml index 7cdffd14d3b..d7439f962f3 100644 --- a/doc/classes/Gradient.xml +++ b/doc/classes/Gradient.xml @@ -4,7 +4,8 @@ A color interpolator resource which can be used to generate colors between user-defined color points. - Given a set of colors, this resource will interpolate them in order. This means that if you have color 1, color 2 and color 3, the ramp will interpolate from color 1 to color 2 and from color 2 to color 3. The ramp will initially have 2 colors (black and white), one (black) at ramp lower offset 0 and the other (white) at the ramp higher offset 1. + Given a set of colors, this resource will interpolate them in order. This means that if you have color 1, color 2 and color 3, the gradient will interpolate from color 1 to color 2 and from color 2 to color 3. The gradient will initially have 2 colors (black and white), one (black) at gradient lower offset 0 and the other (white) at the gradient higher offset 1. + See also [Curve] which supports more complex easing methods, but does not support colors. diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index 4aef4baa4a4..c706c9bac78 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -425,7 +425,7 @@ - Returns an interpolation or extrapolation factor considering the range specified in [code]from[/code] and [code]to[/code], and the interpolated value specified in [code]weight[/code]. The returned value will be between [code]0.0[/code] and [code]1.0[/code] if [code]weight[/code] is between [code]from[/code] and [code]to[/code] (inclusive). If [code]weight[/code] is located outside this range, then an extrapolation factor will be returned (return value lower than [code]0.0[/code] or greater than [code]1.0[/code]). + Returns an interpolation or extrapolation factor considering the range specified in [code]from[/code] and [code]to[/code], and the interpolated value specified in [code]weight[/code]. The returned value will be between [code]0.0[/code] and [code]1.0[/code] if [code]weight[/code] is between [code]from[/code] and [code]to[/code] (inclusive). If [code]weight[/code] is located outside this range, then an extrapolation factor will be returned (return value lower than [code]0.0[/code] or greater than [code]1.0[/code]). Use [method clamp] on the result of [method inverse_lerp] if this is not desired. [codeblock] # The interpolation ratio in the `lerp()` call below is 0.75. var middle = lerp(20, 30, 0.75) @@ -434,7 +434,7 @@ var ratio = inverse_lerp(20, 30, 27.5) # `ratio` is now 0.75. [/codeblock] - See also [method lerp] which performs the reverse of this operation. + See also [method lerp] which performs the reverse of this operation, and [method range_lerp] to map a continuous series of values to another. @@ -494,14 +494,14 @@ - Linearly interpolates between two values by the factor defined in [code]weight[/code]. To perform interpolation, [code]weight[/code] should be between [code]0.0[/code] and [code]1.0[/code] (inclusive). However, values outside this range are allowed and can be used to perform [i]extrapolation[/i]. + Linearly interpolates between two values by the factor defined in [code]weight[/code]. To perform interpolation, [code]weight[/code] should be between [code]0.0[/code] and [code]1.0[/code] (inclusive). However, values outside this range are allowed and can be used to perform [i]extrapolation[/i]. Use [method clamp] on the result of [method lerp] if this is not desired. If the [code]from[/code] and [code]to[/code] arguments are of type [int] or [float], the return value is a [float]. If both are of the same vector type ([Vector2], [Vector3] or [Color]), the return value will be of the same type ([code]lerp[/code] then calls the vector type's [code]linear_interpolate[/code] method). [codeblock] lerp(0, 4, 0.75) # Returns 3.0 lerp(Vector2(1, 5), Vector2(3, 2), 0.5) # Returns Vector2(2, 3.5) [/codeblock] - See also [method inverse_lerp] which performs the reverse of this operation. To perform eased interpolation with [method lerp], combine it with [method ease] or [method smoothstep]. + See also [method inverse_lerp] which performs the reverse of this operation. To perform eased interpolation with [method lerp], combine it with [method ease] or [method smoothstep]. See also [method range_lerp] to map a continuous series of values to another. @@ -892,10 +892,11 @@ - Maps a [code]value[/code] from range [code][istart, istop][/code] to [code][ostart, ostop][/code]. + Maps a [code]value[/code] from range [code][istart, istop][/code] to [code][ostart, ostop][/code]. See also [method lerp] and [method inverse_lerp]. If [code]value[/code] is outside [code][istart, istop][/code], then the resulting value will also be outside [code][ostart, ostop][/code]. Use [method clamp] on the result of [method range_lerp] if this is not desired. [codeblock] range_lerp(75, 0, 100, -1, 1) # Returns 0.5 [/codeblock] + For complex use cases where you need multiple ranges, consider using [Curve] or [Gradient] instead. From 3b3721262c63feabc1d4e340770826f3c3d9cfe2 Mon Sep 17 00:00:00 2001 From: Tom Date: Fri, 5 Aug 2022 22:16:43 +0100 Subject: [PATCH 03/16] updated the String class with info about the 'allow_empty' optional argument (cherry picked from commit 39233c299c63295bc476bd51c1a07c13cb577aae) --- doc/classes/String.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/classes/String.xml b/doc/classes/String.xml index 1097b3090c2..bee606fd131 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -696,6 +696,7 @@ Splits the string by a [code]delimiter[/code] string and returns an array of the substrings, starting from right. The splits in the returned array are sorted in the same order as the original string, from left to right. + If [code]allow_empty[/code] is [code]true[/code], and there are two adjacent delimiters in the string, it will add an empty string to the array of substrings at this position. If [code]maxsplit[/code] is specified, it defines the number of splits to do from the right up to [code]maxsplit[/code]. The default value of 0 means that all items are split, thus giving the same result as [method split]. Example: [codeblock] @@ -765,6 +766,7 @@ Splits the string by a [code]delimiter[/code] string and returns an array of the substrings. The [code]delimiter[/code] can be of any length. + If [code]allow_empty[/code] is [code]true[/code], and there are two adjacent delimiters in the string, it will add an empty string to the array of substrings at this position. If [code]maxsplit[/code] is specified, it defines the number of splits to do from the left up to [code]maxsplit[/code]. The default value of [code]0[/code] means that all items are split. If you need only one element from the array at a specific index, [method get_slice] is a more performant option. Example: @@ -785,6 +787,7 @@ Splits the string in floats by using a delimiter string and returns an array of the substrings. For example, [code]"1,2.5,3"[/code] will return [code][1,2.5,3][/code] if split by [code]","[/code]. + If [code]allow_empty[/code] is [code]true[/code], and there are two adjacent delimiters in the string, it will add an empty string to the array of substrings at this position. From aa26828f76189b7b9072d730149f1ee9bd3c1797 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Sun, 7 Aug 2022 07:21:29 +0200 Subject: [PATCH 04/16] Fix broken rST reference in HTTPClient documentation References in reStructuredText cannot be located within bold/italic text. This caused the online class reference to have the `:ref:` text written as-is. (cherry picked from commit 970920511214032956a2f60b2f5007ccf6dee4f3) --- doc/classes/HTTPClient.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/classes/HTTPClient.xml b/doc/classes/HTTPClient.xml index 08c564aadfa..f6245e77f86 100644 --- a/doc/classes/HTTPClient.xml +++ b/doc/classes/HTTPClient.xml @@ -4,7 +4,8 @@ Low-level hyper-text transfer protocol client. - Hyper-text transfer protocol client (sometimes called "User Agent"). Used to make HTTP requests to download web content, upload files and other data or to communicate with various services, among other use cases. [b]See the [HTTPRequest] node for a higher-level alternative.[/b] + Hyper-text transfer protocol client (sometimes called "User Agent"). Used to make HTTP requests to download web content, upload files and other data or to communicate with various services, among other use cases. + See the [HTTPRequest] node for a higher-level alternative. [b]Note:[/b] This client only needs to connect to a host once (see [method connect_to_host]) to send multiple requests. Because of this, methods that take URLs usually take just the part after the host instead of the full URL, as the client is already connected to a host. See [method request] for a full example and to get started. A [HTTPClient] should be reused between multiple requests or to connect to different hosts instead of creating one client per request. Supports SSL and SSL server certificate verification. HTTP status codes in the 2xx range indicate success, 3xx redirection (i.e. "try again, but over here"), 4xx something was wrong with the request, and 5xx something went wrong on the server's side. For more information on HTTP, see https://developer.mozilla.org/en-US/docs/Web/HTTP (or read RFC 2616 to get it straight from the source: https://tools.ietf.org/html/rfc2616). From 1a023e6b1b3147c66616df8e8a28e9b29bf95246 Mon Sep 17 00:00:00 2001 From: kleonc <9283098+kleonc@users.noreply.github.com> Date: Sun, 7 Aug 2022 02:47:02 +0200 Subject: [PATCH 05/16] `FileSystemDock` Fix crash when renaming a file in split mode (cherry picked from commit 25ce459fc5e324227b8ef3b776c8c7e95a3c71a9) --- editor/filesystem_dock.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index b0afd3fca3b..ef62f81db8b 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -1450,14 +1450,13 @@ void FileSystemDock::_folder_removed(String p_folder) { void FileSystemDock::_rename_operation_confirm() { String new_name = rename_dialog_text->get_text().strip_edges(); - String old_name = tree->get_selected()->get_text(0); if (new_name.length() == 0) { EditorNode::get_singleton()->show_warning(TTR("No name provided.")); return; } else if (new_name.find("/") != -1 || new_name.find("\\") != -1 || new_name.find(":") != -1) { EditorNode::get_singleton()->show_warning(TTR("Name contains invalid characters.")); return; - } else if (to_rename.is_file && old_name.get_extension() != new_name.get_extension()) { + } else if (to_rename.is_file && to_rename.path.get_extension() != new_name.get_extension()) { if (!EditorFileSystem::get_singleton()->get_valid_extensions().find(new_name.get_extension())) { EditorNode::get_singleton()->show_warning(TTR("This file extension is not recognized by the editor.\nIf you want to rename it anyway, use your operating system's file manager.\nAfter renaming to an unknown extension, the file won't be shown in the editor anymore.")); return; From b2ba3bab5264b65066f6aa60d833a39606a2f58d Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Tue, 5 Oct 2021 15:04:10 +0200 Subject: [PATCH 06/16] [File] Fix FileAccessCompressed::get_buffer return value. It used to return the write index instead of the written bytes (i.e. index + 1) when reading until last block. (cherry picked from commit e8f7b79bb00870a6c6b64f81f9a6d7ecea50d823) --- core/io/file_access_compressed.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp index a632ff28f31..f3239335e1c 100644 --- a/core/io/file_access_compressed.cpp +++ b/core/io/file_access_compressed.cpp @@ -315,10 +315,10 @@ uint64_t FileAccessCompressed::get_buffer(uint8_t *p_dst, uint64_t p_length) con } else { read_block--; at_end = true; - if (i < p_length - 1) { + if (i + 1 < p_length) { read_eof = true; } - return i; + return i + 1; } } } From 61e28c28cdac2a58f475e0c3876b2a268116ff14 Mon Sep 17 00:00:00 2001 From: Josh Jones Date: Sun, 7 Aug 2022 10:40:33 -0700 Subject: [PATCH 07/16] Fix typo when setting NavigationRegion travel_cost (cherry picked from commit 8c324132d03d86d2bc243e780db14496b8f10c34) --- scene/2d/navigation_polygon.cpp | 2 +- scene/3d/navigation_mesh_instance.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp index 33bf691b8c7..66b5a28d1a2 100644 --- a/scene/2d/navigation_polygon.cpp +++ b/scene/2d/navigation_polygon.cpp @@ -412,7 +412,7 @@ real_t NavigationPolygonInstance::get_enter_cost() const { void NavigationPolygonInstance::set_travel_cost(real_t p_travel_cost) { ERR_FAIL_COND_MSG(p_travel_cost < 0.0, "The travel_cost must be positive."); travel_cost = MAX(p_travel_cost, 0.0); - Navigation2DServer::get_singleton()->region_set_enter_cost(region, travel_cost); + Navigation2DServer::get_singleton()->region_set_travel_cost(region, travel_cost); } real_t NavigationPolygonInstance::get_travel_cost() const { diff --git a/scene/3d/navigation_mesh_instance.cpp b/scene/3d/navigation_mesh_instance.cpp index 29700273336..f26aace1843 100644 --- a/scene/3d/navigation_mesh_instance.cpp +++ b/scene/3d/navigation_mesh_instance.cpp @@ -94,7 +94,7 @@ real_t NavigationMeshInstance::get_enter_cost() const { void NavigationMeshInstance::set_travel_cost(real_t p_travel_cost) { ERR_FAIL_COND_MSG(p_travel_cost < 0.0, "The travel_cost must be positive."); travel_cost = MAX(p_travel_cost, 0.0); - NavigationServer::get_singleton()->region_set_enter_cost(region, travel_cost); + NavigationServer::get_singleton()->region_set_travel_cost(region, travel_cost); } real_t NavigationMeshInstance::get_travel_cost() const { From bc8293a125e66e0ee1e81d715e13f8da6f3d28d7 Mon Sep 17 00:00:00 2001 From: Raul Santos Date: Mon, 8 Aug 2022 01:41:30 +0200 Subject: [PATCH 08/16] Avoid paths with invalid characters in `IsRider` (cherry picked from commit 34c3966510a1ee204bc9e1579de6d1b43ea51076) --- .../GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs index ac29efb716e..7ff1afdfbf6 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs @@ -66,6 +66,9 @@ namespace GodotTools.Ides.Rider if (string.IsNullOrEmpty(path)) return false; + if (path.IndexOfAny(System.IO.Path.GetInvalidPathChars()) != -1) + return false; + var fileInfo = new FileInfo(path); string filename = fileInfo.Name.ToLowerInvariant(); return filename.StartsWith("rider", StringComparison.Ordinal); From 1f1bed15ba87c6c313a565fac09c695b3a2893ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Grzegorz=20Pu=C5=82awski?= <31245410+pulawskig@users.noreply.github.com> Date: Sun, 7 Aug 2022 15:10:28 +0200 Subject: [PATCH 09/16] Fix axis snapping of CollisionPolygon2d's newly created vertex (cherry picked from commit ba58491ca724bd660257bf4c5a3d76d70a15ad3e) --- editor/plugins/abstract_polygon_2d_editor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 16539e7450d..ae28ec0baec 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -319,9 +319,9 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref &p_event) return true; } else { Vector vertices2 = _get_polygon(insert.polygon); - pre_move_edit = vertices2; edited_point = PosVertex(insert.polygon, insert.vertex + 1, xform.affine_inverse().xform(insert.pos)); vertices2.insert(edited_point.vertex, edited_point.pos); + pre_move_edit = vertices2; selected_point = edited_point; edge_point = PosVertex(); From b00758fe182c76a7dae03096470295ff1f907e62 Mon Sep 17 00:00:00 2001 From: Cristiano Simao <40866219+CristianoSimao@users.noreply.github.com> Date: Thu, 4 Aug 2022 17:43:32 -0300 Subject: [PATCH 10/16] doc: Clarify `MultiMesh.set_instance_color` re: white albedo color If the user does not set the albedo color to pure white, then the multiplication with a value different from 1 will produce modulated colors. Co-authored-by: Hugo Locurcio (cherry picked from commit 1f6709d6e33a5fc3eec0bc6d58fd3011dc5531c4) --- doc/classes/MultiMesh.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/classes/MultiMesh.xml b/doc/classes/MultiMesh.xml index c15997d0956..48c4a11c404 100644 --- a/doc/classes/MultiMesh.xml +++ b/doc/classes/MultiMesh.xml @@ -81,7 +81,7 @@ Sets the color of a specific instance by [i]multiplying[/i] the mesh's existing vertex colors. - For the color to take effect, ensure that [member color_format] is non-[code]null[/code] on the [MultiMesh] and [member SpatialMaterial.vertex_color_use_as_albedo] is [code]true[/code] on the material. + For the color to take effect, ensure that [member color_format] is non-[code]null[/code] on the [MultiMesh] and [member SpatialMaterial.vertex_color_use_as_albedo] is [code]true[/code] on the material. If the color doesn't look as expected, make sure the material's albedo color is set to pure white ([code]Color(1, 1, 1)[/code]). From 396955b4f2a916b57fd796c8fc6089bc3670af98 Mon Sep 17 00:00:00 2001 From: Chia-Hsiang Cheng Date: Thu, 14 Jul 2022 12:03:27 +0800 Subject: [PATCH 11/16] Disable the OK button when no node is selected. (cherry picked from commit 83d478ffcd12a77803b0646749c06eca14802d99) --- editor/scene_tree_editor.cpp | 9 +++++++++ editor/scene_tree_editor.h | 1 + 2 files changed, 10 insertions(+) diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index 20ea15feba7..1c249664539 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -1315,6 +1315,10 @@ void SceneTreeDialog::_select() { } } +void SceneTreeDialog::_selected_changed() { + get_ok()->set_disabled(!tree->get_selected()); +} + void SceneTreeDialog::_filter_changed(const String &p_filter) { tree->set_filter(p_filter); } @@ -1322,6 +1326,7 @@ void SceneTreeDialog::_filter_changed(const String &p_filter) { void SceneTreeDialog::_bind_methods() { ClassDB::bind_method("_select", &SceneTreeDialog::_select); ClassDB::bind_method("_cancel", &SceneTreeDialog::_cancel); + ClassDB::bind_method(D_METHOD("_selected_changed"), &SceneTreeDialog::_selected_changed); ClassDB::bind_method(D_METHOD("_filter_changed"), &SceneTreeDialog::_filter_changed); ADD_SIGNAL(MethodInfo("selected", PropertyInfo(Variant::NODE_PATH, "path"))); @@ -1343,6 +1348,10 @@ SceneTreeDialog::SceneTreeDialog() { tree->set_v_size_flags(SIZE_EXPAND_FILL); tree->get_scene_tree()->connect("item_activated", this, "_select"); vbc->add_child(tree); + + // Disable the OK button when no node is selected. + get_ok()->set_disabled(!tree->get_selected()); + tree->connect("node_selected", this, "_selected_changed"); } SceneTreeDialog::~SceneTreeDialog() { diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h index 4f7ce60dc1e..ea08ba08652 100644 --- a/editor/scene_tree_editor.h +++ b/editor/scene_tree_editor.h @@ -170,6 +170,7 @@ class SceneTreeDialog : public ConfirmationDialog { void _select(); void _cancel(); + void _selected_changed(); void _filter_changed(const String &p_filter); protected: From 77d596088e08afbf708d9f1c594e0b5f2ed61ad3 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Sun, 7 Aug 2022 19:47:22 +0200 Subject: [PATCH 12/16] Remove FOV adjustment with Alt + mouse wheel in the 3D editor This shortcut got in the way when using the Maya navigation scheme, and also when using the slow freelook modifier (regardless of navigation scheme). (cherry picked from commit 53f4ff243d60157101d082f96aef4977f4002c65) --- editor/plugins/spatial_editor_plugin.cpp | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index ee43dcaddbf..c410dc2d814 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -1171,26 +1171,18 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { float zoom_factor = 1 + (ZOOM_FREELOOK_MULTIPLIER - 1) * b->get_factor(); switch (b->get_button_index()) { case BUTTON_WHEEL_UP: { - if (b->get_alt()) { - scale_fov(-0.05); + if (is_freelook_active()) { + scale_freelook_speed(zoom_factor); } else { - if (is_freelook_active()) { - scale_freelook_speed(zoom_factor); - } else { - scale_cursor_distance(1.0 / zoom_factor); - } + scale_cursor_distance(1.0 / zoom_factor); } } break; case BUTTON_WHEEL_DOWN: { - if (b->get_alt()) { - scale_fov(0.05); + if (is_freelook_active()) { + scale_freelook_speed(1.0 / zoom_factor); } else { - if (is_freelook_active()) { - scale_freelook_speed(1.0 / zoom_factor); - } else { - scale_cursor_distance(zoom_factor); - } + scale_cursor_distance(zoom_factor); } } break; From 2f0577fb0f03405a3eeea8e99c5336d9eeaa785e Mon Sep 17 00:00:00 2001 From: kleonc <9283098+kleonc@users.noreply.github.com> Date: Thu, 10 Jun 2021 19:24:58 +0200 Subject: [PATCH 13/16] AnimatedSprite Fix updating inspector when SpriteFrames is modified (cherry picked from commit 8ae246f15efcca2dc72bfbad99373b942c6e6482) --- editor/editor_inspector.cpp | 3 +- .../plugins/sprite_frames_editor_plugin.cpp | 43 +++++++++++++++++-- scene/2d/animated_sprite.cpp | 27 ++++++------ scene/2d/animated_sprite.h | 2 - 4 files changed, 52 insertions(+), 23 deletions(-) diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 32a64f64e87..4b1eac1f393 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -1448,8 +1448,7 @@ void EditorInspector::update_tree() { String group_base; VBoxContainer *category_vbox = nullptr; - List - plist; + List plist; object->get_property_list(&plist, true); HashMap item_path; diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index aefc623a4d0..6d2a00780f3 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -745,9 +745,13 @@ void SpriteFramesEditor::_animation_name_edited() { undo_redo->add_undo_method(frames, "rename_animation", name, edited_anim); for (List::Element *E = nodes.front(); E; E = E->next()) { - String current = E->get()->call("get_animation"); + StringName current = E->get()->call("get_animation"); + if (current != edited_anim) { + continue; + } + undo_redo->add_do_method(E->get(), "set_animation", name); - undo_redo->add_undo_method(E->get(), "set_animation", edited_anim); + undo_redo->add_undo_method(E->get(), "set_animation", current); } undo_redo->add_do_method(this, "_update_library"); @@ -775,8 +779,14 @@ void SpriteFramesEditor::_animation_add() { undo_redo->add_do_method(this, "_update_library"); undo_redo->add_undo_method(this, "_update_library"); + // Assign the newly added animation to the edited anim sprite and to all other anim sprites having invalid animation. + Object *edited_anim_sprite = EditorNode::get_singleton()->get_inspector()->get_edited_object(); for (List::Element *E = nodes.front(); E; E = E->next()) { - String current = E->get()->call("get_animation"); + StringName current = E->get()->call("get_animation"); + if (frames->has_animation(current) && E->get() != edited_anim_sprite) { + continue; + } + undo_redo->add_do_method(E->get(), "set_animation", name); undo_redo->add_undo_method(E->get(), "set_animation", current); } @@ -811,10 +821,35 @@ void SpriteFramesEditor::_animation_remove_confirmed() { Ref frame = frames->get_frame(edited_anim, i); undo_redo->add_undo_method(frames, "add_frame", edited_anim, frame); } + + StringName new_edited_anim = StringName(); + + List anim_names; + frames->get_animation_list(&anim_names); + anim_names.sort_custom(); + + // If removing not the last animation, make the first animation left the new edited one. + if (anim_names.size() > 1) { + new_edited_anim = edited_anim != anim_names.front()->get() ? anim_names.front()->get() : anim_names.front()->next()->get(); + + List nodes; + _find_anim_sprites(EditorNode::get_singleton()->get_edited_scene(), &nodes, Ref(frames)); + + for (List::Element *E = nodes.front(); E; E = E->next()) { + StringName current = E->get()->call("get_animation"); + if (current != edited_anim) { + continue; + } + + undo_redo->add_do_method(E->get(), "set_animation", new_edited_anim); + undo_redo->add_undo_method(E->get(), "set_animation", current); + } + } + undo_redo->add_do_method(this, "_update_library"); undo_redo->add_undo_method(this, "_update_library"); - edited_anim = StringName(); + edited_anim = new_edited_anim; undo_redo->commit_action(); } diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index dc1b39d0df5..5589968796c 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -147,7 +147,7 @@ void SpriteFrames::clear(const StringName &p_anim) { void SpriteFrames::clear_all() { animations.clear(); - add_animation("default"); + add_animation("default"); // Also emits changed. } void SpriteFrames::add_animation(const StringName &p_anim) { @@ -155,13 +155,16 @@ void SpriteFrames::add_animation(const StringName &p_anim) { animations[p_anim] = Anim(); animations[p_anim].normal_name = String(p_anim) + NORMAL_SUFFIX; + emit_changed(); } bool SpriteFrames::has_animation(const StringName &p_anim) const { return animations.has(p_anim); } void SpriteFrames::remove_animation(const StringName &p_anim) { - animations.erase(p_anim); + if (animations.erase(p_anim)) { + emit_changed(); + } } void SpriteFrames::rename_animation(const StringName &p_prev, const StringName &p_next) { @@ -172,17 +175,7 @@ void SpriteFrames::rename_animation(const StringName &p_prev, const StringName & animations.erase(p_prev); animations[p_next] = anim; animations[p_next].normal_name = String(p_next) + NORMAL_SUFFIX; -} - -Vector SpriteFrames::_get_animation_list() const { - Vector ret; - List al; - get_animation_list(&al); - for (List::Element *E = al.front(); E; E = E->next()) { - ret.push_back(E->get()); - } - - return ret; + emit_changed(); } void SpriteFrames::get_animation_list(List *r_animations) const { @@ -578,8 +571,12 @@ bool AnimatedSprite::is_flipped_v() const { void AnimatedSprite::_res_changed() { set_frame(frame); - _change_notify("frame"); - _change_notify("animation"); + + // Calling _change_notify("frame") and _change_notify("animation") instead wouldn't + // make EditorInspector trigger calls to _validate_property(property) which would + // lead to not updating valid values for "frame" and "animation" properties. + _change_notify(); + update(); } diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h index 81f0a3eccbc..0a69572d719 100644 --- a/scene/2d/animated_sprite.h +++ b/scene/2d/animated_sprite.h @@ -58,8 +58,6 @@ class SpriteFrames : public Resource { Array _get_animations() const; void _set_animations(const Array &p_animations); - Vector _get_animation_list() const; - protected: static void _bind_methods(); From ec82655ca00f47c88ed338c64d156c274507609b Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Sat, 16 Jul 2022 13:27:48 +0100 Subject: [PATCH 14/16] Fix skeleton 2D stale bounding rect Adds special logic for handling skeleton bounding rect updates. Previously these were never being updated because the canvas item is never set to "rect_dirty". (cherry picked from commit 18bb668a2ec4207828a52928760c7e8445740a96) --- drivers/dummy/rasterizer_dummy.h | 1 + drivers/gles2/rasterizer_storage_gles2.cpp | 7 ++++ drivers/gles2/rasterizer_storage_gles2.h | 3 ++ drivers/gles3/rasterizer_storage_gles3.cpp | 8 ++++ drivers/gles3/rasterizer_storage_gles3.h | 3 ++ servers/visual/rasterizer.h | 43 ++++++++++++++++------ 6 files changed, 54 insertions(+), 11 deletions(-) diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h index 0373bbcc0ef..72d5050143f 100644 --- a/drivers/dummy/rasterizer_dummy.h +++ b/drivers/dummy/rasterizer_dummy.h @@ -483,6 +483,7 @@ public: Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const { return Transform(); } void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {} Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const { return Transform2D(); } + uint32_t skeleton_get_revision(RID p_skeleton) const { return 0; } /* Light API */ diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 4d7a68c8301..b10e20e0367 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -3731,6 +3731,7 @@ void RasterizerStorageGLES2::skeleton_bone_set_transform_2d(RID p_skeleton, int if (!skeleton->update_list.in_list()) { skeleton_update_list.add(&skeleton->update_list); } + skeleton->revision++; } Transform2D RasterizerStorageGLES2::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const { @@ -3763,6 +3764,12 @@ void RasterizerStorageGLES2::skeleton_set_base_transform_2d(RID p_skeleton, cons skeleton->base_transform_2d = p_base_transform; } +uint32_t RasterizerStorageGLES2::skeleton_get_revision(RID p_skeleton) const { + const Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + ERR_FAIL_COND_V(!skeleton, 0); + return skeleton->revision; +} + void RasterizerStorageGLES2::update_dirty_blend_shapes() { while (blend_shapes_update_list.first()) { Mesh *mesh = blend_shapes_update_list.first()->self(); diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index 4aeb91b17b4..fa9a8e6fab7 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -890,6 +890,7 @@ public: bool use_2d; int size; + uint32_t revision; // TODO use float textures for storage @@ -905,6 +906,7 @@ public: Skeleton() : use_2d(false), size(0), + revision(1), tex_id(0), update_list(this) { } @@ -924,6 +926,7 @@ public: virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform); virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const; virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform); + virtual uint32_t skeleton_get_revision(RID p_skeleton) const; void _update_skeleton_transform_buffer(const PoolVector &p_data, size_t p_size); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 485945103be..a98f6275719 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -5277,6 +5277,8 @@ void RasterizerStorageGLES3::skeleton_bone_set_transform_2d(RID p_skeleton, int if (!skeleton->update_list.in_list()) { skeleton_update_list.add(&skeleton->update_list); } + + skeleton->revision++; } Transform2D RasterizerStorageGLES3::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const { Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); @@ -5310,6 +5312,12 @@ void RasterizerStorageGLES3::skeleton_set_base_transform_2d(RID p_skeleton, cons skeleton->base_transform_2d = p_base_transform; } +uint32_t RasterizerStorageGLES3::skeleton_get_revision(RID p_skeleton) const { + const Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + ERR_FAIL_COND_V(!skeleton, 0); + return skeleton->revision; +} + void RasterizerStorageGLES3::update_dirty_skeletons() { glActiveTexture(GL_TEXTURE0); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 8de3ac4e1b4..8c2a8b72e21 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -920,6 +920,7 @@ public: struct Skeleton : RID_Data { bool use_2d; int size; + uint32_t revision; Vector skel_texture; GLuint texture; SelfList update_list; @@ -929,6 +930,7 @@ public: Skeleton() : use_2d(false), size(0), + revision(1), texture(0), update_list(this) { } @@ -948,6 +950,7 @@ public: virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform); virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const; virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform); + virtual uint32_t skeleton_get_revision(RID p_skeleton) const; /* Light API */ diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 71ff30ad6d3..ce71698a77b 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -448,6 +448,7 @@ public: virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0; virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0; virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0; + virtual uint32_t skeleton_get_revision(RID p_skeleton) const = 0; /* Light API */ @@ -947,19 +948,24 @@ public: }; Transform2D xform; - bool clip; - bool visible; - bool behind; - bool update_when_visible; - //VS::MaterialBlendMode blend_mode; - int light_mask; + bool clip : 1; + bool visible : 1; + bool behind : 1; + bool update_when_visible : 1; + bool distance_field : 1; + bool light_masked : 1; + mutable bool custom_rect : 1; + mutable bool rect_dirty : 1; + Vector commands; - mutable bool custom_rect; - mutable bool rect_dirty; mutable Rect2 rect; RID material; RID skeleton; + //VS::MaterialBlendMode blend_mode; + int32_t light_mask; + mutable uint32_t skeleton_revision; + Item *next; struct CopyBackBuffer { @@ -975,15 +981,29 @@ public: Item *final_clip_owner; Item *material_owner; ViewportRender *vp_render; - bool distance_field; - bool light_masked; Rect2 global_rect_cache; const Rect2 &get_rect() const { - if (custom_rect || (!rect_dirty && !update_when_visible)) { + if (custom_rect) { return rect; } + if (!rect_dirty && !update_when_visible) { + if (skeleton == RID()) { + return rect; + } else { + // special case for skeletons + uint32_t rev = RasterizerStorage::base_singleton->skeleton_get_revision(skeleton); + if (rev == skeleton_revision) { + // no change to the skeleton since we last calculated the bounding rect + return rect; + } else { + // We need to recalculate. + // Mark as done for next time. + skeleton_revision = rev; + } + } + } //must update rect int s = commands.size(); @@ -1171,6 +1191,7 @@ public: } Item() { light_mask = 1; + skeleton_revision = 0; vp_render = nullptr; next = nullptr; final_clip_owner = nullptr; From b779a2332bb9060ca0c99f1a20f345077aba1af2 Mon Sep 17 00:00:00 2001 From: Yuri Sizov Date: Wed, 20 Jul 2022 17:22:36 +0300 Subject: [PATCH 15/16] Use FlowContainer to handle toolbar overflow more gracefully (cherry picked from commit 842c3a644fae82f6736e7043ddc5e06c2b75a76b) --- editor/plugins/canvas_item_editor_plugin.cpp | 84 +++++++++++--------- editor/plugins/canvas_item_editor_plugin.h | 7 +- editor/plugins/spatial_editor_plugin.cpp | 66 ++++++++------- editor/plugins/spatial_editor_plugin.h | 5 +- 4 files changed, 85 insertions(+), 77 deletions(-) diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index f113eed2d5b..e7babb072c2 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -46,6 +46,7 @@ #include "scene/2d/skeleton_2d.h" #include "scene/2d/sprite.h" #include "scene/2d/touch_screen_button.h" +#include "scene/gui/flow_container.h" #include "scene/gui/grid_container.h" #include "scene/gui/nine_patch_rect.h" #include "scene/gui/viewport_container.h" @@ -4401,7 +4402,7 @@ void CanvasItemEditor::_update_context_menu_stylebox() { context_menu_stylebox->set_border_color(accent_color); context_menu_stylebox->set_border_width(MARGIN_BOTTOM, Math::round(2 * EDSCALE)); context_menu_stylebox->set_default_margin(MARGIN_BOTTOM, 0); - context_menu_container->add_style_override("panel", context_menu_stylebox); + context_menu_panel->add_style_override("panel", context_menu_stylebox); } void CanvasItemEditor::_update_scrollbars() { @@ -5737,11 +5738,11 @@ void CanvasItemEditor::remove_control_from_info_overlay(Control *p_control) { void CanvasItemEditor::add_control_to_menu_panel(Control *p_control) { ERR_FAIL_COND(!p_control); - hbc_context_menu->add_child(p_control); + context_menu_hbox->add_child(p_control); } void CanvasItemEditor::remove_control_from_menu_panel(Control *p_control) { - hbc_context_menu->remove_child(p_control); + context_menu_hbox->remove_child(p_control); } void CanvasItemEditor::add_control_to_left_panel(Control *p_control) { @@ -5868,9 +5869,14 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { editor->call_deferred("connect", "play_pressed", this, "_update_override_camera_button", make_binds(true)); editor->call_deferred("connect", "stop_pressed", this, "_update_override_camera_button", make_binds(false)); - hb = memnew(HBoxContainer); - add_child(hb); - hb->set_anchors_and_margins_preset(Control::PRESET_WIDE); + // A fluid container for all toolbars. + HFlowContainer *main_flow = memnew(HFlowContainer); + add_child(main_flow); + + // Main toolbars. + HBoxContainer *main_menu_hbox = memnew(HBoxContainer); + main_menu_hbox->set_anchors_and_margins_preset(Control::PRESET_WIDE); + main_flow->add_child(main_menu_hbox); bottom_split = memnew(VSplitContainer); add_child(bottom_split); @@ -5968,82 +5974,82 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { updating_scroll = false; select_button = memnew(ToolButton); - hb->add_child(select_button); + main_menu_hbox->add_child(select_button); select_button->set_toggle_mode(true); select_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_SELECT)); select_button->set_pressed(true); select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode", TTR("Select Mode"), KEY_Q)); select_button->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+Drag: Move selected node.") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Alt+Drag: Scale selected node.") + "\n" + TTR("V: Set selected node's pivot position.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("RMB: Add node at position clicked.")); - hb->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); move_button = memnew(ToolButton); - hb->add_child(move_button); + main_menu_hbox->add_child(move_button); move_button->set_toggle_mode(true); move_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_MOVE)); move_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/move_mode", TTR("Move Mode"), KEY_W)); move_button->set_tooltip(TTR("Move Mode")); rotate_button = memnew(ToolButton); - hb->add_child(rotate_button); + main_menu_hbox->add_child(rotate_button); rotate_button->set_toggle_mode(true); rotate_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_ROTATE)); rotate_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/rotate_mode", TTR("Rotate Mode"), KEY_E)); rotate_button->set_tooltip(TTR("Rotate Mode")); scale_button = memnew(ToolButton); - hb->add_child(scale_button); + main_menu_hbox->add_child(scale_button); scale_button->set_toggle_mode(true); scale_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_SCALE)); scale_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/scale_mode", TTR("Scale Mode"), KEY_S)); scale_button->set_tooltip(TTR("Shift: Scale proportionally.")); - hb->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); list_select_button = memnew(ToolButton); - hb->add_child(list_select_button); + main_menu_hbox->add_child(list_select_button); list_select_button->set_toggle_mode(true); list_select_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_LIST_SELECT)); list_select_button->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode).")); pivot_button = memnew(ToolButton); - hb->add_child(pivot_button); + main_menu_hbox->add_child(pivot_button); pivot_button->set_toggle_mode(true); pivot_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_EDIT_PIVOT)); pivot_button->set_tooltip(TTR("Click to change object's rotation pivot.")); pan_button = memnew(ToolButton); - hb->add_child(pan_button); + main_menu_hbox->add_child(pan_button); pan_button->set_toggle_mode(true); pan_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_PAN)); pan_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/pan_mode", TTR("Pan Mode"), KEY_G)); pan_button->set_tooltip(TTR("Pan Mode")); ruler_button = memnew(ToolButton); - hb->add_child(ruler_button); + main_menu_hbox->add_child(ruler_button); ruler_button->set_toggle_mode(true); ruler_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_RULER)); ruler_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/ruler_mode", TTR("Ruler Mode"), KEY_R)); ruler_button->set_tooltip(TTR("Ruler Mode")); - hb->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); smart_snap_button = memnew(ToolButton); - hb->add_child(smart_snap_button); + main_menu_hbox->add_child(smart_snap_button); smart_snap_button->set_toggle_mode(true); smart_snap_button->connect("toggled", this, "_button_toggle_smart_snap"); smart_snap_button->set_tooltip(TTR("Toggle smart snapping.")); smart_snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_smart_snap", TTR("Use Smart Snap"), KEY_MASK_SHIFT | KEY_S)); grid_snap_button = memnew(ToolButton); - hb->add_child(grid_snap_button); + main_menu_hbox->add_child(grid_snap_button); grid_snap_button->set_toggle_mode(true); grid_snap_button->connect("toggled", this, "_button_toggle_grid_snap"); grid_snap_button->set_tooltip(TTR("Toggle grid snapping.")); grid_snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_grid_snap", TTR("Use Grid Snap"), KEY_MASK_SHIFT | KEY_G)); snap_config_menu = memnew(MenuButton); - hb->add_child(snap_config_menu); + main_menu_hbox->add_child(snap_config_menu); snap_config_menu->set_h_size_flags(SIZE_SHRINK_END); snap_config_menu->set_tooltip(TTR("Snapping Options")); snap_config_menu->set_switch_on_hover(true); @@ -6072,37 +6078,37 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_other_nodes", TTR("Snap to Other Nodes")), SNAP_USE_OTHER_NODES); smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_guides", TTR("Snap to Guides")), SNAP_USE_GUIDES); - hb->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); lock_button = memnew(ToolButton); - hb->add_child(lock_button); + main_menu_hbox->add_child(lock_button); lock_button->connect("pressed", this, "_popup_callback", varray(LOCK_SELECTED)); lock_button->set_tooltip(TTR("Lock the selected object in place (can't be moved).")); lock_button->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KEY_MASK_CMD | KEY_L)); unlock_button = memnew(ToolButton); - hb->add_child(unlock_button); + main_menu_hbox->add_child(unlock_button); unlock_button->connect("pressed", this, "_popup_callback", varray(UNLOCK_SELECTED)); unlock_button->set_tooltip(TTR("Unlock the selected object (can be moved).")); unlock_button->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_L)); group_button = memnew(ToolButton); - hb->add_child(group_button); + main_menu_hbox->add_child(group_button); group_button->connect("pressed", this, "_popup_callback", varray(GROUP_SELECTED)); group_button->set_tooltip(TTR("Makes sure the object's children are not selectable.")); group_button->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KEY_MASK_CMD | KEY_G)); ungroup_button = memnew(ToolButton); - hb->add_child(ungroup_button); + main_menu_hbox->add_child(ungroup_button); ungroup_button->connect("pressed", this, "_popup_callback", varray(UNGROUP_SELECTED)); ungroup_button->set_tooltip(TTR("Restores the object's children's ability to be selected.")); ungroup_button->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_G)); - hb->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); skeleton_menu = memnew(MenuButton); - hb->add_child(skeleton_menu); + main_menu_hbox->add_child(skeleton_menu); skeleton_menu->set_tooltip(TTR("Skeleton Options")); skeleton_menu->set_switch_on_hover(true); @@ -6117,21 +6123,21 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Custom Bones")), SKELETON_CLEAR_BONES); p->connect("id_pressed", this, "_popup_callback"); - hb->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); override_camera_button = memnew(ToolButton); - hb->add_child(override_camera_button); + main_menu_hbox->add_child(override_camera_button); override_camera_button->connect("toggled", this, "_button_override_camera"); override_camera_button->set_toggle_mode(true); override_camera_button->set_disabled(true); _update_override_camera_button(false); - hb->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); view_menu = memnew(MenuButton); // TRANSLATORS: Noun, name of the 2D/3D View menus. view_menu->set_text(TTR("View")); - hb->add_child(view_menu); + main_menu_hbox->add_child(view_menu); view_menu->get_popup()->connect("id_pressed", this, "_popup_callback"); view_menu->set_switch_on_hover(true); @@ -6164,20 +6170,20 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p->add_separator(); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/preview_canvas_scale", TTR("Preview Canvas Scale"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_P), PREVIEW_CANVAS_SCALE); - hb->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); - context_menu_container = memnew(PanelContainer); - hbc_context_menu = memnew(HBoxContainer); - context_menu_container->add_child(hbc_context_menu); + context_menu_panel = memnew(PanelContainer); + context_menu_hbox = memnew(HBoxContainer); + context_menu_panel->add_child(context_menu_hbox); // Use a custom stylebox to make contextual menu items stand out from the rest. // This helps with editor usability as contextual menu items change when selecting nodes, // even though it may not be immediately obvious at first. - hb->add_child(context_menu_container); + main_flow->add_child(context_menu_panel); _update_context_menu_stylebox(); presets_menu = memnew(MenuButton); presets_menu->set_text(TTR("Layout")); - hbc_context_menu->add_child(presets_menu); + context_menu_hbox->add_child(presets_menu); presets_menu->hide(); presets_menu->set_switch_on_hover(true); @@ -6190,13 +6196,13 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { anchors_popup->connect("id_pressed", this, "_popup_callback"); anchor_mode_button = memnew(ToolButton); - hbc_context_menu->add_child(anchor_mode_button); + context_menu_hbox->add_child(anchor_mode_button); anchor_mode_button->set_toggle_mode(true); anchor_mode_button->hide(); anchor_mode_button->connect("toggled", this, "_button_toggle_anchor_mode"); animation_hb = memnew(HBoxContainer); - hbc_context_menu->add_child(animation_hb); + context_menu_hbox->add_child(animation_hb); animation_hb->add_child(memnew(VSeparator)); animation_hb->hide(); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 37d9788827a..e621b00da59 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -238,11 +238,10 @@ private: HScrollBar *h_scroll; VScrollBar *v_scroll; - HBoxContainer *hb; // Used for secondary menu items which are displayed depending on the currently selected node // (such as MeshInstance's "Mesh" menu). - PanelContainer *context_menu_container; - HBoxContainer *hbc_context_menu; + PanelContainer *context_menu_panel = nullptr; + HBoxContainer *context_menu_hbox = nullptr; ToolButton *zoom_minus; ToolButton *zoom_reset; @@ -584,8 +583,6 @@ protected: static void _bind_methods(); - HBoxContainer *get_panel_hb() { return hb; } - struct compare_items_x { bool operator()(const CanvasItem *a, const CanvasItem *b) const { return a->get_global_transform().elements[2].x < b->get_global_transform().elements[2].x; diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index c410dc2d814..6046006286b 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -49,6 +49,7 @@ #include "scene/3d/physics_body.h" #include "scene/3d/room_manager.h" #include "scene/3d/visual_instance.h" +#include "scene/gui/flow_container.h" #include "scene/gui/viewport_container.h" #include "scene/resources/packed_scene.h" #include "scene/resources/surface_tool.h" @@ -5802,7 +5803,7 @@ void SpatialEditor::_update_context_menu_stylebox() { context_menu_stylebox->set_border_color(accent_color); context_menu_stylebox->set_border_width(MARGIN_BOTTOM, Math::round(2 * EDSCALE)); context_menu_stylebox->set_default_margin(MARGIN_BOTTOM, 0); - context_menu_container->add_style_override("panel", context_menu_stylebox); + context_menu_panel->add_style_override("panel", context_menu_stylebox); } void SpatialEditor::_update_gizmos_menu() { @@ -6322,11 +6323,11 @@ void SpatialEditor::_notification(int p_what) { } void SpatialEditor::add_control_to_menu_panel(Control *p_control) { - hbc_context_menu->add_child(p_control); + context_menu_hbox->add_child(p_control); } void SpatialEditor::remove_control_from_menu_panel(Control *p_control) { - hbc_context_menu->remove_child(p_control); + context_menu_hbox->remove_child(p_control); } void SpatialEditor::set_can_preview(Camera *p_preview) { @@ -6568,15 +6569,20 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { camera_override_viewport_id = 0; - hbc_menu = memnew(HBoxContainer); - vbc->add_child(hbc_menu); + // A fluid container for all toolbars. + HFlowContainer *main_flow = memnew(HFlowContainer); + vbc->add_child(main_flow); + + // Main toolbars. + HBoxContainer *main_menu_hbox = memnew(HBoxContainer); + main_flow->add_child(main_menu_hbox); Vector button_binds; button_binds.resize(1); String sct; tool_button[TOOL_MODE_SELECT] = memnew(ToolButton); - hbc_menu->add_child(tool_button[TOOL_MODE_SELECT]); + main_menu_hbox->add_child(tool_button[TOOL_MODE_SELECT]); tool_button[TOOL_MODE_SELECT]->set_toggle_mode(true); tool_button[TOOL_MODE_SELECT]->set_flat(true); tool_button[TOOL_MODE_SELECT]->set_pressed(true); @@ -6584,10 +6590,10 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_SELECT]->connect("pressed", this, "_menu_item_pressed", button_binds); tool_button[TOOL_MODE_SELECT]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_select", TTR("Select Mode"), KEY_Q)); tool_button[TOOL_MODE_SELECT]->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.")); - hbc_menu->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); tool_button[TOOL_MODE_MOVE] = memnew(ToolButton); - hbc_menu->add_child(tool_button[TOOL_MODE_MOVE]); + main_menu_hbox->add_child(tool_button[TOOL_MODE_MOVE]); tool_button[TOOL_MODE_MOVE]->set_toggle_mode(true); tool_button[TOOL_MODE_MOVE]->set_flat(true); button_binds.write[0] = MENU_TOOL_MOVE; @@ -6595,7 +6601,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_MOVE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_move", TTR("Move Mode"), KEY_W)); tool_button[TOOL_MODE_ROTATE] = memnew(ToolButton); - hbc_menu->add_child(tool_button[TOOL_MODE_ROTATE]); + main_menu_hbox->add_child(tool_button[TOOL_MODE_ROTATE]); tool_button[TOOL_MODE_ROTATE]->set_toggle_mode(true); tool_button[TOOL_MODE_ROTATE]->set_flat(true); button_binds.write[0] = MENU_TOOL_ROTATE; @@ -6603,17 +6609,17 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_ROTATE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_rotate", TTR("Rotate Mode"), KEY_E)); tool_button[TOOL_MODE_SCALE] = memnew(ToolButton); - hbc_menu->add_child(tool_button[TOOL_MODE_SCALE]); + main_menu_hbox->add_child(tool_button[TOOL_MODE_SCALE]); tool_button[TOOL_MODE_SCALE]->set_toggle_mode(true); tool_button[TOOL_MODE_SCALE]->set_flat(true); button_binds.write[0] = MENU_TOOL_SCALE; tool_button[TOOL_MODE_SCALE]->connect("pressed", this, "_menu_item_pressed", button_binds); tool_button[TOOL_MODE_SCALE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_scale", TTR("Scale Mode"), KEY_R)); - hbc_menu->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); tool_button[TOOL_MODE_LIST_SELECT] = memnew(ToolButton); - hbc_menu->add_child(tool_button[TOOL_MODE_LIST_SELECT]); + main_menu_hbox->add_child(tool_button[TOOL_MODE_LIST_SELECT]); tool_button[TOOL_MODE_LIST_SELECT]->set_toggle_mode(true); tool_button[TOOL_MODE_LIST_SELECT]->set_flat(true); button_binds.write[0] = MENU_TOOL_LIST_SELECT; @@ -6621,37 +6627,37 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_LIST_SELECT]->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode).")); tool_button[TOOL_LOCK_SELECTED] = memnew(ToolButton); - hbc_menu->add_child(tool_button[TOOL_LOCK_SELECTED]); + main_menu_hbox->add_child(tool_button[TOOL_LOCK_SELECTED]); button_binds.write[0] = MENU_LOCK_SELECTED; tool_button[TOOL_LOCK_SELECTED]->connect("pressed", this, "_menu_item_pressed", button_binds); tool_button[TOOL_LOCK_SELECTED]->set_tooltip(TTR("Lock the selected object in place (can't be moved).")); tool_button[TOOL_LOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KEY_MASK_CMD | KEY_L)); tool_button[TOOL_UNLOCK_SELECTED] = memnew(ToolButton); - hbc_menu->add_child(tool_button[TOOL_UNLOCK_SELECTED]); + main_menu_hbox->add_child(tool_button[TOOL_UNLOCK_SELECTED]); button_binds.write[0] = MENU_UNLOCK_SELECTED; tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", this, "_menu_item_pressed", button_binds); tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip(TTR("Unlock the selected object (can be moved).")); tool_button[TOOL_UNLOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_L)); tool_button[TOOL_GROUP_SELECTED] = memnew(ToolButton); - hbc_menu->add_child(tool_button[TOOL_GROUP_SELECTED]); + main_menu_hbox->add_child(tool_button[TOOL_GROUP_SELECTED]); button_binds.write[0] = MENU_GROUP_SELECTED; tool_button[TOOL_GROUP_SELECTED]->connect("pressed", this, "_menu_item_pressed", button_binds); tool_button[TOOL_GROUP_SELECTED]->set_tooltip(TTR("Makes sure the object's children are not selectable.")); tool_button[TOOL_GROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KEY_MASK_CMD | KEY_G)); tool_button[TOOL_UNGROUP_SELECTED] = memnew(ToolButton); - hbc_menu->add_child(tool_button[TOOL_UNGROUP_SELECTED]); + main_menu_hbox->add_child(tool_button[TOOL_UNGROUP_SELECTED]); button_binds.write[0] = MENU_UNGROUP_SELECTED; tool_button[TOOL_UNGROUP_SELECTED]->connect("pressed", this, "_menu_item_pressed", button_binds); tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip(TTR("Restores the object's children's ability to be selected.")); tool_button[TOOL_UNGROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_G)); - hbc_menu->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); tool_option_button[TOOL_OPT_LOCAL_COORDS] = memnew(ToolButton); - hbc_menu->add_child(tool_option_button[TOOL_OPT_LOCAL_COORDS]); + main_menu_hbox->add_child(tool_option_button[TOOL_OPT_LOCAL_COORDS]); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_toggle_mode(true); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_flat(true); button_binds.write[0] = MENU_TOOL_LOCAL_COORDS; @@ -6659,17 +6665,17 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_shortcut(ED_SHORTCUT("spatial_editor/local_coords", TTR("Use Local Space"), KEY_T)); tool_option_button[TOOL_OPT_USE_SNAP] = memnew(ToolButton); - hbc_menu->add_child(tool_option_button[TOOL_OPT_USE_SNAP]); + main_menu_hbox->add_child(tool_option_button[TOOL_OPT_USE_SNAP]); tool_option_button[TOOL_OPT_USE_SNAP]->set_toggle_mode(true); tool_option_button[TOOL_OPT_USE_SNAP]->set_flat(true); button_binds.write[0] = MENU_TOOL_USE_SNAP; tool_option_button[TOOL_OPT_USE_SNAP]->connect("toggled", this, "_menu_item_toggled", button_binds); tool_option_button[TOOL_OPT_USE_SNAP]->set_shortcut(ED_SHORTCUT("spatial_editor/snap", TTR("Use Snap"), KEY_Y)); - hbc_menu->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); tool_option_button[TOOL_OPT_OVERRIDE_CAMERA] = memnew(ToolButton); - hbc_menu->add_child(tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]); + main_menu_hbox->add_child(tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]); tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_toggle_mode(true); tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_flat(true); tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_disabled(true); @@ -6678,7 +6684,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { _update_camera_override_button(false); tool_button[TOOL_CONVERT_ROOMS] = memnew(ToolButton); - hbc_menu->add_child(tool_button[TOOL_CONVERT_ROOMS]); + main_menu_hbox->add_child(tool_button[TOOL_CONVERT_ROOMS]); tool_button[TOOL_CONVERT_ROOMS]->set_toggle_mode(false); tool_button[TOOL_CONVERT_ROOMS]->set_flat(true); button_binds.write[0] = MENU_TOOL_CONVERT_ROOMS; @@ -6686,7 +6692,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_button[TOOL_CONVERT_ROOMS]->set_shortcut(ED_SHORTCUT("spatial_editor/convert_rooms", TTR("Convert Rooms"), KEY_MASK_ALT | KEY_C)); tool_button[TOOL_CONVERT_ROOMS]->set_tooltip(TTR("Converts rooms for portal culling.")); - hbc_menu->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); // Drag and drop support; preview_node = memnew(Spatial); @@ -6719,7 +6725,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { transform_menu = memnew(MenuButton); transform_menu->set_text(TTR("Transform")); transform_menu->set_switch_on_hover(true); - hbc_menu->add_child(transform_menu); + main_menu_hbox->add_child(transform_menu); p = transform_menu->get_popup(); p->add_shortcut(ED_SHORTCUT("spatial_editor/snap_to_floor", TTR("Snap Object to Floor"), KEY_PAGEDOWN), MENU_SNAP_TO_FLOOR); @@ -6734,17 +6740,17 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { // TRANSLATORS: Noun, name of the 2D/3D View menus. view_menu->set_text(TTR("View")); view_menu->set_switch_on_hover(true); - hbc_menu->add_child(view_menu); + main_menu_hbox->add_child(view_menu); - hbc_menu->add_child(memnew(VSeparator)); + main_menu_hbox->add_child(memnew(VSeparator)); - context_menu_container = memnew(PanelContainer); - hbc_context_menu = memnew(HBoxContainer); - context_menu_container->add_child(hbc_context_menu); + context_menu_panel = memnew(PanelContainer); + context_menu_hbox = memnew(HBoxContainer); + context_menu_panel->add_child(context_menu_hbox); // Use a custom stylebox to make contextual menu items stand out from the rest. // This helps with editor usability as contextual menu items change when selecting nodes, // even though it may not be immediately obvious at first. - hbc_menu->add_child(context_menu_container); + main_flow->add_child(context_menu_panel); _update_context_menu_stylebox(); // Get the view menu popup and have it stay open when a checkable item is selected diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index a867777ab59..bcb6dc80869 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -712,11 +712,10 @@ private: void _update_camera_override_button(bool p_game_running); void _update_camera_override_viewport(Object *p_viewport); - HBoxContainer *hbc_menu; // Used for secondary menu items which are displayed depending on the currently selected node // (such as MeshInstance's "Mesh" menu). - PanelContainer *context_menu_container; - HBoxContainer *hbc_context_menu; + PanelContainer *context_menu_panel = nullptr; + HBoxContainer *context_menu_hbox = nullptr; void _generate_selection_boxes(); UndoRedo *undo_redo; From 96d3b8d866efb12da1a4e4c69ce2a82fc0c5ec61 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Sat, 6 Aug 2022 05:06:55 +0200 Subject: [PATCH 16/16] Improve Shape2D's `custom_solver_bias` description (cherry picked from commit 373e3dffb47d5a6e03617998e538549a6e7cb3be) --- doc/classes/Shape2D.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/classes/Shape2D.xml b/doc/classes/Shape2D.xml index edac424f7c2..cf3ec4b3d81 100644 --- a/doc/classes/Shape2D.xml +++ b/doc/classes/Shape2D.xml @@ -69,7 +69,8 @@ - The shape's custom solver bias. + The shape's custom solver bias. Defines how much bodies react to enforce contact separation when this shape is involved. + When set to [code]0.0[/code], the default value of [code]0.3[/code] is used.