summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COPYRIGHT.txt2
-rw-r--r--core/image.cpp22
-rw-r--r--core/math/a_star.cpp14
-rw-r--r--core/object.cpp5
-rw-r--r--core/resource.cpp17
-rw-r--r--core/variant_parser.cpp79
-rw-r--r--doc/classes/AStar.xml3
-rw-r--r--doc/classes/AStar2D.xml3
-rw-r--r--doc/classes/Dictionary.xml1
-rw-r--r--doc/classes/File.xml35
-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/editor_properties.cpp103
-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.cpp27
-rw-r--r--editor/plugins/node_3d_editor_plugin.h4
-rw-r--r--editor/plugins/script_editor_plugin.cpp1
-rw-r--r--editor/scene_tree_dock.cpp4
-rw-r--r--modules/assimp/editor_scene_importer_assimp.cpp11
-rw-r--r--modules/assimp/import_state.h3
-rw-r--r--modules/denoise/config.py8
-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/main/node.cpp61
-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
-rw-r--r--thirdparty/README.md6
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp2
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.hpp6
-rw-r--r--thirdparty/oidn/patches/godot-changes-c58c5216.patch (renamed from thirdparty/oidn/godot-changes-c58c5216.patch)0
-rw-r--r--thirdparty/oidn/patches/mkl-dnn-fix-vs2017-build.patch45
47 files changed, 363 insertions, 228 deletions
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt
index 2d32bf1fd9..fc3079c361 100644
--- a/COPYRIGHT.txt
+++ b/COPYRIGHT.txt
@@ -299,7 +299,7 @@ License: Zlib
Files: ./thirdparty/oidn/
Comment: Intel Open Image Denoise
-Copyright: 2009-2020, Intel Corporation
+Copyright: 2009-2019, Intel Corporation
License: Apache-2.0
Files: ./thirdparty/opus/
diff --git a/core/image.cpp b/core/image.cpp
index 4ab71128cd..0f15574053 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -2539,12 +2539,11 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P
int dst_y = dest_rect.position.y + i;
Color sc = img->get_pixel(src_x, src_y);
- Color dc = get_pixel(dst_x, dst_y);
- dc.r = (double)(sc.a * sc.r + dc.a * (1.0 - sc.a) * dc.r);
- dc.g = (double)(sc.a * sc.g + dc.a * (1.0 - sc.a) * dc.g);
- dc.b = (double)(sc.a * sc.b + dc.a * (1.0 - sc.a) * dc.b);
- dc.a = (double)(sc.a + dc.a * (1.0 - sc.a));
- set_pixel(dst_x, dst_y, dc);
+ if (sc.a != 0) {
+ Color dc = get_pixel(dst_x, dst_y);
+ dc = dc.blend(sc);
+ set_pixel(dst_x, dst_y, dc);
+ }
}
}
}
@@ -2594,12 +2593,11 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c
int dst_y = dest_rect.position.y + i;
Color sc = img->get_pixel(src_x, src_y);
- Color dc = get_pixel(dst_x, dst_y);
- dc.r = (double)(sc.a * sc.r + dc.a * (1.0 - sc.a) * dc.r);
- dc.g = (double)(sc.a * sc.g + dc.a * (1.0 - sc.a) * dc.g);
- dc.b = (double)(sc.a * sc.b + dc.a * (1.0 - sc.a) * dc.b);
- dc.a = (double)(sc.a + dc.a * (1.0 - sc.a));
- set_pixel(dst_x, dst_y, dc);
+ if (sc.a != 0) {
+ Color dc = get_pixel(dst_x, dst_y);
+ dc = dc.blend(sc);
+ set_pixel(dst_x, dst_y, dc);
+ }
}
}
}
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index 580a7cf7bb..30f712b2c3 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -280,10 +280,16 @@ int AStar::get_closest_point(const Vector3 &p_point, bool p_include_disabled) co
continue; // Disabled points should not be considered.
}
+ // Keep the closest point's ID, and in case of multiple closest IDs,
+ // the smallest one (makes it deterministic).
real_t d = p_point.distance_squared_to((*it.value)->pos);
- if (closest_id < 0 || d < closest_dist) {
+ int id = *(it.key);
+ if (d <= closest_dist) {
+ if (d == closest_dist && id > closest_id) { // Keep lowest ID.
+ continue;
+ }
closest_dist = d;
- closest_id = *(it.key);
+ closest_id = id;
}
}
@@ -291,7 +297,6 @@ int AStar::get_closest_point(const Vector3 &p_point, bool p_include_disabled) co
}
Vector3 AStar::get_closest_position_in_segment(const Vector3 &p_point) const {
- bool found = false;
real_t closest_dist = 1e20;
Vector3 closest_point;
@@ -311,10 +316,9 @@ Vector3 AStar::get_closest_position_in_segment(const Vector3 &p_point) const {
Vector3 p = Geometry3D::get_closest_point_to_segment(p_point, segment);
real_t d = p_point.distance_squared_to(p);
- if (!found || d < closest_dist) {
+ if (d < closest_dist) {
closest_point = p;
closest_dist = d;
- found = true;
}
}
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/AStar.xml b/doc/classes/AStar.xml
index e930abba87..2695e86f47 100644
--- a/doc/classes/AStar.xml
+++ b/doc/classes/AStar.xml
@@ -131,7 +131,8 @@
<argument index="1" name="include_disabled" type="bool" default="false">
</argument>
<description>
- Returns the ID of the closest point to [code]to_position[/code], optionally taking disabled points into account. Returns -1 if there are no points in the points pool.
+ Returns the ID of the closest point to [code]to_position[/code], optionally taking disabled points into account. Returns [code]-1[/code] if there are no points in the points pool.
+ [b]Note:[/b] If several points are the closest to [code]to_position[/code], the one with the smallest ID will be returned, ensuring a deterministic result.
</description>
</method>
<method name="get_closest_position_in_segment" qualifiers="const">
diff --git a/doc/classes/AStar2D.xml b/doc/classes/AStar2D.xml
index 16fa05041e..622d336ef6 100644
--- a/doc/classes/AStar2D.xml
+++ b/doc/classes/AStar2D.xml
@@ -114,7 +114,8 @@
<argument index="1" name="include_disabled" type="bool" default="false">
</argument>
<description>
- Returns the ID of the closest point to [code]to_position[/code], optionally taking disabled points into account. Returns -1 if there are no points in the points pool.
+ Returns the ID of the closest point to [code]to_position[/code], optionally taking disabled points into account. Returns [code]-1[/code] if there are no points in the points pool.
+ [b]Note:[/b] If several points are the closest to [code]to_position[/code], the one with the smallest ID will be returned, ensuring a deterministic result.
</description>
</method>
<method name="get_closest_position_in_segment" qualifiers="const">
diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml
index 385f4b7e59..4538e5ea4e 100644
--- a/doc/classes/Dictionary.xml
+++ b/doc/classes/Dictionary.xml
@@ -148,6 +148,7 @@
# The line below prints `true`, whereas it would have printed `false` if both variables were compared directly.
print(dict1.hash() == dict2.hash())
[/codeblock]
+ [b]Note:[/b] Dictionaries with the same keys/values but in a different order will have a different hash.
</description>
</method>
<method name="keys">
diff --git a/doc/classes/File.xml b/doc/classes/File.xml
index 17c65731ff..b90039e496 100644
--- a/doc/classes/File.xml
+++ b/doc/classes/File.xml
@@ -54,28 +54,28 @@
<return type="int">
</return>
<description>
- Returns the next 16 bits from the file as an integer.
+ Returns the next 16 bits from the file as an integer. See [method store_16] for details on what values can be stored and retrieved this way.
</description>
</method>
<method name="get_32" qualifiers="const">
<return type="int">
</return>
<description>
- Returns the next 32 bits from the file as an integer.
+ Returns the next 32 bits from the file as an integer. See [method store_32] for details on what values can be stored and retrieved this way.
</description>
</method>
<method name="get_64" qualifiers="const">
<return type="int">
</return>
<description>
- Returns the next 64 bits from the file as an integer.
+ Returns the next 64 bits from the file as an integer. See [method store_64] for details on what values can be stored and retrieved this way.
</description>
</method>
<method name="get_8" qualifiers="const">
<return type="int">
</return>
<description>
- Returns the next 8 bits from the file as an integer.
+ Returns the next 8 bits from the file as an integer. See [method store_8] for details on what values can be stored and retrieved this way.
</description>
</method>
<method name="get_as_text" qualifiers="const">
@@ -297,7 +297,26 @@
</argument>
<description>
Stores an integer as 16 bits in the file.
- [b]Note:[/b] The [code]value[/code] should lie in the interval [code][0, 2^16 - 1][/code].
+ [b]Note:[/b] The [code]value[/code] should lie in the interval [code][0, 2^16 - 1][/code]. Any other value will overflow and wrap around.
+ To store a signed integer, use [method store_64] or store a signed integer from the interval [code][-2^15, 2^15 - 1][/code] (i.e. keeping one bit for the signedness) and compute its sign manually when reading. For example:
+ [codeblock]
+ const MAX_15B = 1 &lt;&lt; 15
+ const MAX_16B = 1 &lt;&lt; 16
+
+ func unsigned16_to_signed(unsigned):
+ return (unsigned + MAX_15B) % MAX_16B - MAX_15B
+
+ func _ready():
+ var f = File.new()
+ f.open("user://file.dat", File.WRITE_READ)
+ f.store_16(-42) # This wraps around and stores 65494 (2^16 - 42).
+ f.store_16(121) # In bounds, will store 121.
+ f.seek(0) # Go back to start to read the stored value.
+ var read1 = f.get_16() # 65494
+ var read2 = f.get_16() # 121
+ var converted1 = unsigned16_to_signed(read1) # -42
+ var converted2 = unsigned16_to_signed(read2) # 121
+ [/codeblock]
</description>
</method>
<method name="store_32">
@@ -307,7 +326,8 @@
</argument>
<description>
Stores an integer as 32 bits in the file.
- [b]Note:[/b] The [code]value[/code] should lie in the interval [code][0, 2^32 - 1][/code].
+ [b]Note:[/b] The [code]value[/code] should lie in the interval [code][0, 2^32 - 1][/code]. Any other value will overflow and wrap around.
+ To store a signed integer, use [method store_64], or convert it manually (see [method store_16] for an example).
</description>
</method>
<method name="store_64">
@@ -327,7 +347,8 @@
</argument>
<description>
Stores an integer as 8 bits in the file.
- [b]Note:[/b] The [code]value[/code] should lie in the interval [code][0, 255][/code].
+ [b]Note:[/b] The [code]value[/code] should lie in the interval [code][0, 255][/code]. Any other value will overflow and wrap around.
+ To store a signed integer, use [method store_64], or convert it manually (see [method store_16] for an example).
</description>
</method>
<method name="store_buffer">
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/editor_properties.cpp b/editor/editor_properties.cpp
index 81c4e48974..cfa0c7a063 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -581,6 +581,7 @@ public:
Vector<Rect2> flag_rects;
Vector<String> names;
Vector<String> tooltips;
+ int hovered_index;
virtual Size2 get_minimum_size() const {
Ref<Font> font = get_theme_font("font", "Label");
@@ -596,56 +597,79 @@ public:
return String();
}
void _gui_input(const Ref<InputEvent> &p_ev) {
- Ref<InputEventMouseButton> mb = p_ev;
- if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
+ const Ref<InputEventMouseMotion> mm = p_ev;
+
+ if (mm.is_valid()) {
for (int i = 0; i < flag_rects.size(); i++) {
- if (flag_rects[i].has_point(mb->get_position())) {
- //toggle
- if (value & (1 << i)) {
- value &= ~(1 << i);
- } else {
- value |= (1 << i);
- }
- emit_signal("flag_changed", value);
+ if (flag_rects[i].has_point(mm->get_position())) {
+ // Used to highlight the hovered flag in the layers grid.
+ hovered_index = i;
update();
+ break;
}
}
}
- }
- void _notification(int p_what) {
- if (p_what == NOTIFICATION_DRAW) {
- Rect2 rect;
- rect.size = get_size();
- flag_rects.clear();
+ const Ref<InputEventMouseButton> mb = p_ev;
- int bsize = (rect.size.height * 80 / 100) / 2;
+ if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
+ // Toggle the flag.
+ // We base our choice on the hovered flag, so that it always matches the hovered flag.
+ if (value & (1 << hovered_index)) {
+ value &= ~(1 << hovered_index);
+ } else {
+ value |= (1 << hovered_index);
+ }
- int h = bsize * 2 + 1;
- int vofs = (rect.size.height - h) / 2;
+ emit_signal("flag_changed", value);
+ update();
+ }
+ }
- Color color = get_theme_color("highlight_color", "Editor");
- for (int i = 0; i < 2; i++) {
- Point2 ofs(4, vofs);
- if (i == 1) {
- ofs.y += bsize + 1;
- }
+ void _notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_DRAW: {
+ Rect2 rect;
+ rect.size = get_size();
+ flag_rects.clear();
+
+ const int bsize = (rect.size.height * 80 / 100) / 2;
+ const int h = bsize * 2 + 1;
+ const int vofs = (rect.size.height - h) / 2;
+
+ Color color = get_theme_color("highlight_color", "Editor");
+ for (int i = 0; i < 2; i++) {
+ Point2 ofs(4, vofs);
+ if (i == 1)
+ ofs.y += bsize + 1;
+
+ ofs += rect.position;
+ for (int j = 0; j < 10; j++) {
+ Point2 o = ofs + Point2(j * (bsize + 1), 0);
+ if (j >= 5)
+ o.x += 1;
+
+ const int idx = i * 10 + j;
+ const bool on = value & (1 << idx);
+ Rect2 rect2 = Rect2(o, Size2(bsize, bsize));
+
+ color.a = on ? 0.6 : 0.2;
+ if (idx == hovered_index) {
+ // Add visual feedback when hovering a flag.
+ color.a += 0.15;
+ }
- ofs += rect.position;
- for (int j = 0; j < 10; j++) {
- Point2 o = ofs + Point2(j * (bsize + 1), 0);
- if (j >= 5) {
- o.x += 1;
+ draw_rect(rect2, color);
+ flag_rects.push_back(rect2);
}
-
- uint32_t idx = i * 10 + j;
- bool on = value & (1 << idx);
- Rect2 rect2 = Rect2(o, Size2(bsize, bsize));
- color.a = on ? 0.6 : 0.2;
- draw_rect(rect2, color);
- flag_rects.push_back(rect2);
}
- }
+ } break;
+ case NOTIFICATION_MOUSE_EXIT: {
+ hovered_index = -1;
+ update();
+ } break;
+ default:
+ break;
}
}
@@ -661,6 +685,7 @@ public:
EditorPropertyLayersGrid() {
value = 0;
+ hovered_index = -1; // Nothing is hovered.
}
};
void EditorPropertyLayers::_grid_changed(uint32_t p_grid) {
@@ -752,7 +777,7 @@ EditorPropertyLayers::EditorPropertyLayers() {
hb->add_child(grid);
button = memnew(Button);
button->set_toggle_mode(true);
- button->set_text("..");
+ button->set_text("...");
button->connect("pressed", callable_mp(this, &EditorPropertyLayers::_button_pressed));
hb->add_child(button);
set_bottom_editor(hb);
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 f59b4171b4..796dd3f8b2 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -3419,11 +3419,7 @@ void Node3DEditorViewport::reset() {
last_message = "";
name = "";
- cursor.x_rot = 0.5;
- cursor.y_rot = 0.5;
- cursor.distance = 4;
- cursor.region_select = false;
- cursor.pos = Vector3();
+ cursor = Cursor();
_update_name();
}
@@ -3658,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;
}
@@ -5397,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/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 32b087c372..83173b5ad2 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -391,7 +391,9 @@ private:
Point2 region_begin, region_end;
Cursor() {
- x_rot = y_rot = 0.5;
+ // These rotations place the camera in +X +Y +Z, aka south east, facing north west.
+ x_rot = 0.5;
+ y_rot = -0.5;
distance = 4;
region_select = false;
}
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 8d6dac3907..48a9febcf9 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -837,7 +837,6 @@ void ScriptEditor::_file_dialog_action(String p_file) {
Error err;
FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err);
if (err) {
- memdelete(file);
editor->show_warning(TTR("Error writing TextFile:") + "\n" + p_file, TTR("Error!"));
break;
}
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index c37d32b26b..5795d85e66 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -2658,7 +2658,9 @@ void SceneTreeDock::_remote_tree_selected() {
}
void SceneTreeDock::_local_tree_selected() {
- scene_tree->show();
+ if (!bool(EDITOR_GET("interface/editors/show_scene_tree_root_selection")) || get_tree()->get_edited_scene_root() != nullptr) {
+ scene_tree->show();
+ }
if (remote_tree) {
remote_tree->hide();
}
diff --git a/modules/assimp/editor_scene_importer_assimp.cpp b/modules/assimp/editor_scene_importer_assimp.cpp
index 9c90faf66b..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);
@@ -145,7 +142,8 @@ Node *EditorSceneImporterAssimp::import_scene(const String &p_path, uint32_t p_f
// aiProcess_EmbedTextures |
//aiProcess_SplitByBoneCount |
0;
- aiScene *scene = (aiScene *)importer.ReadFile(s_path.c_str(), post_process_Steps);
+ String g_path = ProjectSettings::get_singleton()->globalize_path(p_path);
+ aiScene *scene = (aiScene *)importer.ReadFile(g_path.utf8().ptr(), post_process_Steps);
ERR_FAIL_COND_V_MSG(scene == nullptr, nullptr, String("Open Asset Import failed to open: ") + String(importer.GetErrorString()));
@@ -298,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++) {
@@ -829,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;
@@ -1266,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/denoise/config.py b/modules/denoise/config.py
index 53b8f2f2e3..091d7643c0 100644
--- a/modules/denoise/config.py
+++ b/modules/denoise/config.py
@@ -1,5 +1,11 @@
def can_build(env, platform):
- return env["tools"]
+ # Thirdparty dependency OpenImage Denoise includes oneDNN library
+ # which only supports 64-bit architectures.
+ # It's also only relevant for tools build and desktop platforms,
+ # as doing lightmap generation and denoising on Android or HTML5
+ # would be a bit far-fetched.
+ desktop_platforms = ["linuxbsd", "osx", "windows"]
+ return env["tools"] and platform in desktop_platforms and env["bits"] == "64"
def configure(env):
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/main/node.cpp b/scene/main/node.cpp
index c9d430c656..1bf828a03b 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -2238,46 +2238,53 @@ void Node::_duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p
// because re-targeting of connections from some descendant to another is not possible
// if the emitter node comes later in tree order than the receiver
void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const {
- if (this != p_original && (get_owner() != p_original && get_owner() != p_original->get_owner())) {
+ if ((this != p_original) && !(p_original->is_a_parent_of(this))) {
return;
}
- List<Connection> conns;
- get_all_signal_connections(&conns);
+ List<const Node *> process_list;
+ process_list.push_back(this);
+ while (!process_list.empty()) {
+ const Node *n = process_list.front()->get();
+ process_list.pop_front();
- for (List<Connection>::Element *E = conns.front(); E; E = E->next()) {
- if (E->get().flags & CONNECT_PERSIST) {
- //user connected
- NodePath p = p_original->get_path_to(this);
- Node *copy = p_copy->get_node(p);
+ List<Connection> conns;
+ n->get_all_signal_connections(&conns);
- Node *target = Object::cast_to<Node>(E->get().callable.get_object());
- if (!target) {
- continue;
- }
- NodePath ptarget = p_original->get_path_to(target);
+ for (List<Connection>::Element *E = conns.front(); E; E = E->next()) {
+ if (E->get().flags & CONNECT_PERSIST) {
+ //user connected
+ NodePath p = p_original->get_path_to(n);
+ Node *copy = p_copy->get_node(p);
- Node *copytarget = target;
+ Node *target = Object::cast_to<Node>(E->get().callable.get_object());
+ if (!target) {
+ continue;
+ }
+ NodePath ptarget = p_original->get_path_to(target);
- // Attempt to find a path to the duplicate target, if it seems it's not part
- // of the duplicated and not yet parented hierarchy then at least try to connect
- // to the same target as the original
+ Node *copytarget = target;
- if (p_copy->has_node(ptarget)) {
- copytarget = p_copy->get_node(ptarget);
- }
+ // Attempt to find a path to the duplicate target, if it seems it's not part
+ // of the duplicated and not yet parented hierarchy then at least try to connect
+ // to the same target as the original
- if (copy && copytarget) {
- const Callable copy_callable = Callable(copytarget, E->get().callable.get_method());
- if (!copy->is_connected(E->get().signal.get_name(), copy_callable)) {
- copy->connect(E->get().signal.get_name(), copy_callable, E->get().binds, E->get().flags);
+ if (p_copy->has_node(ptarget)) {
+ copytarget = p_copy->get_node(ptarget);
+ }
+
+ if (copy && copytarget) {
+ const Callable copy_callable = Callable(copytarget, E->get().callable.get_method());
+ if (!copy->is_connected(E->get().signal.get_name(), copy_callable)) {
+ copy->connect(E->get().signal.get_name(), copy_callable, E->get().binds, E->get().flags);
+ }
}
}
}
- }
- for (int i = 0; i < get_child_count(); i++) {
- get_child(i)->_duplicate_signals(p_original, p_copy);
+ for (int i = 0; i < n->get_child_count(); i++) {
+ process_list.push_back(n->get_child(i));
+ }
}
}
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;
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 9dff2eb37c..c69ca17fd0 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -446,7 +446,7 @@ Files extracted from the upstream source:
## oidn
- Upstream: https://github.com/OpenImageDenoise/oidn
-- Version: 1.1.0 (c58c5216db05ceef4cde5a096862f2eeffd14c06)
+- Version: 1.1.0 (c58c5216db05ceef4cde5a096862f2eeffd14c06, 2019)
- License: Apache 2.0
Files extracted from upstream source:
@@ -461,8 +461,8 @@ weights/rtlightmap_hdr.tza
scripts/resource_to_cpp.py
Modified files:
-Modifications are marked with `// -- GODOT start --` and `// -- GODOT end --`
-A patch file is provided in `oidn/godot-changes-c58c5216.patch`
+Modifications are marked with `// -- GODOT start --` and `// -- GODOT end --`.
+Patch files are provided in `oidn/patches/`.
core/autoencoder.cpp
core/autoencoder.h
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp
index 597c63e3f8..78cdedbae4 100644
--- a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp
@@ -131,7 +131,7 @@ struct rnn_weights_reorder_t : public cpu_primitive_t {
return status::success;
}
- format_tag_t itag_;
+ format_tag_t itag_ = mkldnn_format_tag_undef;
private:
void init_scratchpad() {
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.hpp
index 5177275452..057cc3c4c7 100644
--- a/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.hpp
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.hpp
@@ -96,9 +96,9 @@ struct simple_concat_t: public cpu_primitive_t {
return status::success;
}
- int perm_[MKLDNN_MAX_NDIMS];
- int iperm_[MKLDNN_MAX_NDIMS];
- dims_t blocks_;
+ int perm_[MKLDNN_MAX_NDIMS] {};
+ int iperm_[MKLDNN_MAX_NDIMS] {};
+ dims_t blocks_ {};
dim_t nelems_to_concat(const memory_desc_wrapper &data_d) const {
const int ndims = data_d.ndims();
diff --git a/thirdparty/oidn/godot-changes-c58c5216.patch b/thirdparty/oidn/patches/godot-changes-c58c5216.patch
index 6a54703064..6a54703064 100644
--- a/thirdparty/oidn/godot-changes-c58c5216.patch
+++ b/thirdparty/oidn/patches/godot-changes-c58c5216.patch
diff --git a/thirdparty/oidn/patches/mkl-dnn-fix-vs2017-build.patch b/thirdparty/oidn/patches/mkl-dnn-fix-vs2017-build.patch
new file mode 100644
index 0000000000..50d94ebffa
--- /dev/null
+++ b/thirdparty/oidn/patches/mkl-dnn-fix-vs2017-build.patch
@@ -0,0 +1,45 @@
+Rediffed by @akien-mga to match oidn 1.1.0 source.
+
+From 1e42e6db81e1a5270ecc0191c5385ce7e7d978e9 Mon Sep 17 00:00:00 2001
+From: Jeremy Wong <jmw@netvigator.com>
+Date: Wed, 11 Sep 2019 04:46:53 +0800
+Subject: [PATCH] src: initialize members in some structures to prevent compile
+ errors with VS2017
+
+addresses "error C3615: constexpr function '...' cannot result in a constant expression" with VS2017
+---
+ src/cpu/rnn/rnn_reorders.hpp | 2 +-
+ src/cpu/simple_concat.hpp | 6 +++---
+ src/cpu/simple_sum.hpp | 2 +-
+ 3 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp
+index 597c63e3f8..ae1551390a 100644
+--- a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp
++++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp
+@@ -131,7 +131,7 @@ struct rnn_weights_reorder_t : public cpu_primitive_t {
+ return status::success;
+ }
+
+- format_tag_t itag_;
++ format_tag_t itag_ = mkldnn_format_tag_undef;
+
+ private:
+ void init_scratchpad() {
+diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.hpp
+index 5177275452..057cc3c4c7 100644
+--- a/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.hpp
++++ b/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.hpp
+@@ -96,9 +96,9 @@ struct simple_concat_t: public cpu_primitive_t {
+ return status::success;
+ }
+
+- int perm_[MKLDNN_MAX_NDIMS];
+- int iperm_[MKLDNN_MAX_NDIMS];
+- dims_t blocks_;
++ int perm_[MKLDNN_MAX_NDIMS] {};
++ int iperm_[MKLDNN_MAX_NDIMS] {};
++ dims_t blocks_ {};
+
+ dim_t nelems_to_concat(const memory_desc_wrapper &data_d) const {
+ const int ndims = data_d.ndims();