summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/io/json.cpp33
-rw-r--r--core/io/json.h9
-rw-r--r--core/object/script_language.cpp31
-rw-r--r--core/object/script_language.h5
-rw-r--r--core/os/os.cpp16
-rw-r--r--core/os/os.h2
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;