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/io/resource_format_binary.cpp93
-rw-r--r--core/io/resource_format_binary.h4
-rw-r--r--core/io/resource_loader.cpp20
-rw-r--r--core/io/resource_loader.h3
-rw-r--r--core/math/bvh.h8
-rw-r--r--core/math/delaunay_3d.h12
-rw-r--r--core/math/geometry_3d.cpp28
-rw-r--r--core/object/script_language.cpp31
-rw-r--r--core/object/script_language.h7
-rw-r--r--core/object/script_language_extension.h1
-rw-r--r--core/object/undo_redo.cpp3
-rw-r--r--core/object/worker_thread_pool.cpp12
-rw-r--r--core/os/os.cpp16
-rw-r--r--core/os/os.h2
-rw-r--r--core/templates/local_vector.h64
-rw-r--r--core/variant/variant_setget.cpp8
18 files changed, 297 insertions, 57 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/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 03beb25b03..c0463de427 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -91,7 +91,8 @@ enum {
// Version 2: added 64 bits support for float and int.
// Version 3: changed nodepath encoding.
// Version 4: new string ID for ext/subresources, breaks forward compat.
- FORMAT_VERSION = 4,
+ // Version 5: Ability to store script class in the header.
+ FORMAT_VERSION = 5,
FORMAT_VERSION_CAN_RENAME_DEPS = 1,
FORMAT_VERSION_NO_NODEPATH_PROPERTY = 3,
};
@@ -1009,6 +1010,10 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p
uid = ResourceUID::INVALID_ID;
}
+ if (flags & ResourceFormatSaverBinaryInstance::FORMAT_FLAG_HAS_SCRIPT_CLASS) {
+ script_class = get_unicode_string();
+ }
+
for (int i = 0; i < ResourceFormatSaverBinaryInstance::RESERVED_FIELDS; i++) {
f->get_32(); //skip a few reserved fields
}
@@ -1113,6 +1118,57 @@ String ResourceLoaderBinary::recognize(Ref<FileAccess> p_f) {
return get_unicode_string();
}
+String ResourceLoaderBinary::recognize_script_class(Ref<FileAccess> p_f) {
+ error = OK;
+
+ f = p_f;
+ uint8_t header[4];
+ f->get_buffer(header, 4);
+ if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') {
+ // Compressed.
+ Ref<FileAccessCompressed> fac;
+ fac.instantiate();
+ error = fac->open_after_magic(f);
+ if (error != OK) {
+ f.unref();
+ return "";
+ }
+ f = fac;
+
+ } else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
+ // Not normal.
+ error = ERR_FILE_UNRECOGNIZED;
+ f.unref();
+ return "";
+ }
+
+ bool big_endian = f->get_32();
+ f->get_32(); // use_real64
+
+ f->set_big_endian(big_endian != 0); //read big endian if saved as big endian
+
+ uint32_t ver_major = f->get_32();
+ f->get_32(); // ver_minor
+ uint32_t ver_fmt = f->get_32();
+
+ if (ver_fmt > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
+ f.unref();
+ return "";
+ }
+
+ get_unicode_string(); // type
+
+ f->get_64(); // Metadata offset
+ uint32_t flags = f->get_32();
+ f->get_64(); // UID
+
+ if (flags & ResourceFormatSaverBinaryInstance::FORMAT_FLAG_HAS_SCRIPT_CLASS) {
+ return get_unicode_string();
+ } else {
+ return String();
+ }
+}
+
Ref<Resource> ResourceFormatLoaderBinary::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_FILE_CANT_OPEN;
@@ -1295,6 +1351,9 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
fw->store_32(flags);
fw->store_64(uid_data);
+ if (flags & ResourceFormatSaverBinaryInstance::FORMAT_FLAG_HAS_SCRIPT_CLASS) {
+ save_ustring(fw, get_ustring(f));
+ }
for (int i = 0; i < ResourceFormatSaverBinaryInstance::RESERVED_FIELDS; i++) {
fw->store_32(0); // reserved
@@ -1416,6 +1475,18 @@ String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const
return ClassDB::get_compatibility_remapped_class(r);
}
+String ResourceFormatLoaderBinary::get_resource_script_class(const String &p_path) const {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ if (f.is_null()) {
+ return ""; //could not read
+ }
+
+ ResourceLoaderBinary loader;
+ loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
+ loader.res_path = loader.local_path;
+ return loader.recognize_script_class(f);
+}
+
ResourceUID::ID ResourceFormatLoaderBinary::get_resource_uid(const String &p_path) const {
String ext = p_path.get_extension().to_lower();
if (!ClassDB::is_resource_extension(ext)) {
@@ -2033,15 +2104,31 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re
save_unicode_string(f, _resource_get_class(p_resource));
f->store_64(0); //offset to import metadata
+
+ String script_class;
{
uint32_t format_flags = FORMAT_FLAG_NAMED_SCENE_IDS | FORMAT_FLAG_UIDS;
#ifdef REAL_T_IS_DOUBLE
format_flags |= FORMAT_FLAG_REAL_T_IS_DOUBLE;
#endif
+ if (!p_resource->is_class("PackedScene")) {
+ Ref<Script> s = p_resource->get_script();
+ if (s.is_valid()) {
+ script_class = s->get_global_name();
+ if (!script_class.is_empty()) {
+ format_flags |= ResourceFormatSaverBinaryInstance::FORMAT_FLAG_HAS_SCRIPT_CLASS;
+ }
+ }
+ }
+
f->store_32(format_flags);
}
ResourceUID::ID uid = ResourceSaver::get_resource_id_for_path(p_path, true);
f->store_64(uid);
+ if (!script_class.is_empty()) {
+ save_unicode_string(f, script_class);
+ }
+
for (int i = 0; i < ResourceFormatSaverBinaryInstance::RESERVED_FIELDS; i++) {
f->store_32(0); // reserved
}
@@ -2294,6 +2381,10 @@ Error ResourceFormatSaverBinaryInstance::set_uid(const String &p_path, ResourceU
fw->store_32(flags);
fw->store_64(p_uid);
+ if (flags & ResourceFormatSaverBinaryInstance::FORMAT_FLAG_HAS_SCRIPT_CLASS) {
+ save_ustring(fw, get_ustring(f));
+ }
+
//rest of file
uint8_t b = f->get_8();
while (!f->eof_reached()) {
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index 9dd208e3cd..add7cdf297 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -65,6 +65,7 @@ class ResourceLoaderBinary {
bool using_named_scene_ids = false;
bool using_uids = false;
+ String script_class;
bool use_sub_threads = false;
float *progress = nullptr;
Vector<ExtResource> external_resources;
@@ -99,6 +100,7 @@ public:
void set_remaps(const HashMap<String, String> &p_remaps) { remaps = p_remaps; }
void open(Ref<FileAccess> p_f, bool p_no_resources = false, bool p_keep_uuid_paths = false);
String recognize(Ref<FileAccess> p_f);
+ String recognize_script_class(Ref<FileAccess> p_f);
void get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types);
void get_classes_used(Ref<FileAccess> p_f, HashSet<StringName> *p_classes);
@@ -112,6 +114,7 @@ public:
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
+ virtual String get_resource_script_class(const String &p_path) const;
virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes);
virtual ResourceUID::ID get_resource_uid(const String &p_path) const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
@@ -164,6 +167,7 @@ public:
FORMAT_FLAG_NAMED_SCENE_IDS = 1,
FORMAT_FLAG_UIDS = 2,
FORMAT_FLAG_REAL_T_IS_DOUBLE = 4,
+ FORMAT_FLAG_HAS_SCRIPT_CLASS = 8,
// Amount of reserved 32-bit fields in resource header
RESERVED_FIELDS = 11
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 68b9f8b6f7..7447119ab7 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -99,6 +99,12 @@ String ResourceFormatLoader::get_resource_type(const String &p_path) const {
return ret;
}
+String ResourceFormatLoader::get_resource_script_class(const String &p_path) const {
+ String ret;
+ GDVIRTUAL_CALL(_get_resource_script_class, p_path, ret);
+ return ret;
+}
+
ResourceUID::ID ResourceFormatLoader::get_resource_uid(const String &p_path) const {
int64_t uid = ResourceUID::INVALID_ID;
GDVIRTUAL_CALL(_get_resource_uid, p_path, uid);
@@ -184,6 +190,7 @@ void ResourceFormatLoader::_bind_methods() {
GDVIRTUAL_BIND(_recognize_path, "path", "type");
GDVIRTUAL_BIND(_handles_type, "type");
GDVIRTUAL_BIND(_get_resource_type, "path");
+ GDVIRTUAL_BIND(_get_resource_script_class, "path");
GDVIRTUAL_BIND(_get_resource_uid, "path");
GDVIRTUAL_BIND(_get_dependencies, "path", "add_types");
GDVIRTUAL_BIND(_rename_dependencies, "path", "renames");
@@ -764,6 +771,19 @@ String ResourceLoader::get_resource_type(const String &p_path) {
return "";
}
+String ResourceLoader::get_resource_script_class(const String &p_path) {
+ String local_path = _validate_local_path(p_path);
+
+ for (int i = 0; i < loader_count; i++) {
+ String result = loader[i]->get_resource_script_class(local_path);
+ if (!result.is_empty()) {
+ return result;
+ }
+ }
+
+ return "";
+}
+
ResourceUID::ID ResourceLoader::get_resource_uid(const String &p_path) {
String local_path = _validate_local_path(p_path);
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index e427a2f5fc..eb8155e046 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -54,6 +54,7 @@ protected:
GDVIRTUAL2RC(bool, _recognize_path, String, StringName)
GDVIRTUAL1RC(bool, _handles_type, StringName)
GDVIRTUAL1RC(String, _get_resource_type, String)
+ GDVIRTUAL1RC(String, _get_resource_script_class, String)
GDVIRTUAL1RC(ResourceUID::ID, _get_resource_uid, String)
GDVIRTUAL2RC(Vector<String>, _get_dependencies, String, bool)
GDVIRTUAL1RC(Vector<String>, _get_classes_used, String)
@@ -71,6 +72,7 @@ public:
virtual bool handles_type(const String &p_type) const;
virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes);
virtual String get_resource_type(const String &p_path) const;
+ virtual String get_resource_script_class(const String &p_path) const;
virtual ResourceUID::ID get_resource_uid(const String &p_path) const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map);
@@ -175,6 +177,7 @@ public:
static void remove_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader);
static void get_classes_used(const String &p_path, HashSet<StringName> *r_classes);
static String get_resource_type(const String &p_path);
+ static String get_resource_script_class(const String &p_path);
static ResourceUID::ID get_resource_uid(const String &p_path);
static void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
static Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map);
diff --git a/core/math/bvh.h b/core/math/bvh.h
index 9de704834b..357d483375 100644
--- a/core/math/bvh.h
+++ b/core/math/bvh.h
@@ -444,9 +444,7 @@ private:
params.result_array = nullptr;
params.subindex_array = nullptr;
- for (unsigned int n = 0; n < changed_items.size(); n++) {
- const BVHHandle &h = changed_items[n];
-
+ for (const BVHHandle &h : changed_items) {
// use the expanded aabb for pairing
const BOUNDS &expanded_aabb = tree._pairs[h.id()].expanded_aabb;
BVHABB_CLASS abb;
@@ -465,9 +463,7 @@ private:
params.result_count_overall = 0; // might not be needed
tree.cull_aabb(params, false);
- for (unsigned int i = 0; i < tree._cull_hits.size(); i++) {
- uint32_t ref_id = tree._cull_hits[i];
-
+ for (const uint32_t ref_id : tree._cull_hits) {
// don't collide against ourself
if (ref_id == changed_item_ref_id) {
continue;
diff --git a/core/math/delaunay_3d.h b/core/math/delaunay_3d.h
index 8ca38d571a..55923e0133 100644
--- a/core/math/delaunay_3d.h
+++ b/core/math/delaunay_3d.h
@@ -313,20 +313,20 @@ public:
//remove simplex and continue
simplex_list.erase(simplex->SE);
- for (uint32_t k = 0; k < simplex->grid_positions.size(); k++) {
- Vector3i p = simplex->grid_positions[k].pos;
- acceleration_grid[p.x][p.y][p.z].erase(simplex->grid_positions[k].E);
+ for (const GridPos &gp : simplex->grid_positions) {
+ Vector3i p = gp.pos;
+ acceleration_grid[p.x][p.y][p.z].erase(gp.E);
}
memdelete(simplex);
}
E = N;
}
- for (uint32_t j = 0; j < triangles.size(); j++) {
- if (triangles[j].bad) {
+ for (const Triangle &triangle : triangles) {
+ if (triangle.bad) {
continue;
}
- Simplex *new_simplex = memnew(Simplex(triangles[j].triangle[0], triangles[j].triangle[1], triangles[j].triangle[2], i));
+ Simplex *new_simplex = memnew(Simplex(triangle.triangle[0], triangle.triangle[1], triangle.triangle[2], i));
circum_sphere_compute(points, new_simplex);
new_simplex->SE = simplex_list.push_back(new_simplex);
{
diff --git a/core/math/geometry_3d.cpp b/core/math/geometry_3d.cpp
index 51523ea296..4786110054 100644
--- a/core/math/geometry_3d.cpp
+++ b/core/math/geometry_3d.cpp
@@ -141,21 +141,19 @@ real_t Geometry3D::get_closest_distance_between_segments(const Vector3 &p_p0, co
void Geometry3D::MeshData::optimize_vertices() {
HashMap<int, int> vtx_remap;
- for (uint32_t i = 0; i < faces.size(); i++) {
- for (uint32_t j = 0; j < faces[i].indices.size(); j++) {
- int idx = faces[i].indices[j];
- if (!vtx_remap.has(idx)) {
+ for (MeshData::Face &face : faces) {
+ for (int &index : face.indices) {
+ if (!vtx_remap.has(index)) {
int ni = vtx_remap.size();
- vtx_remap[idx] = ni;
+ vtx_remap[index] = ni;
}
-
- faces[i].indices[j] = vtx_remap[idx];
+ index = vtx_remap[index];
}
}
- for (uint32_t i = 0; i < edges.size(); i++) {
- int a = edges[i].vertex_a;
- int b = edges[i].vertex_b;
+ for (MeshData::Edge edge : edges) {
+ int a = edge.vertex_a;
+ int b = edge.vertex_b;
if (!vtx_remap.has(a)) {
int ni = vtx_remap.size();
@@ -166,8 +164,8 @@ void Geometry3D::MeshData::optimize_vertices() {
vtx_remap[b] = ni;
}
- edges[i].vertex_a = vtx_remap[a];
- edges[i].vertex_b = vtx_remap[b];
+ edge.vertex_a = vtx_remap[a];
+ edge.vertex_b = vtx_remap[b];
}
LocalVector<Vector3> new_vertices;
@@ -673,10 +671,10 @@ Geometry3D::MeshData Geometry3D::build_convex_mesh(const Vector<Plane> &p_planes
MeshData::Face face;
// Add face indices.
- for (uint32_t j = 0; j < vertices.size(); j++) {
+ for (const Vector3 &vertex : vertices) {
int idx = -1;
for (uint32_t k = 0; k < mesh.vertices.size(); k++) {
- if (mesh.vertices[k].distance_to(vertices[j]) < 0.001f) {
+ if (mesh.vertices[k].distance_to(vertex) < 0.001f) {
idx = k;
break;
}
@@ -684,7 +682,7 @@ Geometry3D::MeshData Geometry3D::build_convex_mesh(const Vector<Plane> &p_planes
if (idx == -1) {
idx = mesh.vertices.size();
- mesh.vertices.push_back(vertices[j]);
+ mesh.vertices.push_back(vertex);
}
face.indices.push_back(idx);
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..f82b58439f 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();
@@ -120,7 +123,7 @@ public:
virtual bool can_instantiate() const = 0;
virtual Ref<Script> get_base_script() const = 0; //for script inheritance
-
+ virtual StringName get_global_name() const = 0;
virtual bool inherits_script(const Ref<Script> &p_script) const = 0;
virtual StringName get_instance_base_type() const = 0; // this may not work in all scripts, will return empty if so
diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h
index 912f2218c4..8e162a1b0f 100644
--- a/core/object/script_language_extension.h
+++ b/core/object/script_language_extension.h
@@ -53,6 +53,7 @@ protected:
public:
EXBIND0RC(bool, can_instantiate)
EXBIND0RC(Ref<Script>, get_base_script)
+ EXBIND0RC(StringName, get_global_name)
EXBIND1RC(bool, inherits_script, const Ref<Script> &)
EXBIND0RC(StringName, get_instance_base_type)
diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp
index e84933eb69..077929351e 100644
--- a/core/object/undo_redo.cpp
+++ b/core/object/undo_redo.cpp
@@ -99,8 +99,7 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) {
}
}
- for (unsigned int i = 0; i < to_remove.size(); i++) {
- List<Operation>::Element *E = to_remove[i];
+ for (List<Operation>::Element *E : to_remove) {
// Delete all object references
E->get().delete_reference();
E->erase();
diff --git a/core/object/worker_thread_pool.cpp b/core/object/worker_thread_pool.cpp
index fc907b2301..721c8d0a10 100644
--- a/core/object/worker_thread_pool.cpp
+++ b/core/object/worker_thread_pool.cpp
@@ -377,11 +377,11 @@ void WorkerThreadPool::wait_for_group_task_completion(GroupID p_group) {
Group *group = *groupp;
if (group->low_priority_native_tasks.size() > 0) {
- for (uint32_t i = 0; i < group->low_priority_native_tasks.size(); i++) {
- group->low_priority_native_tasks[i]->low_priority_thread->wait_to_finish();
- native_thread_allocator.free(group->low_priority_native_tasks[i]->low_priority_thread);
+ for (Task *task : group->low_priority_native_tasks) {
+ task->low_priority_thread->wait_to_finish();
+ native_thread_allocator.free(task->low_priority_thread);
task_mutex.lock();
- task_allocator.free(group->low_priority_native_tasks[i]);
+ task_allocator.free(task);
task_mutex.unlock();
}
@@ -449,8 +449,8 @@ void WorkerThreadPool::finish() {
task_available_semaphore.post();
}
- for (uint32_t i = 0; i < threads.size(); i++) {
- threads[i].thread.wait_to_finish();
+ for (ThreadData &data : threads) {
+ data.thread.wait_to_finish();
}
threads.clear();
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;
diff --git a/core/templates/local_vector.h b/core/templates/local_vector.h
index 55761bb604..5311a94987 100644
--- a/core/templates/local_vector.h
+++ b/core/templates/local_vector.h
@@ -169,6 +169,70 @@ public:
return data[p_index];
}
+ struct Iterator {
+ _FORCE_INLINE_ T &operator*() const {
+ return *elem_ptr;
+ }
+ _FORCE_INLINE_ T *operator->() const { return elem_ptr; }
+ _FORCE_INLINE_ Iterator &operator++() {
+ elem_ptr++;
+ return *this;
+ }
+ _FORCE_INLINE_ Iterator &operator--() {
+ elem_ptr--;
+ return *this;
+ }
+
+ _FORCE_INLINE_ bool operator==(const Iterator &b) const { return elem_ptr == b.elem_ptr; }
+ _FORCE_INLINE_ bool operator!=(const Iterator &b) const { return elem_ptr != b.elem_ptr; }
+
+ Iterator(T *p_ptr) { elem_ptr = p_ptr; }
+ Iterator() {}
+ Iterator(const Iterator &p_it) { elem_ptr = p_it.elem_ptr; }
+
+ private:
+ T *elem_ptr = nullptr;
+ };
+
+ struct ConstIterator {
+ _FORCE_INLINE_ const T &operator*() const {
+ return *elem_ptr;
+ }
+ _FORCE_INLINE_ const T *operator->() const { return elem_ptr; }
+ _FORCE_INLINE_ ConstIterator &operator++() {
+ elem_ptr++;
+ return *this;
+ }
+ _FORCE_INLINE_ ConstIterator &operator--() {
+ elem_ptr--;
+ return *this;
+ }
+
+ _FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return elem_ptr == b.elem_ptr; }
+ _FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return elem_ptr != b.elem_ptr; }
+
+ ConstIterator(const T *p_ptr) { elem_ptr = p_ptr; }
+ ConstIterator() {}
+ ConstIterator(const ConstIterator &p_it) { elem_ptr = p_it.elem_ptr; }
+
+ private:
+ const T *elem_ptr = nullptr;
+ };
+
+ _FORCE_INLINE_ Iterator begin() {
+ return Iterator(data);
+ }
+ _FORCE_INLINE_ Iterator end() {
+ return Iterator(data + size());
+ }
+
+ _FORCE_INLINE_ ConstIterator begin() const {
+ return ConstIterator(ptr());
+ }
+ _FORCE_INLINE_ ConstIterator end() const {
+ return ConstIterator(ptr() + size());
+ }
+
void insert(U p_pos, T p_val) {
ERR_FAIL_UNSIGNED_INDEX(p_pos, count + 1);
if (p_pos == count) {
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index ba37e15f31..30fb5d0e9f 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -151,8 +151,8 @@ void unregister_named_setters_getters() {
bool Variant::has_member(Variant::Type p_type, const StringName &p_member) {
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
- for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) {
- if (variant_setters_getters_names[p_type][i] == p_member) {
+ for (const StringName &member : variant_setters_getters_names[p_type]) {
+ if (member == p_member) {
return true;
}
}
@@ -172,8 +172,8 @@ Variant::Type Variant::get_member_type(Variant::Type p_type, const StringName &p
}
void Variant::get_member_list(Variant::Type p_type, List<StringName> *r_members) {
- for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) {
- r_members->push_back(variant_setters_getters_names[p_type][i]);
+ for (const StringName &member : variant_setters_getters_names[p_type]) {
+ r_members->push_back(member);
}
}