summaryrefslogtreecommitdiff
path: root/core/object
diff options
context:
space:
mode:
Diffstat (limited to 'core/object')
-rw-r--r--core/object/make_virtuals.py4
-rw-r--r--core/object/object.cpp6
-rw-r--r--core/object/object.h29
-rw-r--r--core/object/script_language.cpp86
-rw-r--r--core/object/script_language.h10
-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
8 files changed, 115 insertions, 36 deletions
diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py
index 0ee95835a6..18f27ae4a4 100644
--- a/core/object/make_virtuals.py
+++ b/core/object/make_virtuals.py
@@ -72,6 +72,7 @@ def generate_version(argcount, const=False, returns=False):
s = s.replace("$RVOID", "(void)r_ret;") # If required, may lead to uninitialized errors
s = s.replace("$CALLPTRRETDEF", "PtrToArg<m_ret>::EncodeT ret;")
method_info += "\tmethod_info.return_val = GetTypeInfo<m_ret>::get_class_info();\\\n"
+ method_info += "\tmethod_info.return_val_metadata = GetTypeInfo<m_ret>::METADATA;\\\n"
else:
s = s.replace("$RET", "")
s = s.replace("$RVOID", "")
@@ -113,6 +114,9 @@ def generate_version(argcount, const=False, returns=False):
)
callptrargsptr += "&argval" + str(i + 1)
method_info += "\tmethod_info.arguments.push_back(GetTypeInfo<m_type" + str(i + 1) + ">::get_class_info());\\\n"
+ method_info += (
+ "\tmethod_info.arguments_metadata.push_back(GetTypeInfo<m_type" + str(i + 1) + ">::METADATA);\\\n"
+ )
if argcount:
callsiargs += "};\\\n"
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 2cb56dfe6c..57aa1339ec 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -499,7 +499,7 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
_get_property_listv(p_list, p_reversed);
if (!is_class("Script")) { // can still be set, but this is for user-friendliness
- p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NEVER_DUPLICATE));
}
if (script_instance && !p_reversed) {
@@ -1549,7 +1549,9 @@ void Object::_bind_methods() {
#define BIND_OBJ_CORE_METHOD(m_method) \
::ClassDB::add_virtual_method(get_class_static(), m_method, true, Vector<String>(), true);
- BIND_OBJ_CORE_METHOD(MethodInfo("_notification", PropertyInfo(Variant::INT, "what")));
+ MethodInfo notification_mi("_notification", PropertyInfo(Variant::INT, "what"));
+ notification_mi.arguments_metadata.push_back(GodotTypeInfo::Metadata::METADATA_INT_IS_INT32);
+ BIND_OBJ_CORE_METHOD(notification_mi);
BIND_OBJ_CORE_METHOD(MethodInfo(Variant::BOOL, "_set", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value")));
#ifdef TOOLS_ENABLED
MethodInfo miget("_get", PropertyInfo(Variant::STRING_NAME, "property"));
diff --git a/core/object/object.h b/core/object/object.h
index f78c7c34fd..5ec69a371b 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -109,15 +109,16 @@ enum PropertyUsageFlags {
PROPERTY_USAGE_CLASS_IS_ENUM = 1 << 16,
PROPERTY_USAGE_NIL_IS_VARIANT = 1 << 17,
PROPERTY_USAGE_ARRAY = 1 << 18, // Used in the inspector to group properties as elements of an array.
- PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE = 1 << 19, // If the object is duplicated also this property will be duplicated.
- PROPERTY_USAGE_HIGH_END_GFX = 1 << 20,
- PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT = 1 << 21,
- PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT = 1 << 22,
- PROPERTY_USAGE_KEYING_INCREMENTS = 1 << 23, // Used in inspector to increment property when keyed in animation player.
- PROPERTY_USAGE_DEFERRED_SET_RESOURCE = 1 << 24, // when loading, the resource for this property can be set at the end of loading.
- PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT = 1 << 25, // For Object properties, instantiate them when creating in editor.
- PROPERTY_USAGE_EDITOR_BASIC_SETTING = 1 << 26, //for project or editor settings, show when basic settings are selected.
- PROPERTY_USAGE_READ_ONLY = 1 << 27, // Mark a property as read-only in the inspector.
+ PROPERTY_USAGE_ALWAYS_DUPLICATE = 1 << 19, // When duplicating a resource, always duplicate, even with subresource duplication disabled.
+ PROPERTY_USAGE_NEVER_DUPLICATE = 1 << 20, // When duplicating a resource, never duplicate, even with subresource duplication enabled.
+ PROPERTY_USAGE_HIGH_END_GFX = 1 << 21,
+ PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT = 1 << 22,
+ PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT = 1 << 23,
+ PROPERTY_USAGE_KEYING_INCREMENTS = 1 << 24, // Used in inspector to increment property when keyed in animation player.
+ PROPERTY_USAGE_DEFERRED_SET_RESOURCE = 1 << 25, // when loading, the resource for this property can be set at the end of loading.
+ PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT = 1 << 26, // For Object properties, instantiate them when creating in editor.
+ PROPERTY_USAGE_EDITOR_BASIC_SETTING = 1 << 27, //for project or editor settings, show when basic settings are selected.
+ PROPERTY_USAGE_READ_ONLY = 1 << 28, // Mark a property as read-only in the inspector.
PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR,
PROPERTY_USAGE_NO_EDITOR = PROPERTY_USAGE_STORAGE,
@@ -222,6 +223,16 @@ struct MethodInfo {
int id = 0;
List<PropertyInfo> arguments;
Vector<Variant> default_arguments;
+ int return_val_metadata = 0;
+ Vector<int> arguments_metadata;
+
+ int get_argument_meta(int p_arg) const {
+ ERR_FAIL_COND_V(p_arg < -1 || p_arg > arguments.size(), 0);
+ if (p_arg == -1) {
+ return return_val_metadata;
+ }
+ return arguments_metadata.size() > p_arg ? arguments_metadata[p_arg] : 0;
+ }
inline bool operator==(const MethodInfo &p_method) const { return id == p_method.id; }
inline bool operator<(const MethodInfo &p_method) const { return id == p_method.id ? (name < p_method.name) : (id < p_method.id); }
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp
index 7be3a6c688..61f5cfc22a 100644
--- a/core/object/script_language.cpp
+++ b/core/object/script_language.cpp
@@ -186,6 +186,7 @@ void ScriptServer::unregister_language(const ScriptLanguage *p_language) {
void ScriptServer::init_languages() {
{ // Load global classes.
global_classes_clear();
+#ifndef DISABLE_DEPRECATED
if (ProjectSettings::get_singleton()->has_setting("_global_script_classes")) {
Array script_classes = GLOBAL_GET("_global_script_classes");
@@ -196,6 +197,17 @@ void ScriptServer::init_languages() {
}
add_global_class(c["class"], c["base"], c["language"], c["path"]);
}
+ ProjectSettings::get_singleton()->clear("_global_script_classes");
+ }
+#endif
+
+ Array script_classes = ProjectSettings::get_singleton()->get_global_class_list();
+ for (int i = 0; i < script_classes.size(); i++) {
+ Dictionary c = script_classes[i];
+ if (!c.has("class") || !c.has("language") || !c.has("path") || !c.has("base")) {
+ continue;
+ }
+ add_global_class(c["class"], c["base"], c["language"], c["path"]);
}
}
@@ -233,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) {
@@ -245,10 +260,47 @@ 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;
+ }
+ }
}
bool ScriptServer::is_global_class(const StringName &p_class) {
@@ -291,6 +343,17 @@ void ScriptServer::get_global_class_list(List<StringName> *r_global_classes) {
}
void ScriptServer::save_global_classes() {
+ Dictionary class_icons;
+
+ Array script_classes = ProjectSettings::get_singleton()->get_global_class_list();
+ for (int i = 0; i < script_classes.size(); i++) {
+ Dictionary d = script_classes[i];
+ if (!d.has("name") || !d.has("icon")) {
+ continue;
+ }
+ class_icons[d["name"]] = d["icon"];
+ }
+
List<StringName> gc;
get_global_class_list(&gc);
Array gcarr;
@@ -300,25 +363,18 @@ void ScriptServer::save_global_classes() {
d["language"] = global_classes[E].language;
d["path"] = global_classes[E].path;
d["base"] = global_classes[E].base;
+ d["icon"] = class_icons.get(E, "");
gcarr.push_back(d);
}
+ ProjectSettings::get_singleton()->store_global_class_list(gcarr);
+}
- Array old;
- if (ProjectSettings::get_singleton()->has_setting("_global_script_classes")) {
- old = GLOBAL_GET("_global_script_classes");
- }
- if ((!old.is_empty() || gcarr.is_empty()) && gcarr.hash() == old.hash()) {
- return;
- }
+bool ScriptServer::has_global_classes() {
+ return !global_classes.is_empty();
+}
- if (gcarr.is_empty()) {
- if (ProjectSettings::get_singleton()->has_setting("_global_script_classes")) {
- ProjectSettings::get_singleton()->clear("_global_script_classes");
- }
- } else {
- ProjectSettings::get_singleton()->set("_global_script_classes", gcarr);
- }
- ProjectSettings::get_singleton()->save();
+String ScriptServer::get_global_class_cache_file_path() {
+ return ProjectSettings::get_singleton()->get_global_class_list_path();
}
////////////////////
diff --git a/core/object/script_language.h b/core/object/script_language.h
index ff678bcd25..b1393c7196 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;
@@ -80,13 +82,17 @@ public:
static void global_classes_clear();
static void add_global_class(const StringName &p_class, const StringName &p_base, const StringName &p_language, const String &p_path);
static void remove_global_class(const StringName &p_class);
+ static void remove_global_class_by_path(const String &p_path);
static bool is_global_class(const StringName &p_class);
static StringName get_global_class_language(const StringName &p_class);
static String get_global_class_path(const String &p_class);
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 bool has_global_classes();
+ static String get_global_class_cache_file_path();
static void init_languages();
static void finish_languages();
@@ -119,7 +125,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();