Browse Source

Add script hierarchies,add-script btn auto-derives

Will Nations 7 years ago
parent
commit
3de15363ab
4 changed files with 127 additions and 83 deletions
  1. 62 57
      editor/create_dialog.cpp
  2. 35 0
      editor/editor_data.cpp
  3. 3 0
      editor/editor_data.h
  4. 27 26
      editor/scene_tree_dock.cpp

+ 62 - 57
editor/create_dialog.cpp

@@ -40,6 +40,11 @@
 
 
 void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode) {
 void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode) {
 
 
+	type_list.clear();
+	ClassDB::get_class_list(&type_list);
+	ScriptServer::get_global_class_list(&type_list);
+	type_list.sort_custom<StringName::AlphCompare>();
+
 	recent->clear();
 	recent->clear();
 
 
 	FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::READ);
 	FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::READ);
@@ -173,10 +178,28 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p
 
 
 	if (p_types.has(p_type))
 	if (p_types.has(p_type))
 		return;
 		return;
-	if (!ClassDB::is_parent_class(p_type, base_type) || p_type == base_type)
+
+	bool cpp_type = ClassDB::class_exists(p_type);
+	EditorData &ed = EditorNode::get_singleton()->get_editor_data();
+
+	if (p_type == base_type)
 		return;
 		return;
 
 
-	String inherits = ClassDB::get_parent_class(p_type);
+	if (cpp_type) {
+		if (!ClassDB::is_parent_class(p_type, base_type))
+			return;
+	} else {
+		if (!ScriptServer::is_global_class(p_type) || !ed.script_class_is_parent(p_type, base_type))
+			return;
+
+		String script_path = ScriptServer::get_global_class_path(p_type);
+		if (script_path.find("res://addons/", 0) != -1) {
+			if (!EditorNode::get_singleton()->is_addon_plugin_enabled(script_path.get_slicec('/', 3)))
+				return;
+		}
+	}
+
+	String inherits = cpp_type ? ClassDB::get_parent_class(p_type) : ed.script_class_get_base(p_type);
 
 
 	TreeItem *parent = p_root;
 	TreeItem *parent = p_root;
 
 
@@ -189,17 +212,32 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p
 
 
 		if (p_types.has(inherits))
 		if (p_types.has(inherits))
 			parent = p_types[inherits];
 			parent = p_types[inherits];
+		else if (ScriptServer::is_global_class(inherits))
+			return;
 	}
 	}
 
 
+	bool can_instance = (cpp_type && ClassDB::can_instance(p_type)) || ScriptServer::is_global_class(p_type);
+
 	TreeItem *item = search_options->create_item(parent);
 	TreeItem *item = search_options->create_item(parent);
-	item->set_text(0, p_type);
-	if (!ClassDB::can_instance(p_type)) {
+	if (cpp_type) {
+		item->set_text(0, p_type);
+	} else {
+		item->set_metadata(0, p_type);
+		item->set_text(0, p_type + " (" + ScriptServer::get_global_class_path(p_type).get_file() + ")");
+	}
+	if (!can_instance) {
 		item->set_custom_color(0, get_color("disabled_font_color", "Editor"));
 		item->set_custom_color(0, get_color("disabled_font_color", "Editor"));
 		item->set_selectable(0, false);
 		item->set_selectable(0, false);
 	} else {
 	} else {
 		bool is_search_subsequence = search_box->get_text().is_subsequence_ofi(p_type);
 		bool is_search_subsequence = search_box->get_text().is_subsequence_ofi(p_type);
 		String to_select_type = *to_select ? (*to_select)->get_text(0) : "";
 		String to_select_type = *to_select ? (*to_select)->get_text(0) : "";
-		bool current_item_is_preffered = ClassDB::is_parent_class(p_type, preferred_search_result_type) && !ClassDB::is_parent_class(to_select_type, preferred_search_result_type);
+		to_select_type = to_select_type.split(" ")[0];
+		bool current_item_is_preffered;
+		if (cpp_type) {
+			current_item_is_preffered = ClassDB::is_parent_class(p_type, preferred_search_result_type) && !ClassDB::is_parent_class(to_select_type, preferred_search_result_type);
+		} else {
+			current_item_is_preffered = ed.script_class_is_parent(p_type, preferred_search_result_type) && !ed.script_class_is_parent(to_select_type, preferred_search_result_type);
+		}
 		if (*to_select && p_type.length() < (*to_select)->get_text(0).length()) {
 		if (*to_select && p_type.length() < (*to_select)->get_text(0).length()) {
 			current_item_is_preffered = true;
 			current_item_is_preffered = true;
 		}
 		}
@@ -217,16 +255,19 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p
 		// don't collapse the root node
 		// don't collapse the root node
 		collapse &= (item != p_root);
 		collapse &= (item != p_root);
 		// don't collapse abstract nodes on the first tree level
 		// don't collapse abstract nodes on the first tree level
-		collapse &= ((parent != p_root) || (ClassDB::can_instance(p_type)));
+		collapse &= ((parent != p_root) || (can_instance));
 		item->set_collapsed(collapse);
 		item->set_collapsed(collapse);
 	}
 	}
 
 
 	const String &description = EditorHelp::get_doc_data()->class_list[p_type].brief_description;
 	const String &description = EditorHelp::get_doc_data()->class_list[p_type].brief_description;
 	item->set_tooltip(0, description);
 	item->set_tooltip(0, description);
 
 
-	if (has_icon(p_type, "EditorIcons")) {
+	if (cpp_type && has_icon(p_type, "EditorIcons")) {
 
 
 		item->set_icon(0, get_icon(p_type, "EditorIcons"));
 		item->set_icon(0, get_icon(p_type, "EditorIcons"));
+	} else if (!cpp_type && has_icon(ScriptServer::get_global_class_base(p_type), "EditorIcons")) {
+
+		item->set_icon(0, get_icon(ScriptServer::get_global_class_base(p_type), "EditorIcons"));
 	}
 	}
 
 
 	p_types[p_type] = item;
 	p_types[p_type] = item;
@@ -243,47 +284,38 @@ void CreateDialog::_update_search() {
 	_parse_fs(EditorFileSystem::get_singleton()->get_filesystem());
 	_parse_fs(EditorFileSystem::get_singleton()->get_filesystem());
 */
 */
 
 
-	List<StringName> global_classes;
-	ScriptServer::get_global_class_list(&global_classes);
-
-	Map<String, List<String> > global_class_map;
-	for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) {
-		String base = ScriptServer::get_global_class_base(E->get());
-		if (!global_class_map.has(base)) {
-			global_class_map[base] = List<String>();
-		}
-		global_class_map[base].push_back(E->get());
-	}
-
 	HashMap<String, TreeItem *> types;
 	HashMap<String, TreeItem *> types;
 
 
 	TreeItem *root = search_options->create_item();
 	TreeItem *root = search_options->create_item();
+	EditorData &ed = EditorNode::get_singleton()->get_editor_data();
 
 
 	root->set_text(0, base_type);
 	root->set_text(0, base_type);
 	if (has_icon(base_type, "EditorIcons")) {
 	if (has_icon(base_type, "EditorIcons")) {
 		root->set_icon(0, get_icon(base_type, "EditorIcons"));
 		root->set_icon(0, get_icon(base_type, "EditorIcons"));
 	}
 	}
 
 
-	List<StringName>::Element *I = type_list.front();
 	TreeItem *to_select = search_box->get_text() == base_type ? root : NULL;
 	TreeItem *to_select = search_box->get_text() == base_type ? root : NULL;
 
 
-	for (; I; I = I->next()) {
+	for (List<StringName>::Element *I = type_list.front(); I; I = I->next()) {
 
 
 		String type = I->get();
 		String type = I->get();
+		bool cpp_type = ClassDB::class_exists(type);
 
 
 		if (base_type == "Node" && type.begins_with("Editor"))
 		if (base_type == "Node" && type.begins_with("Editor"))
 			continue; // do not show editor nodes
 			continue; // do not show editor nodes
 
 
-		if (!ClassDB::can_instance(type))
+		if (cpp_type && !ClassDB::can_instance(type))
 			continue; // can't create what can't be instanced
 			continue; // can't create what can't be instanced
 
 
 		bool skip = false;
 		bool skip = false;
-		for (Set<StringName>::Element *E = type_blacklist.front(); E && !skip; E = E->next()) {
-			if (ClassDB::is_parent_class(type, E->get()))
-				skip = true;
+		if (cpp_type) {
+			for (Set<StringName>::Element *E = type_blacklist.front(); E && !skip; E = E->next()) {
+				if (ClassDB::is_parent_class(type, E->get()))
+					skip = true;
+			}
+			if (skip)
+				continue;
 		}
 		}
-		if (skip)
-			continue;
 
 
 		if (search_box->get_text() == "") {
 		if (search_box->get_text() == "") {
 			add_type(type, types, root, &to_select);
 			add_type(type, types, root, &to_select);
@@ -291,7 +323,7 @@ void CreateDialog::_update_search() {
 
 
 			bool found = false;
 			bool found = false;
 			String type = I->get();
 			String type = I->get();
-			while (type != "" && ClassDB::is_parent_class(type, base_type) && type != base_type) {
+			while (type != "" && (cpp_type ? ClassDB::is_parent_class(type, base_type) : ed.script_class_is_parent(type, base_type)) && type != base_type) {
 				if (search_box->get_text().is_subsequence_ofi(type)) {
 				if (search_box->get_text().is_subsequence_ofi(type)) {
 
 
 					found = true;
 					found = true;
@@ -305,32 +337,6 @@ void CreateDialog::_update_search() {
 				add_type(I->get(), types, root, &to_select);
 				add_type(I->get(), types, root, &to_select);
 		}
 		}
 
 
-		if (global_class_map.has(type) && ClassDB::is_parent_class(type, base_type)) {
-			for (List<String>::Element *J = global_class_map[type].front(); J; J = J->next()) {
-				bool show = search_box->get_text().is_subsequence_ofi(J->get());
-
-				if (!show)
-					continue;
-
-				if (!types.has(type))
-					add_type(type, types, root, &to_select);
-
-				TreeItem *ti;
-				if (types.has(type))
-					ti = types[type];
-				else
-					ti = search_options->get_root();
-
-				TreeItem *item = search_options->create_item(ti);
-				item->set_metadata(0, J->get());
-				item->set_text(0, J->get() + " (" + ScriptServer::get_global_class_path(J->get()).get_file() + ")");
-				item->set_icon(0, _get_editor_icon(type));
-				if (!to_select || J->get() == search_box->get_text()) {
-					to_select = item;
-				}
-			}
-		}
-
 		if (EditorNode::get_editor_data().get_custom_types().has(type) && ClassDB::is_parent_class(type, base_type)) {
 		if (EditorNode::get_editor_data().get_custom_types().has(type) && ClassDB::is_parent_class(type, base_type)) {
 			//there are custom types based on this... cool.
 			//there are custom types based on this... cool.
 
 
@@ -694,9 +700,6 @@ CreateDialog::CreateDialog() {
 
 
 	is_replace_mode = false;
 	is_replace_mode = false;
 
 
-	ClassDB::get_class_list(&type_list);
-	type_list.sort_custom<StringName::AlphCompare>();
-
 	set_resizable(true);
 	set_resizable(true);
 
 
 	HSplitContainer *hsc = memnew(HSplitContainer);
 	HSplitContainer *hsc = memnew(HSplitContainer);
@@ -762,4 +765,6 @@ CreateDialog::CreateDialog() {
 
 
 	type_blacklist.insert("PluginScript"); // PluginScript must be initialized before use, which is not possible here
 	type_blacklist.insert("PluginScript"); // PluginScript must be initialized before use, which is not possible here
 	type_blacklist.insert("ScriptCreateDialog"); // This is an exposed editor Node that doesn't have an Editor prefix.
 	type_blacklist.insert("ScriptCreateDialog"); // This is an exposed editor Node that doesn't have an Editor prefix.
+
+	EDITOR_DEF("interface/editors/derive_script_globals_by_name", true);
 }
 }

+ 35 - 0
editor/editor_data.cpp

@@ -853,6 +853,41 @@ void EditorData::get_plugin_window_layout(Ref<ConfigFile> p_layout) {
 	}
 	}
 }
 }
 
 
+bool EditorData::script_class_is_parent(const String &p_class, const String &p_inherits) {
+	if (!ScriptServer::is_global_class(p_class))
+		return false;
+	String base = script_class_get_base(p_class);
+	while (p_inherits != base) {
+		if (ClassDB::class_exists(base)) {
+			return ClassDB::is_parent_class(base, p_inherits);
+		} else if (ScriptServer::is_global_class(base)) {
+			base = script_class_get_base(base);
+		} else {
+			return false;
+		}
+	}
+	return true;
+}
+
+StringName EditorData::script_class_get_base(const String &p_class) {
+
+	if (!ScriptServer::is_global_class(p_class))
+		return StringName();
+
+	String path = ScriptServer::get_global_class_path(p_class);
+
+	Ref<Script> script = ResourceLoader::load(path, "Script");
+	if (script.is_null())
+		return StringName();
+
+	Ref<Script> base_script = script->get_base_script();
+	if (base_script.is_null()) {
+		return ScriptServer::get_global_class_base(p_class);
+	}
+
+	return script->get_language()->get_global_class_name(base_script->get_path());
+}
+
 EditorData::EditorData() {
 EditorData::EditorData() {
 
 
 	current_edited_scene = -1;
 	current_edited_scene = -1;

+ 3 - 0
editor/editor_data.h

@@ -211,6 +211,9 @@ public:
 	void notify_edited_scene_changed();
 	void notify_edited_scene_changed();
 	void notify_resource_saved(const Ref<Resource> &p_resource);
 	void notify_resource_saved(const Ref<Resource> &p_resource);
 
 
+	bool script_class_is_parent(const String &p_class, const String &p_inherits);
+	StringName script_class_get_base(const String &p_class);
+
 	EditorData();
 	EditorData();
 };
 };
 
 

+ 27 - 26
editor/scene_tree_dock.cpp

@@ -349,21 +349,33 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
 				break;
 				break;
 
 
 			Ref<Script> existing = selected->get_script();
 			Ref<Script> existing = selected->get_script();
-			if (existing.is_valid())
-				editor->push_item(existing.ptr());
-			else {
-				String path = selected->get_filename();
-				if (path == "") {
-					String root_path = editor_data->get_edited_scene_root()->get_filename();
-					if (root_path == "") {
-						path = "res://" + selected->get_name();
-					} else {
-						path = root_path.get_base_dir() + "/" + selected->get_name();
+
+			String path = selected->get_filename();
+			if (path == "") {
+				String root_path = editor_data->get_edited_scene_root()->get_filename();
+				if (root_path == "") {
+					path = "res://" + selected->get_name();
+				} else {
+					path = root_path.get_base_dir() + "/" + selected->get_name();
+				}
+			}
+
+			String inherits = selected->get_class();
+			if (existing.is_valid()) {
+				for (int i = 0; i < ScriptServer::get_language_count(); i++) {
+					ScriptLanguage *l = ScriptServer::get_language(i);
+					if (l->get_type() == existing->get_class()) {
+						if (EDITOR_GET("interface/editors/derive_script_globals_by_name").operator bool()) {
+							String name = l->get_global_class_name(existing->get_path(), NULL);
+							inherits = editor->get_editor_data().script_class_get_base(name);
+						} else if (l->can_inherit_from_file()) {
+							inherits = "\"" + existing->get_path() + "\"";
+						}
 					}
 					}
 				}
 				}
-				script_create_dialog->config(selected->get_class(), path);
-				script_create_dialog->popup_centered();
 			}
 			}
+			script_create_dialog->config(inherits, path);
+			script_create_dialog->popup_centered();
 
 
 		} break;
 		} break;
 		case TOOL_CLEAR_SCRIPT: {
 		case TOOL_CLEAR_SCRIPT: {
@@ -1426,13 +1438,9 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) {
 		editor_data->get_undo_redo().add_undo_method(E->get(), "set_script", existing);
 		editor_data->get_undo_redo().add_undo_method(E->get(), "set_script", existing);
 	}
 	}
 
 
-	editor_data->get_undo_redo().add_do_method(editor, "push_item", p_script.operator->());
-	editor_data->get_undo_redo().add_undo_method(editor, "push_item", (Script *)NULL);
-
-	editor_data->get_undo_redo().add_do_method(this, "_update_script_button");
-	editor_data->get_undo_redo().add_undo_method(this, "_update_script_button");
-
 	editor_data->get_undo_redo().commit_action();
 	editor_data->get_undo_redo().commit_action();
+
+	editor->push_item(p_script.operator->());
 }
 }
 
 
 void SceneTreeDock::_delete_confirm() {
 void SceneTreeDock::_delete_confirm() {
@@ -1521,16 +1529,9 @@ void SceneTreeDock::_delete_confirm() {
 
 
 void SceneTreeDock::_update_script_button() {
 void SceneTreeDock::_update_script_button() {
 	if (EditorNode::get_singleton()->get_editor_selection()->get_selection().size() == 1) {
 	if (EditorNode::get_singleton()->get_editor_selection()->get_selection().size() == 1) {
-		if (EditorNode::get_singleton()->get_editor_selection()->get_selection().front()->key()->get_script().is_null()) {
-			button_create_script->show();
-			button_clear_script->hide();
-		} else {
-			button_create_script->hide();
-			button_clear_script->show();
-		}
+		button_create_script->show();
 	} else {
 	} else {
 		button_create_script->hide();
 		button_create_script->hide();
-		button_clear_script->hide();
 	}
 	}
 }
 }