diff options
32 files changed, 234 insertions, 233 deletions
diff --git a/core/io/resource.cpp b/core/io/resource.cpp index ed7228d0b9..fec5ca5c7b 100644 --- a/core/io/resource.cpp +++ b/core/io/resource.cpp @@ -52,41 +52,36 @@ void Resource::set_path(const String &p_path, bool p_take_over) { return; } + if (p_path.is_empty()) { + p_take_over = false; // Can't take over an empty path + } + + ResourceCache::lock.lock(); + if (!path_cache.is_empty()) { - ResourceCache::lock.write_lock(); ResourceCache::resources.erase(path_cache); - ResourceCache::lock.write_unlock(); } path_cache = ""; - ResourceCache::lock.read_lock(); - bool has_path = ResourceCache::resources.has(p_path); - ResourceCache::lock.read_unlock(); + Ref<Resource> existing = ResourceCache::get_ref(p_path); - if (has_path) { + if (existing.is_valid()) { if (p_take_over) { - ResourceCache::lock.write_lock(); - Resource **res = ResourceCache::resources.getptr(p_path); - if (res) { - (*res)->set_name(""); - } - ResourceCache::lock.write_unlock(); + existing->path_cache = String(); + ResourceCache::resources.erase(p_path); } else { - ResourceCache::lock.read_lock(); - bool exists = ResourceCache::resources.has(p_path); - ResourceCache::lock.read_unlock(); - - ERR_FAIL_COND_MSG(exists, "Another resource is loaded from path '" + p_path + "' (possible cyclic resource inclusion)."); + ResourceCache::lock.unlock(); + ERR_FAIL_MSG("Another resource is loaded from path '" + p_path + "' (possible cyclic resource inclusion)."); } } + path_cache = p_path; if (!path_cache.is_empty()) { - ResourceCache::lock.write_lock(); ResourceCache::resources[path_cache] = this; - ResourceCache::lock.write_unlock(); } + ResourceCache::lock.unlock(); _resource_path_changed(); } @@ -380,7 +375,7 @@ void Resource::set_as_translation_remapped(bool p_remapped) { return; } - ResourceCache::lock.write_lock(); + ResourceCache::lock.lock(); if (p_remapped) { ResourceLoader::remapped_list.add(&remapped_list); @@ -388,7 +383,7 @@ void Resource::set_as_translation_remapped(bool p_remapped) { ResourceLoader::remapped_list.remove(&remapped_list); } - ResourceCache::lock.write_unlock(); + ResourceCache::lock.unlock(); } bool Resource::is_translation_remapped() const { @@ -455,9 +450,9 @@ Resource::Resource() : Resource::~Resource() { if (!path_cache.is_empty()) { - ResourceCache::lock.write_lock(); + ResourceCache::lock.lock(); ResourceCache::resources.erase(path_cache); - ResourceCache::lock.write_unlock(); + ResourceCache::lock.unlock(); } if (owners.size()) { WARN_PRINT("Resource is still owned."); @@ -469,7 +464,7 @@ HashMap<String, Resource *> ResourceCache::resources; HashMap<String, HashMap<String, String>> ResourceCache::resource_path_cache; #endif -RWLock ResourceCache::lock; +Mutex ResourceCache::lock; #ifdef TOOLS_ENABLED RWLock ResourceCache::path_cache_lock; #endif @@ -491,46 +486,67 @@ void ResourceCache::reload_externals() { } bool ResourceCache::has(const String &p_path) { - lock.read_lock(); - bool b = resources.has(p_path); - lock.read_unlock(); + lock.lock(); + + Resource **res = resources.getptr(p_path); - return b; + if (res && (*res)->reference_get_count() == 0) { + // This resource is in the process of being deleted, ignore its existence. + (*res)->path_cache = String(); + resources.erase(p_path); + res = nullptr; + } + + lock.unlock(); + + if (!res) { + return false; + } + + return true; } -Resource *ResourceCache::get(const String &p_path) { - lock.read_lock(); +Ref<Resource> ResourceCache::get_ref(const String &p_path) { + Ref<Resource> ref; + lock.lock(); Resource **res = resources.getptr(p_path); - lock.read_unlock(); + if (res) { + ref = Ref<Resource>(*res); + } - if (!res) { - return nullptr; + if (res && !ref.is_valid()) { + // This resource is in the process of being deleted, ignore its existence + (*res)->path_cache = String(); + resources.erase(p_path); + res = nullptr; } - return *res; + lock.unlock(); + + return ref; } void ResourceCache::get_cached_resources(List<Ref<Resource>> *p_resources) { - lock.read_lock(); + lock.lock(); for (KeyValue<String, Resource *> &E : resources) { p_resources->push_back(Ref<Resource>(E.value)); } - lock.read_unlock(); + lock.unlock(); } int ResourceCache::get_cached_resource_count() { - lock.read_lock(); + lock.lock(); int rc = resources.size(); - lock.read_unlock(); + lock.unlock(); return rc; } void ResourceCache::dump(const char *p_file, bool p_short) { #ifdef DEBUG_ENABLED - lock.read_lock(); + lock.lock(); HashMap<String, int> type_count; @@ -562,7 +578,7 @@ void ResourceCache::dump(const char *p_file, bool p_short) { } } - lock.read_unlock(); + lock.unlock(); #else WARN_PRINT("ResourceCache::dump only with in debug builds."); #endif diff --git a/core/io/resource.h b/core/io/resource.h index a45bc6e1e4..a2cde87990 100644 --- a/core/io/resource.h +++ b/core/io/resource.h @@ -153,7 +153,7 @@ public: class ResourceCache { friend class Resource; friend class ResourceLoader; //need the lock - static RWLock lock; + static Mutex lock; static HashMap<String, Resource *> resources; #ifdef TOOLS_ENABLED static HashMap<String, HashMap<String, String>> resource_path_cache; // Each tscn has a set of resource paths and IDs. @@ -166,7 +166,7 @@ class ResourceCache { public: static void reload_externals(); static bool has(const String &p_path); - static Resource *get(const String &p_path); + static Ref<Resource> get_ref(const String &p_path); static void dump(const char *p_file = nullptr, bool p_short = false); static void get_cached_resources(List<Ref<Resource>> *p_resources); static int get_cached_resource_count(); diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 2469e1a4be..b1c50e829c 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -693,7 +693,7 @@ Error ResourceLoaderBinary::load() { } if (cache_mode == ResourceFormatLoader::CACHE_MODE_REUSE && ResourceCache::has(path)) { - Ref<Resource> cached = ResourceCache::get(path); + Ref<Resource> cached = ResourceCache::get_ref(path); if (cached.is_valid()) { //already loaded, don't do anything error = OK; @@ -717,10 +717,10 @@ Error ResourceLoaderBinary::load() { if (cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE && ResourceCache::has(path)) { //use the existing one - Resource *r = ResourceCache::get(path); - if (r->get_class() == t) { - r->reset_state(); - res = Ref<Resource>(r); + Ref<Resource> cached = ResourceCache::get_ref(path); + if (cached->get_class() == t) { + cached->reset_state(); + res = cached; } } diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index fb21db1a19..2cd455475c 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -335,23 +335,15 @@ Error ResourceLoader::load_threaded_request(const String &p_path, const String & thread_load_mutex->unlock(); ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Attempted to load a resource already being loaded from this thread, cyclic reference?"); } - //lock first if possible - ResourceCache::lock.read_lock(); - - //get ptr - Resource **rptr = ResourceCache::resources.getptr(local_path); - - if (rptr) { - Ref<Resource> res(*rptr); - //it is possible this resource was just freed in a thread. If so, this referencing will not work and resource is considered not cached - if (res.is_valid()) { - //referencing is fine - load_task.resource = res; - load_task.status = THREAD_LOAD_LOADED; - load_task.progress = 1.0; - } + + Ref<Resource> existing = ResourceCache::get_ref(local_path); + + if (existing.is_valid()) { + //referencing is fine + load_task.resource = existing; + load_task.status = THREAD_LOAD_LOADED; + load_task.progress = 1.0; } - ResourceCache::lock.read_unlock(); } if (!p_source_resource.is_empty()) { @@ -530,27 +522,18 @@ Ref<Resource> ResourceLoader::load(const String &p_path, const String &p_type_hi } //Is it cached? - ResourceCache::lock.read_lock(); - - Resource **rptr = ResourceCache::resources.getptr(local_path); - if (rptr) { - Ref<Resource> res(*rptr); + Ref<Resource> existing = ResourceCache::get_ref(local_path); - //it is possible this resource was just freed in a thread. If so, this referencing will not work and resource is considered not cached - if (res.is_valid()) { - ResourceCache::lock.read_unlock(); - thread_load_mutex->unlock(); - - if (r_error) { - *r_error = OK; - } + if (existing.is_valid()) { + thread_load_mutex->unlock(); - return res; //use cached + if (r_error) { + *r_error = OK; } - } - ResourceCache::lock.read_unlock(); + return existing; //use cached + } //load using task (but this thread) ThreadLoadTask load_task; @@ -867,7 +850,7 @@ String ResourceLoader::path_remap(const String &p_path) { } void ResourceLoader::reload_translation_remaps() { - ResourceCache::lock.read_lock(); + ResourceCache::lock.lock(); List<Resource *> to_reload; SelfList<Resource> *E = remapped_list.first(); @@ -877,7 +860,7 @@ void ResourceLoader::reload_translation_remaps() { E = E->next(); } - ResourceCache::lock.read_unlock(); + ResourceCache::lock.unlock(); //now just make sure to not delete any of these resources while changing locale.. while (to_reload.front()) { diff --git a/core/object/object.h b/core/object/object.h index fe9231cfd8..2a9f2ebf93 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -47,7 +47,7 @@ enum PropertyHint { PROPERTY_HINT_NONE, ///< no hint provided. - PROPERTY_HINT_RANGE, ///< hint_text = "min,max[,step][,or_greater][,or_lesser][,noslider][,radians][,degrees][,exp][,suffix:<keyword>] range. + PROPERTY_HINT_RANGE, ///< hint_text = "min,max[,step][,or_greater][,or_lesser][,no_slider][,radians][,degrees][,exp][,suffix:<keyword>] range. PROPERTY_HINT_ENUM, ///< hint_text= "val1,val2,val3,etc" PROPERTY_HINT_ENUM_SUGGESTION, ///< hint_text= "val1,val2,val3,etc" PROPERTY_HINT_EXP_EASING, /// exponential easing function (Math::ease) use "attenuation" hint string to revert (flip h), "full" to also include in/out. (ie: "attenuation,inout") diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 4048b483e8..475d166925 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -2460,7 +2460,7 @@ </constant> <constant name="PROPERTY_HINT_RANGE" value="1" enum="PropertyHint"> Hints that an integer or float property should be within a range specified via the hint string [code]"min,max"[/code] or [code]"min,max,step"[/code]. The hint string can optionally include [code]"or_greater"[/code] and/or [code]"or_lesser"[/code] to allow manual input going respectively above the max or below the min values. Example: [code]"-360,360,1,or_greater,or_lesser"[/code]. - Additionally, other keywords can be included: "exp" for exponential range editing, "radians" for editing radian angles in degrees, "degrees" to hint at an angle and "noslider" to hide the slider. + Additionally, other keywords can be included: "exp" for exponential range editing, "radians" for editing radian angles in degrees, "degrees" to hint at an angle and "no_slider" to hide the slider. </constant> <constant name="PROPERTY_HINT_ENUM" value="2" enum="PropertyHint"> Hints that an integer, float or string property is an enumerated value to pick in a list specified via a hint string. diff --git a/doc/classes/HTTPRequest.xml b/doc/classes/HTTPRequest.xml index 641d73e333..166923314f 100644 --- a/doc/classes/HTTPRequest.xml +++ b/doc/classes/HTTPRequest.xml @@ -15,7 +15,7 @@ # Create an HTTP request node and connect its completion signal. var http_request = HTTPRequest.new() add_child(http_request) - http_request.connect("request_completed", self, "_http_request_completed") + http_request.request_completed.connect(self._http_request_completed) # Perform a GET request. The URL below returns JSON as of writing. var error = http_request.request("https://httpbin.org/get") @@ -25,7 +25,7 @@ # Perform a POST request. The URL below returns JSON as of writing. # Note: Don't make simultaneous requests using a single HTTPRequest node. # The snippet below is provided for reference only. - var body = {"name": "Godette"} + var body = JSON.new().stringify({"name": "Godette"}) error = http_request.request("https://httpbin.org/post", [], true, HTTPClient.METHOD_POST, body) if error != OK: push_error("An error occurred in the HTTP request.") @@ -33,7 +33,9 @@ # Called when the HTTP request is completed. func _http_request_completed(result, response_code, headers, body): - var response = parse_json(body.get_string_from_utf8()) + var json = JSON.new() + json.parse(body.get_string_from_utf8()) + var response = json.get_data() # Will print the user agent string used by the HTTPRequest node (as recognized by httpbin.org). print(response.headers["User-Agent"]) @@ -44,7 +46,7 @@ // Create an HTTP request node and connect its completion signal. var httpRequest = new HTTPRequest(); AddChild(httpRequest); - httpRequest.Connect("request_completed", this, nameof(HttpRequestCompleted)); + httpRequest.RequestCompleted += HttpRequestCompleted; // Perform a GET request. The URL below returns JSON as of writing. Error error = httpRequest.Request("https://httpbin.org/get"); @@ -56,21 +58,24 @@ // Perform a POST request. The URL below returns JSON as of writing. // Note: Don't make simultaneous requests using a single HTTPRequest node. // The snippet below is provided for reference only. - string[] body = { "name", "Godette" }; - // GDScript to_json is non existent, so we use JSON.Print() here. - error = httpRequest.Request("https://httpbin.org/post", null, true, HTTPClient.Method.Post, JSON.Print(body)); + string body = new JSON().Stringify(new Godot.Collections.Dictionary + { + { "name", "Godette" } + }); + error = httpRequest.Request("https://httpbin.org/post", null, true, HTTPClient.Method.Post, body); if (error != Error.Ok) { GD.PushError("An error occurred in the HTTP request."); } } - // Called when the HTTP request is completed. private void HttpRequestCompleted(int result, int response_code, string[] headers, byte[] body) { - // GDScript parse_json is non existent so we have to use JSON.parse, which has a slightly different syntax. - var response = JSON.Parse(body.GetStringFromUTF8()).Result as Godot.Collections.Dictionary; + var json = new JSON(); + json.Parse(body.GetStringFromUTF8()); + var response = json.GetData() as Godot.Collections.Dictionary; + // Will print the user agent string used by the HTTPRequest node (as recognized by httpbin.org). GD.Print((response["headers"] as Godot.Collections.Dictionary)["User-Agent"]); } @@ -83,7 +88,7 @@ # Create an HTTP request node and connect its completion signal. var http_request = HTTPRequest.new() add_child(http_request) - http_request.connect("request_completed", self, "_http_request_completed") + http_request.request_completed.connect(self._http_request_completed) # Perform the HTTP request. The URL below returns a PNG image as of writing. var error = http_request.request("https://via.placeholder.com/512") @@ -115,7 +120,7 @@ // Create an HTTP request node and connect its completion signal. var httpRequest = new HTTPRequest(); AddChild(httpRequest); - httpRequest.Connect("request_completed", this, nameof(HttpRequestCompleted)); + httpRequest.RequestCompleted += HttpRequestCompleted; // Perform the HTTP request. The URL below returns a PNG image as of writing. Error error = httpRequest.Request("https://via.placeholder.com/512"); @@ -125,7 +130,6 @@ } } - // Called when the HTTP request is completed. private void HttpRequestCompleted(int result, int response_code, string[] headers, byte[] body) { diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index 97699d0349..9a1b2b5ff5 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -487,7 +487,7 @@ void DependencyRemoveDialog::show(const Vector<String> &p_folders, const Vector< void DependencyRemoveDialog::ok_pressed() { for (int i = 0; i < files_to_delete.size(); ++i) { if (ResourceCache::has(files_to_delete[i])) { - Resource *res = ResourceCache::get(files_to_delete[i]); + Ref<Resource> res = ResourceCache::get_ref(files_to_delete[i]); res->set_path(""); } diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index f9a4c14c48..adbba98897 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -1792,9 +1792,9 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector //if file is currently up, maybe the source it was loaded from changed, so import math must be updated for it //to reload properly - if (ResourceCache::has(file)) { - Resource *r = ResourceCache::get(file); + Ref<Resource> r = ResourceCache::get_ref(file); + if (r.is_valid()) { if (!r->get_import_path().is_empty()) { String dst_path = ResourceFormatImporter::get_singleton()->get_internal_resource_path(file); r->set_import_path(dst_path); @@ -2034,9 +2034,8 @@ void EditorFileSystem::_reimport_file(const String &p_file, const HashMap<String //if file is currently up, maybe the source it was loaded from changed, so import math must be updated for it //to reload properly - if (ResourceCache::has(p_file)) { - Resource *r = ResourceCache::get(p_file); - + Ref<Resource> r = ResourceCache::get_ref(p_file); + if (r.is_valid()) { if (!r->get_import_path().is_empty()) { String dst_path = ResourceFormatImporter::get_singleton()->get_internal_resource_path(p_file); r->set_import_path(dst_path); diff --git a/editor/editor_folding.cpp b/editor/editor_folding.cpp index 9e1b361f64..8c508494c0 100644 --- a/editor/editor_folding.cpp +++ b/editor/editor_folding.cpp @@ -193,10 +193,7 @@ void EditorFolding::load_scene_folding(Node *p_scene, const String &p_path) { for (int i = 0; i < res_unfolds.size(); i += 2) { String path2 = res_unfolds[i]; - Ref<Resource> res; - if (ResourceCache::has(path2)) { - res = Ref<Resource>(ResourceCache::get(path2)); - } + Ref<Resource> res = ResourceCache::get_ref(path2); if (res.is_null()) { continue; } diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 93caf7944c..9b0ac305d1 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -881,7 +881,7 @@ void EditorNode::_resources_changed(const Vector<String> &p_resources) { int rc = p_resources.size(); for (int i = 0; i < rc; i++) { - Ref<Resource> res(ResourceCache::get(p_resources.get(i))); + Ref<Resource> res = ResourceCache::get_ref(p_resources.get(i)); if (res.is_null()) { continue; } @@ -1011,8 +1011,8 @@ void EditorNode::_resources_reimported(const Vector<String> &p_resources) { continue; } // Reload normally. - Resource *resource = ResourceCache::get(p_resources[i]); - if (resource) { + Ref<Resource> resource = ResourceCache::get_ref(p_resources[i]); + if (resource.is_valid()) { resource->reload_from_file(); } } @@ -1725,7 +1725,7 @@ void EditorNode::_save_scene(String p_file, int idx) { // We must update it, but also let the previous scene state go, as // old version still work for referencing changes in instantiated or inherited scenes. - sdata = Ref<PackedScene>(Object::cast_to<PackedScene>(ResourceCache::get(p_file))); + sdata = ResourceCache::get_ref(p_file); if (sdata.is_valid()) { sdata->recreate_state(); } else { @@ -3717,7 +3717,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b if (ResourceCache::has(lpath)) { // Used from somewhere else? No problem! Update state and replace sdata. - Ref<PackedScene> ps = Ref<PackedScene>(Object::cast_to<PackedScene>(ResourceCache::get(lpath))); + Ref<PackedScene> ps = ResourceCache::get_ref(lpath); if (ps.is_valid()) { ps->replace_state(sdata->get_state()); ps->set_last_modified_time(sdata->get_last_modified_time()); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 61b434a240..2562c740aa 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -3601,7 +3601,7 @@ static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const Stri hint.greater = true; } else if (slice == "or_lesser") { hint.lesser = true; - } else if (slice == "noslider") { + } else if (slice == "no_slider") { hint.hide_slider = true; } else if (slice == "exp") { hint.exp_range = true; diff --git a/editor/editor_property_name_processor.cpp b/editor/editor_property_name_processor.cpp index 397afc0653..09d2992e07 100644 --- a/editor/editor_property_name_processor.cpp +++ b/editor/editor_property_name_processor.cpp @@ -176,6 +176,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["lowpass"] = "Low-pass"; capitalize_string_remaps["macos"] = "macOS"; capitalize_string_remaps["mb"] = "(MB)"; // Unit. + capitalize_string_remaps["mjpeg"] = "MJPEG"; capitalize_string_remaps["mms"] = "MMS"; capitalize_string_remaps["ms"] = "(ms)"; // Unit capitalize_string_remaps["msaa"] = "MSAA"; diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index f2975b1d7a..171ef5bf4c 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -1115,7 +1115,7 @@ Ref<Animation> ResourceImporterScene::_save_animation_to_file(Ref<Animation> ani } if (ResourceCache::has(p_save_to_path)) { - Ref<Animation> old_anim = Ref<Resource>(ResourceCache::get(p_save_to_path)); + Ref<Animation> old_anim = ResourceCache::get_ref(p_save_to_path); if (old_anim.is_valid()) { old_anim->copy_from(anim); anim = old_anim; @@ -1711,7 +1711,7 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m } if (!save_to_file.is_empty()) { - Ref<Mesh> existing = Ref<Resource>(ResourceCache::get(save_to_file)); + Ref<Mesh> existing = ResourceCache::get_ref(save_to_file); if (existing.is_valid()) { //if somehow an existing one is useful, create existing->reset_state(); diff --git a/editor/import/resource_importer_texture_atlas.cpp b/editor/import/resource_importer_texture_atlas.cpp index aa338a6c0d..e5fe99890e 100644 --- a/editor/import/resource_importer_texture_atlas.cpp +++ b/editor/import/resource_importer_texture_atlas.cpp @@ -306,10 +306,8 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file //update cache if existing, else create Ref<Texture2D> cache; - if (ResourceCache::has(p_group_file)) { - Resource *resptr = ResourceCache::get(p_group_file); - cache.reference_ptr(resptr); - } else { + cache = ResourceCache::get_ref(p_group_file); + if (!cache.is_valid()) { Ref<ImageTexture> res_cache; res_cache.instantiate(); res_cache->create_from_image(new_atlas); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 1ea0299d4e..dea4aaded7 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -5455,7 +5455,7 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String & } child->set_name(name); - Ref<Texture2D> texture = Ref<Texture2D>(Object::cast_to<Texture2D>(ResourceCache::get(path))); + Ref<Texture2D> texture = ResourceCache::get_ref(path); if (parent) { editor_data->get_undo_redo().add_do_method(parent, "add_child", child, true); diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 617db883f8..e6aeef2fd1 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -1254,6 +1254,14 @@ GDScript::~GDScript() { memdelete(E.value); } + if (implicit_initializer) { + memdelete(implicit_initializer); + } + + if (implicit_ready) { + memdelete(implicit_ready); + } + if (GDScriptCache::singleton) { // Cache may have been already destroyed at engine shutdown. GDScriptCache::remove_script(get_path()); } @@ -1541,6 +1549,18 @@ bool GDScriptInstance::has_method(const StringName &p_method) const { Variant GDScriptInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { GDScript *sptr = script.ptr(); + if (unlikely(p_method == SNAME("_ready"))) { + // Call implicit ready first, including for the super classes. + while (sptr) { + if (sptr->implicit_ready) { + sptr->implicit_ready->call(this, nullptr, 0, r_error); + } + sptr = sptr->_base; + } + + // Reset this back for the regular call. + sptr = script.ptr(); + } while (sptr) { HashMap<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(p_method); if (E) { diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 0057962d5e..feb0a237df 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -120,6 +120,7 @@ class GDScript : public Script { GDScriptFunction *implicit_initializer = nullptr; GDScriptFunction *initializer = nullptr; //direct pointer to new , faster to locate + GDScriptFunction *implicit_ready = nullptr; int subclass_count = 0; RBSet<Object *> instances; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 25454030b1..16a0b17d61 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -1990,18 +1990,18 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_ // Parse initializer if applies. bool is_implicit_initializer = !p_for_ready && !p_func && !p_for_lambda; - bool is_initializer = p_func && !p_for_lambda && String(p_func->identifier->name) == GDScriptLanguage::get_singleton()->strings._init; - bool is_for_ready = p_for_ready || (p_func && !p_for_lambda && String(p_func->identifier->name) == "_ready"); + bool is_initializer = p_func && !p_for_lambda && p_func->identifier->name == GDScriptLanguage::get_singleton()->strings._init; + bool is_implicit_ready = !p_func && p_for_ready; - if (!p_for_lambda && (is_implicit_initializer || is_for_ready)) { + if (!p_for_lambda && (is_implicit_initializer || is_implicit_ready)) { // Initialize class fields. for (int i = 0; i < p_class->members.size(); i++) { if (p_class->members[i].type != GDScriptParser::ClassNode::Member::VARIABLE) { continue; } const GDScriptParser::VariableNode *field = p_class->members[i].variable; - if (field->onready != is_for_ready) { - // Only initialize in _ready. + if (field->onready != is_implicit_ready) { + // Only initialize in @implicit_ready. continue; } @@ -2123,6 +2123,8 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_ p_script->initializer = gd_function; } else if (is_implicit_initializer) { p_script->implicit_initializer = gd_function; + } else if (is_implicit_ready) { + p_script->implicit_ready = gd_function; } if (p_func) { @@ -2140,7 +2142,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_ #endif } - if (!p_for_lambda) { + if (!is_implicit_initializer && !is_implicit_ready && !p_for_lambda) { p_script->member_functions[func_name] = gd_function; } @@ -2208,11 +2210,19 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar for (const KeyValue<StringName, GDScriptFunction *> &E : p_script->member_functions) { memdelete(E.value); } + if (p_script->implicit_initializer) { + memdelete(p_script->implicit_initializer); + } + if (p_script->implicit_ready) { + memdelete(p_script->implicit_ready); + } p_script->member_functions.clear(); p_script->member_indices.clear(); p_script->member_info.clear(); p_script->_signals.clear(); p_script->initializer = nullptr; + p_script->implicit_initializer = nullptr; + p_script->implicit_ready = nullptr; p_script->tool = parser->is_tool(); p_script->name = p_class->identifier ? p_class->identifier->name : ""; @@ -2456,15 +2466,10 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) { //parse methods - bool has_ready = false; - for (int i = 0; i < p_class->members.size(); i++) { const GDScriptParser::ClassNode::Member &member = p_class->members[i]; if (member.type == member.FUNCTION) { const GDScriptParser::FunctionNode *function = member.function; - if (!has_ready && function->identifier->name == "_ready") { - has_ready = true; - } Error err = OK; _parse_function(err, p_script, p_class, function); if (err) { @@ -2498,8 +2503,8 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa } } - if (!has_ready && p_class->onready_used) { - //create a _ready constructor + if (p_class->onready_used) { + // Create an implicit_ready constructor. Error err = OK; _parse_function(err, p_script, p_class, nullptr, true); if (err) { diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 5345143271..474c8094f2 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -746,7 +746,7 @@ static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_a ScriptLanguage::CodeCompletionOption slider2("or_lesser", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); slider2.insert_text = slider2.display.quote(p_quote_style); r_result.insert(slider2.display, slider2); - ScriptLanguage::CodeCompletionOption slider3("noslider", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); + ScriptLanguage::CodeCompletionOption slider3("no_slider", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); slider3.insert_text = slider3.display.quote(p_quote_style); r_result.insert(slider3.display, slider3); } diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp index bbbb995635..19bbd834cc 100644 --- a/modules/visual_script/visual_script_flow_control.cpp +++ b/modules/visual_script/visual_script_flow_control.cpp @@ -803,7 +803,7 @@ public: //if the script is not in use by anyone, we can safely assume whatever we got is not casting to it. return 1; } - Ref<Script> cast_script = Ref<Resource>(ResourceCache::get(script)); + Ref<Script> cast_script = ResourceCache::get_ref(script); if (!cast_script.is_valid()) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; r_error_str = "Script path is not a script: " + script; diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index 483fc8b6c3..b16358ae38 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -377,7 +377,7 @@ void VisualScriptFunctionCall::_update_method_cache() { } if (ResourceCache::has(base_script)) { - script = Ref<Resource>(ResourceCache::get(base_script)); + script = ResourceCache::get_ref(base_script); } else { return; } @@ -587,7 +587,7 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const } if (ResourceCache::has(base_script)) { - Ref<Script> script = Ref<Resource>(ResourceCache::get(base_script)); + Ref<Script> script = ResourceCache::get_ref(base_script); if (script.is_valid()) { property.hint = PROPERTY_HINT_METHOD_OF_SCRIPT; property.hint_string = itos(script->get_instance_id()); @@ -1178,7 +1178,7 @@ void VisualScriptPropertySet::_update_cache() { } if (ResourceCache::has(base_script)) { - script = Ref<Resource>(ResourceCache::get(base_script)); + script = ResourceCache::get_ref(base_script); } else { return; } @@ -1338,7 +1338,7 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const { } if (ResourceCache::has(base_script)) { - Ref<Script> script = Ref<Resource>(ResourceCache::get(base_script)); + Ref<Script> script = ResourceCache::get_ref(base_script); if (script.is_valid()) { property.hint = PROPERTY_HINT_PROPERTY_OF_SCRIPT; property.hint_string = itos(script->get_instance_id()); @@ -1864,7 +1864,7 @@ void VisualScriptPropertyGet::_update_cache() { } if (ResourceCache::has(base_script)) { - script = Ref<Resource>(ResourceCache::get(base_script)); + script = ResourceCache::get_ref(base_script); } else { return; } @@ -2044,7 +2044,7 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const { } if (ResourceCache::has(base_script)) { - Ref<Script> script = Ref<Resource>(ResourceCache::get(base_script)); + Ref<Script> script = ResourceCache::get_ref(base_script); if (script.is_valid()) { property.hint = PROPERTY_HINT_PROPERTY_OF_SCRIPT; property.hint_string = itos(script->get_instance_id()); diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index b2b848d380..4599785ce4 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -437,7 +437,7 @@ void Node2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_relative_transform_to_parent", "parent"), &Node2D::get_relative_transform_to_parent); ADD_GROUP("Transform", ""); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_lesser,or_greater,noslider,suffix:px"), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_lesser,or_greater,no_slider,suffix:px"), "set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians"), "set_rotation", "get_rotation"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale", PROPERTY_HINT_LINK), "set_scale", "get_scale"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "skew", PROPERTY_HINT_RANGE, "-89.9,89.9,0.1,radians"), "set_skew", "get_skew"); diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index 78d53439e8..60858b00b1 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -85,13 +85,10 @@ void Node3D::_notify_dirty() { } void Node3D::_update_local_transform() const { - if (this->get_rotation_edit_mode() == ROTATION_EDIT_MODE_EULER) { - data.local_transform.basis.set_euler(data.rotation, data.rotation_order); - data.local_transform.basis.scale_local(data.scale); - } else if (this->get_rotation_edit_mode() == ROTATION_EDIT_MODE_QUATERNION) { - data.local_transform.basis = Basis(data.quaternion); - data.local_transform.basis.scale_local(data.scale); + if (this->get_rotation_edit_mode() != ROTATION_EDIT_MODE_BASIS) { + data.local_transform = data.local_transform.orthogonalized(); } + data.local_transform.basis.set_euler_scale(data.rotation, data.scale); data.dirty &= ~DIRTY_LOCAL; } @@ -215,18 +212,7 @@ void Node3D::set_basis(const Basis &p_basis) { set_transform(Transform3D(p_basis, data.local_transform.origin)); } void Node3D::set_quaternion(const Quaternion &p_quaternion) { - if (data.dirty & DIRTY_VECTORS) { - data.rotation = get_transform().basis.get_euler_normalized(data.rotation_order); - data.scale = get_transform().basis.get_scale(); - data.dirty &= ~DIRTY_VECTORS; - } - - data.quaternion = p_quaternion; - data.dirty |= DIRTY_LOCAL; - _propagate_transform_changed(this); - if (data.notify_local_transform) { - notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); - } + set_transform(Transform3D(Basis(p_quaternion), data.local_transform.origin)); } void Node3D::set_transform(const Transform3D &p_transform) { @@ -242,14 +228,7 @@ Basis Node3D::get_basis() const { return get_transform().basis; } Quaternion Node3D::get_quaternion() const { - if (data.dirty & DIRTY_VECTORS) { - data.quaternion = get_transform().basis.get_rotation_quaternion(); - data.rotation = get_transform().basis.get_euler_normalized(data.rotation_order); - data.scale = get_transform().basis.get_scale(); - data.dirty &= ~DIRTY_VECTORS; - } - - return data.quaternion; + return Quaternion(get_transform().basis); } void Node3D::set_global_transform(const Transform3D &p_transform) { @@ -276,9 +255,9 @@ Transform3D Node3D::get_global_transform() const { } if (data.parent && !data.top_level_active) { - data.global_transform = data.parent->get_global_transform() * get_transform(); + data.global_transform = data.parent->get_global_transform() * data.local_transform; } else { - data.global_transform = get_transform(); + data.global_transform = data.local_transform; } if (data.disable_scale) { @@ -324,7 +303,7 @@ Transform3D Node3D::get_relative_transform(const Node *p_parent) const { } void Node3D::set_position(const Vector3 &p_position) { - get_transform().origin = p_position; + data.local_transform.origin = p_position; _propagate_transform_changed(this); if (data.notify_local_transform) { notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); @@ -335,13 +314,9 @@ void Node3D::set_rotation_edit_mode(RotationEditMode p_mode) { if (data.rotation_edit_mode == p_mode) { return; } - - data.quaternion = get_transform().basis.get_rotation_quaternion(); - data.rotation = get_transform().basis.get_euler_normalized(data.rotation_order); - data.scale = get_transform().basis.get_scale(); data.rotation_edit_mode = p_mode; - // Shearing is not allowed except in ROTATION_EDIT_MODE_BASIS, so validate local_transform. + // Shearing is not allowed except in ROTATION_EDIT_MODE_BASIS. data.dirty |= DIRTY_LOCAL; _propagate_transform_changed(this); if (data.notify_local_transform) { @@ -365,9 +340,8 @@ void Node3D::set_rotation_order(RotationOrder p_order) { ERR_FAIL_INDEX(int32_t(order), 6); if (data.dirty & DIRTY_VECTORS) { - data.quaternion = get_transform().basis.get_rotation_quaternion(); - data.rotation = get_transform().basis.get_euler_normalized(order); - data.scale = get_transform().basis.get_scale(); + data.rotation = data.local_transform.basis.get_euler_normalized(order); + data.scale = data.local_transform.basis.get_scale(); data.dirty &= ~DIRTY_VECTORS; } else { data.rotation = Basis::from_euler(data.rotation, data.rotation_order).get_euler_normalized(order); @@ -385,8 +359,7 @@ Node3D::RotationOrder Node3D::get_rotation_order() const { void Node3D::set_rotation(const Vector3 &p_euler_rad) { if (data.dirty & DIRTY_VECTORS) { - data.quaternion = get_transform().basis.get_rotation_quaternion(); - data.scale = get_transform().basis.get_scale(); + data.scale = data.local_transform.basis.get_scale(); data.dirty &= ~DIRTY_VECTORS; } @@ -400,8 +373,7 @@ void Node3D::set_rotation(const Vector3 &p_euler_rad) { void Node3D::set_scale(const Vector3 &p_scale) { if (data.dirty & DIRTY_VECTORS) { - data.quaternion = get_transform().basis.get_rotation_quaternion(); - data.rotation = get_transform().basis.get_euler_normalized(data.rotation_order); + data.rotation = data.local_transform.basis.get_euler_normalized(data.rotation_order); data.dirty &= ~DIRTY_VECTORS; } @@ -414,14 +386,14 @@ void Node3D::set_scale(const Vector3 &p_scale) { } Vector3 Node3D::get_position() const { - return get_transform().origin; + return data.local_transform.origin; } Vector3 Node3D::get_rotation() const { if (data.dirty & DIRTY_VECTORS) { - data.quaternion = get_transform().basis.get_rotation_quaternion(); - data.rotation = get_transform().basis.get_euler_normalized(data.rotation_order); - data.scale = get_transform().basis.get_scale(); + data.scale = data.local_transform.basis.get_scale(); + data.rotation = data.local_transform.basis.get_euler_normalized(data.rotation_order); + data.dirty &= ~DIRTY_VECTORS; } @@ -430,9 +402,9 @@ Vector3 Node3D::get_rotation() const { Vector3 Node3D::get_scale() const { if (data.dirty & DIRTY_VECTORS) { - data.quaternion = get_transform().basis.get_rotation_quaternion(); - data.rotation = get_transform().basis.get_euler_normalized(data.rotation_order); - data.scale = get_transform().basis.get_scale(); + data.scale = data.local_transform.basis.get_scale(); + data.rotation = data.local_transform.basis.get_euler_normalized(data.rotation_order); + data.dirty &= ~DIRTY_VECTORS; } @@ -893,7 +865,7 @@ Variant Node3D::property_get_revert(const String &p_name) { } else if (p_name == "quaternion") { Variant variant = PropertyUtils::get_property_default_value(this, "transform", &valid); if (valid && variant.get_type() == Variant::Type::TRANSFORM3D) { - r_ret = Transform3D(variant).get_basis().get_rotation_quaternion(); + r_ret = Quaternion(Transform3D(variant).get_basis()); } else { return Quaternion(); } @@ -1008,7 +980,7 @@ void Node3D::_bind_methods() { ADD_GROUP("Transform", ""); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform", PROPERTY_HINT_NONE, "suffix:m", PROPERTY_USAGE_NO_EDITOR), "set_transform", "get_transform"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "global_transform", PROPERTY_HINT_NONE, "suffix:m", PROPERTY_USAGE_NONE), "set_global_transform", "get_global_transform"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_greater,or_lesser,noslider,suffix:m", PROPERTY_USAGE_EDITOR), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_greater,or_lesser,no_slider,suffix:m", PROPERTY_USAGE_EDITOR), "set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians", PROPERTY_USAGE_EDITOR), "set_rotation", "get_rotation"); ADD_PROPERTY(PropertyInfo(Variant::QUATERNION, "quaternion", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_quaternion", "get_quaternion"); ADD_PROPERTY(PropertyInfo(Variant::BASIS, "basis", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_basis", "get_basis"); diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h index 3d561e8620..6d857a83ea 100644 --- a/scene/3d/node_3d.h +++ b/scene/3d/node_3d.h @@ -81,7 +81,6 @@ private: mutable Transform3D global_transform; mutable Transform3D local_transform; mutable Basis::EulerOrder rotation_order = Basis::EULER_ORDER_YXZ; - mutable Quaternion quaternion; mutable Vector3 rotation; mutable Vector3 scale = Vector3(1, 1, 1); mutable RotationEditMode rotation_edit_mode = ROTATION_EDIT_MODE_EULER; diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp index a54e728c1b..e9c33b1839 100644 --- a/scene/debugger/scene_debugger.cpp +++ b/scene/debugger/scene_debugger.cpp @@ -701,7 +701,7 @@ void LiveEditor::_res_set_func(int p_id, const StringName &p_prop, const Variant return; } - Ref<Resource> r = ResourceCache::get(resp); + Ref<Resource> r = ResourceCache::get_ref(resp); if (!r.is_valid()) { return; } @@ -728,7 +728,7 @@ void LiveEditor::_res_call_func(int p_id, const StringName &p_method, const Vari return; } - Ref<Resource> r = ResourceCache::get(resp); + Ref<Resource> r = ResourceCache::get_ref(resp); if (!r.is_valid()) { return; } diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 192d214262..a2b05ee50d 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -262,7 +262,7 @@ Button *AcceptDialog::add_button(const String &p_text, bool p_right, const Strin Button *AcceptDialog::add_cancel_button(const String &p_cancel) { String c = p_cancel; if (p_cancel.is_empty()) { - c = TTRC("Cancel"); + c = RTR("Cancel"); } Button *b = swap_cancel_ok ? add_button(c, true) : add_button(c); b->connect("pressed", callable_mp(this, &AcceptDialog::_cancel_pressed)); @@ -349,7 +349,7 @@ AcceptDialog::AcceptDialog() { hbc->add_spacer(); ok = memnew(Button); - ok->set_text(TTRC("OK")); + ok->set_text(RTR("OK")); hbc->add_child(ok); hbc->add_spacer(); diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 1725816c31..0e0f8bde83 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -337,7 +337,7 @@ void FileDialog::_action_pressed() { } if (dir_access->file_exists(f)) { - confirm_save->set_text(TTRC("File exists, overwrite?")); + confirm_save->set_text(RTR("File exists, overwrite?")); confirm_save->popup_centered(Size2(200, 80)); } else { emit_signal(SNAME("file_selected"), f); @@ -423,10 +423,10 @@ void FileDialog::deselect_all() { switch (mode) { case FILE_MODE_OPEN_FILE: case FILE_MODE_OPEN_FILES: - get_ok_button()->set_text(TTRC("Open")); + get_ok_button()->set_text(RTR("Open")); break; case FILE_MODE_OPEN_DIR: - get_ok_button()->set_text(TTRC("Select Current Folder")); + get_ok_button()->set_text(RTR("Select Current Folder")); break; case FILE_MODE_OPEN_ANY: case FILE_MODE_SAVE_FILE: @@ -450,7 +450,7 @@ void FileDialog::_tree_selected() { if (!d["dir"]) { file->set_text(d["name"]); } else if (mode == FILE_MODE_OPEN_DIR) { - get_ok_button()->set_text(TTRC("Select This Folder")); + get_ok_button()->set_text(RTR("Select This Folder")); } get_ok_button()->set_disabled(_is_open_should_be_disabled()); @@ -502,7 +502,7 @@ void FileDialog::update_file_list() { if (dir_access->is_readable(dir_access->get_current_dir().utf8().get_data())) { message->hide(); } else { - message->set_text(TTRC("You don't have permission to access contents of this folder.")); + message->set_text(RTR("You don't have permission to access contents of this folder.")); message->show(); } @@ -746,35 +746,35 @@ void FileDialog::set_file_mode(FileMode p_mode) { mode = p_mode; switch (mode) { case FILE_MODE_OPEN_FILE: - get_ok_button()->set_text(TTRC("Open")); + get_ok_button()->set_text(RTR("Open")); if (mode_overrides_title) { set_title(TTRC("Open a File")); } makedir->hide(); break; case FILE_MODE_OPEN_FILES: - get_ok_button()->set_text(TTRC("Open")); + get_ok_button()->set_text(RTR("Open")); if (mode_overrides_title) { set_title(TTRC("Open File(s)")); } makedir->hide(); break; case FILE_MODE_OPEN_DIR: - get_ok_button()->set_text(TTRC("Select Current Folder")); + get_ok_button()->set_text(RTR("Select Current Folder")); if (mode_overrides_title) { set_title(TTRC("Open a Directory")); } makedir->show(); break; case FILE_MODE_OPEN_ANY: - get_ok_button()->set_text(TTRC("Open")); + get_ok_button()->set_text(RTR("Open")); if (mode_overrides_title) { set_title(TTRC("Open a File or Directory")); } makedir->show(); break; case FILE_MODE_SAVE_FILE: - get_ok_button()->set_text(TTRC("Save")); + get_ok_button()->set_text(RTR("Save")); if (mode_overrides_title) { set_title(TTRC("Save a File")); } @@ -964,13 +964,13 @@ FileDialog::FileDialog() { dir_prev = memnew(Button); dir_prev->set_flat(true); - dir_prev->set_tooltip(TTRC("Go to previous folder.")); + dir_prev->set_tooltip(RTR("Go to previous folder.")); dir_next = memnew(Button); dir_next->set_flat(true); - dir_next->set_tooltip(TTRC("Go to next folder.")); + dir_next->set_tooltip(RTR("Go to next folder.")); dir_up = memnew(Button); dir_up->set_flat(true); - dir_up->set_tooltip(TTRC("Go to parent folder.")); + dir_up->set_tooltip(RTR("Go to parent folder.")); hbc->add_child(dir_prev); hbc->add_child(dir_next); hbc->add_child(dir_up); @@ -978,7 +978,7 @@ FileDialog::FileDialog() { dir_next->connect("pressed", callable_mp(this, &FileDialog::_go_forward)); dir_up->connect("pressed", callable_mp(this, &FileDialog::_go_up)); - hbc->add_child(memnew(Label(TTRC("Path:")))); + hbc->add_child(memnew(Label(RTR("Path:")))); drives_container = memnew(HBoxContainer); hbc->add_child(drives_container); @@ -994,7 +994,7 @@ FileDialog::FileDialog() { refresh = memnew(Button); refresh->set_flat(true); - refresh->set_tooltip(TTRC("Refresh files.")); + refresh->set_tooltip(RTR("Refresh files.")); refresh->connect("pressed", callable_mp(this, &FileDialog::update_file_list)); hbc->add_child(refresh); @@ -1002,7 +1002,7 @@ FileDialog::FileDialog() { show_hidden->set_flat(true); show_hidden->set_toggle_mode(true); show_hidden->set_pressed(is_showing_hidden_files()); - show_hidden->set_tooltip(TTRC("Toggle the visibility of hidden files.")); + show_hidden->set_tooltip(RTR("Toggle the visibility of hidden files.")); show_hidden->connect("toggled", callable_mp(this, &FileDialog::set_show_hidden_files)); hbc->add_child(show_hidden); @@ -1010,14 +1010,14 @@ FileDialog::FileDialog() { hbc->add_child(shortcuts_container); makedir = memnew(Button); - makedir->set_text(TTRC("Create Folder")); + makedir->set_text(RTR("Create Folder")); makedir->connect("pressed", callable_mp(this, &FileDialog::_make_dir)); hbc->add_child(makedir); vbox->add_child(hbc); tree = memnew(Tree); tree->set_hide_root(true); - vbox->add_margin_child(TTRC("Directories & Files:"), tree, true); + vbox->add_margin_child(RTR("Directories & Files:"), tree, true); message = memnew(Label); message->hide(); @@ -1027,7 +1027,7 @@ FileDialog::FileDialog() { tree->add_child(message); file_box = memnew(HBoxContainer); - file_box->add_child(memnew(Label(TTRC("File:")))); + file_box->add_child(memnew(Label(RTR("File:")))); file = memnew(LineEdit); file->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE); file->set_stretch_ratio(4); @@ -1058,22 +1058,22 @@ FileDialog::FileDialog() { confirm_save->connect("confirmed", callable_mp(this, &FileDialog::_save_confirm_pressed)); makedialog = memnew(ConfirmationDialog); - makedialog->set_title(TTRC("Create Folder")); + makedialog->set_title(RTR("Create Folder")); VBoxContainer *makevb = memnew(VBoxContainer); makedialog->add_child(makevb); makedirname = memnew(LineEdit); makedirname->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE); - makevb->add_margin_child(TTRC("Name:"), makedirname); + makevb->add_margin_child(RTR("Name:"), makedirname); add_child(makedialog, false, INTERNAL_MODE_FRONT); makedialog->register_text_enter(makedirname); makedialog->connect("confirmed", callable_mp(this, &FileDialog::_make_dir_confirm)); mkdirerr = memnew(AcceptDialog); - mkdirerr->set_text(TTRC("Could not create folder.")); + mkdirerr->set_text(RTR("Could not create folder.")); add_child(mkdirerr, false, INTERNAL_MODE_FRONT); exterr = memnew(AcceptDialog); - exterr->set_text(TTRC("Must use a valid extension.")); + exterr->set_text(RTR("Must use a valid extension.")); add_child(exterr, false, INTERNAL_MODE_FRONT); update_filters(); diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp index f36682942f..80859e8eb9 100644 --- a/scene/gui/progress_bar.cpp +++ b/scene/gui/progress_bar.cpp @@ -126,7 +126,11 @@ int ProgressBar::get_fill_mode() { } void ProgressBar::set_percent_visible(bool p_visible) { + if (percent_visible == p_visible) { + return; + } percent_visible = p_visible; + update_minimum_size(); update(); } diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 8299d73b68..fa929344d4 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -727,6 +727,7 @@ void TabContainer::set_tab_hidden(int p_tab, bool p_hidden) { if (!get_clip_tabs()) { update_minimum_size(); } + call_deferred(SNAME("_repaint")); } bool TabContainer::is_tab_hidden(int p_tab) const { diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index b2fd8eb895..f4fd81b25f 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -439,12 +439,15 @@ void CapsuleMesh::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater,suffix:m"), "set_height", "get_height"); ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_radial_segments", "get_radial_segments"); ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_rings", "get_rings"); + + ADD_LINKED_PROPERTY("radius", "height"); + ADD_LINKED_PROPERTY("height", "radius"); } void CapsuleMesh::set_radius(const float p_radius) { radius = p_radius; if (radius > height * 0.5) { - radius = height * 0.5; + height = radius * 2.0; } _request_update(); } @@ -456,7 +459,7 @@ float CapsuleMesh::get_radius() const { void CapsuleMesh::set_height(const float p_height) { height = p_height; if (radius > height * 0.5) { - height = radius * 2; + radius = height * 0.5; } _request_update(); } diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index dba53338eb..3cda2f05b2 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -526,9 +526,9 @@ Error ResourceLoaderText::load() { if (cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE && ResourceCache::has(path)) { //reuse existing - Resource *r = ResourceCache::get(path); - if (r && r->get_class() == type) { - res = Ref<Resource>(r); + Ref<Resource> cache = ResourceCache::get_ref(path); + if (cache.is_valid() && cache->get_class() == type) { + res = cache; res->reset_state(); do_assign = true; } @@ -537,10 +537,10 @@ Error ResourceLoaderText::load() { MissingResource *missing_resource = nullptr; if (res.is_null()) { //not reuse - if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE && ResourceCache::has(path)) { //only if it doesn't exist + Ref<Resource> cache = ResourceCache::get_ref(path); + if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE && cache.is_valid()) { //only if it doesn't exist //cached, do not assign - Resource *r = ResourceCache::get(path); - res = Ref<Resource>(r); + res = cache; } else { //create @@ -650,12 +650,10 @@ Error ResourceLoaderText::load() { return error; } - if (cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE && ResourceCache::has(local_path)) { - Resource *r = ResourceCache::get(local_path); - if (r->get_class() == res_type) { - r->reset_state(); - resource = Ref<Resource>(r); - } + Ref<Resource> cache = ResourceCache::get_ref(local_path); + if (cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE && cache.is_valid() && cache->get_class() == res_type) { + cache->reset_state(); + resource = cache; } MissingResource *missing_resource = nullptr; |