summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/io/resource_uid.cpp2
-rw-r--r--doc/classes/MultiplayerAPIExtension.xml11
-rw-r--r--doc/classes/ParticleProcessMaterial.xml1
-rw-r--r--doc/classes/Resource.xml1
-rw-r--r--doc/classes/Time.xml4
-rw-r--r--editor/editor_node.cpp11
-rw-r--r--editor/export/editor_export_preset.cpp58
-rw-r--r--editor/import_defaults_editor.cpp1
-rw-r--r--modules/text_server_adv/text_server_adv.cpp2
-rw-r--r--scene/gui/popup_menu.cpp1
-rw-r--r--scene/gui/rich_text_label.cpp2
-rw-r--r--scene/resources/text_paragraph.cpp11
12 files changed, 75 insertions, 30 deletions
diff --git a/core/io/resource_uid.cpp b/core/io/resource_uid.cpp
index 216fc24fff..edff3e1f14 100644
--- a/core/io/resource_uid.cpp
+++ b/core/io/resource_uid.cpp
@@ -35,6 +35,8 @@
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
+// These constants are off by 1, causing the 'z' and '9' characters never to be used.
+// This cannot be fixed without breaking compatibility; see GH-83843.
static constexpr uint32_t char_count = ('z' - 'a');
static constexpr uint32_t base = char_count + ('9' - '0');
diff --git a/doc/classes/MultiplayerAPIExtension.xml b/doc/classes/MultiplayerAPIExtension.xml
index 4a2d397260..7f6e7951b2 100644
--- a/doc/classes/MultiplayerAPIExtension.xml
+++ b/doc/classes/MultiplayerAPIExtension.xml
@@ -15,7 +15,7 @@
var base_multiplayer = SceneMultiplayer.new()
func _init():
- # Just passthourgh base signals (copied to var to avoid cyclic reference)
+ # Just passthrough base signals (copied to var to avoid cyclic reference)
var cts = connected_to_server
var cf = connection_failed
var pc = peer_connected
@@ -25,13 +25,16 @@
base_multiplayer.peer_connected.connect(func(id): pc.emit(id))
base_multiplayer.peer_disconnected.connect(func(id): pd.emit(id))
+ func _poll():
+ return base_multiplayer.poll()
+
# Log RPC being made and forward it to the default multiplayer.
- func _rpc(peer: int, object: Object, method: StringName, args: Array) -> int: # Error
+ func _rpc(peer: int, object: Object, method: StringName, args: Array) -> Error:
print("Got RPC for %d: %s::%s(%s)" % [peer, object, method, args])
return base_multiplayer.rpc(peer, object, method, args)
# Log configuration add. E.g. root path (nullptr, NodePath), replication (Node, Spawner|Synchronizer), custom.
- func _object_configuration_add(object, config: Variant) -> int: # Error
+ func _object_configuration_add(object, config: Variant) -> Error:
if config is MultiplayerSynchronizer:
print("Adding synchronization configuration for %s. Synchronizer: %s" % [object, config])
elif config is MultiplayerSpawner:
@@ -39,7 +42,7 @@
return base_multiplayer.object_configuration_add(object, config)
# Log configuration remove. E.g. root path (nullptr, NodePath), replication (Node, Spawner|Synchronizer), custom.
- func _object_configuration_remove(object, config: Variant) -> int: # Error
+ func _object_configuration_remove(object, config: Variant) -> Error:
if config is MultiplayerSynchronizer:
print("Removing synchronization configuration for %s. Synchronizer: %s" % [object, config])
elif config is MultiplayerSpawner:
diff --git a/doc/classes/ParticleProcessMaterial.xml b/doc/classes/ParticleProcessMaterial.xml
index 79dccbbaa4..aa20260849 100644
--- a/doc/classes/ParticleProcessMaterial.xml
+++ b/doc/classes/ParticleProcessMaterial.xml
@@ -384,6 +384,7 @@
A [CurveTexture] that defines the maximum velocity of a particle during its lifetime.
</member>
<member name="velocity_pivot" type="Vector3" setter="set_velocity_pivot" getter="get_velocity_pivot" default="Vector3(0, 0, 0)">
+ A pivot point used to calculate radial and orbital velocity of particles.
</member>
</members>
<constants>
diff --git a/doc/classes/Resource.xml b/doc/classes/Resource.xml
index 75c258253d..c8146bb48f 100644
--- a/doc/classes/Resource.xml
+++ b/doc/classes/Resource.xml
@@ -92,6 +92,7 @@
</member>
<member name="resource_name" type="String" setter="set_name" getter="get_name" default="&quot;&quot;">
An optional name for this resource. When defined, its value is displayed to represent the resource in the Inspector dock. For built-in scripts, the name is displayed as part of the tab name in the script editor.
+ [b]Note:[/b] Some resource formats do not support resource names. You can still set the name in the editor or via code, but it will be lost when the resource is reloaded. For example, only built-in scripts can have a resource name, while scripts stored in separate files cannot.
</member>
<member name="resource_path" type="String" setter="set_path" getter="get_path" default="&quot;&quot;">
The unique path to this resource. If it has been saved to disk, the value will be its filepath. If the resource is exclusively contained within a scene, the value will be the [PackedScene]'s filepath, followed by a unique identifier.
diff --git a/doc/classes/Time.xml b/doc/classes/Time.xml
index 0313381ff0..79c332327f 100644
--- a/doc/classes/Time.xml
+++ b/doc/classes/Time.xml
@@ -153,8 +153,8 @@
<return type="Dictionary" />
<description>
Returns the current time zone as a dictionary of keys: [code]bias[/code] and [code]name[/code].
- - [code]bias[/code] is the offset from UTC in minutes, since not all time zones are multiples of an hour from UTC.
- - [code]name[/code] is localized according to the current user default UI language.
+ - [code]bias[/code] is the offset from UTC in minutes, since not all time zones are multiples of an hour from UTC.
+ - [code]name[/code] is the localized name of the time zone, according to the OS locale settings of the current user.
</description>
</method>
<method name="get_unix_time_from_datetime_dict" qualifiers="const">
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 6d28b9abc8..ce4f32f0ee 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -8076,6 +8076,17 @@ EditorNode::~EditorNode() {
GDExtensionEditorPlugins::editor_node_add_plugin = nullptr;
GDExtensionEditorPlugins::editor_node_remove_plugin = nullptr;
+ FileDialog::get_icon_func = nullptr;
+ FileDialog::register_func = nullptr;
+ FileDialog::unregister_func = nullptr;
+
+ EditorFileDialog::get_icon_func = nullptr;
+ EditorFileDialog::register_func = nullptr;
+ EditorFileDialog::unregister_func = nullptr;
+
+ file_dialogs.clear();
+ editor_file_dialogs.clear();
+
singleton = nullptr;
}
diff --git a/editor/export/editor_export_preset.cpp b/editor/export/editor_export_preset.cpp
index 29a31c0470..b941170b7b 100644
--- a/editor/export/editor_export_preset.cpp
+++ b/editor/export/editor_export_preset.cpp
@@ -334,31 +334,55 @@ Variant EditorExportPreset::get_or_env(const StringName &p_name, const String &p
return get(p_name, r_valid);
}
+_FORCE_INLINE_ bool _check_digits(const String &p_str) {
+ for (int i = 0; i < p_str.length(); i++) {
+ char32_t c = p_str.operator[](i);
+ if (!is_digit(c)) {
+ return false;
+ }
+ }
+ return true;
+}
+
String EditorExportPreset::get_version(const StringName &p_preset_string, bool p_windows_version) const {
String result = get(p_preset_string);
if (result.is_empty()) {
result = GLOBAL_GET("application/config/version");
- if (p_windows_version) {
- // Modify version number to match Windows constraints (version numbers must have 4 components).
- const PackedStringArray result_split = result.split(".");
- String windows_version;
- if (result_split.is_empty()) {
- // Use a valid fallback if the version string is empty, as a version number must be specified.
+ // Split and validate version number components.
+ const PackedStringArray result_split = result.split(".", false);
+ bool valid_version = !result_split.is_empty();
+ for (const String &E : result_split) {
+ if (!_check_digits(E)) {
+ valid_version = false;
+ break;
+ }
+ }
+
+ if (valid_version) {
+ if (p_windows_version) {
+ // Modify version number to match Windows constraints (version numbers must have 4 components).
+ if (result_split.size() == 1) {
+ result = result + ".0.0.0";
+ } else if (result_split.size() == 2) {
+ result = result + ".0.0";
+ } else if (result_split.size() == 3) {
+ result = result + ".0";
+ } else {
+ result = vformat("%s.%s.%s.%s", result_split[0], result_split[1], result_split[2], result_split[3]);
+ }
+ } else {
+ result = String(".").join(result_split);
+ }
+ } else {
+ if (!result.is_empty()) {
+ WARN_PRINT(vformat("Invalid version number \"%s\". The version number can only contain numeric characters (0-9) and non-consecutive periods (.).", result));
+ }
+ if (p_windows_version) {
result = "1.0.0.0";
- } else if (result_split.size() == 1) {
- result = result + ".0.0.0";
- } else if (result_split.size() == 2) {
- result = result + ".0.0";
- } else if (result_split.size() == 3) {
- result = result + ".0";
} else {
- // 4 components or more in the version string. Trim to contain only the first 4 components.
- result = vformat("%s.%s.%s.%s", result_split[0] + result_split[1] + result_split[2] + result_split[3]);
+ result = "1.0.0";
}
- } else if (result.is_empty()) {
- // Use a valid fallback if the version string is empty, as a version number must be specified.
- result = "1.0.0";
}
}
diff --git a/editor/import_defaults_editor.cpp b/editor/import_defaults_editor.cpp
index 8288594dff..569fdc091e 100644
--- a/editor/import_defaults_editor.cpp
+++ b/editor/import_defaults_editor.cpp
@@ -109,6 +109,7 @@ void ImportDefaultsEditor::_save() {
} else {
ProjectSettings::get_singleton()->set("importer_defaults/" + settings->importer->get_importer_name(), Variant());
}
+ ProjectSettings::get_singleton()->save();
}
}
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 8987a491cb..eaab04b49a 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -4312,6 +4312,8 @@ bool TextServerAdvanced::_shaped_text_resize_object(const RID &p_shaped, const V
sd->width += gl.advance * gl.repeat;
}
}
+ sd->sort_valid = false;
+ sd->glyphs_logical.clear();
_realign(sd);
}
return true;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index ec9e2cacb4..0cda27ec24 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -1487,6 +1487,7 @@ void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, cons
}
void PopupMenu::add_submenu_item(const String &p_label, const String &p_submenu, int p_id) {
+ ERR_FAIL_COND_MSG(p_submenu.validate_node_name() != p_submenu, "Invalid node name for submenu, the following characters are not allowed:\n" + String::get_invalid_node_name_characters());
Item item;
item.text = p_label;
item.xl_text = atr(p_label);
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 1e2f010aad..31ed5984a4 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -307,7 +307,7 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
Size2 img_size = img->size;
if (img->size_in_percent) {
img_size = _get_image_size(img->image, p_width * img->rq_size.width / 100.f, p_width * img->rq_size.height / 100.f, img->region);
- l.text_buf->resize_object((uint64_t)it, img_size, img->inline_align, 1);
+ l.text_buf->resize_object((uint64_t)it, img_size, img->inline_align);
}
} break;
case ITEM_TABLE: {
diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp
index 239ecb500e..147c9044b8 100644
--- a/scene/resources/text_paragraph.cpp
+++ b/scene/resources/text_paragraph.cpp
@@ -175,17 +175,16 @@ void TextParagraph::_shape_lines() {
for (int i = 0; i < line_breaks.size(); i = i + 2) {
RID line = TS->shaped_text_substr(rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
float h = (TS->shaped_text_get_orientation(line) == TextServer::ORIENTATION_HORIZONTAL) ? TS->shaped_text_get_size(line).y : TS->shaped_text_get_size(line).x;
- if (v_offset < h) {
- TS->free_rid(line);
- break;
- }
if (!tab_stops.is_empty()) {
TS->shaped_text_tab_align(line, tab_stops);
}
- dropcap_lines++;
- v_offset -= h;
start = line_breaks[i + 1];
lines_rid.push_back(line);
+ if (v_offset < h) {
+ break;
+ }
+ dropcap_lines++;
+ v_offset -= h;
}
}
// Use fixed for the rest of lines.