diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/io/json.cpp | 33 | ||||
-rw-r--r-- | core/io/json.h | 9 | ||||
-rw-r--r-- | core/object/script_language.cpp | 31 | ||||
-rw-r--r-- | core/object/script_language.h | 5 | ||||
-rw-r--r-- | core/os/os.cpp | 16 | ||||
-rw-r--r-- | core/os/os.h | 2 |
6 files changed, 80 insertions, 16 deletions
diff --git a/core/io/json.cpp b/core/io/json.cpp index ca29534c35..448e39b2c3 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -30,6 +30,7 @@ #include "json.h" +#include "core/config/engine.h" #include "core/string/print_string.h" const char *JSON::tk_name[TK_MAX] = { @@ -506,6 +507,7 @@ Error JSON::_parse_object(Dictionary &object, const char32_t *p_str, int &index, void JSON::set_data(const Variant &p_data) { data = p_data; + text.clear(); } Error JSON::_parse_string(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line) { @@ -539,14 +541,21 @@ Error JSON::_parse_string(const String &p_json, Variant &r_ret, String &r_err_st return err; } -Error JSON::parse(const String &p_json_string) { +Error JSON::parse(const String &p_json_string, bool p_keep_text) { Error err = _parse_string(p_json_string, data, err_str, err_line); if (err == Error::OK) { err_line = 0; } + if (p_keep_text) { + text = p_json_string; + } return err; } +String JSON::get_parsed_text() const { + return text; +} + String JSON::stringify(const Variant &p_var, const String &p_indent, bool p_sort_keys, bool p_full_precision) { Ref<JSON> jason; jason.instantiate(); @@ -565,10 +574,11 @@ Variant JSON::parse_string(const String &p_json_string) { void JSON::_bind_methods() { ClassDB::bind_static_method("JSON", D_METHOD("stringify", "data", "indent", "sort_keys", "full_precision"), &JSON::stringify, DEFVAL(""), DEFVAL(true), DEFVAL(false)); ClassDB::bind_static_method("JSON", D_METHOD("parse_string", "json_string"), &JSON::parse_string); - ClassDB::bind_method(D_METHOD("parse", "json_string"), &JSON::parse); + ClassDB::bind_method(D_METHOD("parse", "json_text", "keep_text"), &JSON::parse, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_data"), &JSON::get_data); ClassDB::bind_method(D_METHOD("set_data", "data"), &JSON::set_data); + ClassDB::bind_method(D_METHOD("get_parsed_text"), &JSON::get_parsed_text); ClassDB::bind_method(D_METHOD("get_error_line"), &JSON::get_error_line); ClassDB::bind_method(D_METHOD("get_error_message"), &JSON::get_error_message); @@ -592,13 +602,20 @@ Ref<Resource> ResourceFormatLoaderJSON::load(const String &p_path, const String Ref<JSON> json; json.instantiate(); - Error err = json->parse(FileAccess::get_file_as_string(p_path)); + Error err = json->parse(FileAccess::get_file_as_string(p_path), Engine::get_singleton()->is_editor_hint()); if (err != OK) { - if (r_error) { - *r_error = err; + String err_text = "Error parsing JSON file at '" + p_path + "', on line " + itos(json->get_error_line()) + ": " + json->get_error_message(); + + if (Engine::get_singleton()->is_editor_hint()) { + // If running on editor, still allow opening the JSON so the code editor can edit it. + WARN_PRINT(err_text); + } else { + if (r_error) { + *r_error = err; + } + ERR_PRINT(err_text); + return Ref<Resource>(); } - ERR_PRINT("Error parsing JSON file at '" + p_path + "', on line " + itos(json->get_error_line()) + ": " + json->get_error_message()); - return Ref<Resource>(); } if (r_error) { @@ -628,7 +645,7 @@ Error ResourceFormatSaverJSON::save(const Ref<Resource> &p_resource, const Strin Ref<JSON> json = p_resource; ERR_FAIL_COND_V(json.is_null(), ERR_INVALID_PARAMETER); - String source = JSON::stringify(json->get_data(), "\t", false, true); + String source = json->get_parsed_text().is_empty() ? JSON::stringify(json->get_data(), "\t", false, true) : json->get_parsed_text(); Error err; Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err); diff --git a/core/io/json.h b/core/io/json.h index d66a4e24a3..a21cc542fd 100644 --- a/core/io/json.h +++ b/core/io/json.h @@ -36,8 +36,8 @@ #include "core/io/resource_saver.h" #include "core/variant/variant.h" -class JSON : public RefCounted { - GDCLASS(JSON, RefCounted); +class JSON : public Resource { + GDCLASS(JSON, Resource); enum TokenType { TK_CURLY_BRACKET_OPEN, @@ -65,6 +65,7 @@ class JSON : public RefCounted { Variant value; }; + String text; Variant data; String err_str; int err_line = 0; @@ -83,7 +84,9 @@ protected: static void _bind_methods(); public: - Error parse(const String &p_json_string); + Error parse(const String &p_json_string, bool p_keep_text = false); + String get_parsed_text() const; + static String stringify(const Variant &p_var, const String &p_indent = "", bool p_sort_keys = true, bool p_full_precision = false); static Variant parse_string(const String &p_json_string); diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp index 66ef418e42..df5486512d 100644 --- a/core/object/script_language.cpp +++ b/core/object/script_language.cpp @@ -245,9 +245,12 @@ void ScriptServer::thread_exit() { } HashMap<StringName, ScriptServer::GlobalScriptClass> ScriptServer::global_classes; +HashMap<StringName, Vector<StringName>> ScriptServer::inheriters_cache; +bool ScriptServer::inheriters_cache_dirty = true; void ScriptServer::global_classes_clear() { global_classes.clear(); + inheriters_cache.clear(); } void ScriptServer::add_global_class(const StringName &p_class, const StringName &p_base, const StringName &p_language, const String &p_path) { @@ -257,16 +260,44 @@ void ScriptServer::add_global_class(const StringName &p_class, const StringName g.path = p_path; g.base = p_base; global_classes[p_class] = g; + inheriters_cache_dirty = true; } void ScriptServer::remove_global_class(const StringName &p_class) { global_classes.erase(p_class); + inheriters_cache_dirty = true; +} + +void ScriptServer::get_inheriters_list(const StringName &p_base_type, List<StringName> *r_classes) { + if (inheriters_cache_dirty) { + inheriters_cache.clear(); + for (const KeyValue<StringName, GlobalScriptClass> &K : global_classes) { + if (!inheriters_cache.has(K.value.base)) { + inheriters_cache[K.value.base] = Vector<StringName>(); + } + inheriters_cache[K.value.base].push_back(K.key); + } + for (KeyValue<StringName, Vector<StringName>> &K : inheriters_cache) { + K.value.sort_custom<StringName::AlphCompare>(); + } + inheriters_cache_dirty = false; + } + + if (!inheriters_cache.has(p_base_type)) { + return; + } + + const Vector<StringName> &v = inheriters_cache[p_base_type]; + for (int i = 0; i < v.size(); i++) { + r_classes->push_back(v[i]); + } } void ScriptServer::remove_global_class_by_path(const String &p_path) { for (const KeyValue<StringName, GlobalScriptClass> &kv : global_classes) { if (kv.value.path == p_path) { global_classes.erase(kv.key); + inheriters_cache_dirty = true; return; } } diff --git a/core/object/script_language.h b/core/object/script_language.h index 02d1880dc2..0c64b079c1 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -56,10 +56,12 @@ class ScriptServer { struct GlobalScriptClass { StringName language; String path; - String base; + StringName base; }; static HashMap<StringName, GlobalScriptClass> global_classes; + static HashMap<StringName, Vector<StringName>> inheriters_cache; + static bool inheriters_cache_dirty; public: static ScriptEditRequestFunction edit_request_func; @@ -87,6 +89,7 @@ public: static StringName get_global_class_base(const String &p_class); static StringName get_global_class_native_base(const String &p_class); static void get_global_class_list(List<StringName> *r_global_classes); + static void get_inheriters_list(const StringName &p_base_type, List<StringName> *r_classes); static void save_global_classes(); static void init_languages(); diff --git a/core/os/os.cpp b/core/os/os.cpp index c6fa8d307b..86469852e3 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -203,16 +203,26 @@ uint64_t OS::get_embedded_pck_offset() const { } // Helper function to ensure that a dir name/path will be valid on the OS -String OS::get_safe_dir_name(const String &p_dir_name, bool p_allow_dir_separator) const { +String OS::get_safe_dir_name(const String &p_dir_name, bool p_allow_paths) const { + String safe_dir_name = p_dir_name; Vector<String> invalid_chars = String(": * ? \" < > |").split(" "); - if (p_allow_dir_separator) { + if (p_allow_paths) { // Dir separators are allowed, but disallow ".." to avoid going up the filesystem invalid_chars.push_back(".."); + safe_dir_name = safe_dir_name.replace("\\", "/").strip_edges(); } else { invalid_chars.push_back("/"); + invalid_chars.push_back("\\"); + safe_dir_name = safe_dir_name.strip_edges(); + + // These directory names are invalid. + if (safe_dir_name == ".") { + safe_dir_name = "dot"; + } else if (safe_dir_name == "..") { + safe_dir_name = "twodots"; + } } - String safe_dir_name = p_dir_name.replace("\\", "/").strip_edges(); for (int i = 0; i < invalid_chars.size(); i++) { safe_dir_name = safe_dir_name.replace(invalid_chars[i], "-"); } diff --git a/core/os/os.h b/core/os/os.h index 4818e9281a..436a83eae3 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -238,7 +238,7 @@ public: virtual uint64_t get_embedded_pck_offset() const; - String get_safe_dir_name(const String &p_dir_name, bool p_allow_dir_separator = false) const; + String get_safe_dir_name(const String &p_dir_name, bool p_allow_paths = false) const; virtual String get_godot_dir_name() const; virtual String get_data_path() const; |