Repository: godotengine/godot
File: editor/create_dialog.cpp (C++)

Code before:
			type_list.push_back(type);

			if (!ed.get_custom_types().has(type)) {
				continue;
			}

			const Vector<EditorData::CustomType> &ct = ed.get_custom_types()[type];
			for (int i = 0; i < ct.size(); i++) {
				custom_type_parents[ct[i].name] = type;
				custom_type_indices[ct[i].name] = i;
				type_list.push_back(ct[i].name);
			}
		}
	}
	type_list.sort_custom<StringName::AlphCompare>();
}

bool CreateDialog::_is_type_preferred(const String &p_type) const {
	if (ClassDB::class_exists(p_type)) {
		return ClassDB::is_parent_class(p_type, preferred_search_result_type);
	}

	return EditorNode::get_editor_data().script_class_is_parent(p_type, preferred_search_result_type);
}

bool CreateDialog::_is_class_disabled_by_feature_profile(const StringName &p_class) const {
	Ref<EditorFeatureProfile> profile = EditorFeatureProfileManager::get_singleton()->get_current_profile();

	return !profile.is_null() && profile->is_class_disabled(p_class);
}

bool CreateDialog::_should_hide_type(const String &p_type) const {
	if (_is_class_disabled_by_feature_profile(p_type)) {
		return true;
	}

	if (base_type == "Node" && p_type.begins_with("Editor")) {
		return true; // Do not show editor nodes.
	}

	if (p_type == base_type && !EditorNode::get_editor_data().get_custom_types().has(p_type)) {
		return true; // Root is already added.
	}

	if (ClassDB::class_exists(p_type)) {
		if (!ClassDB::can_instantiate(p_type) || ClassDB::is_virtual(p_type)) {
			return true; // Can't create abstract or virtual class.
		}

		if (!ClassDB::is_parent_class(p_type, base_type)) {
			return true; // Wrong inheritance.

Review comment (suggestion):
`CreateDialog` is used in visual script with `p_replace_mode` enabled but no other parameters passed:

```
void VisualScriptEditor::_change_base_type() {
	select_base_type->popup_create(true, true);
}
```

This change would make the title look weird, and probably needs addressing. (Though visual script is on its way out so, maybe we don't care).

Code after:

	for (List<StringName>::Element *I = complete_type_list.front(); I; I = I->next()) {
		String type = I->get();
		if (!_should_hide_type(type)) {
			type_list.push_back(type);

			if (!ed.get_custom_types().has(type)) {
				continue;
			}

			const Vector<EditorData::CustomType> &ct = ed.get_custom_types()[type];
			for (int i = 0; i < ct.size(); i++) {
				custom_type_parents[ct[i].name] = type;
				custom_type_indices[ct[i].name] = i;
				type_list.push_back(ct[i].name);
			}
		}
	}
	type_list.sort_custom<StringName::AlphCompare>();
}

bool CreateDialog::_is_type_preferred(const String &p_type) const {
	if (ClassDB::class_exists(p_type)) {
		return ClassDB::is_parent_class(p_type, preferred_search_result_type);
	}

	return EditorNode::get_editor_data().script_class_is_parent(p_type, preferred_search_result_type);
}

bool CreateDialog::_is_class_disabled_by_feature_profile(const StringName &p_class) const {
	Ref<EditorFeatureProfile> profile = EditorFeatureProfileManager::get_singleton()->get_current_profile();

	return !profile.is_null() && profile->is_class_disabled(p_class);
}

bool CreateDialog::_should_hide_type(const String &p_type) const {
	if (_is_class_disabled_by_feature_profile(p_type)) {
		return true;
	}

	if (base_type == "Node" && p_type.begins_with("Editor")) {
		return true; // Do not show editor nodes.
	}

	if (p_type == base_type && !EditorNode::get_editor_data().get_custom_types().has(p_type)) {
		return true; // Root is already added.
	}

	if (ClassDB::class_exists(p_type)) {
		if (!ClassDB::can_instantiate(p_type) || ClassDB::is_virtual(p_type)) {
			return true; // Can't create abstract or virtual class.