Browse Source

Merge pull request #40162 from vnen/autoloads-list

Add a map of autoloads to ProjectSettings
Rémi Verschelde 5 years ago
parent
commit
b96b0d90d7

+ 42 - 0
core/project_settings.cpp

@@ -144,6 +144,12 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
 
 	if (p_value.get_type() == Variant::NIL) {
 		props.erase(p_name);
+		if (p_name.operator String().begins_with("autoload/")) {
+			String node_name = p_name.operator String().split("/")[1];
+			if (autoloads.has(node_name)) {
+				remove_autoload(node_name);
+			}
+		}
 	} else {
 		if (p_name == CoreStringNames::get_singleton()->_custom_features) {
 			Vector<String> custom_feature_array = String(p_value).split(",");
@@ -181,6 +187,19 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
 		} else {
 			props[p_name] = VariantContainer(p_value, last_order++);
 		}
+		if (p_name.operator String().begins_with("autoload/")) {
+			String node_name = p_name.operator String().split("/")[1];
+			AutoloadInfo autoload;
+			autoload.name = node_name;
+			String path = p_value;
+			if (path.begins_with("*")) {
+				autoload.is_singleton = true;
+				autoload.path = path.substr(1);
+			} else {
+				autoload.path = path;
+			}
+			add_autoload(autoload);
+		}
 	}
 
 	return true;
@@ -945,6 +964,29 @@ bool ProjectSettings::has_custom_feature(const String &p_feature) const {
 	return custom_features.has(p_feature);
 }
 
+Map<StringName, ProjectSettings::AutoloadInfo> ProjectSettings::get_autoload_list() const {
+	return autoloads;
+}
+
+void ProjectSettings::add_autoload(const AutoloadInfo &p_autoload) {
+	ERR_FAIL_COND_MSG(p_autoload.name == StringName(), "Trying to add autoload with no name.");
+	autoloads[p_autoload.name] = p_autoload;
+}
+
+void ProjectSettings::remove_autoload(const StringName &p_autoload) {
+	ERR_FAIL_COND_MSG(!autoloads.has(p_autoload), "Trying to remove non-existent autoload.");
+	autoloads.erase(p_autoload);
+}
+
+bool ProjectSettings::has_autoload(const StringName &p_autoload) const {
+	return autoloads.has(p_autoload);
+}
+
+ProjectSettings::AutoloadInfo ProjectSettings::get_autoload(const StringName &p_name) const {
+	ERR_FAIL_COND_V_MSG(!autoloads.has(p_name), AutoloadInfo(), "Trying to get non-existent autoload.");
+	return autoloads[p_name];
+}
+
 void ProjectSettings::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("has_setting", "name"), &ProjectSettings::has_setting);
 	ClassDB::bind_method(D_METHOD("set_setting", "name", "value"), &ProjectSettings::set_setting);

+ 14 - 0
core/project_settings.h

@@ -47,6 +47,12 @@ public:
 		NO_BUILTIN_ORDER_BASE = 1 << 16
 	};
 
+	struct AutoloadInfo {
+		StringName name;
+		String path;
+		bool is_singleton = false;
+	};
+
 protected:
 	struct VariantContainer {
 		int order = 0;
@@ -79,6 +85,8 @@ protected:
 	Set<String> custom_features;
 	Map<StringName, StringName> feature_overrides;
 
+	Map<StringName, AutoloadInfo> autoloads;
+
 	bool _set(const StringName &p_name, const Variant &p_value);
 	bool _get(const StringName &p_name, Variant &r_ret) const;
 	void _get_property_list(List<PropertyInfo> *p_list) const;
@@ -148,6 +156,12 @@ public:
 
 	bool has_custom_feature(const String &p_feature) const;
 
+	Map<StringName, AutoloadInfo> get_autoload_list() const;
+	void add_autoload(const AutoloadInfo &p_autoload);
+	void remove_autoload(const StringName &p_autoload);
+	bool has_autoload(const StringName &p_autoload) const;
+	AutoloadInfo get_autoload(const StringName &p_name) const;
+
 	ProjectSettings();
 	~ProjectSettings();
 };

+ 8 - 0
editor/editor_autoload_settings.cpp

@@ -477,6 +477,8 @@ void EditorAutoloadSettings::update_autoload() {
 			info.node->queue_delete();
 			info.node = nullptr;
 		}
+
+		ProjectSettings::get_singleton()->remove_autoload(info.name);
 	}
 
 	// Load new/changed autoloads
@@ -503,6 +505,12 @@ void EditorAutoloadSettings::update_autoload() {
 			}
 		}
 
+		ProjectSettings::AutoloadInfo prop_info;
+		prop_info.name = info->name;
+		prop_info.path = info->path;
+		prop_info.is_singleton = info->is_singleton;
+		ProjectSettings::get_singleton()->add_autoload(prop_info);
+
 		if (!info->in_editor && !info->is_singleton) {
 			// No reason to keep this node
 			memdelete(info->node);

+ 11 - 17
editor/plugins/script_text_editor.cpp

@@ -343,16 +343,11 @@ void ScriptTextEditor::_set_theme_for_script() {
 	}
 
 	//colorize singleton autoloads (as types, just as engine singletons are)
-	List<PropertyInfo> props;
-	ProjectSettings::get_singleton()->get_property_list(&props);
-	for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
-		String s = E->get().name;
-		if (!s.begins_with("autoload/")) {
-			continue;
-		}
-		String path = ProjectSettings::get_singleton()->get(s);
-		if (path.begins_with("*")) {
-			text_edit->add_keyword_color(s.get_slice("/", 1), colors_cache.usertype_color);
+	Map<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
+	for (Map<StringName, ProjectSettings::AutoloadInfo>::Element *E = autoloads.front(); E; E = E->next()) {
+		const ProjectSettings::AutoloadInfo &info = E->value();
+		if (info.is_singleton) {
+			text_edit->add_keyword_color(info.name, colors_cache.usertype_color);
 		}
 	}
 
@@ -942,12 +937,11 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c
 				emit_signal("go_to_help", "class_global:" + result.class_name + ":" + result.class_member);
 			} break;
 		}
-	} else if (ProjectSettings::get_singleton()->has_setting("autoload/" + p_symbol)) {
-		//check for Autoload scenes
-		String path = ProjectSettings::get_singleton()->get("autoload/" + p_symbol);
-		if (path.begins_with("*")) {
-			path = path.substr(1, path.length());
-			EditorNode::get_singleton()->load_scene(path);
+	} else if (ProjectSettings::get_singleton()->has_autoload(p_symbol)) {
+		// Check for Autoload scenes.
+		const ProjectSettings::AutoloadInfo &info = ProjectSettings::get_singleton()->get_autoload(p_symbol);
+		if (info.is_singleton) {
+			EditorNode::get_singleton()->load_scene(info.path);
 		}
 	} else if (p_symbol.is_rel_path()) {
 		// Every symbol other than absolute path is relative path so keep this condition at last.
@@ -974,7 +968,7 @@ void ScriptTextEditor::_validate_symbol(const String &p_symbol) {
 	}
 
 	ScriptLanguage::LookupResult result;
-	if (ScriptServer::is_global_class(p_symbol) || p_symbol.is_resource_file() || script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK || ProjectSettings::get_singleton()->has_setting("autoload/" + p_symbol)) {
+	if (ScriptServer::is_global_class(p_symbol) || p_symbol.is_resource_file() || script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK || (ProjectSettings::get_singleton()->has_autoload(p_symbol) && ProjectSettings::get_singleton()->get_autoload(p_symbol).is_singleton)) {
 		text_edit->set_highlighted_word(p_symbol);
 	} else if (p_symbol.is_rel_path()) {
 		String path = _get_absolute_path(p_symbol);

+ 14 - 34
main/main.cpp

@@ -1792,46 +1792,26 @@ bool Main::start() {
 		if (!project_manager && !editor) { // game
 			if (game_path != "" || script != "") {
 				//autoload
-				List<PropertyInfo> props;
-				ProjectSettings::get_singleton()->get_property_list(&props);
+				Map<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
 
 				//first pass, add the constants so they exist before any script is loaded
-				for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
-					String s = E->get().name;
-					if (!s.begins_with("autoload/")) {
-						continue;
-					}
-					String name = s.get_slicec('/', 1);
-					String path = ProjectSettings::get_singleton()->get(s);
-					bool global_var = false;
-					if (path.begins_with("*")) {
-						global_var = true;
-					}
+				for (Map<StringName, ProjectSettings::AutoloadInfo>::Element *E = autoloads.front(); E; E = E->next()) {
+					const ProjectSettings::AutoloadInfo &info = E->get();
 
-					if (global_var) {
+					if (info.is_singleton) {
 						for (int i = 0; i < ScriptServer::get_language_count(); i++) {
-							ScriptServer::get_language(i)->add_global_constant(name, Variant());
+							ScriptServer::get_language(i)->add_global_constant(info.name, Variant());
 						}
 					}
 				}
 
 				//second pass, load into global constants
 				List<Node *> to_add;
-				for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
-					String s = E->get().name;
-					if (!s.begins_with("autoload/")) {
-						continue;
-					}
-					String name = s.get_slicec('/', 1);
-					String path = ProjectSettings::get_singleton()->get(s);
-					bool global_var = false;
-					if (path.begins_with("*")) {
-						global_var = true;
-						path = path.substr(1, path.length() - 1);
-					}
+				for (Map<StringName, ProjectSettings::AutoloadInfo>::Element *E = autoloads.front(); E; E = E->next()) {
+					const ProjectSettings::AutoloadInfo &info = E->get();
 
-					RES res = ResourceLoader::load(path);
-					ERR_CONTINUE_MSG(res.is_null(), "Can't autoload: " + path);
+					RES res = ResourceLoader::load(info.path);
+					ERR_CONTINUE_MSG(res.is_null(), "Can't autoload: " + info.path);
 					Node *n = nullptr;
 					if (res->is_class("PackedScene")) {
 						Ref<PackedScene> ps = res;
@@ -1840,7 +1820,7 @@ bool Main::start() {
 						Ref<Script> script_res = res;
 						StringName ibt = script_res->get_instance_base_type();
 						bool valid_type = ClassDB::is_parent_class(ibt, "Node");
-						ERR_CONTINUE_MSG(!valid_type, "Script does not inherit a Node: " + path);
+						ERR_CONTINUE_MSG(!valid_type, "Script does not inherit a Node: " + info.path);
 
 						Object *obj = ClassDB::instance(ibt);
 
@@ -1850,15 +1830,15 @@ bool Main::start() {
 						n->set_script(script_res);
 					}
 
-					ERR_CONTINUE_MSG(!n, "Path in autoload not a node or script: " + path);
-					n->set_name(name);
+					ERR_CONTINUE_MSG(!n, "Path in autoload not a node or script: " + info.path);
+					n->set_name(info.name);
 
 					//defer so references are all valid on _ready()
 					to_add.push_back(n);
 
-					if (global_var) {
+					if (info.is_singleton) {
 						for (int i = 0; i < ScriptServer::get_language_count(); i++) {
-							ScriptServer::get_language(i)->add_global_constant(name, n);
+							ScriptServer::get_language(i)->add_global_constant(info.name, n);
 						}
 					}
 				}

+ 4 - 9
modules/mono/editor/code_completion.cpp

@@ -123,16 +123,11 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
 		case CompletionKind::NODE_PATHS: {
 			{
 				// AutoLoads
-				List<PropertyInfo> props;
-				ProjectSettings::get_singleton()->get_property_list(&props);
+				Map<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
 
-				for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
-					String s = E->get().name;
-					if (!s.begins_with("autoload/")) {
-						continue;
-					}
-					String name = s.get_slice("/", 1);
-					suggestions.push_back(quoted("/root/" + name));
+				for (Map<StringName, ProjectSettings::AutoloadInfo>::Element *E = autoloads.front(); E; E = E->next()) {
+					const ProjectSettings::AutoloadInfo &info = E->value();
+					suggestions.push_back(quoted("/root/" + String(info.name)));
 				}
 			}