summaryrefslogtreecommitdiff
path: root/core/script_language.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/script_language.cpp')
-rw-r--r--core/script_language.cpp185
1 files changed, 176 insertions, 9 deletions
diff --git a/core/script_language.cpp b/core/script_language.cpp
index 1dab58e29e..e146fb773c 100644
--- a/core/script_language.cpp
+++ b/core/script_language.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "script_language.h"
+#include "project_settings.h"
ScriptLanguage *ScriptServer::_languages[MAX_LANGUAGES];
int ScriptServer::_language_count = 0;
@@ -103,6 +104,20 @@ void ScriptServer::unregister_language(ScriptLanguage *p_language) {
void ScriptServer::init_languages() {
+ { //load global classes
+ global_classes_clear();
+ if (ProjectSettings::get_singleton()->has_setting("_global_script_classes")) {
+ Array script_classes = ProjectSettings::get_singleton()->get("_global_script_classes");
+
+ 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"]);
+ }
+ }
+ }
+
for (int i = 0; i < _language_count; i++) {
_languages[i]->init();
}
@@ -113,6 +128,7 @@ void ScriptServer::finish_languages() {
for (int i = 0; i < _language_count; i++) {
_languages[i]->finish();
}
+ global_classes_clear();
}
void ScriptServer::set_reload_scripts_on_save(bool p_enable) {
@@ -139,6 +155,67 @@ void ScriptServer::thread_exit() {
}
}
+HashMap<StringName, ScriptServer::GlobalScriptClass> ScriptServer::global_classes;
+
+void ScriptServer::global_classes_clear() {
+ global_classes.clear();
+}
+
+void ScriptServer::add_global_class(const StringName &p_class, const StringName &p_base, const StringName &p_language, const String &p_path) {
+ GlobalScriptClass g;
+ g.language = p_language;
+ g.path = p_path;
+ g.base = p_base;
+ global_classes[p_class] = g;
+}
+void ScriptServer::remove_global_class(const StringName &p_class) {
+ global_classes.erase(p_class);
+}
+bool ScriptServer::is_global_class(const StringName &p_class) {
+ return global_classes.has(p_class);
+}
+StringName ScriptServer::get_global_class_language(const StringName &p_class) {
+ ERR_FAIL_COND_V(!global_classes.has(p_class), StringName());
+ return global_classes[p_class].language;
+}
+String ScriptServer::get_global_class_path(const String &p_class) {
+ ERR_FAIL_COND_V(!global_classes.has(p_class), String());
+ return global_classes[p_class].path;
+}
+
+StringName ScriptServer::get_global_class_base(const String &p_class) {
+ ERR_FAIL_COND_V(!global_classes.has(p_class), String());
+ return global_classes[p_class].base;
+}
+void ScriptServer::get_global_class_list(List<StringName> *r_global_classes) {
+ const StringName *K = NULL;
+ List<StringName> classes;
+ while ((K = global_classes.next(K))) {
+ classes.push_back(*K);
+ }
+ classes.sort_custom<StringName::AlphCompare>();
+ for (List<StringName>::Element *E = classes.front(); E; E = E->next()) {
+ r_global_classes->push_back(E->get());
+ }
+}
+void ScriptServer::save_global_classes() {
+ List<StringName> gc;
+ get_global_class_list(&gc);
+ Array gcarr;
+ for (List<StringName>::Element *E = gc.front(); E; E = E->next()) {
+ Dictionary d;
+ d["class"] = E->get();
+ d["language"] = global_classes[E->get()].language;
+ d["path"] = global_classes[E->get()].path;
+ d["base"] = global_classes[E->get()].base;
+ gcarr.push_back(d);
+ }
+
+ ProjectSettings::get_singleton()->set("_global_script_classes", gcarr);
+ ProjectSettings::get_singleton()->save();
+}
+
+////////////////////
void ScriptInstance::get_property_state(List<Pair<StringName, Variant> > &state) {
List<PropertyInfo> pinfo;
@@ -178,6 +255,17 @@ void ScriptInstance::call_multilevel_reversed(const StringName &p_method, const
call(p_method, p_args, p_argcount, ce); // script may not support multilevel calls
}
+void ScriptInstance::property_set_fallback(const StringName &, const Variant &, bool *r_valid) {
+ if (r_valid)
+ *r_valid = false;
+}
+
+Variant ScriptInstance::property_get_fallback(const StringName &, bool *r_valid) {
+ if (r_valid)
+ *r_valid = false;
+ return Variant();
+}
+
void ScriptInstance::call_multilevel(const StringName &p_method, VARIANT_ARG_DECLARE) {
VARIANT_ARGPTRS;
@@ -287,6 +375,9 @@ ScriptDebugger::ScriptDebugger() {
bool PlaceHolderScriptInstance::set(const StringName &p_name, const Variant &p_value) {
+ if (build_failed)
+ return false;
+
if (values.has(p_name)) {
Variant defval;
if (script->get_property_default_value(p_name, defval)) {
@@ -315,22 +406,31 @@ bool PlaceHolderScriptInstance::get(const StringName &p_name, Variant &r_ret) co
return true;
}
- Variant defval;
- if (script->get_property_default_value(p_name, defval)) {
- r_ret = defval;
- return true;
+ if (!build_failed) {
+ Variant defval;
+ if (script->get_property_default_value(p_name, defval)) {
+ r_ret = defval;
+ return true;
+ }
}
+
return false;
}
void PlaceHolderScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const {
- for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
- PropertyInfo pinfo = E->get();
- if (!values.has(pinfo.name)) {
- pinfo.usage |= PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE;
+ if (build_failed) {
+ for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
+ p_properties->push_back(E->get());
+ }
+ } else {
+ for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
+ PropertyInfo pinfo = E->get();
+ if (!values.has(pinfo.name)) {
+ pinfo.usage |= PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE;
+ }
+ p_properties->push_back(E->get());
}
- p_properties->push_back(E->get());
}
}
@@ -347,8 +447,30 @@ Variant::Type PlaceHolderScriptInstance::get_property_type(const StringName &p_n
return Variant::NIL;
}
+void PlaceHolderScriptInstance::get_method_list(List<MethodInfo> *p_list) const {
+
+ if (build_failed)
+ return;
+
+ if (script.is_valid()) {
+ script->get_script_method_list(p_list);
+ }
+}
+bool PlaceHolderScriptInstance::has_method(const StringName &p_method) const {
+
+ if (build_failed)
+ return false;
+
+ if (script.is_valid()) {
+ return script->has_method(p_method);
+ }
+ return false;
+}
+
void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, const Map<StringName, Variant> &p_values) {
+ build_failed = false;
+
Set<StringName> new_values;
for (const List<PropertyInfo>::Element *E = p_properties.front(); E; E = E->next()) {
@@ -392,6 +514,51 @@ void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, c
//change notify
}
+void PlaceHolderScriptInstance::property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid) {
+
+ if (build_failed) {
+ Map<StringName, Variant>::Element *E = values.find(p_name);
+
+ if (E) {
+ E->value() = p_value;
+ } else {
+ values.insert(p_name, p_value);
+ }
+
+ bool found = false;
+ for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
+ if (E->get().name == p_name) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ properties.push_back(PropertyInfo(p_value.get_type(), p_name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_SCRIPT_VARIABLE));
+ }
+ }
+
+ if (r_valid)
+ *r_valid = false; // Cannot change the value in either case
+}
+
+Variant PlaceHolderScriptInstance::property_get_fallback(const StringName &p_name, bool *r_valid) {
+
+ if (build_failed) {
+ const Map<StringName, Variant>::Element *E = values.find(p_name);
+
+ if (E) {
+ if (r_valid)
+ *r_valid = true;
+ return E->value();
+ }
+ }
+
+ if (r_valid)
+ *r_valid = false;
+
+ return Variant();
+}
+
PlaceHolderScriptInstance::PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script, Object *p_owner) :
owner(p_owner),
language(p_language),