summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/io/resource_loader.cpp7
-rw-r--r--doc/classes/ProjectSettings.xml5
-rw-r--r--doc/classes/ScriptEditorBase.xml2
-rw-r--r--editor/animation_bezier_editor.cpp2
-rw-r--r--editor/plugins/script_editor_plugin.cpp2
-rw-r--r--modules/gdscript/gdscript_editor.cpp13
-rw-r--r--modules/gltf/editor/editor_import_blend_runner.cpp67
-rw-r--r--modules/gltf/editor/editor_import_blend_runner.h1
-rw-r--r--modules/gltf/editor/editor_scene_importer_blend.cpp4
9 files changed, 81 insertions, 22 deletions
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 58ad61b621..ab263d9485 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -304,9 +304,10 @@ void ResourceLoader::_thread_load_function(void *p_userdata) {
thread_load_mutex.unlock();
// Thread-safe either if it's the current thread or a brand new one.
- bool mq_override_present = false;
+ thread_local bool mq_override_present = false;
CallQueue *own_mq_override = nullptr;
if (load_nesting == 0) {
+ mq_override_present = false;
load_paths_stack = memnew(Vector<String>);
if (!load_task.dependent_path.is_empty()) {
@@ -326,10 +327,6 @@ void ResourceLoader::_thread_load_function(void *p_userdata) {
}
// --
- if (!Thread::is_main_thread()) {
- set_current_thread_safe_for_nodes(true);
- }
-
Ref<Resource> res = _load(load_task.remapped_path, load_task.remapped_path != load_task.local_path ? load_task.local_path : String(), load_task.type_hint, load_task.cache_mode, &load_task.error, load_task.use_sub_threads, &load_task.progress);
if (mq_override_present) {
MessageQueue::get_singleton()->flush();
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 037f2f3811..b0f421e932 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -934,8 +934,9 @@
Changing this value allows setting up a multi-project scenario where there are multiple [code].csproj[/code]. Keep in mind that the Godot project is considered one of the C# projects in the workspace and it's root directory should contain the [code]project.godot[/code] and [code].csproj[/code] next to each other.
</member>
<member name="editor/export/convert_text_resources_to_binary" type="bool" setter="" getter="" default="true">
- If [code]true[/code], text resources are converted to a binary format on export. This decreases file sizes and speeds up loading slightly.
- [b]Note:[/b] If [member editor/export/convert_text_resources_to_binary] is [code]true[/code], [method @GDScript.load] will not be able to return the converted files in an exported project. Some file paths within the exported PCK will also change, such as [code]project.godot[/code] becoming [code]project.binary[/code]. If you rely on run-time loading of files present within the PCK, set [member editor/export/convert_text_resources_to_binary] to [code]false[/code].
+ If [code]true[/code], text resource ([code]tres[/code]) and text scene ([code]tscn[/code]) files are converted to their corresponding binary format on export. This decreases file sizes and speeds up loading slightly.
+ [b]Note:[/b] Because a resource's file extension may change in an exported project, it is heavily recommended to use [method @GDScript.load] or [ResourceLoader] instead of [FileAccess] to load resources dynamically.
+ [b]Note:[/b] The project settings file ([code]project.godot[/code]) will always be converted to binary on export, regardless of this setting.
</member>
<member name="editor/import/atlas_max_width" type="int" setter="" getter="" default="2048">
The maximum width to use when importing textures as an atlas. The value will be rounded to the nearest power of two when used. Use this to prevent imported textures from growing too large in the other direction.
diff --git a/doc/classes/ScriptEditorBase.xml b/doc/classes/ScriptEditorBase.xml
index 403608355a..638bc921d6 100644
--- a/doc/classes/ScriptEditorBase.xml
+++ b/doc/classes/ScriptEditorBase.xml
@@ -72,7 +72,7 @@
</description>
</signal>
<signal name="request_save_previous_state">
- <param index="0" name="line" type="int" />
+ <param index="0" name="state" type="Dictionary" />
<description>
Emitted when the user changes current script or moves caret by 10 or more columns within the same script.
</description>
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp
index 9e5281368a..48b9e01fd8 100644
--- a/editor/animation_bezier_editor.cpp
+++ b/editor/animation_bezier_editor.cpp
@@ -965,7 +965,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
real_t minimum_value = INFINITY;
real_t maximum_value = -INFINITY;
- for (const IntPair &E : selection) {
+ for (const IntPair &E : focused_keys) {
IntPair key_pair = E;
real_t time = animation->track_get_key_time(key_pair.first, key_pair.second);
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index a670c7937b..c51eb44aee 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -272,7 +272,7 @@ void ScriptEditorBase::_bind_methods() {
ADD_SIGNAL(MethodInfo("request_help", PropertyInfo(Variant::STRING, "topic")));
ADD_SIGNAL(MethodInfo("request_open_script_at_line", PropertyInfo(Variant::OBJECT, "script"), PropertyInfo(Variant::INT, "line")));
ADD_SIGNAL(MethodInfo("request_save_history"));
- ADD_SIGNAL(MethodInfo("request_save_previous_state", PropertyInfo(Variant::INT, "line")));
+ ADD_SIGNAL(MethodInfo("request_save_previous_state", PropertyInfo(Variant::DICTIONARY, "state")));
ADD_SIGNAL(MethodInfo("go_to_help", PropertyInfo(Variant::STRING, "what")));
ADD_SIGNAL(MethodInfo("search_in_files_requested", PropertyInfo(Variant::STRING, "text")));
ADD_SIGNAL(MethodInfo("replace_in_files_requested", PropertyInfo(Variant::STRING, "text")));
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index f557727718..b58b44973e 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -1959,11 +1959,14 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
break;
}
- if (base.value.in(index.value)) {
- Variant value = base.value.get(index.value);
- r_type = _type_from_variant(value, p_context);
- found = true;
- break;
+ {
+ bool valid;
+ Variant value = base.value.get(index.value, &valid);
+ if (valid) {
+ r_type = _type_from_variant(value, p_context);
+ found = true;
+ break;
+ }
}
// Look if it is a dictionary node.
diff --git a/modules/gltf/editor/editor_import_blend_runner.cpp b/modules/gltf/editor/editor_import_blend_runner.cpp
index 330310d92a..22c8adfe88 100644
--- a/modules/gltf/editor/editor_import_blend_runner.cpp
+++ b/modules/gltf/editor/editor_import_blend_runner.cpp
@@ -43,6 +43,7 @@ from xmlrpc.server import SimpleXMLRPCServer
req = threading.Condition()
res = threading.Condition()
info = None
+export_err = None
def xmlrpc_server():
server = SimpleXMLRPCServer(('127.0.0.1', %d))
server.register_function(export_gltf)
@@ -54,6 +55,10 @@ def export_gltf(opts):
req.notify()
with res:
res.wait()
+ if export_err:
+ raise export_err
+ # Important to return a value to prevent the error 'cannot marshal None unless allow_none is enabled'.
+ return 'BLENDER_GODOT_EXPORT_SUCCESSFUL'
if bpy.app.version < (3, 0, 0):
print('Blender 3.0 or higher is required.', file=sys.stderr)
threading.Thread(target=xmlrpc_server).start()
@@ -64,12 +69,13 @@ while True:
method, opts = info
if method == 'export_gltf':
try:
+ export_err = None
bpy.ops.wm.open_mainfile(filepath=opts['path'])
if opts['unpack_all']:
bpy.ops.file.unpack_all(method='USE_LOCAL')
bpy.ops.export_scene.gltf(**opts['gltf_options'])
- except:
- pass
+ except Exception as e:
+ export_err = e
info = None
with res:
res.notify()
@@ -184,7 +190,9 @@ Error EditorImportBlendRunner::do_import(const Dictionary &p_options) {
EditorSettings::get_singleton()->set_manually("filesystem/import/blender/rpc_port", 0);
rpc_port = 0;
}
- err = do_import_direct(p_options);
+ if (err != ERR_QUERY_FAILED) {
+ err = do_import_direct(p_options);
+ }
}
return err;
} else {
@@ -259,6 +267,7 @@ Error EditorImportBlendRunner::do_import_rpc(const Dictionary &p_options) {
// Wait for response.
bool done = false;
+ PackedByteArray response;
while (!done) {
status = client->get_status();
switch (status) {
@@ -268,7 +277,10 @@ Error EditorImportBlendRunner::do_import_rpc(const Dictionary &p_options) {
}
case HTTPClient::STATUS_BODY: {
client->poll();
- // Parse response here if needed. For now we can just ignore it.
+ response.append_array(client->read_response_body_chunk());
+ break;
+ }
+ case HTTPClient::STATUS_CONNECTED: {
done = true;
break;
}
@@ -278,9 +290,56 @@ Error EditorImportBlendRunner::do_import_rpc(const Dictionary &p_options) {
}
}
+ String response_text = "No response from Blender.";
+ if (response.size() > 0) {
+ response_text = String::utf8((const char *)response.ptr(), response.size());
+ }
+
+ if (client->get_response_code() != HTTPClient::RESPONSE_OK) {
+ ERR_FAIL_V_MSG(ERR_QUERY_FAILED, vformat("Error received from Blender - status code: %s, error: %s", client->get_response_code(), response_text));
+ } else if (response_text.find("BLENDER_GODOT_EXPORT_SUCCESSFUL") < 0) {
+ // Previous versions of Godot used a Python script where the RPC function did not return
+ // a value, causing the error 'cannot marshal None unless allow_none is enabled'.
+ // If an older version of Godot is running and has started Blender with this script,
+ // we will receive the error, but there's a good chance that the import was successful.
+ // We are discarding this error to maintain backward compatibility and prevent situations
+ // where the user needs to close the older version of Godot or kill Blender.
+ if (response_text.find("cannot marshal None unless allow_none is enabled") < 0) {
+ String error_message;
+ if (_extract_error_message_xml(response, error_message)) {
+ ERR_FAIL_V_MSG(ERR_QUERY_FAILED, vformat("Blender exportation failed: %s", error_message));
+ } else {
+ ERR_FAIL_V_MSG(ERR_QUERY_FAILED, vformat("Blender exportation failed: %s", response_text));
+ }
+ }
+ }
+
return OK;
}
+bool EditorImportBlendRunner::_extract_error_message_xml(const Vector<uint8_t> &p_response_data, String &r_error_message) {
+ // Based on RPC Xml spec from: https://xmlrpc.com/spec.md
+ Ref<XMLParser> parser = memnew(XMLParser);
+ Error err = parser->open_buffer(p_response_data);
+ if (err) {
+ return false;
+ }
+
+ r_error_message = String();
+ while (parser->read() == OK) {
+ if (parser->get_node_type() == XMLParser::NODE_TEXT) {
+ if (parser->get_node_data().size()) {
+ if (r_error_message.size()) {
+ r_error_message += " ";
+ }
+ r_error_message += parser->get_node_data().trim_suffix("\n");
+ }
+ }
+ }
+
+ return r_error_message.size();
+}
+
Error EditorImportBlendRunner::do_import_direct(const Dictionary &p_options) {
// Export glTF directly.
String python = vformat(PYTHON_SCRIPT_DIRECT, dict_to_python(p_options));
diff --git a/modules/gltf/editor/editor_import_blend_runner.h b/modules/gltf/editor/editor_import_blend_runner.h
index 626f3c9eba..b3b49ebfb2 100644
--- a/modules/gltf/editor/editor_import_blend_runner.h
+++ b/modules/gltf/editor/editor_import_blend_runner.h
@@ -47,6 +47,7 @@ class EditorImportBlendRunner : public Node {
void _resources_reimported(const PackedStringArray &p_files);
void _kill_blender();
void _notification(int p_what);
+ bool _extract_error_message_xml(const Vector<uint8_t> &p_response_data, String &r_error_message);
protected:
int rpc_port = 0;
diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp
index 519e2646a0..b474128fd6 100644
--- a/modules/gltf/editor/editor_scene_importer_blend.cpp
+++ b/modules/gltf/editor/editor_scene_importer_blend.cpp
@@ -132,12 +132,10 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_
}
#endif
- source_global = source_global.c_escape();
-
const String blend_basename = p_path.get_file().get_basename();
const String sink = ProjectSettings::get_singleton()->get_imported_files_path().path_join(
vformat("%s-%s.gltf", blend_basename, p_path.md5_text()));
- const String sink_global = ProjectSettings::get_singleton()->globalize_path(sink).c_escape();
+ const String sink_global = ProjectSettings::get_singleton()->globalize_path(sink);
// Handle configuration options.