summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/variant/variant_op.h1
-rw-r--r--doc/classes/Array.xml6
-rw-r--r--doc/classes/CollisionObject2D.xml2
-rw-r--r--doc/classes/CollisionObject3D.xml2
-rw-r--r--editor/editor_file_system.cpp4
-rw-r--r--editor/editor_file_system.h1
-rw-r--r--editor/filesystem_dock.cpp6
-rw-r--r--main/main.cpp23
-rw-r--r--modules/gdscript/gdscript_compiler.cpp2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/params_default_forward_reference.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/params_default_forward_reference.out2
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/params_default_values.gd35
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/params_default_values.out6
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp3
14 files changed, 92 insertions, 10 deletions
diff --git a/core/variant/variant_op.h b/core/variant/variant_op.h
index 9791cb67b3..f72a92d31a 100644
--- a/core/variant/variant_op.h
+++ b/core/variant/variant_op.h
@@ -775,6 +775,7 @@ public:
r_valid = true;
}
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ *r_ret = Array();
_add_arrays(*VariantGetInternalPtr<Array>::get_ptr(r_ret), *VariantGetInternalPtr<Array>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right));
}
static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml
index 5b1861bc9a..7cb6f71190 100644
--- a/doc/classes/Array.xml
+++ b/doc/classes/Array.xml
@@ -470,6 +470,12 @@
// There is no sort support for Godot.Collections.Array
[/csharp]
[/codeblocks]
+ To perform natural order sorting, you can use [method sort_custom] with [method String.naturalnocasecmp_to] as follows:
+ [codeblock]
+ var strings = ["string1", "string2", "string10", "string11"]
+ strings.sort_custom(func(a, b): return a.naturalnocasecmp_to(b) &lt; 0)
+ print(strings) # Prints [string1, string2, string10, string11]
+ [/codeblock]
</description>
</method>
<method name="sort_custom">
diff --git a/doc/classes/CollisionObject2D.xml b/doc/classes/CollisionObject2D.xml
index 63492bf9a0..828b24be83 100644
--- a/doc/classes/CollisionObject2D.xml
+++ b/doc/classes/CollisionObject2D.xml
@@ -208,7 +208,7 @@
Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes.
</member>
<member name="input_pickable" type="bool" setter="set_pickable" getter="is_pickable" default="true">
- If [code]true[/code], this object is pickable. A pickable object can detect the mouse pointer entering/leaving, and if the mouse is inside it, report input events. Requires at least one [code]collision_layer[/code] bit to be set.
+ If [code]true[/code], this object is pickable. A pickable object can detect the mouse pointer entering/leaving, and if the mouse is inside it, report input events. Requires at least one [member collision_layer] bit to be set.
</member>
</members>
<signals>
diff --git a/doc/classes/CollisionObject3D.xml b/doc/classes/CollisionObject3D.xml
index 33305471b8..96912cf469 100644
--- a/doc/classes/CollisionObject3D.xml
+++ b/doc/classes/CollisionObject3D.xml
@@ -183,7 +183,7 @@
If [code]true[/code], the [CollisionObject3D] will continue to receive input events as the mouse is dragged across its shapes.
</member>
<member name="input_ray_pickable" type="bool" setter="set_ray_pickable" getter="is_ray_pickable" default="true">
- If [code]true[/code], the [CollisionObject3D]'s shapes will respond to [RayCast3D]s.
+ If [code]true[/code], this object is pickable. A pickable object can detect the mouse pointer entering/leaving, and if the mouse is inside it, report input events. Requires at least one [member collision_layer] bit to be set.
</member>
</members>
<signals>
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index 703f606c76..5beed352a6 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -1604,6 +1604,10 @@ void EditorFileSystem::update_file(const String &p_file) {
_queue_update_script_classes();
}
+Set<String> EditorFileSystem::get_valid_extensions() const {
+ return valid_extensions;
+}
+
Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector<String> &p_files) {
String importer_name;
diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h
index ecc71e7d42..0c1bfbca47 100644
--- a/editor/editor_file_system.h
+++ b/editor/editor_file_system.h
@@ -272,6 +272,7 @@ public:
void scan();
void scan_changes();
void update_file(const String &p_file);
+ Set<String> get_valid_extensions() const;
EditorFileSystemDirectory *get_filesystem_path(const String &p_path);
String get_file_type(const String &p_file) const;
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 0253307d5a..d71861e72d 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -1472,12 +1472,18 @@ void FileSystemDock::_folder_removed(String p_folder) {
void FileSystemDock::_rename_operation_confirm() {
String new_name = rename_dialog_text->get_text().strip_edges();
+ String old_name = tree->get_selected()->get_text(0);
if (new_name.length() == 0) {
EditorNode::get_singleton()->show_warning(TTR("No name provided."));
return;
} else if (new_name.find("/") != -1 || new_name.find("\\") != -1 || new_name.find(":") != -1) {
EditorNode::get_singleton()->show_warning(TTR("Name contains invalid characters."));
return;
+ } else if (to_rename.is_file && old_name.get_extension() != new_name.get_extension()) {
+ if (!EditorFileSystem::get_singleton()->get_valid_extensions().find(new_name.get_extension())) {
+ EditorNode::get_singleton()->show_warning(TTR("This file extension is not recognized by the editor.\nIf you want to rename it anyway, use your operating system's file manager.\nAfter renaming to an unknown extension, the file won't be shown in the editor anymore."));
+ return;
+ }
}
String old_path = to_rename.path.ends_with("/") ? to_rename.path.substr(0, to_rename.path.length() - 1) : to_rename.path;
diff --git a/main/main.cpp b/main/main.cpp
index 4e63f8750a..7350e15ef5 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -2091,6 +2091,7 @@ bool Main::start() {
GLOBAL_DEF("mono/runtime/unhandled_exception_policy", 0);
#endif
+ Error err;
DocTools doc;
doc.generate(doc_base);
@@ -2112,34 +2113,42 @@ bool Main::start() {
// Create the module documentation directory if it doesn't exist
DirAccess *da = DirAccess::create_for_path(path);
- da->make_dir_recursive(path);
+ err = da->make_dir_recursive(path);
memdelete(da);
+ ERR_FAIL_COND_V_MSG(err != OK, false, "Error: Can't create directory: " + path + ": " + itos(err));
- docsrc.load_classes(path);
print_line("Loading docs from: " + path);
+ err = docsrc.load_classes(path);
+ ERR_FAIL_COND_V_MSG(err != OK, false, "Error loading docs from: " + path + ": " + itos(err));
}
}
String index_path = doc_tool_path.plus_file("doc/classes");
// Create the main documentation directory if it doesn't exist
DirAccess *da = DirAccess::create_for_path(index_path);
- da->make_dir_recursive(index_path);
+ err = da->make_dir_recursive(index_path);
memdelete(da);
+ ERR_FAIL_COND_V_MSG(err != OK, false, "Error: Can't create index directory: " + index_path + ": " + itos(err));
- docsrc.load_classes(index_path);
+ print_line("Loading classes from: " + index_path);
+ err = docsrc.load_classes(index_path);
+ ERR_FAIL_COND_V_MSG(err != OK, false, "Error loading classes from: " + index_path + ": " + itos(err));
checked_paths.insert(index_path);
- print_line("Loading docs from: " + index_path);
print_line("Merging docs...");
doc.merge_from(docsrc);
+
for (Set<String>::Element *E = checked_paths.front(); E; E = E->next()) {
print_line("Erasing old docs at: " + E->get());
- DocTools::erase_classes(E->get());
+ err = DocTools::erase_classes(E->get());
+ ERR_FAIL_COND_V_MSG(err != OK, false, "Error erasing old docs at: " + E->get() + ": " + itos(err));
}
print_line("Generating new docs...");
- doc.save_classes(index_path, doc_data_classes);
+ err = doc.save_classes(index_path, doc_data_classes);
+ ERR_FAIL_COND_V_MSG(err != OK, false, "Error saving new docs:" + itos(err));
+ OS::get_singleton()->set_exit_code(EXIT_SUCCESS);
return false;
}
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 117ca68c18..ca125d3a07 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -2019,7 +2019,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
codegen.generator->start_parameters();
for (int i = p_func->parameters.size() - optional_parameters; i < p_func->parameters.size(); i++) {
const GDScriptParser::ParameterNode *parameter = p_func->parameters[i];
- GDScriptCodeGenerator::Address src_addr = _parse_expression(codegen, r_error, parameter->default_value, true);
+ GDScriptCodeGenerator::Address src_addr = _parse_expression(codegen, r_error, parameter->default_value);
if (r_error) {
memdelete(codegen.generator);
return nullptr;
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/params_default_forward_reference.gd b/modules/gdscript/tests/scripts/analyzer/errors/params_default_forward_reference.gd
new file mode 100644
index 0000000000..05d9bd6a3d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/params_default_forward_reference.gd
@@ -0,0 +1,9 @@
+# https://github.com/godotengine/godot/issues/56702
+
+func test():
+ # somewhat obscure feature: referencing parameters in defaults, but only earlier ones!
+ ref_default("non-optional")
+
+
+func ref_default(nondefault1, defa=nondefault1, defb=defc, defc=1):
+ prints(nondefault1, nondefault2, defa, defb, defc)
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/params_default_forward_reference.out b/modules/gdscript/tests/scripts/analyzer/errors/params_default_forward_reference.out
new file mode 100644
index 0000000000..1d5b5bf393
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/params_default_forward_reference.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Identifier "defc" not declared in the current scope.
diff --git a/modules/gdscript/tests/scripts/runtime/features/params_default_values.gd b/modules/gdscript/tests/scripts/runtime/features/params_default_values.gd
new file mode 100644
index 0000000000..8156b4ec68
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/params_default_values.gd
@@ -0,0 +1,35 @@
+# https://github.com/godotengine/godot/issues/56702
+
+func test():
+ const_default()
+ func_result_default()
+ # calling again will run the initializer again,
+ # as the default is not evaluated at time of defining the function (as in python)
+ # but every time the function is called (as in C++)
+ func_result_default()
+ lots_of_defaults("non-optional")
+ # somewhat obscure feature: referencing earlier parameters
+ ref_default("non-optional", 42)
+
+
+func const_default(param=42):
+ print(param)
+
+
+var default_val := 0
+
+func get_default():
+ default_val += 1
+ return default_val
+
+
+func func_result_default(param=get_default()):
+ print(param)
+
+
+func lots_of_defaults(nondefault, one=1, two=2, three=get_default()):
+ prints(nondefault, one, two, three)
+
+
+func ref_default(nondefault1, nondefault2, defa=nondefault1, defb=nondefault2 - 1):
+ prints(nondefault1, nondefault2, defa, defb)
diff --git a/modules/gdscript/tests/scripts/runtime/features/params_default_values.out b/modules/gdscript/tests/scripts/runtime/features/params_default_values.out
new file mode 100644
index 0000000000..50e0885ae5
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/params_default_values.out
@@ -0,0 +1,6 @@
+GDTEST_OK
+42
+1
+2
+non-optional 1 2 3
+non-optional 42 non-optional 41
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index a499cedd2c..f6d58cb094 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -4011,6 +4011,9 @@ void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) {
RD::get_singleton()->free(rb->volumetric_fog->prev_light_density_map);
RD::get_singleton()->free(rb->volumetric_fog->light_density_map);
RD::get_singleton()->free(rb->volumetric_fog->fog_map);
+ RD::get_singleton()->free(rb->volumetric_fog->density_map);
+ RD::get_singleton()->free(rb->volumetric_fog->light_map);
+ RD::get_singleton()->free(rb->volumetric_fog->emissive_map);
if (rb->volumetric_fog->fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) {
RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set);