Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TypeDB. Refactor Custom Types, CreateDialog. #27566

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 60 additions & 96 deletions editor/create_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@

void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode, const String &p_select_type) {

type_list.clear();
ClassDB::get_class_list(&type_list);
ScriptServer::get_global_class_list(&type_list);
type_list.sort_custom<StringName::AlphCompare>();

recent->clear();

FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::READ);
Expand All @@ -60,7 +55,7 @@ void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode, const St
if (ClassDB::class_exists(name) || ScriptServer::is_global_class(name)) {
TreeItem *ti = recent->create_item(root);
ti->set_text(0, l);
ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(l, base_type));
ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(name, base_type));
}
}

Expand Down Expand Up @@ -141,31 +136,25 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p
if (p_types.has(p_type))
return;

bool cpp_type = ClassDB::class_exists(p_type);
EditorData &ed = EditorNode::get_editor_data();
const TypeDB &tdb = EditorNode::get_editor_data().get_type_db();

if (p_type == base_type)
return;

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;
if (!tdb.is_parent_class(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 path = tdb.get_path_by_class(p_type);
if (path.length() && path.find("res://addons/", 0) != -1 && !EditorNode::get_singleton()->is_addon_plugin_enabled(path.get_slicec('/', 3))) {
return;
}

String inherits = cpp_type ? ClassDB::get_parent_class(p_type) : ed.script_class_get_base(p_type);
StringName inherits = tdb.get_parent_class(p_type);
StringName empty;

TreeItem *parent = p_root;

if (inherits.length()) {
if (inherits != empty) {

if (!p_types.has(inherits)) {

Expand All @@ -174,18 +163,20 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p

if (p_types.has(inherits))
parent = p_types[inherits];
else if (ScriptServer::is_global_class(inherits))
else {
return;
}
}

bool can_instance = (cpp_type && ClassDB::can_instance(p_type)) || ScriptServer::is_global_class(p_type);
bool can_instance = tdb.can_instance(p_type);

TreeItem *item = search_options->create_item(parent);
if (cpp_type) {
String to_select_type = *to_select ? (*to_select)->get_text(0).split(" ")[0] : "";
if (ClassDB::class_exists(p_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() + ")");
item->set_text(0, p_type + " (" + tdb.get_path_by_class(p_type).get_file() + ")");
}
if (!can_instance) {
item->set_custom_color(0, get_color("disabled_font_color", "Editor"));
Expand Down Expand Up @@ -236,7 +227,7 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p
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.has(p_type)) ? EditorHelp::get_doc_data()->class_list[p_type].brief_description : "";
item->set_tooltip(0, description);

item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_type, base_type));
Expand Down Expand Up @@ -305,92 +296,36 @@ void CreateDialog::_update_search() {
search_options_types.clear();

TreeItem *root = search_options->create_item();
EditorData &ed = EditorNode::get_editor_data();
const TypeDB &tdb = EditorNode::get_editor_data().get_type_db();

root->set_text(0, base_type);
if (has_icon(base_type, "EditorIcons")) {
root->set_icon(0, get_icon(base_type, "EditorIcons"));
}
root->set_icon(0, EditorNode::get_singleton()->get_class_icon(base_type));
search_options_types[base_type] = root;

TreeItem *to_select = search_box->get_text() == base_type ? root : NULL;

for (List<StringName>::Element *I = type_list.front(); I; I = I->next()) {

String type = I->get();

if (_is_class_disabled_by_feature_profile(type)) {
continue;
}
bool cpp_type = ClassDB::class_exists(type);

if (base_type == "Node" && type.begins_with("Editor"))
continue; // do not show editor nodes

if (cpp_type && !ClassDB::can_instance(type))
continue; // can't create what can't be instanced

if (cpp_type) {
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 (skip)
continue;
}
for (int i = 0; i < type_listv.size(); ++i) {
StringName type = type_listv[i];

if (search_box->get_text() == "") {
add_type(type, search_options_types, root, &to_select);
} else {

bool found = false;
String type2 = I->get();
while (type2 != "" && (cpp_type ? ClassDB::is_parent_class(type2, base_type) : ed.script_class_is_parent(type2, base_type)) && type2 != base_type) {
if (search_box->get_text().is_subsequence_ofi(type2)) {
StringName current_type = type; // will move up through inherited types. One of them must be a subsequence.
StringName empty;
while (current_type != empty && tdb.is_parent_class(current_type, base_type) && current_type != base_type) {
if (search_box->get_text().is_subsequence_ofi(current_type)) {

found = true;
break;
}

type2 = cpp_type ? ClassDB::get_parent_class(type2) : ed.script_class_get_base(type2);
current_type = tdb.get_parent_class(current_type);
}

if (found)
add_type(I->get(), search_options_types, root, &to_select);
}

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.

const Vector<EditorData::CustomType> &ct = EditorNode::get_editor_data().get_custom_types()[type];
for (int i = 0; i < ct.size(); i++) {

bool show = search_box->get_text().is_subsequence_ofi(ct[i].name);

if (!show)
continue;

if (!search_options_types.has(type))
add_type(type, search_options_types, root, &to_select);

TreeItem *ti;
if (search_options_types.has(type))
ti = search_options_types[type];
else
ti = search_options->get_root();

TreeItem *item = search_options->create_item(ti);
item->set_metadata(0, type);
item->set_text(0, ct[i].name);
if (ct[i].icon.is_valid()) {
item->set_icon(0, ct[i].icon);
}

if (!to_select || ct[i].name == search_box->get_text()) {
to_select = item;
}
}
add_type(type, search_options_types, root, &to_select);
}
}

Expand Down Expand Up @@ -451,6 +386,7 @@ void CreateDialog::_notification(int p_what) {
search_box->set_right_icon(get_icon("Search", "EditorIcons"));
search_box->set_clear_button_enabled(true);
favorite->set_icon(get_icon("Favorites", "EditorIcons"));
add_to_group("create_dialogs");
} break;
case NOTIFICATION_EXIT_TREE: {
disconnect("confirmed", this, "_confirmed");
Expand Down Expand Up @@ -520,7 +456,7 @@ Object *CreateDialog::instance_selected() {
n->set_name(custom);
return obj;
}
return EditorNode::get_editor_data().instance_custom_type(selected->get_text(0), custom);
return EditorNode::get_editor_data().instance_custom_type(selected->get_text(0));
} else {
return ClassDB::instance(selected->get_text(0));
}
Expand Down Expand Up @@ -567,6 +503,34 @@ void CreateDialog::_favorite_toggled() {
_save_and_update_favorite_list();
}

void CreateDialog::fs_changed() {
type_list.clear();
const TypeDB &tdb = EditorNode::get_editor_data().get_type_db();
tdb.get_class_list(&type_list);
type_list.sort_custom<StringName::AlphCompare>();
type_listv.clear();
for (List<StringName>::Element *E = type_list.front(); E; E = E->next()) {
StringName type = E->get();
if (base_type == "Node" && String(type).begins_with("Editor"))
continue; // do not show editor nodes
if (!tdb.can_instance(type))
continue; // can't create what can't be instanced
if (_is_class_disabled_by_feature_profile(type)) {
continue;
}
type_listv.push_back(type);
}
for (int i = 0; i < type_listv.size(); ++i) {
for (int j = 0; j < type_blacklist.size(); ++j) {
if (tdb.is_parent_class(type_listv[i], type_blacklist[j])) {
type_listv.remove(i);
--i;
break;
}
}
}
}

void CreateDialog::_save_favorite_list() {

FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE);
Expand Down Expand Up @@ -802,8 +766,8 @@ CreateDialog::CreateDialog() {
vbc->add_margin_child(TTR("Description:"), help_bit);
help_bit->connect("request_hide", this, "_closed");

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.push_back("PluginScript"); // PluginScript must be initialized before use, which is not possible here
type_blacklist.push_back("ScriptCreateDialog"); // This is an exposed editor Node that doesn't have an Editor prefix.

EDITOR_DEF("interface/editors/derive_script_globals_by_name", true);
}
7 changes: 5 additions & 2 deletions editor/create_dialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ class CreateDialog : public ConfirmationDialog {
String preferred_search_result_type;
EditorHelpBit *help_bit;
List<StringName> type_list;
Set<StringName> type_blacklist;
Vector<StringName> type_listv;
Vector<StringName> type_blacklist;

void _item_selected();

Expand Down Expand Up @@ -110,7 +111,9 @@ class CreateDialog : public ConfirmationDialog {

void popup_create(bool p_dont_clear, bool p_replace_mode = false, const String &p_select_type = "Node");

void fs_changed();

CreateDialog();
};

#endif
#endif
87 changes: 56 additions & 31 deletions editor/editor_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -479,56 +479,81 @@ EditorPlugin *EditorData::get_editor_plugin(int p_idx) {
return editor_plugins[p_idx];
}

void EditorData::get_custom_type_class_list(List<StringName> *p_classes) const {
ERR_FAIL_COND(!p_classes);
custom_types.get_key_list(p_classes);
}

StringName EditorData::get_custom_type_name(const String &p_path) const {
List<StringName> names;
get_custom_type_class_list(&names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
Ref<Script> script = custom_types[E->get()].script;
if (script.is_null())
continue;
if (script->get_path() == p_path)
return E->get();
}
return StringName();
}

Ref<Script> EditorData::get_custom_type_script(const StringName &p_type) const {
ERR_FAIL_COND_V(!custom_types.has(p_type), NULL);
return custom_types[p_type].script;
}

String EditorData::get_custom_type_path(const StringName &p_type) const {
ERR_FAIL_COND_V(!custom_types.has(p_type), String());
Ref<Script> script = custom_types[p_type].script;
ERR_FAIL_COND_V(script.is_null(), String());
return script->get_path();
}

StringName EditorData::get_custom_type_base(const StringName &p_type) const {
ERR_FAIL_COND_V(!custom_types.has(p_type), StringName());
return custom_types[p_type].base;
}

Ref<Texture> EditorData::get_custom_type_icon(const String &p_type) const {
ERR_FAIL_COND_V(!custom_types.has(p_type), NULL);
return custom_types[p_type].icon;
}

void EditorData::add_custom_type(const String &p_type, const String &p_inherits, const Ref<Script> &p_script, const Ref<Texture> &p_icon) {

ERR_FAIL_COND(custom_types.has(p_type));
ERR_FAIL_COND(ScriptServer::is_global_class(p_type));
ERR_FAIL_COND(p_script.is_null());
CustomType ct;
ct.name = p_type;
ct.icon = p_icon;
ct.script = p_script;
if (!custom_types.has(p_inherits)) {
custom_types[p_inherits] = Vector<CustomType>();
}

custom_types[p_inherits].push_back(ct);
custom_types[p_type] = ct;
}

Object *EditorData::instance_custom_type(const String &p_type, const String &p_inherits) {
Object *EditorData::instance_custom_type(const String &p_type) {

if (get_custom_types().has(p_inherits)) {
ERR_FAIL_COND_V(!custom_types.has(p_type), NULL);

for (int i = 0; i < get_custom_types()[p_inherits].size(); i++) {
if (get_custom_types()[p_inherits][i].name == p_type) {
Ref<Script> script = get_custom_types()[p_inherits][i].script;
const CustomType &ct = custom_types[p_type];
Ref<Script> script = ct.script;
ERR_FAIL_COND_V(script.is_null(), NULL);

Object *ob = ClassDB::instance(p_inherits);
ERR_FAIL_COND_V(!ob, NULL);
if (ob->is_class("Node")) {
ob->call("set_name", p_type);
}
ob->set_script(script.get_ref_ptr());
return ob;
}
}
Object *ob = ClassDB::instance(script->get_instance_base_type());
ERR_FAIL_COND_V(!ob, NULL);

if (ob->is_class("Node")) {
ob->call("set_name", p_type);
}
ob->set_script(script.get_ref_ptr());

return NULL;
return ob;
}

void EditorData::remove_custom_type(const String &p_type) {

for (Map<String, Vector<CustomType> >::Element *E = custom_types.front(); E; E = E->next()) {

for (int i = 0; i < E->get().size(); i++) {
if (E->get()[i].name == p_type) {
E->get().remove(i);
if (E->get().empty()) {
custom_types.erase(E->key());
}
return;
}
}
}
custom_types.erase(p_type);
}

int EditorData::add_edited_scene(int p_at_pos) {
Expand Down
Loading