summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/classes/RenderingDevice.xml3
-rw-r--r--drivers/gles3/shaders/scene.glsl1
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp10
-rw-r--r--drivers/vulkan/rendering_device_vulkan.h2
-rw-r--r--editor/animation_bezier_editor.cpp4
-rw-r--r--editor/editor_sectioned_inspector.cpp4
-rw-r--r--editor/editor_settings_dialog.cpp4
-rw-r--r--editor/import/audio_stream_import_settings.cpp4
-rw-r--r--editor/plugins/bone_map_editor_plugin.cpp2
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp3
-rw-r--r--editor/project_converter_3_to_4.cpp16
-rw-r--r--modules/gdscript/gdscript_editor.cpp2
-rw-r--r--modules/gdscript/gdscript_warning.cpp2
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out2
-rw-r--r--modules/gltf/doc_classes/GLTFDocument.xml9
-rw-r--r--modules/gltf/doc_classes/GLTFDocumentExtension.xml46
-rw-r--r--modules/gltf/extensions/gltf_document_extension.cpp64
-rw-r--r--modules/gltf/extensions/gltf_document_extension.h19
-rw-r--r--modules/gltf/gltf_document.cpp73
-rw-r--r--modules/mbedtls/packet_peer_mbed_dtls.cpp7
-rw-r--r--modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp2
-rw-r--r--modules/text_server_adv/text_server_adv.cpp5
-rw-r--r--modules/vorbis/audio_stream_ogg_vorbis.cpp2
-rw-r--r--platform/ios/export/export_plugin.cpp6
-rw-r--r--platform/macos/display_server_macos.h1
-rw-r--r--platform/macos/display_server_macos.mm71
-rw-r--r--platform/macos/export/export_plugin.cpp7
-rw-r--r--platform/macos/godot_window_delegate.mm9
-rw-r--r--platform/windows/export/export_plugin.cpp7
-rw-r--r--scene/gui/color_picker.cpp6
-rw-r--r--scene/gui/split_container.cpp3
-rw-r--r--scene/gui/tab_bar.cpp3
-rw-r--r--scene/resources/animation.cpp6
-rw-r--r--servers/physics_3d/godot_soft_body_3d.cpp1
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.cpp1
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp8
-rw-r--r--servers/rendering/rendering_device.cpp12
-rw-r--r--servers/rendering/rendering_device.h4
-rw-r--r--servers/rendering/shader_language.cpp4
39 files changed, 305 insertions, 130 deletions
diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml
index dc39c85af6..580ce6f382 100644
--- a/doc/classes/RenderingDevice.xml
+++ b/doc/classes/RenderingDevice.xml
@@ -648,8 +648,9 @@
<param index="0" name="vertex_count" type="int" />
<param index="1" name="vertex_format" type="int" />
<param index="2" name="src_buffers" type="RID[]" />
+ <param index="3" name="offsets" type="PackedInt64Array" default="PackedInt64Array()" />
<description>
- Creates a vertex array based on the specified buffers.
+ Creates a vertex array based on the specified buffers. Optionally, [param offsets] (in bytes) may be defined for each buffer.
</description>
</method>
<method name="vertex_buffer_create">
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 01135a9bbd..04dba602dd 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -920,6 +920,7 @@ void main() {
#else
vec3 view = -normalize(vertex_interp);
#endif
+ highp mat4 model_matrix = world_transform;
vec3 albedo = vec3(1.0);
vec3 backlight = vec3(0.0);
vec4 transmittance_color = vec4(0.0, 0.0, 0.0, 1.0);
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 1c7edb52c0..01d1583ca4 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -4378,7 +4378,7 @@ RenderingDevice::VertexFormatID RenderingDeviceVulkan::vertex_format_create(cons
return id;
}
-RID RenderingDeviceVulkan::vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers) {
+RID RenderingDeviceVulkan::vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers, const Vector<uint64_t> &p_offsets) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!vertex_formats.has(p_vertex_format), RID());
@@ -4392,6 +4392,13 @@ RID RenderingDeviceVulkan::vertex_array_create(uint32_t p_vertex_count, VertexFo
VertexArray vertex_array;
+ if (p_offsets.is_empty()) {
+ vertex_array.offsets.resize_zeroed(p_src_buffers.size());
+ } else {
+ ERR_FAIL_COND_V(p_offsets.size() != p_src_buffers.size(), RID());
+ vertex_array.offsets = p_offsets;
+ }
+
vertex_array.vertex_count = p_vertex_count;
vertex_array.description = p_vertex_format;
vertex_array.max_instances_allowed = 0xFFFFFFFF; // By default as many as you want.
@@ -4423,7 +4430,6 @@ RID RenderingDeviceVulkan::vertex_array_create(uint32_t p_vertex_count, VertexFo
}
vertex_array.buffers.push_back(buffer->buffer);
- vertex_array.offsets.push_back(0); // Offset unused, but passing anyway.
}
RID id = vertex_array_owner.make_rid(vertex_array);
diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h
index 607c5c3e5d..537ad88f5a 100644
--- a/drivers/vulkan/rendering_device_vulkan.h
+++ b/drivers/vulkan/rendering_device_vulkan.h
@@ -1095,7 +1095,7 @@ public:
// Internally reference counted, this ID is warranted to be unique for the same description, but needs to be freed as many times as it was allocated.
virtual VertexFormatID vertex_format_create(const Vector<VertexAttribute> &p_vertex_formats);
- virtual RID vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers);
+ virtual RID vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers, const Vector<uint64_t> &p_offsets = Vector<uint64_t>());
virtual RID index_buffer_create(uint32_t p_size_indices, IndexBufferFormat p_format, const Vector<uint8_t> &p_data = Vector<uint8_t>(), bool p_use_restart_indices = false);
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp
index af0c3fca5c..da75bf1f3b 100644
--- a/editor/animation_bezier_editor.cpp
+++ b/editor/animation_bezier_editor.cpp
@@ -944,9 +944,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
Vector2 popup_pos = get_screen_position() + mb->get_position();
menu->clear();
- if (!locked_tracks.has(selected_track) || locked_tracks.has(selected_track)) {
- menu->add_icon_item(bezier_icon, TTR("Insert Key Here"), MENU_KEY_INSERT);
- }
+ menu->add_icon_item(bezier_icon, TTR("Insert Key Here"), MENU_KEY_INSERT);
if (selection.size()) {
menu->add_separator();
menu->add_icon_item(get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons")), TTR("Duplicate Selected Key(s)"), MENU_KEY_DUPLICATE);
diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp
index ae47bbe864..5c8ef89ac9 100644
--- a/editor/editor_sectioned_inspector.cpp
+++ b/editor/editor_sectioned_inspector.cpp
@@ -312,7 +312,9 @@ void SectionedInspector::_search_changed(const String &p_what) {
void SectionedInspector::_notification(int p_what) {
switch (p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- inspector->set_property_name_style(EditorPropertyNameProcessor::get_settings_style());
+ if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/localize_settings")) {
+ inspector->set_property_name_style(EditorPropertyNameProcessor::get_settings_style());
+ }
} break;
}
}
diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp
index 77a0d9f85c..b1b54fd717 100644
--- a/editor/editor_settings_dialog.cpp
+++ b/editor/editor_settings_dialog.cpp
@@ -152,7 +152,9 @@ void EditorSettingsDialog::_notification(int p_what) {
_update_shortcuts();
}
- inspector->update_category_list();
+ if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/localize_settings")) {
+ inspector->update_category_list();
+ }
} break;
}
}
diff --git a/editor/import/audio_stream_import_settings.cpp b/editor/import/audio_stream_import_settings.cpp
index a8cd4c3e49..f635c74547 100644
--- a/editor/import/audio_stream_import_settings.cpp
+++ b/editor/import/audio_stream_import_settings.cpp
@@ -288,17 +288,15 @@ void AudioStreamImportSettings::_draw_indicator() {
float preview_len = zoom_bar->get_page();
float beat_size = 60 / float(stream->get_bpm());
int prev_beat = 0;
- int last_text_end_x = 0;
for (int i = 0; i < rect.size.width; i++) {
float ofs = preview_offset + i * preview_len / rect.size.width;
int beat = int(ofs / beat_size);
if (beat != prev_beat) {
String text = itos(beat);
int text_w = beat_font->get_string_size(text).width;
- if (i - text_w / 2 > last_text_end_x + 2 * EDSCALE && beat == _hovering_beat) {
+ if (i - text_w / 2 > 2 * EDSCALE && beat == _hovering_beat) {
int x_ofs = i - text_w / 2;
_indicator->draw_string(beat_font, Point2(x_ofs, 2 * EDSCALE + beat_font->get_ascent(main_size)), text, HORIZONTAL_ALIGNMENT_LEFT, rect.size.width - x_ofs, Font::DEFAULT_FONT_SIZE, color);
- last_text_end_x = i + text_w / 2;
break;
}
prev_beat = beat;
diff --git a/editor/plugins/bone_map_editor_plugin.cpp b/editor/plugins/bone_map_editor_plugin.cpp
index 22c30c9af8..9ceedb18b3 100644
--- a/editor/plugins/bone_map_editor_plugin.cpp
+++ b/editor/plugins/bone_map_editor_plugin.cpp
@@ -742,7 +742,6 @@ void BoneMapper::auto_mapping_process(Ref<BoneMap> &p_bone_map) {
} else {
p_bone_map->_set_skeleton_bone_name("LeftEye", skeleton->get_bone_name(bone_idx));
}
- bone_idx = -1;
bone_idx = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_RIGHT, neck_or_head);
if (bone_idx == -1) {
@@ -750,7 +749,6 @@ void BoneMapper::auto_mapping_process(Ref<BoneMap> &p_bone_map) {
} else {
p_bone_map->_set_skeleton_bone_name("RightEye", skeleton->get_bone_name(bone_idx));
}
- bone_idx = -1;
picklist.clear();
// 4-2. Guess Jaw
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index ce176e3a99..42eceb82ab 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -2481,9 +2481,6 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
if (terrain_set == -1 || !tile_data || tile_data->get_terrain_set() != terrain_set) {
// Paint terrain sets.
- if (mb->get_button_index() == MouseButton::RIGHT) {
- terrain_set = -1;
- }
drag_type = DRAG_TYPE_PAINT_TERRAIN_SET;
drag_modified.clear();
drag_painted_value = int(dummy_object->get("terrain_set"));
diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp
index 3b764a9466..90738a59e8 100644
--- a/editor/project_converter_3_to_4.cpp
+++ b/editor/project_converter_3_to_4.cpp
@@ -2172,7 +2172,7 @@ int ProjectConverter3To4::validate_conversion() {
lines.append(line);
}
}
- print_line(vformat("Checking for conversion - %d/%d file - \"%s\" with size - %d KB"), i + 1, collected_files.size(), file_name.trim_prefix("res://"), file_size / 1024);
+ print_line(vformat("Checking for conversion - %d/%d file - \"%s\" with size - %d KB", i + 1, collected_files.size(), file_name.trim_prefix("res://"), file_size / 1024));
Vector<String> changed_elements;
Vector<String> reason;
@@ -2444,10 +2444,10 @@ bool ProjectConverter3To4::test_conversion(RegExContainer &reg_container) {
valid = valid && test_conversion_with_regex("\n\nmaster func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("\n\nmastersync func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc(call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
- valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function , get_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Copy here content of get_function\n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
- valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function , ", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Non existent get function \n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
- valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Non existent get function \n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
- valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget , get_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Copy here content of get_function \n set(mod_value):\n mod_value # TODOConverter40 Non existent set function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function , get_function", "var size : Vector2 = Vector2() : get = get_function, set = set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function , ", "var size : Vector2 = Vector2() : set = set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function", "var size : Vector2 = Vector2() : set = set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget , get_function", "var size : Vector2 = Vector2() : get = get_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("get_node(@", "get_node(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
@@ -3143,17 +3143,17 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai
// Setget Setget
if (line.contains("setget")) {
- line = reg_container.reg_setget_setget.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $4\n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true);
+ line = reg_container.reg_setget_setget.sub(line, "var $1$2: get = $4, set = $3", true);
}
// Setget set
if (line.contains("setget")) {
- line = reg_container.reg_setget_set.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Non existent get function \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true);
+ line = reg_container.reg_setget_set.sub(line, "var $1$2: set = $3", true);
}
// Setget get
if (line.contains("setget")) {
- line = reg_container.reg_setget_get.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $3 \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Non existent set function", true);
+ line = reg_container.reg_setget_get.sub(line, "var $1$2: get = $3", true);
}
// OS.window_fullscreen = a -> if a: DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN) else: DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 48a6e3fb51..7628bffd22 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -2512,7 +2512,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
}
static bool _get_subscript_type(GDScriptParser::CompletionContext &p_context, const GDScriptParser::SubscriptNode *p_subscript, GDScriptParser::DataType &r_base_type, Variant *r_base = nullptr) {
- if (p_subscript->base->type == GDScriptParser::Node::IDENTIFIER) {
+ if (p_subscript->base->type == GDScriptParser::Node::IDENTIFIER && p_context.base != nullptr) {
const GDScriptParser::GetNodeNode *get_node = nullptr;
const GDScriptParser::IdentifierNode *identifier_node = static_cast<GDScriptParser::IdentifierNode *>(p_subscript->base);
diff --git a/modules/gdscript/gdscript_warning.cpp b/modules/gdscript/gdscript_warning.cpp
index a0c107aa53..2548d26e14 100644
--- a/modules/gdscript/gdscript_warning.cpp
+++ b/modules/gdscript/gdscript_warning.cpp
@@ -96,7 +96,7 @@ String GDScriptWarning::get_message() const {
} break;
case RETURN_VALUE_DISCARDED: {
CHECK_SYMBOLS(1);
- return "The function '" + symbols[0] + "()' returns a value, but this value is never used.";
+ return "The function '" + symbols[0] + "()' returns a value that will be discarded if not used.";
} break;
case PROPERTY_USED_AS_FUNCTION: {
CHECK_SYMBOLS(2);
diff --git a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out
index 13f759dd46..e89bb9226f 100644
--- a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out
+++ b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out
@@ -2,4 +2,4 @@ GDTEST_OK
>> WARNING
>> Line: 6
>> RETURN_VALUE_DISCARDED
->> The function 'i_return_int()' returns a value, but this value is never used.
+>> The function 'i_return_int()' returns a value that will be discarded if not used.
diff --git a/modules/gltf/doc_classes/GLTFDocument.xml b/modules/gltf/doc_classes/GLTFDocument.xml
index 57727a7416..1967df5218 100644
--- a/modules/gltf/doc_classes/GLTFDocument.xml
+++ b/modules/gltf/doc_classes/GLTFDocument.xml
@@ -16,6 +16,8 @@
<param index="3" name="flags" type="int" default="0" />
<param index="4" name="bake_fps" type="int" default="30" />
<description>
+ Takes a [PackedByteArray] defining a gLTF and returns a [GLTFState] object through the [param state] parameter.
+ [b]Note:[/b] The [param base_path] tells [method append_from_buffer] where to find dependencies and can be empty.
</description>
</method>
<method name="append_from_file">
@@ -26,6 +28,8 @@
<param index="3" name="bake_fps" type="int" default="30" />
<param index="4" name="base_path" type="String" default="&quot;&quot;" />
<description>
+ Takes a path to a gLTF file and returns a [GLTFState] object through the [param state] parameter.
+ [b]Note:[/b] The [param base_path] tells [method append_from_file] where to find dependencies and can be empty.
</description>
</method>
<method name="append_from_scene">
@@ -35,12 +39,14 @@
<param index="2" name="flags" type="int" default="0" />
<param index="3" name="bake_fps" type="int" default="30" />
<description>
+ Takes a Godot Engine scene node and returns a [GLTFState] object through the [param state] parameter.
</description>
</method>
<method name="generate_buffer">
<return type="PackedByteArray" />
<param index="0" name="state" type="GLTFState" />
<description>
+ Takes a [GLTFState] object through the [param state] parameter and returns a gLTF [PackedByteArray].
</description>
</method>
<method name="generate_scene">
@@ -48,6 +54,7 @@
<param index="0" name="state" type="GLTFState" />
<param index="1" name="bake_fps" type="int" default="30" />
<description>
+ Takes a [GLTFState] object through the [param state] parameter and returns a Godot Engine scene node.
</description>
</method>
<method name="register_gltf_document_extension" qualifiers="static">
@@ -64,6 +71,8 @@
<param index="0" name="state" type="GLTFState" />
<param index="1" name="path" type="String" />
<description>
+ Takes a [GLTFState] object through the [param state] parameter and writes a glTF file to the filesystem.
+ [b]Note:[/b] The extension of the glTF file determines if it is a .glb binary file or a .gltf file.
</description>
</method>
</methods>
diff --git a/modules/gltf/doc_classes/GLTFDocumentExtension.xml b/modules/gltf/doc_classes/GLTFDocumentExtension.xml
index adc32df8dc..87d3d9bcb0 100644
--- a/modules/gltf/doc_classes/GLTFDocumentExtension.xml
+++ b/modules/gltf/doc_classes/GLTFDocumentExtension.xml
@@ -11,6 +11,16 @@
<tutorials>
</tutorials>
<methods>
+ <method name="_convert_scene_node" qualifiers="virtual">
+ <return type="void" />
+ <param index="0" name="state" type="GLTFState" />
+ <param index="1" name="gltf_node" type="GLTFNode" />
+ <param index="2" name="scene_node" type="Node" />
+ <description>
+ Part of the export process. This method is run after [method _export_preflight] and before [method _export_node].
+ Runs when converting the data from a Godot scene node. This method can be used to process the Godot scene node data into a format that can be used by [method _export_node].
+ </description>
+ </method>
<method name="_export_node" qualifiers="virtual">
<return type="int" />
<param index="0" name="state" type="GLTFState" />
@@ -18,23 +28,40 @@
<param index="2" name="json" type="Dictionary" />
<param index="3" name="node" type="Node" />
<description>
+ Part of the export process. This method is run after [method _convert_scene_node] and before [method _export_post].
+ This method can be used to modify the final JSON of each node.
</description>
</method>
<method name="_export_post" qualifiers="virtual">
<return type="int" />
<param index="0" name="state" type="GLTFState" />
<description>
+ Part of the export process. This method is run last, after all other parts of the export process.
+ This method can be used to modify the final JSON of the generated GLTF file.
</description>
</method>
<method name="_export_preflight" qualifiers="virtual">
<return type="int" />
<param index="0" name="root" type="Node" />
<description>
+ Part of the export process. This method is run first, before all other parts of the export process.
+ The return value is used to determine if this GLTFDocumentExtension class should be used for exporting a given GLTF file. If [constant OK], the export will use this GLTFDocumentExtension class. If not overridden, [constant OK] is returned.
+ </description>
+ </method>
+ <method name="_generate_scene_node" qualifiers="virtual">
+ <return type="Node3D" />
+ <param index="0" name="state" type="GLTFState" />
+ <param index="1" name="gltf_node" type="GLTFNode" />
+ <param index="2" name="scene_parent" type="Node" />
+ <description>
+ Part of the import process. This method is run after [method _parse_node_extensions] and before [method _import_post_parse].
+ Runs when generating a Godot scene node from a GLTFNode. The returned node will be added to the scene tree. Multiple nodes can be generated in this step if they are added as a child of the returned node.
</description>
</method>
<method name="_get_supported_extensions" qualifiers="virtual">
<return type="PackedStringArray" />
<description>
+ Part of the import process. This method is run after [method _import_preflight] and before [method _parse_node_extensions].
Returns an array of the GLTF extensions supported by this GLTFDocumentExtension class. This is used to validate if a GLTF file with required extensions can be loaded.
</description>
</method>
@@ -45,6 +72,8 @@
<param index="2" name="json" type="Dictionary" />
<param index="3" name="node" type="Node" />
<description>
+ Part of the import process. This method is run after [method _import_post_parse] and before [method _import_post].
+ This method can be used to make modifications to each of the generated Godot scene nodes.
</description>
</method>
<method name="_import_post" qualifiers="virtual">
@@ -52,12 +81,16 @@
<param index="0" name="state" type="GLTFState" />
<param index="1" name="root" type="Node" />
<description>
+ Part of the import process. This method is run last, after all other parts of the import process.
+ This method can be used to modify the final Godot scene generated by the import process.
</description>
</method>
<method name="_import_post_parse" qualifiers="virtual">
<return type="int" />
<param index="0" name="state" type="GLTFState" />
<description>
+ Part of the import process. This method is run after [method _generate_scene_node] and before [method _import_node].
+ This method can be used to modify any of the data imported so far, including any scene nodes, before running the final per-node import step.
</description>
</method>
<method name="_import_preflight" qualifiers="virtual">
@@ -65,7 +98,18 @@
<param index="0" name="state" type="GLTFState" />
<param index="1" name="extensions" type="PackedStringArray" />
<description>
- This callback is run first. It is used to determine if this GLTFDocumentExtension class should be used for importing a given GLTF file. If [constant OK], the import will use this GLTFDocumentExtension class.
+ Part of the import process. This method is run first, before all other parts of the import process.
+ The return value is used to determine if this GLTFDocumentExtension class should be used for importing a given GLTF file. If [constant OK], the import will use this GLTFDocumentExtension class. If not overridden, [constant OK] is returned.
+ </description>
+ </method>
+ <method name="_parse_node_extensions" qualifiers="virtual">
+ <return type="int" />
+ <param index="0" name="state" type="GLTFState" />
+ <param index="1" name="gltf_node" type="GLTFNode" />
+ <param index="2" name="extensions" type="Dictionary" />
+ <description>
+ Part of the import process. This method is run after [method _get_supported_extensions] and before [method _generate_scene_node].
+ Runs when parsing the node extensions of a GLTFNode. This method can be used to process the extension JSON data into a format that can be used by [method _generate_scene_node].
</description>
</method>
</methods>
diff --git a/modules/gltf/extensions/gltf_document_extension.cpp b/modules/gltf/extensions/gltf_document_extension.cpp
index 56519f70d3..f997fe8f66 100644
--- a/modules/gltf/extensions/gltf_document_extension.cpp
+++ b/modules/gltf/extensions/gltf_document_extension.cpp
@@ -31,50 +31,77 @@
#include "gltf_document_extension.h"
void GLTFDocumentExtension::_bind_methods() {
- GDVIRTUAL_BIND(_get_supported_extensions);
+ // Import process.
GDVIRTUAL_BIND(_import_preflight, "state", "extensions");
+ GDVIRTUAL_BIND(_get_supported_extensions);
+ GDVIRTUAL_BIND(_parse_node_extensions, "state", "gltf_node", "extensions");
+ GDVIRTUAL_BIND(_generate_scene_node, "state", "gltf_node", "scene_parent");
GDVIRTUAL_BIND(_import_post_parse, "state");
GDVIRTUAL_BIND(_import_node, "state", "gltf_node", "json", "node");
GDVIRTUAL_BIND(_import_post, "state", "root");
+ // Export process.
GDVIRTUAL_BIND(_export_preflight, "root");
+ GDVIRTUAL_BIND(_convert_scene_node, "state", "gltf_node", "scene_node");
GDVIRTUAL_BIND(_export_node, "state", "gltf_node", "json", "node");
GDVIRTUAL_BIND(_export_post, "state");
}
+// Import process.
+Error GLTFDocumentExtension::import_preflight(Ref<GLTFState> p_state, Vector<String> p_extensions) {
+ ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
+ int err = OK;
+ GDVIRTUAL_CALL(_import_preflight, p_state, p_extensions, err);
+ return Error(err);
+}
+
Vector<String> GLTFDocumentExtension::get_supported_extensions() {
Vector<String> ret;
GDVIRTUAL_CALL(_get_supported_extensions, ret);
return ret;
}
-Error GLTFDocumentExtension::import_post(Ref<GLTFState> p_state, Node *p_root) {
- ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER);
+Error GLTFDocumentExtension::parse_node_extensions(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &p_extensions) {
ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
+ ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER);
int err = OK;
- GDVIRTUAL_CALL(_import_post, p_state, p_root, err);
+ GDVIRTUAL_CALL(_parse_node_extensions, p_state, p_gltf_node, p_extensions, err);
return Error(err);
}
-Error GLTFDocumentExtension::import_preflight(Ref<GLTFState> p_state, Vector<String> p_extensions) {
+Node3D *GLTFDocumentExtension::generate_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent) {
+ ERR_FAIL_NULL_V(p_state, nullptr);
+ ERR_FAIL_NULL_V(p_gltf_node, nullptr);
+ ERR_FAIL_NULL_V(p_scene_parent, nullptr);
+ Node3D *ret_node = nullptr;
+ GDVIRTUAL_CALL(_generate_scene_node, p_state, p_gltf_node, p_scene_parent, ret_node);
+ return ret_node;
+}
+
+Error GLTFDocumentExtension::import_post_parse(Ref<GLTFState> p_state) {
ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
int err = OK;
- GDVIRTUAL_CALL(_import_preflight, p_state, p_extensions, err);
+ GDVIRTUAL_CALL(_import_post_parse, p_state, err);
return Error(err);
}
-Error GLTFDocumentExtension::import_post_parse(Ref<GLTFState> p_state) {
+Error GLTFDocumentExtension::import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_dict, Node *p_node) {
ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
+ ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER);
+ ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER);
int err = OK;
- GDVIRTUAL_CALL(_import_post_parse, p_state, err);
+ GDVIRTUAL_CALL(_import_node, p_state, p_gltf_node, r_dict, p_node, err);
return Error(err);
}
-Error GLTFDocumentExtension::export_post(Ref<GLTFState> p_state) {
+Error GLTFDocumentExtension::import_post(Ref<GLTFState> p_state, Node *p_root) {
+ ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER);
ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
int err = OK;
- GDVIRTUAL_CALL(_export_post, p_state, err);
+ GDVIRTUAL_CALL(_import_post, p_state, p_root, err);
return Error(err);
}
+
+// Export process.
Error GLTFDocumentExtension::export_preflight(Node *p_root) {
ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER);
int err = OK;
@@ -82,20 +109,25 @@ Error GLTFDocumentExtension::export_preflight(Node *p_root) {
return Error(err);
}
-Error GLTFDocumentExtension::import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_dict, Node *p_node) {
+void GLTFDocumentExtension::convert_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_node) {
+ ERR_FAIL_NULL(p_state);
+ ERR_FAIL_NULL(p_gltf_node);
+ ERR_FAIL_NULL(p_scene_node);
+ GDVIRTUAL_CALL(_convert_scene_node, p_state, p_gltf_node, p_scene_node);
+}
+
+Error GLTFDocumentExtension::export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_dict, Node *p_node) {
ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER);
ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER);
int err = OK;
- GDVIRTUAL_CALL(_import_node, p_state, p_gltf_node, r_dict, p_node, err);
+ GDVIRTUAL_CALL(_export_node, p_state, p_gltf_node, r_dict, p_node, err);
return Error(err);
}
-Error GLTFDocumentExtension::export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_dict, Node *p_node) {
+Error GLTFDocumentExtension::export_post(Ref<GLTFState> p_state) {
ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
- ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER);
- ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER);
int err = OK;
- GDVIRTUAL_CALL(_export_node, p_state, p_gltf_node, r_dict, p_node, err);
+ GDVIRTUAL_CALL(_export_post, p_state, err);
return Error(err);
}
diff --git a/modules/gltf/extensions/gltf_document_extension.h b/modules/gltf/extensions/gltf_document_extension.h
index 43e29ea0ab..7cc9ca592f 100644
--- a/modules/gltf/extensions/gltf_document_extension.h
+++ b/modules/gltf/extensions/gltf_document_extension.h
@@ -40,20 +40,31 @@ protected:
static void _bind_methods();
public:
- virtual Vector<String> get_supported_extensions();
+ // Import process.
virtual Error import_preflight(Ref<GLTFState> p_state, Vector<String> p_extensions);
+ virtual Vector<String> get_supported_extensions();
+ virtual Error parse_node_extensions(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &p_extensions);
+ virtual Node3D *generate_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent);
virtual Error import_post_parse(Ref<GLTFState> p_state);
- virtual Error export_post(Ref<GLTFState> p_state);
+ virtual Error import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_json, Node *p_node);
virtual Error import_post(Ref<GLTFState> p_state, Node *p_node);
+ // Export process.
virtual Error export_preflight(Node *p_state);
- virtual Error import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_json, Node *p_node);
+ virtual void convert_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_node);
virtual Error export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_json, Node *p_node);
- GDVIRTUAL0R(Vector<String>, _get_supported_extensions);
+ virtual Error export_post(Ref<GLTFState> p_state);
+
+ // Import process.
GDVIRTUAL2R(int, _import_preflight, Ref<GLTFState>, Vector<String>);
+ GDVIRTUAL0R(Vector<String>, _get_supported_extensions);
+ GDVIRTUAL3R(int, _parse_node_extensions, Ref<GLTFState>, Ref<GLTFNode>, Dictionary);
+ GDVIRTUAL3R(Node3D *, _generate_scene_node, Ref<GLTFState>, Ref<GLTFNode>, Node *);
GDVIRTUAL1R(int, _import_post_parse, Ref<GLTFState>);
GDVIRTUAL4R(int, _import_node, Ref<GLTFState>, Ref<GLTFNode>, Dictionary, Node *);
GDVIRTUAL2R(int, _import_post, Ref<GLTFState>, Node *);
+ // Export process.
GDVIRTUAL1R(int, _export_preflight, Node *);
+ GDVIRTUAL3(_convert_scene_node, Ref<GLTFState>, Ref<GLTFNode>, Node *);
GDVIRTUAL4R(int, _export_node, Ref<GLTFState>, Ref<GLTFNode>, Dictionary, Node *);
GDVIRTUAL1R(int, _export_post, Ref<GLTFState>);
};
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 49797bb8fa..faa8ed267a 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -625,6 +625,11 @@ Error GLTFDocument::_parse_nodes(Ref<GLTFState> state) {
node->light = light;
}
}
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
+ ERR_CONTINUE(ext.is_null());
+ Error err = ext->parse_node_extensions(state, node, extensions);
+ ERR_CONTINUE_MSG(err != OK, "GLTF: Encountered error " + itos(err) + " when parsing node extensions for node " + node->get_name() + " in file " + state->filename + ". Continuing.");
+ }
}
if (n.has("children")) {
@@ -5266,6 +5271,10 @@ void GLTFDocument::_convert_scene_node(Ref<GLTFState> state, Node *p_current, co
AnimationPlayer *animation_player = Object::cast_to<AnimationPlayer>(p_current);
_convert_animation_player_to_gltf(animation_player, state, p_gltf_parent, p_gltf_root, gltf_node, p_current);
}
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
+ ERR_CONTINUE(ext.is_null());
+ ext->convert_scene_node(state, gltf_node, p_current);
+ }
GLTFNodeIndex current_node_i = state->nodes.size();
GLTFNodeIndex gltf_root = p_gltf_root;
if (gltf_root == -1) {
@@ -5589,21 +5598,32 @@ void GLTFDocument::_generate_scene_node(Ref<GLTFState> state, Node *scene_parent
// and attach it to the bone_attachment
scene_parent = bone_attachment;
}
- if (gltf_node->mesh >= 0) {
- current_node = _generate_mesh_instance(state, node_index);
- } else if (gltf_node->camera >= 0) {
- current_node = _generate_camera(state, node_index);
- } else if (gltf_node->light >= 0) {
- current_node = _generate_light(state, node_index);
+ // Check if any GLTFDocumentExtension classes want to generate a node for us.
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
+ ERR_CONTINUE(ext.is_null());
+ current_node = ext->generate_scene_node(state, gltf_node, scene_parent);
+ if (current_node) {
+ break;
+ }
}
-
- // We still have not managed to make a node.
+ // If none of our GLTFDocumentExtension classes generated us a node, we generate one.
if (!current_node) {
- current_node = _generate_spatial(state, node_index);
+ if (gltf_node->mesh >= 0) {
+ current_node = _generate_mesh_instance(state, node_index);
+ } else if (gltf_node->camera >= 0) {
+ current_node = _generate_camera(state, node_index);
+ } else if (gltf_node->light >= 0) {
+ current_node = _generate_light(state, node_index);
+ } else {
+ current_node = _generate_spatial(state, node_index);
+ }
}
+ // Add the node we generated and set the owner to the scene root.
scene_parent->add_child(current_node, true);
if (current_node != scene_root) {
- current_node->set_owner(scene_root);
+ Array args;
+ args.append(scene_root);
+ current_node->propagate_call(StringName("set_owner"), args);
}
current_node->set_transform(gltf_node->xform);
current_node->set_name(gltf_node->get_name());
@@ -5669,19 +5689,32 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> state, Node *scen
// and attach it to the bone_attachment
scene_parent = bone_attachment;
}
-
- // We still have not managed to make a node
- if (gltf_node->mesh >= 0) {
- current_node = _generate_mesh_instance(state, node_index);
- } else if (gltf_node->camera >= 0) {
- current_node = _generate_camera(state, node_index);
- } else if (gltf_node->light >= 0) {
- current_node = _generate_light(state, node_index);
+ // Check if any GLTFDocumentExtension classes want to generate a node for us.
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
+ ERR_CONTINUE(ext.is_null());
+ current_node = ext->generate_scene_node(state, gltf_node, scene_parent);
+ if (current_node) {
+ break;
+ }
+ }
+ // If none of our GLTFDocumentExtension classes generated us a node, we generate one.
+ if (!current_node) {
+ if (gltf_node->mesh >= 0) {
+ current_node = _generate_mesh_instance(state, node_index);
+ } else if (gltf_node->camera >= 0) {
+ current_node = _generate_camera(state, node_index);
+ } else if (gltf_node->light >= 0) {
+ current_node = _generate_light(state, node_index);
+ } else {
+ current_node = _generate_spatial(state, node_index);
+ }
}
-
+ // Add the node we generated and set the owner to the scene root.
scene_parent->add_child(current_node, true);
if (current_node != scene_root) {
- current_node->set_owner(scene_root);
+ Array args;
+ args.append(scene_root);
+ current_node->propagate_call(StringName("set_owner"), args);
}
// Do not set transform here. Transform is already applied to our bone.
current_node->set_name(gltf_node->get_name());
diff --git a/modules/mbedtls/packet_peer_mbed_dtls.cpp b/modules/mbedtls/packet_peer_mbed_dtls.cpp
index e84d95773d..e658668355 100644
--- a/modules/mbedtls/packet_peer_mbed_dtls.cpp
+++ b/modules/mbedtls/packet_peer_mbed_dtls.cpp
@@ -118,7 +118,6 @@ Error PacketPeerMbedDTLS::connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_vali
ERR_FAIL_COND_V(!p_base.is_valid() || !p_base->is_socket_connected(), ERR_INVALID_PARAMETER);
base = p_base;
- int ret = 0;
int authmode = p_validate_certs ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE;
Error err = tls_ctx->init_client(MBEDTLS_SSL_TRANSPORT_DATAGRAM, authmode, p_ca_certs);
@@ -130,7 +129,7 @@ Error PacketPeerMbedDTLS::connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_vali
status = STATUS_HANDSHAKING;
- if ((ret = _do_handshake()) != OK) {
+ if (_do_handshake() != OK) {
status = STATUS_ERROR_HOSTNAME_MISMATCH;
return FAILED;
}
@@ -158,7 +157,7 @@ Error PacketPeerMbedDTLS::accept_peer(Ref<PacketPeerUDP> p_base, Ref<CryptoKey>
status = STATUS_HANDSHAKING;
- if ((ret = _do_handshake()) != OK) {
+ if (_do_handshake() != OK) {
status = STATUS_ERROR;
return FAILED;
}
@@ -175,7 +174,7 @@ Error PacketPeerMbedDTLS::put_packet(const uint8_t *p_buffer, int p_bytes) {
int ret = mbedtls_ssl_write(tls_ctx->get_context(), p_buffer, p_bytes);
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
- ret = 0; // non blocking io
+ // Non blocking io.
} else if (ret <= 0) {
TLSContextMbedTLS::print_mbedtls_error(ret);
_cleanup();
diff --git a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp
index 4d996e6283..29208efb20 100644
--- a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp
+++ b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp
@@ -91,8 +91,6 @@ bool OpenXRHTCViveTrackerExtension::is_path_supported(const String &p_path) {
return available;
} else if (p_path == "/user/vive_tracker_htcx/role/chest") {
return available;
- } else if (p_path == "/user/vive_tracker_htcx/role/chest") {
- return available;
} else if (p_path == "/user/vive_tracker_htcx/role/camera") {
return available;
} else if (p_path == "/user/vive_tracker_htcx/role/keyboard") {
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 166325c551..cf2d8c9986 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -4750,7 +4750,10 @@ bool TextServerAdvanced::_shaped_text_update_breaks(const RID &p_shaped) {
i += (sd_glyphs[i].count - 1);
}
}
- ERR_FAIL_COND_V_MSG(sd_shift != sd->break_inserts, false, "Invalid break insert count!");
+ if (sd_shift < sd->break_inserts) {
+ // Note: should not happen with a normal text, but might be a case with special fonts that substitute a long string (with breaks opportunities in it) with a single glyph (like Font Awesome).
+ glyphs_new.resize(sd->glyphs.size() + sd_shift);
+ }
if (sd->break_inserts > 0) {
sd->glyphs = glyphs_new;
diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp
index 792103cd31..63909257d9 100644
--- a/modules/vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp
@@ -438,9 +438,7 @@ void AudioStreamOggVorbis::maybe_update_info() {
}
if (i == 0) {
packet->b_o_s = 1;
- }
- if (i == 0) {
ERR_FAIL_COND(!vorbis_synthesis_idheader(packet));
}
diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp
index 0dad4a2c1c..33f1071077 100644
--- a/platform/ios/export/export_plugin.cpp
+++ b/platform/ios/export/export_plugin.cpp
@@ -666,7 +666,7 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
Ref<Image> image;
String image_path = p_dest_dir.path_join("splash@2x.png");
image.instantiate();
- Error err = image->load(custom_launch_image_2x);
+ Error err = ImageLoader::load_image(custom_launch_image_2x, image);
if (err) {
image.unref();
@@ -680,7 +680,7 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
image.unref();
image_path = p_dest_dir.path_join("splash@3x.png");
image.instantiate();
- err = image->load(custom_launch_image_3x);
+ err = ImageLoader::load_image(custom_launch_image_3x, image);
if (err) {
image.unref();
@@ -697,7 +697,7 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
if (!splash_path.is_empty()) {
splash.instantiate();
- const Error err = splash->load(splash_path);
+ const Error err = ImageLoader::load_image(splash_path, splash);
if (err) {
splash.unref();
}
diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h
index 8e75b98302..8f315f736b 100644
--- a/platform/macos/display_server_macos.h
+++ b/platform/macos/display_server_macos.h
@@ -233,6 +233,7 @@ public:
void popup_close(WindowID p_window);
void set_is_resizing(bool p_is_resizing);
bool get_is_resizing() const;
+ void reparent_check(WindowID p_window);
void window_update(WindowID p_window);
void window_destroy(WindowID p_window);
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 3557511c28..3aff5b8b7e 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -2337,22 +2337,64 @@ void DisplayServerMacOS::window_set_current_screen(int p_screen, WindowID p_wind
}
}
-void DisplayServerMacOS::window_set_exclusive(WindowID p_window, bool p_exclusive) {
- _THREAD_SAFE_METHOD_
+void DisplayServerMacOS::reparent_check(WindowID p_window) {
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
- if (wd.exclusive != p_exclusive) {
- wd.exclusive = p_exclusive;
- if (wd.transient_parent != INVALID_WINDOW_ID) {
- WindowData &wd_parent = windows[wd.transient_parent];
- if (wd.exclusive) {
- ERR_FAIL_COND_MSG([[wd_parent.window_object childWindows] count] > 0, "Transient parent has another exclusive child.");
+ NSScreen *screen = [wd.window_object screen];
+
+ if (wd.transient_parent != INVALID_WINDOW_ID) {
+ WindowData &wd_parent = windows[wd.transient_parent];
+ NSScreen *parent_screen = [wd_parent.window_object screen];
+
+ if (parent_screen == screen) {
+ if (![[wd_parent.window_object childWindows] containsObject:wd.window_object]) {
+ if (wd.exclusive) {
+ ERR_FAIL_COND_MSG([[wd_parent.window_object childWindows] count] > 0, "Transient parent has another exclusive child.");
+ }
+ [wd.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
[wd_parent.window_object addChildWindow:wd.window_object ordered:NSWindowAbove];
- } else {
+ }
+ } else {
+ if ([[wd_parent.window_object childWindows] containsObject:wd.window_object]) {
[wd_parent.window_object removeChildWindow:wd.window_object];
+ [wd.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
+ [wd.window_object orderFront:nil];
}
}
}
+
+ for (const WindowID &child : wd.transient_children) {
+ WindowData &wd_child = windows[child];
+ NSScreen *child_screen = [wd_child.window_object screen];
+
+ if (child_screen == screen) {
+ if (![[wd.window_object childWindows] containsObject:wd_child.window_object]) {
+ if (wd_child.exclusive) {
+ ERR_FAIL_COND_MSG([[wd.window_object childWindows] count] > 0, "Transient parent has another exclusive child.");
+ }
+ if (wd_child.fullscreen) {
+ [wd_child.window_object toggleFullScreen:nil];
+ }
+ [wd_child.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
+ [wd.window_object addChildWindow:wd_child.window_object ordered:NSWindowAbove];
+ }
+ } else {
+ if ([[wd.window_object childWindows] containsObject:wd_child.window_object]) {
+ [wd.window_object removeChildWindow:wd_child.window_object];
+ [wd_child.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
+ }
+ }
+ }
+}
+
+void DisplayServerMacOS::window_set_exclusive(WindowID p_window, bool p_exclusive) {
+ _THREAD_SAFE_METHOD_
+ ERR_FAIL_COND(!windows.has(p_window));
+ WindowData &wd = windows[p_window];
+ if (wd.exclusive != p_exclusive) {
+ wd.exclusive = p_exclusive;
+ reparent_check(p_window);
+ }
}
Point2i DisplayServerMacOS::window_get_position(WindowID p_window) const {
@@ -2429,11 +2471,10 @@ void DisplayServerMacOS::window_set_transient(WindowID p_window, WindowID p_pare
wd_window.transient_parent = INVALID_WINDOW_ID;
wd_parent.transient_children.erase(p_window);
- [wd_window.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
-
- if (wd_window.exclusive) {
+ if ([[wd_parent.window_object childWindows] containsObject:wd_window.window_object]) {
[wd_parent.window_object removeChildWindow:wd_window.window_object];
}
+ [wd_window.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
} else {
ERR_FAIL_COND(!windows.has(p_parent));
ERR_FAIL_COND_MSG(wd_window.transient_parent != INVALID_WINDOW_ID, "Window already has a transient parent");
@@ -2441,11 +2482,7 @@ void DisplayServerMacOS::window_set_transient(WindowID p_window, WindowID p_pare
wd_window.transient_parent = p_parent;
wd_parent.transient_children.insert(p_window);
- [wd_window.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
-
- if (wd_window.exclusive) {
- [wd_parent.window_object addChildWindow:wd_window.window_object ordered:NSWindowAbove];
- }
+ reparent_check(p_window);
}
}
diff --git a/platform/macos/export/export_plugin.cpp b/platform/macos/export/export_plugin.cpp
index ae8c802caf..5860a4f0ae 100644
--- a/platform/macos/export/export_plugin.cpp
+++ b/platform/macos/export/export_plugin.cpp
@@ -34,6 +34,7 @@
#include "lipo.h"
#include "macho.h"
+#include "core/io/image_loader.h"
#include "core/string/translation.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
@@ -1269,8 +1270,10 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
icon->get_buffer(&data.write[0], icon->get_length());
}
} else {
- Ref<Image> icon = Image::load_from_file(iconpath);
- if (icon.is_valid() && !icon->is_empty()) {
+ Ref<Image> icon;
+ icon.instantiate();
+ err = ImageLoader::load_image(iconpath, icon);
+ if (err == OK && !icon->is_empty()) {
_make_icon(p_preset, icon, data);
}
}
diff --git a/platform/macos/godot_window_delegate.mm b/platform/macos/godot_window_delegate.mm
index 3bdbc8c5ec..27efd3ebb2 100644
--- a/platform/macos/godot_window_delegate.mm
+++ b/platform/macos/godot_window_delegate.mm
@@ -256,6 +256,15 @@
}
}
+- (void)windowDidChangeScreen:(NSNotification *)notification {
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
+ if (!ds || !ds->has_window(window_id)) {
+ return;
+ }
+
+ ds->reparent_check(window_id);
+}
+
- (void)windowDidMove:(NSNotification *)notification {
DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp
index bfd40e1c9c..f04177d79a 100644
--- a/platform/windows/export/export_plugin.cpp
+++ b/platform/windows/export/export_plugin.cpp
@@ -31,6 +31,7 @@
#include "export_plugin.h"
#include "core/config/project_settings.h"
+#include "core/io/image_loader.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
@@ -84,8 +85,10 @@ Error EditorExportPlatformWindows::_process_icon(const Ref<EditorExportPreset> &
f->seek(prev_offset);
}
} else {
- Ref<Image> src_image = Image::load_from_file(p_src_path);
- ERR_FAIL_COND_V(src_image.is_null() || src_image->is_empty(), ERR_CANT_OPEN);
+ Ref<Image> src_image;
+ src_image.instantiate();
+ err = ImageLoader::load_image(p_src_path, src_image);
+ ERR_FAIL_COND_V(err != OK || src_image->is_empty(), ERR_CANT_OPEN);
for (size_t i = 0; i < sizeof(icon_size) / sizeof(icon_size[0]); ++i) {
int size = (icon_size[i] == 0) ? 256 : icon_size[i];
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 724e5bcaf6..eb9f9039b7 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -959,7 +959,7 @@ void ColorPicker::_sample_draw() {
// Draw both old and new colors for easier comparison (only if spawned from a ColorPickerButton).
const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95));
- if (display_old_color && old_color.a < 1.0) {
+ if (old_color.a < 1.0) {
sample->draw_texture_rect(get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), rect_old, true);
}
@@ -1088,7 +1088,9 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
} else if (p_which == 1) {
if (actual_shape == SHAPE_HSV_RECTANGLE) {
Ref<Texture2D> hue = get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker"));
- c->draw_texture_rect(hue, Rect2(Point2(), c->get_size()));
+ c->draw_set_transform(Point2(), -Math_PI / 2, Size2(c->get_size().x, -c->get_size().y));
+ c->draw_texture_rect(hue, Rect2(Point2(), Size2(1, 1)));
+ c->draw_set_transform(Point2(), 0, Size2(1, 1));
int y = c->get_size().y - c->get_size().y * (1.0 - h);
Color col;
col.set_hsv(h, 1, 1);
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index 2ca1d6239e..9830b41389 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -71,7 +71,7 @@ void SplitContainerDragger::gui_input(const Ref<InputEvent> &p_event) {
Vector2i in_parent_pos = get_transform().xform(mm->get_position());
if (!sc->vertical && is_layout_rtl()) {
- sc->split_offset = drag_ofs - ((sc->vertical ? in_parent_pos.y : in_parent_pos.x) - drag_from);
+ sc->split_offset = drag_ofs - (in_parent_pos.x - drag_from);
} else {
sc->split_offset = drag_ofs + ((sc->vertical ? in_parent_pos.y : in_parent_pos.x) - drag_from);
}
@@ -194,7 +194,6 @@ void SplitContainer::_compute_middle_sep(bool p_clamp) {
// Clamp the split_offset if requested.
if (p_clamp) {
split_offset -= wished_middle_sep - middle_sep;
- p_clamp = false;
}
}
diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp
index cf6681f809..f87829cf71 100644
--- a/scene/gui/tab_bar.cpp
+++ b/scene/gui/tab_bar.cpp
@@ -385,9 +385,6 @@ void TabBar::_notification(int p_what) {
if (tabs[i].disabled) {
sb = theme_cache.tab_disabled_style;
col = theme_cache.font_disabled_color;
- } else if (i == current) {
- sb = theme_cache.tab_selected_style;
- col = theme_cache.font_selected_color;
} else {
sb = theme_cache.tab_unselected_style;
col = theme_cache.font_unselected_color;
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index e3c12b7e52..da73a479ce 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -2464,7 +2464,6 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol
ERR_FAIL_COND_V(idx == -2, T());
- bool result = true;
int next = 0;
real_t c = 0.0;
// prepare for all cases of interpolation
@@ -2596,10 +2595,7 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol
}
if (p_ok) {
- *p_ok = result;
- }
- if (!result) {
- return T();
+ *p_ok = true;
}
real_t tr = p_keys[idx].transition;
diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp
index 77110c5fbc..31b6b9e12f 100644
--- a/servers/physics_3d/godot_soft_body_3d.cpp
+++ b/servers/physics_3d/godot_soft_body_3d.cpp
@@ -1011,7 +1011,6 @@ void GodotSoftBody3D::predict_motion(real_t p_delta) {
} break;
case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
- gravity = Vector3(0, 0, 0);
gravity = area_gravity;
gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
} break;
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp
index 9653382e96..8e43869b4d 100644
--- a/servers/rendering/renderer_rd/effects/ss_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp
@@ -1332,7 +1332,6 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
for (int pass = 0; pass < blur_passes; pass++) {
int blur_pipeline = SSAO_BLUR_PASS;
if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
- blur_pipeline = SSAO_BLUR_PASS_SMART;
if (pass < blur_passes - 2) {
blur_pipeline = SSAO_BLUR_PASS_WIDE;
} else {
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 7590f76a0c..cc8238a8dd 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -796,7 +796,6 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
RenderingServerDefault::redraw_request(); // active particles means redraw request
- bool local_coords = true;
int dpc = particles_storage->particles_get_draw_passes(pt->particles);
if (dpc == 0) {
break; //nothing to draw
@@ -818,12 +817,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
if (particles_storage->particles_has_collision(pt->particles) && texture_storage->render_target_is_sdf_enabled(p_render_target)) {
//pass collision information
- Transform2D xform;
- if (local_coords) {
- xform = p_item->final_transform;
- } else {
- xform = p_canvas_transform_inverse;
- }
+ Transform2D xform = p_item->final_transform;
RID sdf_texture = texture_storage->render_target_get_sdf_texture(p_render_target);
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 9c964da2e8..c09b185137 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -170,10 +170,16 @@ RenderingDevice::VertexFormatID RenderingDevice::_vertex_format_create(const Typ
return vertex_format_create(descriptions);
}
-RID RenderingDevice::_vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers) {
+RID RenderingDevice::_vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers, const Vector<int64_t> &p_offsets) {
Vector<RID> buffers = Variant(p_src_buffers);
- return vertex_array_create(p_vertex_count, p_vertex_format, buffers);
+ Vector<uint64_t> offsets;
+ offsets.resize(p_offsets.size());
+ for (int i = 0; i < p_offsets.size(); i++) {
+ offsets.write[i] = p_offsets[i];
+ }
+
+ return vertex_array_create(p_vertex_count, p_vertex_format, buffers, offsets);
}
Ref<RDShaderSPIRV> RenderingDevice::_shader_compile_spirv_from_source(const Ref<RDShaderSource> &p_source, bool p_allow_cache) {
@@ -393,7 +399,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("vertex_buffer_create", "size_bytes", "data", "use_as_storage"), &RenderingDevice::vertex_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("vertex_format_create", "vertex_descriptions"), &RenderingDevice::_vertex_format_create);
- ClassDB::bind_method(D_METHOD("vertex_array_create", "vertex_count", "vertex_format", "src_buffers"), &RenderingDevice::_vertex_array_create);
+ ClassDB::bind_method(D_METHOD("vertex_array_create", "vertex_count", "vertex_format", "src_buffers", "offsets"), &RenderingDevice::_vertex_array_create, DEFVAL(Vector<int64_t>()));
ClassDB::bind_method(D_METHOD("index_buffer_create", "size_indices", "format", "data", "use_restart_indices"), &RenderingDevice::index_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("index_array_create", "index_buffer", "index_offset", "index_count"), &RenderingDevice::index_array_create);
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index d4dc1c0f7f..abdd07844a 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -683,7 +683,7 @@ public:
// This ID is warranted to be unique for the same formats, does not need to be freed
virtual VertexFormatID vertex_format_create(const Vector<VertexAttribute> &p_vertex_formats) = 0;
- virtual RID vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers) = 0;
+ virtual RID vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers, const Vector<uint64_t> &p_offsets = Vector<uint64_t>()) = 0;
enum IndexBufferFormat {
INDEX_BUFFER_FORMAT_UINT16,
@@ -1312,7 +1312,7 @@ protected:
RID _framebuffer_create_multipass(const TypedArray<RID> &p_textures, const TypedArray<RDFramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);
RID _sampler_create(const Ref<RDSamplerState> &p_state);
VertexFormatID _vertex_format_create(const TypedArray<RDVertexAttribute> &p_vertex_formats);
- RID _vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers);
+ RID _vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers, const Vector<int64_t> &p_offsets = Vector<int64_t>());
Ref<RDShaderSPIRV> _shader_compile_spirv_from_source(const Ref<RDShaderSource> &p_source, bool p_allow_cache = true);
Vector<uint8_t> _shader_compile_binary_from_spirv(const Ref<RDShaderSPIRV> &p_bytecode, const String &p_shader_name = "");
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 62f061c9c0..79fbc59b06 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -7590,7 +7590,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_BUG;
}
- if (b && b->parent_function && p_function_info.main_function) {
+ if (b->parent_function && p_function_info.main_function) {
_set_error(vformat(RTR("Using '%s' in the '%s' processor function is incorrect."), "return", b->parent_function->name));
return ERR_PARSE_ERROR;
}
@@ -8880,7 +8880,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
_set_error(RTR("Expected an uniform group identifier or `;`."));
}
return ERR_PARSE_ERROR;
- } else if (tk.type == TK_SEMICOLON && current_uniform_group_name.is_empty()) {
+ } else if (current_uniform_group_name.is_empty()) {
_set_error(RTR("Group needs to be opened before."));
return ERR_PARSE_ERROR;
} else {