summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/object.cpp5
-rw-r--r--core/resource.cpp17
-rw-r--r--core/variant_parser.cpp79
-rw-r--r--doc/classes/FileDialog.xml6
-rw-r--r--doc/classes/RigidBody2D.xml7
-rw-r--r--doc/classes/RigidBody3D.xml7
-rw-r--r--editor/editor_node.cpp18
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp6
-rw-r--r--editor/import/editor_scene_importer_gltf.h3
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp21
-rw-r--r--modules/assimp/editor_scene_importer_assimp.cpp8
-rw-r--r--modules/assimp/import_state.h3
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.cpp1
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.cpp15
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.h6
-rw-r--r--modules/gdscript/language_server/gdscript_language_server.cpp1
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.cpp1
-rw-r--r--modules/gdscript/language_server/gdscript_workspace.cpp13
-rw-r--r--scene/animation/animation_player.cpp2
-rw-r--r--scene/gui/file_dialog.cpp5
-rw-r--r--scene/resources/default_theme/default_theme.cpp2
-rw-r--r--scene/resources/default_theme/icon_file.pngbin0 -> 183 bytes
-rw-r--r--scene/resources/default_theme/theme_data.h4
-rw-r--r--scene/resources/packed_scene.cpp3
-rw-r--r--servers/physics_2d/broad_phase_2d_basic.cpp4
-rw-r--r--servers/physics_2d/broad_phase_2d_hash_grid.cpp5
-rw-r--r--servers/physics_2d/space_2d_sw.cpp8
-rw-r--r--servers/physics_3d/broad_phase_3d_basic.cpp4
-rw-r--r--servers/physics_3d/space_3d_sw.cpp8
29 files changed, 144 insertions, 118 deletions
diff --git a/core/object.cpp b/core/object.cpp
index f3c5a13809..3ea3e27d41 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -2038,7 +2038,7 @@ void ObjectDB::cleanup() {
if (slot_count > 0) {
spin_lock.lock();
- WARN_PRINT("ObjectDB Instances still exist!");
+ WARN_PRINT("ObjectDB instances leaked at exit (run with --verbose for details).");
if (OS::get_singleton()->is_stdout_verbose()) {
for (uint32_t i = 0; i < slot_count; i++) {
uint32_t slot = object_slots[i].next_free;
@@ -2049,12 +2049,13 @@ void ObjectDB::cleanup() {
node_name = " - Node name: " + String(obj->call("get_name"));
}
if (obj->is_class("Resource")) {
- node_name = " - Resource name: " + String(obj->call("get_name")) + " Path: " + String(obj->call("get_path"));
+ node_name = " - Resource path: " + String(obj->call("get_path"));
}
uint64_t id = uint64_t(slot) | (uint64_t(object_slots[slot].validator) << OBJECTDB_VALIDATOR_BITS) | (object_slots[slot].is_reference ? OBJECTDB_REFERENCE_BIT : 0);
print_line("Leaked instance: " + String(obj->get_class()) + ":" + itos(id) + node_name);
}
+ print_line("Hint: Leaked instances typically happen when nodes are removed from the scene tree (with `remove_child()`) but not freed (with `free()` or `queue_free()`).");
}
spin_lock.unlock();
}
diff --git a/core/resource.cpp b/core/resource.cpp
index 0af8c9c2b3..3b589793ef 100644
--- a/core/resource.cpp
+++ b/core/resource.cpp
@@ -33,6 +33,7 @@
#include "core/core_string_names.h"
#include "core/io/resource_loader.h"
#include "core/os/file_access.h"
+#include "core/os/os.h"
#include "core/script_language.h"
#include "scene/main/node.h" //only so casting works
@@ -431,7 +432,14 @@ void ResourceCache::setup() {
void ResourceCache::clear() {
if (resources.size()) {
- ERR_PRINT("Resources Still in use at Exit!");
+ ERR_PRINT("Resources still in use at exit (run with --verbose for details).");
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ const String *K = nullptr;
+ while ((K = resources.next(K))) {
+ Resource *r = resources[*K];
+ print_line(vformat("Resource still in use: %s (%s)", *K, r->get_class()));
+ }
+ }
}
resources.clear();
@@ -442,12 +450,6 @@ void ResourceCache::clear() {
}
void ResourceCache::reload_externals() {
- /*
- const String *K=nullptr;
- while ((K=resources.next(K))) {
- resources[*K]->reload_external_data();
- }
- */
}
bool ResourceCache::has(const String &p_path) {
@@ -530,6 +532,5 @@ void ResourceCache::dump(const char *p_file, bool p_short) {
}
lock->read_unlock();
-
#endif
}
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
index bdcad03353..74f4f32c0e 100644
--- a/core/variant_parser.cpp
+++ b/core/variant_parser.cpp
@@ -479,12 +479,6 @@ Error VariantParser::_parse_construct(Stream *p_stream, Vector<T> &r_construct,
}
Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser) {
- /* {
- Error err = get_token(p_stream,token,line,r_err_str);
- if (err)
- return err;
- }*/
-
if (token.type == TK_CURLY_BRACKET_OPEN) {
Dictionary d;
Error err = _parse_dictionary(d, p_stream, line, r_err_str, p_res_parser);
@@ -501,7 +495,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = a;
return OK;
-
} else if (token.type == TK_IDENTIFIER) {
String id = token.value;
if (id == "true") {
@@ -523,10 +516,10 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
if (args.size() != 2) {
r_err_str = "Expected 2 arguments for constructor";
+ return ERR_PARSE_ERROR;
}
value = Vector2(args[0], args[1]);
- return OK;
} else if (id == "Vector2i") {
Vector<int32_t> args;
Error err = _parse_construct<int32_t>(p_stream, args, line, r_err_str);
@@ -536,10 +529,10 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
if (args.size() != 2) {
r_err_str = "Expected 2 arguments for constructor";
+ return ERR_PARSE_ERROR;
}
value = Vector2i(args[0], args[1]);
- return OK;
} else if (id == "Rect2") {
Vector<float> args;
Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
@@ -549,10 +542,10 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
if (args.size() != 4) {
r_err_str = "Expected 4 arguments for constructor";
+ return ERR_PARSE_ERROR;
}
value = Rect2(args[0], args[1], args[2], args[3]);
- return OK;
} else if (id == "Rect2i") {
Vector<int32_t> args;
Error err = _parse_construct<int32_t>(p_stream, args, line, r_err_str);
@@ -562,10 +555,10 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
if (args.size() != 4) {
r_err_str = "Expected 4 arguments for constructor";
+ return ERR_PARSE_ERROR;
}
value = Rect2i(args[0], args[1], args[2], args[3]);
- return OK;
} else if (id == "Vector3") {
Vector<float> args;
Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
@@ -575,10 +568,10 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
if (args.size() != 3) {
r_err_str = "Expected 3 arguments for constructor";
+ return ERR_PARSE_ERROR;
}
value = Vector3(args[0], args[1], args[2]);
- return OK;
} else if (id == "Vector3i") {
Vector<int32_t> args;
Error err = _parse_construct<int32_t>(p_stream, args, line, r_err_str);
@@ -588,12 +581,11 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
if (args.size() != 3) {
r_err_str = "Expected 3 arguments for constructor";
+ return ERR_PARSE_ERROR;
}
value = Vector3i(args[0], args[1], args[2]);
- return OK;
} else if (id == "Transform2D" || id == "Matrix32") { //compatibility
-
Vector<float> args;
Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
if (err) {
@@ -602,13 +594,14 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
if (args.size() != 6) {
r_err_str = "Expected 6 arguments for constructor";
+ return ERR_PARSE_ERROR;
}
+
Transform2D m;
m[0] = Vector2(args[0], args[1]);
m[1] = Vector2(args[2], args[3]);
m[2] = Vector2(args[4], args[5]);
value = m;
- return OK;
} else if (id == "Plane") {
Vector<float> args;
Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
@@ -618,10 +611,10 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
if (args.size() != 4) {
r_err_str = "Expected 4 arguments for constructor";
+ return ERR_PARSE_ERROR;
}
value = Plane(args[0], args[1], args[2], args[3]);
- return OK;
} else if (id == "Quat") {
Vector<float> args;
Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
@@ -631,11 +624,10 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
if (args.size() != 4) {
r_err_str = "Expected 4 arguments for constructor";
+ return ERR_PARSE_ERROR;
}
value = Quat(args[0], args[1], args[2], args[3]);
- return OK;
-
} else if (id == "AABB" || id == "Rect3") {
Vector<float> args;
Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
@@ -645,13 +637,11 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
if (args.size() != 6) {
r_err_str = "Expected 6 arguments for constructor";
+ return ERR_PARSE_ERROR;
}
value = AABB(Vector3(args[0], args[1], args[2]), Vector3(args[3], args[4], args[5]));
- return OK;
-
} else if (id == "Basis" || id == "Matrix3") { //compatibility
-
Vector<float> args;
Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
if (err) {
@@ -660,10 +650,10 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
if (args.size() != 9) {
r_err_str = "Expected 9 arguments for constructor";
+ return ERR_PARSE_ERROR;
}
value = Basis(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
- return OK;
} else if (id == "Transform") {
Vector<float> args;
Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
@@ -673,11 +663,10 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
if (args.size() != 12) {
r_err_str = "Expected 12 arguments for constructor";
+ return ERR_PARSE_ERROR;
}
value = Transform(Basis(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]), Vector3(args[9], args[10], args[11]));
- return OK;
-
} else if (id == "Color") {
Vector<float> args;
Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
@@ -687,11 +676,10 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
if (args.size() != 4) {
r_err_str = "Expected 4 arguments for constructor";
+ return ERR_PARSE_ERROR;
}
value = Color(args[0], args[1], args[2], args[3]);
- return OK;
-
} else if (id == "NodePath") {
get_token(p_stream, token, line, r_err_str);
if (token.type != TK_PARENTHESIS_OPEN) {
@@ -712,7 +700,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
r_err_str = "Expected ')'";
return ERR_PARSE_ERROR;
}
-
} else if (id == "RID") {
get_token(p_stream, token, line, r_err_str);
if (token.type != TK_PARENTHESIS_OPEN) {
@@ -733,8 +720,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
r_err_str = "Expected ')'";
return ERR_PARSE_ERROR;
}
-
- return OK;
} else if (id == "Object") {
get_token(p_stream, token, line, r_err_str);
if (token.type != TK_PARENTHESIS_OPEN) {
@@ -834,7 +819,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
at_key = true;
}
}
-
} else if (id == "Resource" || id == "SubResource" || id == "ExtResource") {
get_token(p_stream, token, line, r_err_str);
if (token.type != TK_PARENTHESIS_OPEN) {
@@ -850,8 +834,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = res;
-
- return OK;
} else if (p_res_parser && id == "ExtResource" && p_res_parser->ext_func) {
RES res;
Error err = p_res_parser->ext_func(p_res_parser->userdata, p_stream, res, line, r_err_str);
@@ -860,8 +842,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = res;
-
- return OK;
} else if (p_res_parser && id == "SubResource" && p_res_parser->sub_func) {
RES res;
Error err = p_res_parser->sub_func(p_res_parser->userdata, p_stream, res, line, r_err_str);
@@ -870,8 +850,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = res;
-
- return OK;
} else {
get_token(p_stream, token, line, r_err_str);
if (token.type == TK_STRING) {
@@ -889,14 +867,11 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = res;
- return OK;
-
} else {
r_err_str = "Expected string as argument for Resource().";
return ERR_PARSE_ERROR;
}
}
-
} else if (id == "PackedByteArray" || id == "PoolByteArray" || id == "ByteArray") {
Vector<uint8_t> args;
Error err = _parse_construct<uint8_t>(p_stream, args, line, r_err_str);
@@ -915,9 +890,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = arr;
-
- return OK;
-
} else if (id == "PackedInt32Array" || id == "PackedIntArray" || id == "PoolIntArray" || id == "IntArray") {
Vector<int32_t> args;
Error err = _parse_construct<int32_t>(p_stream, args, line, r_err_str);
@@ -936,9 +908,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = arr;
-
- return OK;
-
} else if (id == "PackedInt64Array") {
Vector<int64_t> args;
Error err = _parse_construct<int64_t>(p_stream, args, line, r_err_str);
@@ -957,9 +926,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = arr;
-
- return OK;
-
} else if (id == "PackedFloat32Array" || id == "PackedRealArray" || id == "PoolRealArray" || id == "FloatArray") {
Vector<float> args;
Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
@@ -978,8 +944,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = arr;
-
- return OK;
} else if (id == "PackedFloat64Array") {
Vector<double> args;
Error err = _parse_construct<double>(p_stream, args, line, r_err_str);
@@ -998,8 +962,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = arr;
-
- return OK;
} else if (id == "PackedStringArray" || id == "PoolStringArray" || id == "StringArray") {
get_token(p_stream, token, line, r_err_str);
if (token.type != TK_PARENTHESIS_OPEN) {
@@ -1046,9 +1008,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = arr;
-
- return OK;
-
} else if (id == "PackedVector2Array" || id == "PoolVector2Array" || id == "Vector2Array") {
Vector<float> args;
Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
@@ -1067,9 +1026,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = arr;
-
- return OK;
-
} else if (id == "PackedVector3Array" || id == "PoolVector3Array" || id == "Vector3Array") {
Vector<float> args;
Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
@@ -1088,9 +1044,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = arr;
-
- return OK;
-
} else if (id == "PackedColorArray" || id == "PoolColorArray" || id == "ColorArray") {
Vector<float> args;
Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
@@ -1109,15 +1062,13 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = arr;
-
- return OK;
} else {
r_err_str = "Unexpected identifier: '" + id + "'.";
return ERR_PARSE_ERROR;
}
+ // All above branches end up here unless they had an early return.
return OK;
-
} else if (token.type == TK_NUMBER) {
value = token.value;
return OK;
diff --git a/doc/classes/FileDialog.xml b/doc/classes/FileDialog.xml
index 99563ee367..f4868df6a4 100644
--- a/doc/classes/FileDialog.xml
+++ b/doc/classes/FileDialog.xml
@@ -132,6 +132,12 @@
</constant>
</constants>
<theme_items>
+ <theme_item name="file" type="Texture2D">
+ Custom icon for files.
+ </theme_item>
+ <theme_item name="file_icon_modulate" type="Color" default="Color( 1, 1, 1, 1 )">
+ The color modulation applied to the file icon.
+ </theme_item>
<theme_item name="files_disabled" type="Color" default="Color( 0, 0, 0, 0.7 )">
The color tint for disabled files (when the [FileDialog] is used in open folder mode).
</theme_item>
diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml
index 8379fc5b58..a3fd2e81fd 100644
--- a/doc/classes/RigidBody2D.xml
+++ b/doc/classes/RigidBody2D.xml
@@ -127,7 +127,7 @@
The body's total applied torque.
</member>
<member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep" default="true">
- If [code]true[/code], the body will not calculate forces and will act as a static body if there is no movement. The body will wake up when other forces are applied via collisions or by using [method apply_impulse] or [method add_force].
+ If [code]true[/code], the body can enter sleep mode when there is no movement. See [member sleeping].
</member>
<member name="contact_monitor" type="bool" setter="set_contact_monitor" getter="is_contact_monitor_enabled" default="false">
If [code]true[/code], the body will emit signals when it collides with another RigidBody2D. See also [member contacts_reported].
@@ -165,7 +165,7 @@
If a material is assigned to this property, it will be used instead of any other physics material, such as an inherited one.
</member>
<member name="sleeping" type="bool" setter="set_sleeping" getter="is_sleeping" default="false">
- If [code]true[/code], the body is sleeping and will not calculate forces until woken up by a collision or by using [method apply_impulse] or [method add_force].
+ If [code]true[/code], the body will not move and will not calculate forces until woken up by another body through, for example, a collision, or by using the [method apply_impulse] or [method add_force] methods.
</member>
<member name="weight" type="float" setter="set_weight" getter="get_weight" default="9.8">
The body's weight based on its mass and the [b]Default Gravity[/b] value in [b]Project &gt; Project Settings &gt; Physics &gt; 2d[/b].
@@ -214,7 +214,8 @@
</signal>
<signal name="sleeping_state_changed">
<description>
- Emitted when [member sleeping] changes.
+ Emitted when the physics engine changes the body's sleeping state.
+ [b]Note:[/b] Changing the value [member sleeping] will not trigger this signal. It is only emitted if the sleeping state is changed by the physics engine or [code]emit_signal("sleeping_state_changed")[/code] is used.
</description>
</signal>
</signals>
diff --git a/doc/classes/RigidBody3D.xml b/doc/classes/RigidBody3D.xml
index 1db818d6af..063cc3ca59 100644
--- a/doc/classes/RigidBody3D.xml
+++ b/doc/classes/RigidBody3D.xml
@@ -147,7 +147,7 @@
Lock the body's movement in the Z axis.
</member>
<member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep" default="true">
- If [code]true[/code], the body is deactivated when there is no movement, so it will not take part in the simulation until it is awaken by an external force.
+ If [code]true[/code], the body can enter sleep mode when there is no movement. See [member sleeping].
</member>
<member name="contact_monitor" type="bool" setter="set_contact_monitor" getter="is_contact_monitor_enabled" default="false">
If [code]true[/code], the RigidBody3D will emit signals when it collides with another RigidBody3D.
@@ -182,7 +182,7 @@
If a material is assigned to this property, it will be used instead of any other physics material, such as an inherited one.
</member>
<member name="sleeping" type="bool" setter="set_sleeping" getter="is_sleeping" default="false">
- If [code]true[/code], the body is sleeping and will not calculate forces until woken up by a collision or the [code]apply_impulse[/code] method.
+ If [code]true[/code], the body will not move and will not calculate forces until woken up by another body through, for example, a collision, or by using the [method apply_impulse] or [method add_force] methods.
</member>
<member name="weight" type="float" setter="set_weight" getter="get_weight" default="9.8">
The body's weight based on its mass and the global 3D gravity. Global values are set in [b]Project &gt; Project Settings &gt; Physics &gt; 3d[/b].
@@ -233,7 +233,8 @@
</signal>
<signal name="sleeping_state_changed">
<description>
- Emitted when the body changes its sleeping state. Either by sleeping or waking up.
+ Emitted when the physics engine changes the body's sleeping state.
+ [b]Note:[/b] Changing the value [member sleeping] will not trigger this signal. It is only emitted if the sleeping state is changed by the physics engine or [code]emit_signal("sleeping_state_changed")[/code] is used.
</description>
</signal>
</signals>
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 14a03c5377..9a9a1bfdeb 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -619,7 +619,9 @@ void EditorNode::_fs_changed() {
preset.unref();
}
if (preset.is_null()) {
- export_error = vformat("Invalid export preset name: %s.", preset_name);
+ export_error = vformat(
+ "Invalid export preset name: %s. Make sure `export_presets.cfg` is present in the current directory.",
+ preset_name);
} else {
Ref<EditorExportPlatform> platform = preset->get_platform();
if (platform.is_null()) {
@@ -903,19 +905,19 @@ void EditorNode::_dialog_display_load_error(String p_file, Error p_error) {
if (p_error) {
switch (p_error) {
case ERR_CANT_OPEN: {
- show_accept(vformat(TTR("Can't open '%s'. The file could have been moved or deleted."), p_file.get_file()), TTR("OK"));
+ show_accept(vformat(TTR("Can't open file '%s'. The file could have been moved or deleted."), p_file.get_file()), TTR("OK"));
} break;
case ERR_PARSE_ERROR: {
- show_accept(vformat(TTR("Error while parsing '%s'."), p_file.get_file()), TTR("OK"));
+ show_accept(vformat(TTR("Error while parsing file '%s'."), p_file.get_file()), TTR("OK"));
} break;
case ERR_FILE_CORRUPT: {
- show_accept(vformat(TTR("Unexpected end of file '%s'."), p_file.get_file()), TTR("OK"));
+ show_accept(vformat(TTR("Scene file '%s' appears to be invalid/corrupt."), p_file.get_file()), TTR("OK"));
} break;
case ERR_FILE_NOT_FOUND: {
- show_accept(vformat(TTR("Missing '%s' or its dependencies."), p_file.get_file()), TTR("OK"));
+ show_accept(vformat(TTR("Missing file '%s' or one its dependencies."), p_file.get_file()), TTR("OK"));
} break;
default: {
- show_accept(vformat(TTR("Error while loading '%s'."), p_file.get_file()), TTR("OK"));
+ show_accept(vformat(TTR("Error while loading file '%s'."), p_file.get_file()), TTR("OK"));
} break;
}
}
@@ -3254,13 +3256,13 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
if (!new_scene) {
sdata.unref();
- _dialog_display_load_error(lpath, ERR_FILE_NOT_FOUND);
+ _dialog_display_load_error(lpath, ERR_FILE_CORRUPT);
opening_prev = false;
if (prev != -1) {
set_current_scene(prev);
editor_data.remove_scene(idx);
}
- return ERR_FILE_NOT_FOUND;
+ return ERR_FILE_CORRUPT;
}
if (p_set_inherited) {
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index 6ffff09ce5..e340f41e3b 100644
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ b/editor/import/editor_scene_importer_gltf.cpp
@@ -952,6 +952,9 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
return OK;
}
+ bool compress_vert_data = state.import_flags & IMPORT_USE_COMPRESSION;
+ uint32_t mesh_flags = compress_vert_data ? Mesh::ARRAY_COMPRESS_DEFAULT : 0;
+
Array meshes = state.json["meshes"];
for (GLTFMeshIndex i = 0; i < meshes.size(); i++) {
print_verbose("glTF: Parsing mesh: " + itos(i));
@@ -1206,7 +1209,7 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
}
//just add it
- mesh.mesh->add_surface_from_arrays(primitive, array, morphs);
+ mesh.mesh->add_surface_from_arrays(primitive, array, morphs, Dictionary(), mesh_flags);
if (p.has("material")) {
const int material = p["material"];
@@ -2951,6 +2954,7 @@ Node *EditorSceneImporterGLTF::import_scene(const String &p_path, uint32_t p_fla
String version = asset["version"];
+ state.import_flags = p_flags;
state.major_version = version.get_slice(".", 0).to_int();
state.minor_version = version.get_slice(".", 1).to_int();
state.use_named_skin_binds = p_flags & IMPORT_USE_NAMED_SKIN_BINDS;
diff --git a/editor/import/editor_scene_importer_gltf.h b/editor/import/editor_scene_importer_gltf.h
index eee978ce16..d45410fa57 100644
--- a/editor/import/editor_scene_importer_gltf.h
+++ b/editor/import/editor_scene_importer_gltf.h
@@ -279,6 +279,9 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
Map<GLTFNodeIndex, Node *> scene_nodes;
+ // EditorSceneImporter::ImportFlags
+ uint32_t import_flags;
+
~GLTFState() {
for (int i = 0; i < nodes.size(); i++) {
memdelete(nodes[i]);
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 741614cf7d..796dd3f8b2 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -3654,15 +3654,19 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po
editor_data->get_undo_redo().add_do_method(ed, "live_debug_instance_node", editor->get_edited_scene()->get_path_to(parent), path, new_name);
editor_data->get_undo_redo().add_undo_method(ed, "live_debug_remove_node", NodePath(String(editor->get_edited_scene()->get_path_to(parent)) + "/" + new_name));
- Transform global_transform;
- Node3D *parent_spatial = Object::cast_to<Node3D>(parent);
- if (parent_spatial) {
- global_transform = parent_spatial->get_global_gizmo_transform();
- }
+ Node3D *node3d = Object::cast_to<Node3D>(instanced_scene);
+ if (node3d) {
+ Transform global_transform;
+ Node3D *parent_node3d = Object::cast_to<Node3D>(parent);
+ if (parent_node3d) {
+ global_transform = parent_node3d->get_global_gizmo_transform();
+ }
- global_transform.origin = spatial_editor->snap_point(_get_instance_position(p_point));
+ global_transform.origin = spatial_editor->snap_point(_get_instance_position(p_point));
+ global_transform.basis *= node3d->get_transform().basis;
- editor_data->get_undo_redo().add_do_method(instanced_scene, "set_global_transform", global_transform);
+ editor_data->get_undo_redo().add_do_method(instanced_scene, "set_global_transform", global_transform);
+ }
return true;
}
@@ -5393,6 +5397,9 @@ void Node3DEditor::_update_gizmos_menu() {
const int plugin_state = gizmo_plugins_by_name[i]->get_state();
gizmos_menu->add_multistate_item(TTR(plugin_name), 3, plugin_state, i);
const int idx = gizmos_menu->get_item_index(i);
+ gizmos_menu->set_item_tooltip(
+ idx,
+ TTR("Click to toggle between visibility states.\n\nOpen eye: Gizmo is visible.\nClosed eye: Gizmo is hidden.\nHalf-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\")."));
switch (plugin_state) {
case EditorNode3DGizmoPlugin::VISIBLE:
gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_visible"));
diff --git a/modules/assimp/editor_scene_importer_assimp.cpp b/modules/assimp/editor_scene_importer_assimp.cpp
index fed54a76b7..aedc4b690a 100644
--- a/modules/assimp/editor_scene_importer_assimp.cpp
+++ b/modules/assimp/editor_scene_importer_assimp.cpp
@@ -44,7 +44,6 @@
#include <assimp/scene.h>
#include <assimp/Importer.hpp>
#include <assimp/LogStream.hpp>
-#include <string>
// move into assimp
aiBone *get_bone_by_name(const aiScene *scene, aiString bone_name) {
@@ -102,8 +101,6 @@ void EditorSceneImporterAssimp::_bind_methods() {
Node *EditorSceneImporterAssimp::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps,
List<String> *r_missing_deps, Error *r_err) {
Assimp::Importer importer;
- std::wstring w_path = ProjectSettings::get_singleton()->globalize_path(p_path).c_str();
- std::string s_path(w_path.begin(), w_path.end());
importer.SetPropertyBool(AI_CONFIG_PP_FD_REMOVE, true);
// Cannot remove pivot points because the static mesh will be in the wrong place
importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, false);
@@ -299,6 +296,7 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene,
state.assimp_scene = scene;
state.max_bone_weights = p_max_bone_weights;
state.animation_player = nullptr;
+ state.import_flags = p_flags;
// populate light map
for (unsigned int l = 0; l < scene->mNumLights; l++) {
@@ -830,6 +828,8 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat
Ref<ArrayMesh> mesh;
mesh.instance();
bool has_uvs = false;
+ bool compress_vert_data = state.import_flags & IMPORT_USE_COMPRESSION;
+ uint32_t mesh_flags = compress_vert_data ? Mesh::ARRAY_COMPRESS_DEFAULT : 0;
Map<String, uint32_t> morph_mesh_string_lookup;
@@ -1267,7 +1267,7 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat
morphs[j] = array_copy;
}
- mesh->add_surface_from_arrays(primitive, array_mesh, morphs);
+ mesh->add_surface_from_arrays(primitive, array_mesh, morphs, Dictionary(), mesh_flags);
mesh->surface_set_material(i, mat);
mesh->surface_set_name(i, AssimpUtils::get_assimp_string(ai_mesh->mName));
}
diff --git a/modules/assimp/import_state.h b/modules/assimp/import_state.h
index 4a3bd17acb..ee22800ac4 100644
--- a/modules/assimp/import_state.h
+++ b/modules/assimp/import_state.h
@@ -87,6 +87,9 @@ struct ImportState {
// this means we can detect
// what bones are for other armatures
List<aiBone *> bone_stack;
+
+ // EditorSceneImporter::ImportFlags
+ uint32_t import_flags;
};
struct AssimpImageData {
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp
index f87e8687e5..330530be80 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.cpp
+++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "gdscript_extend_parser.h"
+
#include "../gdscript.h"
#include "core/io/json.h"
#include "gdscript_language_protocol.h"
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp
index 35bf4287b8..8a805196a1 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.cpp
+++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "gdscript_language_protocol.h"
+
#include "core/io/json.h"
#include "core/os/copymem.h"
#include "core/project_settings.h"
@@ -161,7 +162,7 @@ void GDScriptLanguageProtocol::_bind_methods() {
ClassDB::bind_method(D_METHOD("initialized", "params"), &GDScriptLanguageProtocol::initialized);
ClassDB::bind_method(D_METHOD("on_client_connected"), &GDScriptLanguageProtocol::on_client_connected);
ClassDB::bind_method(D_METHOD("on_client_disconnected"), &GDScriptLanguageProtocol::on_client_disconnected);
- ClassDB::bind_method(D_METHOD("notify_client", "p_method", "p_params"), &GDScriptLanguageProtocol::notify_client, DEFVAL(Variant()), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("notify_client", "method", "params"), &GDScriptLanguageProtocol::notify_client, DEFVAL(Variant()), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("is_smart_resolve_enabled"), &GDScriptLanguageProtocol::is_smart_resolve_enabled);
ClassDB::bind_method(D_METHOD("get_text_document"), &GDScriptLanguageProtocol::get_text_document);
ClassDB::bind_method(D_METHOD("get_workspace"), &GDScriptLanguageProtocol::get_workspace);
@@ -187,8 +188,12 @@ Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) {
Dictionary params;
params["path"] = workspace->root;
- Dictionary request = make_notification("gdscrip_client/changeWorkspace", params);
+ Dictionary request = make_notification("gdscript_client/changeWorkspace", params);
+ ERR_FAIL_COND_V_MSG(latest_client_id == -1, ret.to_json(),
+ "GDScriptLanguageProtocol: Can't initialize as no client is connected.");
+ ERR_FAIL_INDEX_V_MSG((uint64_t)latest_client_id, clients.size(), ret.to_json(),
+ vformat("GDScriptLanguageProtocol: Can't initialize invalid peer '%d'.", latest_client_id));
Ref<LSPeer> peer = clients.get(latest_client_id);
if (peer != nullptr) {
String msg = JSON::print(request);
@@ -268,8 +273,11 @@ void GDScriptLanguageProtocol::stop() {
void GDScriptLanguageProtocol::notify_client(const String &p_method, const Variant &p_params, int p_client_id) {
if (p_client_id == -1) {
+ ERR_FAIL_COND_MSG(latest_client_id == -1,
+ "GDScript LSP: Can't notify client as none was connected.");
p_client_id = latest_client_id;
}
+ ERR_FAIL_INDEX((uint64_t)p_client_id, clients.size());
Ref<LSPeer> peer = clients.get(p_client_id);
ERR_FAIL_COND(peer == nullptr);
@@ -290,13 +298,10 @@ bool GDScriptLanguageProtocol::is_goto_native_symbols_enabled() const {
GDScriptLanguageProtocol::GDScriptLanguageProtocol() {
server.instance();
singleton = this;
- _initialized = false;
workspace.instance();
text_document.instance();
set_scope("textDocument", text_document.ptr());
set_scope("completionItem", text_document.ptr());
set_scope("workspace", workspace.ptr());
workspace->root = ProjectSettings::get_singleton()->get_resource_path();
- latest_client_id = 0;
- next_client_id = 0;
}
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.h b/modules/gdscript/language_server/gdscript_language_protocol.h
index d929fd255d..564878313d 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.h
+++ b/modules/gdscript/language_server/gdscript_language_protocol.h
@@ -70,8 +70,8 @@ private:
HashMap<int, Ref<LSPeer>> clients;
Ref<TCP_Server> server;
- int latest_client_id;
- int next_client_id;
+ int latest_client_id = -1;
+ int next_client_id = 0;
Ref<GDScriptTextDocument> text_document;
Ref<GDScriptWorkspace> workspace;
@@ -82,7 +82,7 @@ private:
String process_message(const String &p_text);
String format_output(const String &p_text);
- bool _initialized;
+ bool _initialized = false;
protected:
static void _bind_methods();
diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp
index d53914814f..3387d262f8 100644
--- a/modules/gdscript/language_server/gdscript_language_server.cpp
+++ b/modules/gdscript/language_server/gdscript_language_server.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "gdscript_language_server.h"
+
#include "core/os/file_access.h"
#include "core/os/os.h"
#include "editor/editor_log.h"
diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp
index 778cb4d254..c6fe3169dc 100644
--- a/modules/gdscript/language_server/gdscript_text_document.cpp
+++ b/modules/gdscript/language_server/gdscript_text_document.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "gdscript_text_document.h"
+
#include "../gdscript.h"
#include "core/os/os.h"
#include "editor/editor_settings.h"
diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp
index 9285d88157..a203b9bfdb 100644
--- a/modules/gdscript/language_server/gdscript_workspace.cpp
+++ b/modules/gdscript/language_server/gdscript_workspace.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "gdscript_workspace.h"
+
#include "../gdscript.h"
#include "../gdscript_parser.h"
#include "core/project_settings.h"
@@ -41,12 +42,12 @@
void GDScriptWorkspace::_bind_methods() {
ClassDB::bind_method(D_METHOD("symbol"), &GDScriptWorkspace::symbol);
- ClassDB::bind_method(D_METHOD("parse_script", "p_path", "p_content"), &GDScriptWorkspace::parse_script);
- ClassDB::bind_method(D_METHOD("parse_local_script", "p_path"), &GDScriptWorkspace::parse_local_script);
- ClassDB::bind_method(D_METHOD("get_file_path", "p_uri"), &GDScriptWorkspace::get_file_path);
- ClassDB::bind_method(D_METHOD("get_file_uri", "p_path"), &GDScriptWorkspace::get_file_uri);
- ClassDB::bind_method(D_METHOD("publish_diagnostics", "p_path"), &GDScriptWorkspace::publish_diagnostics);
- ClassDB::bind_method(D_METHOD("generate_script_api", "p_path"), &GDScriptWorkspace::generate_script_api);
+ ClassDB::bind_method(D_METHOD("parse_script", "path", "content"), &GDScriptWorkspace::parse_script);
+ ClassDB::bind_method(D_METHOD("parse_local_script", "path"), &GDScriptWorkspace::parse_local_script);
+ ClassDB::bind_method(D_METHOD("get_file_path", "uri"), &GDScriptWorkspace::get_file_path);
+ ClassDB::bind_method(D_METHOD("get_file_uri", "path"), &GDScriptWorkspace::get_file_uri);
+ ClassDB::bind_method(D_METHOD("publish_diagnostics", "path"), &GDScriptWorkspace::publish_diagnostics);
+ ClassDB::bind_method(D_METHOD("generate_script_api", "path"), &GDScriptWorkspace::generate_script_api);
}
void GDScriptWorkspace::remove_cache_parser(const String &p_path) {
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 4e56f1acf0..319d0171b3 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -396,7 +396,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
Animation::UpdateMode update_mode = a->value_track_get_update_mode(i);
if (update_mode == Animation::UPDATE_CAPTURE) {
- if (p_started) {
+ if (p_started || pa->capture == Variant()) {
pa->capture = pa->object->get_indexed(pa->subpath);
}
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index be6b542ae1..630f3c8ff6 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -402,7 +402,9 @@ void FileDialog::update_file_list() {
TreeItem *root = tree->create_item();
Ref<Texture2D> folder = vbox->get_theme_icon("folder", "FileDialog");
+ Ref<Texture2D> file_icon = vbox->get_theme_icon("file", "FileDialog");
const Color folder_color = vbox->get_theme_color("folder_icon_modulate", "FileDialog");
+ const Color file_color = vbox->get_theme_color("file_icon_modulate", "FileDialog");
List<String> files;
List<String> dirs;
@@ -491,7 +493,10 @@ void FileDialog::update_file_list() {
if (get_icon_func) {
Ref<Texture2D> icon = get_icon_func(base_dir.plus_file(files.front()->get()));
ti->set_icon(0, icon);
+ } else {
+ ti->set_icon(0, file_icon);
}
+ ti->set_icon_modulate(0, file_color);
if (mode == FILE_MODE_OPEN_DIR) {
ti->set_custom_color(0, vbox->get_theme_color("files_disabled", "FileDialog"));
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index de39fac627..fd5c861eb5 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -726,7 +726,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
// FileDialog
theme->set_icon("folder", "FileDialog", make_icon(icon_folder_png));
+ theme->set_icon("file", "FileDialog", make_icon(icon_file_png));
theme->set_color("folder_icon_modulate", "FileDialog", Color(1, 1, 1));
+ theme->set_color("file_icon_modulate", "FileDialog", Color(1, 1, 1));
theme->set_color("files_disabled", "FileDialog", Color(0, 0, 0, 0.7));
// ColorPicker
diff --git a/scene/resources/default_theme/icon_file.png b/scene/resources/default_theme/icon_file.png
new file mode 100644
index 0000000000..bb4c361a8d
--- /dev/null
+++ b/scene/resources/default_theme/icon_file.png
Binary files differ
diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h
index 0a4e557451..edcdb90db9 100644
--- a/scene/resources/default_theme/theme_data.h
+++ b/scene/resources/default_theme/theme_data.h
@@ -150,6 +150,10 @@ static const unsigned char icon_color_pick_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0xaa, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x9d, 0x8e, 0x35, 0x82, 0x2, 0x41, 0x10, 0x45, 0x3b, 0xda, 0x3d, 0xca, 0xba, 0x44, 0x2b, 0x70, 0x9, 0xdc, 0xe1, 0x20, 0xe8, 0x91, 0x90, 0x78, 0x6e, 0x40, 0x4c, 0x82, 0x74, 0xff, 0xc2, 0x9d, 0x18, 0xa7, 0x6, 0x77, 0x7b, 0x23, 0x2d, 0xaf, 0x4c, 0xdc, 0xc, 0xbd, 0x65, 0x1e, 0x84, 0x80, 0x19, 0x55, 0x34, 0x60, 0x3e, 0xd0, 0xea, 0x17, 0x3d, 0x4a, 0xc8, 0x80, 0x1a, 0x60, 0xc2, 0x4f, 0xfd, 0x30, 0xe0, 0x1b, 0x2d, 0x16, 0xab, 0xa7, 0x2c, 0xe, 0x41, 0x68, 0xa5, 0xb9, 0xca, 0x91, 0x16, 0x2e, 0x54, 0xe0, 0x59, 0x54, 0x91, 0xfe, 0xa3, 0x3a, 0xff, 0xce, 0xab, 0x5b, 0xf, 0xa0, 0x4, 0x8f, 0x7b, 0x4c, 0xd3, 0x1b, 0xca, 0x32, 0xcc, 0x55, 0x7a, 0xf4, 0x76, 0x42, 0x2b, 0x97, 0x3e, 0xae, 0xfa, 0xdd, 0xd2, 0xd2, 0x8e, 0x72, 0xe1, 0x83, 0xaf, 0x9f, 0xa9, 0x28, 0x7d, 0x5b, 0xe2, 0x2a, 0xd, 0xc3, 0xa2, 0x78, 0xfe, 0x7d, 0x51, 0xfc, 0x0, 0x8a, 0x41, 0xcb, 0x3d, 0xb2, 0xae, 0x1c, 0xd3, 0xc, 0xa5, 0x30, 0x81, 0xc6, 0xda, 0x29, 0x8e, 0x83, 0x34, 0x25, 0x29, 0x4a, 0x46, 0x71, 0x1f, 0x33, 0xbe, 0x51, 0x89, 0xaf, 0x78, 0xe3, 0x97, 0x7e, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
+static const unsigned char icon_file_png[] = {
+ 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x2, 0x3, 0x0, 0x0, 0x0, 0x62, 0x9d, 0x17, 0xf2, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xe, 0xc3, 0x0, 0x0, 0xe, 0xc3, 0x1, 0xc7, 0x6f, 0xa8, 0x64, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x0, 0x0, 0x0, 0x9, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0x42, 0xf, 0xc7, 0x49, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x88, 0x95, 0xf0, 0xc6, 0x2a, 0x0, 0x0, 0x0, 0x21, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x0, 0x1, 0xae, 0x55, 0x2d, 0x20, 0xa2, 0x13, 0x44, 0x74, 0x39, 0x80, 0x88, 0x9, 0x40, 0xa2, 0x1, 0xc4, 0x5d, 0xb5, 0x80, 0x68, 0x2, 0x4, 0x0, 0x95, 0x34, 0x18, 0xe4, 0x5e, 0x46, 0xf7, 0x27, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
+};
+
static const unsigned char icon_folder_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x2e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xa0, 0x6, 0x78, 0x70, 0xf4, 0xc1, 0x7f, 0x24, 0x78, 0x18, 0x53, 0xc1, 0x7f, 0x54, 0x48, 0x50, 0xc1, 0x43, 0x1b, 0xbc, 0xa, 0x50, 0xad, 0x23, 0xa4, 0xe0, 0xff, 0x70, 0x52, 0x70, 0x18, 0x97, 0xf4, 0xfd, 0x43, 0xd4, 0x88, 0x4a, 0x0, 0x5a, 0xcb, 0x18, 0xab, 0x5e, 0xd9, 0x1a, 0x53, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 058e89cf2e..cb201bc539 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -98,6 +98,9 @@ Node *SceneState::instance(GenEditState p_edit_state) const {
}
#endif
parent = nparent;
+ } else {
+ // i == 0 is root node. Confirm that it doesn't have a parent defined.
+ ERR_FAIL_COND_V_MSG(n.parent != -1, nullptr, vformat("Invalid scene: root node %s cannot specify a parent node.", snames[n.name]));
}
Node *node = nullptr;
diff --git a/servers/physics_2d/broad_phase_2d_basic.cpp b/servers/physics_2d/broad_phase_2d_basic.cpp
index 8c7e715a09..3bdfc1a973 100644
--- a/servers/physics_2d/broad_phase_2d_basic.cpp
+++ b/servers/physics_2d/broad_phase_2d_basic.cpp
@@ -152,8 +152,10 @@ void BroadPhase2DBasic::update() {
void *data = nullptr;
if (pair_callback) {
data = pair_callback(elem_A->owner, elem_A->subindex, elem_B->owner, elem_B->subindex, unpair_userdata);
+ if (data) {
+ pair_map.insert(key, data);
+ }
}
- pair_map.insert(key, data);
}
}
}
diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.cpp b/servers/physics_2d/broad_phase_2d_hash_grid.cpp
index ae549ed2e4..cfd02cef2c 100644
--- a/servers/physics_2d/broad_phase_2d_hash_grid.cpp
+++ b/servers/physics_2d/broad_phase_2d_hash_grid.cpp
@@ -75,7 +75,10 @@ void BroadPhase2DHashGrid::_check_motion(Element *p_elem) {
if (pairing != E->get()->colliding) {
if (pairing) {
if (pair_callback) {
- E->get()->ud = pair_callback(p_elem->owner, p_elem->subindex, E->key()->owner, E->key()->subindex, pair_userdata);
+ void *ud = pair_callback(p_elem->owner, p_elem->subindex, E->key()->owner, E->key()->subindex, pair_userdata);
+ if (ud) {
+ E->get()->ud = ud;
+ }
}
} else {
if (unpair_callback) {
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index f4a21da254..966dcbd651 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -1111,6 +1111,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
void *Space2DSW::_broadphase_pair(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_self) {
+ if (!A->test_collision_mask(B)) {
+ return nullptr;
+ }
+
CollisionObject2DSW::Type type_A = A->get_type();
CollisionObject2DSW::Type type_B = B->get_type();
if (type_A > type_B) {
@@ -1143,6 +1147,10 @@ void *Space2DSW::_broadphase_pair(CollisionObject2DSW *A, int p_subindex_A, Coll
}
void Space2DSW::_broadphase_unpair(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_data, void *p_self) {
+ if (!p_data) {
+ return;
+ }
+
Space2DSW *self = (Space2DSW *)p_self;
self->collision_pairs--;
Constraint2DSW *c = (Constraint2DSW *)p_data;
diff --git a/servers/physics_3d/broad_phase_3d_basic.cpp b/servers/physics_3d/broad_phase_3d_basic.cpp
index 0f271b33af..f5ea1897a9 100644
--- a/servers/physics_3d/broad_phase_3d_basic.cpp
+++ b/servers/physics_3d/broad_phase_3d_basic.cpp
@@ -190,8 +190,10 @@ void BroadPhase3DBasic::update() {
void *data = nullptr;
if (pair_callback) {
data = pair_callback(elem_A->owner, elem_A->subindex, elem_B->owner, elem_B->subindex, unpair_userdata);
+ if (data) {
+ pair_map.insert(key, data);
+ }
}
- pair_map.insert(key, data);
}
}
}
diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/space_3d_sw.cpp
index 4d272bdabd..48f250ba35 100644
--- a/servers/physics_3d/space_3d_sw.cpp
+++ b/servers/physics_3d/space_3d_sw.cpp
@@ -987,6 +987,10 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, cons
}
void *Space3DSW::_broadphase_pair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_self) {
+ if (!A->test_collision_mask(B)) {
+ return nullptr;
+ }
+
CollisionObject3DSW::Type type_A = A->get_type();
CollisionObject3DSW::Type type_B = B->get_type();
if (type_A > type_B) {
@@ -1019,6 +1023,10 @@ void *Space3DSW::_broadphase_pair(CollisionObject3DSW *A, int p_subindex_A, Coll
}
void Space3DSW::_broadphase_unpair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_data, void *p_self) {
+ if (!p_data) {
+ return;
+ }
+
Space3DSW *self = (Space3DSW *)p_self;
self->collision_pairs--;
Constraint3DSW *c = (Constraint3DSW *)p_data;