Browse Source

Merge pull request #55509 from V-Sekai/create_node_and_doc_fix

Fix crashes when global named scripts extends an unnamed script
Rémi Verschelde 3 years ago
parent
commit
ae52ad2fc4
2 changed files with 72 additions and 15 deletions
  1. 64 13
      editor/create_dialog.cpp
  2. 8 2
      editor/create_dialog.h

+ 64 - 13
editor/create_dialog.cpp

@@ -170,7 +170,7 @@ void CreateDialog::_update_search() {
 	root->set_text(0, base_type);
 	root->set_text(0, base_type);
 	root->set_icon(0, search_options->get_theme_icon(icon_fallback, SNAME("EditorIcons")));
 	root->set_icon(0, search_options->get_theme_icon(icon_fallback, SNAME("EditorIcons")));
 	search_options_types[base_type] = root;
 	search_options_types[base_type] = root;
-	_configure_search_option_item(root, base_type, ClassDB::class_exists(base_type));
+	_configure_search_option_item(root, base_type, ClassDB::class_exists(base_type) ? TypeCategory::CPP_TYPE : TypeCategory::OTHER_TYPE);
 
 
 	const String search_text = search_box->get_text();
 	const String search_text = search_box->get_text();
 	bool empty_search = search_text.is_empty();
 	bool empty_search = search_text.is_empty();
@@ -185,7 +185,7 @@ void CreateDialog::_update_search() {
 
 
 	// Build the type tree.
 	// Build the type tree.
 	for (int i = 0; i < candidates.size(); i++) {
 	for (int i = 0; i < candidates.size(); i++) {
-		_add_type(candidates[i], ClassDB::class_exists(candidates[i]));
+		_add_type(candidates[i], ClassDB::class_exists(candidates[i]) ? TypeCategory::CPP_TYPE : TypeCategory::OTHER_TYPE);
 	}
 	}
 
 
 	// Select the best result.
 	// Select the best result.
@@ -202,31 +202,80 @@ void CreateDialog::_update_search() {
 	}
 	}
 }
 }
 
 
-void CreateDialog::_add_type(const String &p_type, bool p_cpp_type) {
+void CreateDialog::_add_type(const String &p_type, const TypeCategory p_type_category) {
 	if (search_options_types.has(p_type)) {
 	if (search_options_types.has(p_type)) {
 		return;
 		return;
 	}
 	}
 
 
 	String inherits;
 	String inherits;
-	if (p_cpp_type) {
+
+	TypeCategory inherited_type = TypeCategory::OTHER_TYPE;
+
+	if (p_type_category == TypeCategory::CPP_TYPE) {
 		inherits = ClassDB::get_parent_class(p_type);
 		inherits = ClassDB::get_parent_class(p_type);
-	} else if (ScriptServer::is_global_class(p_type)) {
-		inherits = EditorNode::get_editor_data().script_class_get_base(p_type);
+		inherited_type = TypeCategory::CPP_TYPE;
+	} else if (p_type_category == TypeCategory::PATH_TYPE) {
+		ERR_FAIL_COND(!ResourceLoader::exists(p_type, "Script"));
+		Ref<Script> script = ResourceLoader::load(p_type, "Script");
+		ERR_FAIL_COND(script.is_null());
+
+		Ref<Script> base = script->get_base_script();
+		if (base.is_null()) {
+			String extends;
+			script->get_language()->get_global_class_name(script->get_path(), &extends);
+
+			inherits = extends;
+			inherited_type = TypeCategory::CPP_TYPE;
+		} else {
+			inherits = script->get_language()->get_global_class_name(base->get_path());
+			if (inherits.is_empty()) {
+				inherits = base->get_path();
+				inherited_type = TypeCategory::PATH_TYPE;
+			}
+		}
 	} else {
 	} else {
-		inherits = custom_type_parents[p_type];
+		if (ScriptServer::is_global_class(p_type)) {
+			inherits = EditorNode::get_editor_data().script_class_get_base(p_type);
+			if (inherits.is_empty()) {
+				Ref<Script> script = EditorNode::get_editor_data().script_class_load_script(p_type);
+				ERR_FAIL_COND(script.is_null());
+
+				Ref<Script> base = script->get_base_script();
+				if (base.is_null()) {
+					String extends;
+					script->get_language()->get_global_class_name(script->get_path(), &extends);
+
+					inherits = extends;
+					inherited_type = TypeCategory::CPP_TYPE;
+				} else {
+					inherits = base->get_path();
+					inherited_type = TypeCategory::PATH_TYPE;
+				}
+			}
+		} else {
+			inherits = custom_type_parents[p_type];
+			if (ClassDB::class_exists(inherits)) {
+				inherited_type = TypeCategory::CPP_TYPE;
+			}
+		}
 	}
 	}
 
 
-	_add_type(inherits, p_cpp_type || ClassDB::class_exists(inherits));
+	// Should never happen, but just in case...
+	ERR_FAIL_COND(inherits.is_empty());
+
+	_add_type(inherits, inherited_type);
 
 
 	TreeItem *item = search_options->create_item(search_options_types[inherits]);
 	TreeItem *item = search_options->create_item(search_options_types[inherits]);
 	search_options_types[p_type] = item;
 	search_options_types[p_type] = item;
-	_configure_search_option_item(item, p_type, p_cpp_type);
+	_configure_search_option_item(item, p_type, p_type_category);
 }
 }
 
 
-void CreateDialog::_configure_search_option_item(TreeItem *r_item, const String &p_type, const bool p_cpp_type) {
+void CreateDialog::_configure_search_option_item(TreeItem *r_item, const String &p_type, const TypeCategory p_type_category) {
 	bool script_type = ScriptServer::is_global_class(p_type);
 	bool script_type = ScriptServer::is_global_class(p_type);
-	if (p_cpp_type) {
+	if (p_type_category == TypeCategory::CPP_TYPE) {
 		r_item->set_text(0, p_type);
 		r_item->set_text(0, p_type);
+	} else if (p_type_category == TypeCategory::PATH_TYPE) {
+		r_item->set_text(0, "\"" + p_type + "\"");
 	} else if (script_type) {
 	} else if (script_type) {
 		r_item->set_metadata(0, p_type);
 		r_item->set_metadata(0, p_type);
 		r_item->set_text(0, p_type + " (" + ScriptServer::get_global_class_path(p_type).get_file() + ")");
 		r_item->set_text(0, p_type + " (" + ScriptServer::get_global_class_path(p_type).get_file() + ")");
@@ -235,7 +284,9 @@ void CreateDialog::_configure_search_option_item(TreeItem *r_item, const String
 		r_item->set_text(0, p_type);
 		r_item->set_text(0, p_type);
 	}
 	}
 
 
-	bool can_instantiate = (p_cpp_type && ClassDB::can_instantiate(p_type)) || !p_cpp_type;
+	bool can_instantiate = (p_type_category == TypeCategory::CPP_TYPE && ClassDB::can_instantiate(p_type)) ||
+			p_type_category == TypeCategory::OTHER_TYPE;
+
 	if (!can_instantiate) {
 	if (!can_instantiate) {
 		r_item->set_custom_color(0, search_options->get_theme_color(SNAME("disabled_font_color"), SNAME("Editor")));
 		r_item->set_custom_color(0, search_options->get_theme_color(SNAME("disabled_font_color"), SNAME("Editor")));
 		r_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_type, "NodeDisabled"));
 		r_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_type, "NodeDisabled"));
@@ -259,7 +310,7 @@ void CreateDialog::_configure_search_option_item(TreeItem *r_item, const String
 	const String &description = DTR(EditorHelp::get_doc_data()->class_list[p_type].brief_description);
 	const String &description = DTR(EditorHelp::get_doc_data()->class_list[p_type].brief_description);
 	r_item->set_tooltip(0, description);
 	r_item->set_tooltip(0, description);
 
 
-	if (!p_cpp_type && !script_type) {
+	if (p_type_category == TypeCategory::OTHER_TYPE && !script_type) {
 		Ref<Texture2D> icon = EditorNode::get_editor_data().get_custom_types()[custom_type_parents[p_type]][custom_type_indices[p_type]].icon;
 		Ref<Texture2D> icon = EditorNode::get_editor_data().get_custom_types()[custom_type_parents[p_type]][custom_type_indices[p_type]].icon;
 		if (icon.is_valid()) {
 		if (icon.is_valid()) {
 			r_item->set_icon(0, icon);
 			r_item->set_icon(0, icon);

+ 8 - 2
editor/create_dialog.h

@@ -41,6 +41,12 @@
 class CreateDialog : public ConfirmationDialog {
 class CreateDialog : public ConfirmationDialog {
 	GDCLASS(CreateDialog, ConfirmationDialog);
 	GDCLASS(CreateDialog, ConfirmationDialog);
 
 
+	enum TypeCategory {
+		CPP_TYPE,
+		PATH_TYPE,
+		OTHER_TYPE
+	};
+
 	LineEdit *search_box;
 	LineEdit *search_box;
 	Tree *search_options;
 	Tree *search_options;
 
 
@@ -62,8 +68,8 @@ class CreateDialog : public ConfirmationDialog {
 
 
 	void _update_search();
 	void _update_search();
 	bool _should_hide_type(const String &p_type) const;
 	bool _should_hide_type(const String &p_type) const;
-	void _add_type(const String &p_current, bool p_cpp_type);
-	void _configure_search_option_item(TreeItem *r_item, const String &p_type, const bool p_cpp_type);
+	void _add_type(const String &p_type, const TypeCategory p_type_category);
+	void _configure_search_option_item(TreeItem *r_item, const String &p_type, const TypeCategory p_type_category);
 	String _top_result(const Vector<String> p_candidates, const String &p_search_text) const;
 	String _top_result(const Vector<String> p_candidates, const String &p_search_text) const;
 	float _score_type(const String &p_type, const String &p_search) const;
 	float _score_type(const String &p_type, const String &p_search) const;
 	bool _is_type_preferred(const String &p_type) const;
 	bool _is_type_preferred(const String &p_type) const;