diff options
Diffstat (limited to 'editor')
-rw-r--r-- | editor/editor_node.cpp | 26 | ||||
-rw-r--r-- | editor/editor_node.h | 4 | ||||
-rw-r--r-- | editor/filesystem_dock.cpp | 4 | ||||
-rw-r--r-- | editor/find_in_files.cpp | 8 | ||||
-rw-r--r-- | editor/groups_editor.cpp | 213 | ||||
-rw-r--r-- | editor/groups_editor.h | 20 | ||||
-rw-r--r-- | editor/import/resource_importer_scene.cpp | 66 | ||||
-rw-r--r-- | editor/import/resource_importer_scene.h | 2 | ||||
-rw-r--r-- | editor/plugins/asset_library_editor_plugin.cpp | 95 | ||||
-rw-r--r-- | editor/plugins/asset_library_editor_plugin.h | 3 | ||||
-rw-r--r-- | editor/plugins/canvas_item_editor_plugin.cpp | 22 | ||||
-rw-r--r-- | editor/plugins/canvas_item_editor_plugin.h | 1 | ||||
-rw-r--r-- | editor/plugins/shader_editor_plugin.cpp | 1 | ||||
-rw-r--r-- | editor/plugins/tile_set_editor_plugin.cpp | 85 | ||||
-rw-r--r-- | editor/plugins/tile_set_editor_plugin.h | 6 | ||||
-rw-r--r-- | editor/plugins/visual_shader_editor_plugin.cpp | 79 | ||||
-rw-r--r-- | editor/plugins/visual_shader_editor_plugin.h | 5 | ||||
-rw-r--r-- | editor/project_manager.cpp | 37 | ||||
-rw-r--r-- | editor/project_manager.h | 2 |
19 files changed, 510 insertions, 169 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 3e97dbd96c..635f6d4fc7 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -135,6 +135,8 @@ void EditorNode::_update_scene_tabs() { bool show_rb = EditorSettings::get_singleton()->get("interface/scene_tabs/show_script_button"); + OS::get_singleton()->global_menu_clear("_dock"); + scene_tabs->clear_tabs(); Ref<Texture> script_icon = gui_base->get_icon("Script", "EditorIcons"); for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { @@ -149,11 +151,16 @@ void EditorNode::_update_scene_tabs() { bool unsaved = (i == current) ? saved_version != editor_data.get_undo_redo().get_version() : editor_data.get_scene_version(i) != 0; scene_tabs->add_tab(editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), icon); + OS::get_singleton()->global_menu_add_item("_dock", editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), GLOBAL_SCENE, i); + if (show_rb && editor_data.get_scene_root_script(i).is_valid()) { scene_tabs->set_tab_right_button(i, script_icon); } } + OS::get_singleton()->global_menu_add_separator("_dock"); + OS::get_singleton()->global_menu_add_item("_dock", TTR("New Window"), GLOBAL_NEW_WINDOW, Variant()); + scene_tabs->set_current_tab(editor_data.get_edited_scene()); if (scene_tabs->get_offset_buttons_visible()) { @@ -290,6 +297,7 @@ void EditorNode::_notification(int p_what) { get_tree()->get_root()->set_as_audio_listener_2d(false); get_tree()->set_auto_accept_quit(false); get_tree()->connect("files_dropped", this, "_dropped_files"); + get_tree()->connect("global_menu_action", this, "_global_menu_action"); /* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */ } break; @@ -4941,6 +4949,23 @@ void EditorNode::remove_tool_menu_item(const String &p_name) { } } +void EditorNode::_global_menu_action(const Variant &p_id, const Variant &p_meta) { + + int id = (int)p_id; + if (id == GLOBAL_NEW_WINDOW) { + if (OS::get_singleton()->get_main_loop()) { + List<String> args; + String exec = OS::get_singleton()->get_executable_path(); + + OS::ProcessID pid = 0; + OS::get_singleton()->execute(exec, args, false, &pid); + } + } else if (id == GLOBAL_SCENE) { + int idx = (int)p_meta; + scene_tabs->set_current_tab(idx); + } +} + void EditorNode::_dropped_files(const Vector<String> &p_files, int p_screen) { String to_path = ProjectSettings::get_singleton()->globalize_path(get_filesystem_dock()->get_selected_path()); @@ -5322,6 +5347,7 @@ void EditorNode::_bind_methods() { ClassDB::bind_method("_clear_undo_history", &EditorNode::_clear_undo_history); ClassDB::bind_method("_dropped_files", &EditorNode::_dropped_files); + ClassDB::bind_method(D_METHOD("_global_menu_action"), &EditorNode::_global_menu_action, DEFVAL(Variant())); ClassDB::bind_method("_toggle_distraction_free_mode", &EditorNode::_toggle_distraction_free_mode); ClassDB::bind_method("edit_item_resource", &EditorNode::edit_item_resource); diff --git a/editor/editor_node.h b/editor/editor_node.h index a8443549ed..61bbb7b86d 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -207,6 +207,9 @@ private: SET_VIDEO_DRIVER_SAVE_AND_RESTART, + GLOBAL_NEW_WINDOW, + GLOBAL_SCENE, + IMPORT_PLUGIN_BASE = 100, TOOL_MENU_BASE = 1000 @@ -504,6 +507,7 @@ private: void _add_to_recent_scenes(const String &p_scene); void _update_recent_scenes(); void _open_recent_scene(int p_idx); + void _global_menu_action(const Variant &p_id, const Variant &p_meta); void _dropped_files(const Vector<String> &p_files, int p_screen); void _add_dropped_files_recursive(const Vector<String> &p_files, String to_path); String _recent_scene; diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 84631f3e38..a729befe8e 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -63,7 +63,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory subdirectory_item->set_text(0, dname); subdirectory_item->set_icon(0, get_icon("Folder", "EditorIcons")); - subdirectory_item->set_icon_color(0, get_color("folder_icon_modulate", "FileDialog")); + subdirectory_item->set_icon_modulate(0, get_color("folder_icon_modulate", "FileDialog")); subdirectory_item->set_selectable(0, true); String lpath = p_dir->get_path(); subdirectory_item->set_metadata(0, lpath); @@ -214,7 +214,7 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo TreeItem *ti = tree->create_item(favorites); ti->set_text(0, text); ti->set_icon(0, icon); - ti->set_icon_color(0, color); + ti->set_icon_modulate(0, color); ti->set_tooltip(0, fave); ti->set_selectable(0, true); ti->set_metadata(0, fave); diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index cc2efb92ae..def22d07de 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -221,8 +221,8 @@ float FindInFiles::get_progress() const { void FindInFiles::_scan_dir(String path, PoolStringArray &out_folders) { - DirAccess *dir = DirAccess::open(path); - if (dir == NULL) { + DirAccessRef dir = DirAccess::open(path); + if (!dir) { print_verbose("Cannot open directory! " + path); return; } @@ -253,8 +253,8 @@ void FindInFiles::_scan_dir(String path, PoolStringArray &out_folders) { void FindInFiles::_scan_file(String fpath) { - FileAccess *f = FileAccess::open(fpath, FileAccess::READ); - if (f == NULL) { + FileAccessRef f = FileAccess::open(fpath, FileAccess::READ); + if (!f) { print_verbose(String("Cannot open file ") + fpath); return; } diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp index 5a8dc205c2..4cefb53617 100644 --- a/editor/groups_editor.cpp +++ b/editor/groups_editor.cpp @@ -35,12 +35,6 @@ #include "scene/gui/label.h" #include "scene/resources/packed_scene.h" -void GroupDialog::ok_pressed() { -} - -void GroupDialog::_cancel_pressed() { -} - void GroupDialog::_group_selected() { nodes_to_add->clear(); add_node_root = nodes_to_add->create_item(); @@ -49,11 +43,14 @@ void GroupDialog::_group_selected() { remove_node_root = nodes_to_remove->create_item(); if (!groups->is_anything_selected()) { + group_empty->hide(); return; } selected_group = groups->get_selected()->get_text(0); _load_nodes(scene_tree->get_edited_scene_root()); + + group_empty->set_visible(!remove_node_root->get_children()); } void GroupDialog::_load_nodes(Node *p_current) { @@ -129,15 +126,26 @@ void GroupDialog::_add_pressed() { return; } + undo_redo->create_action(TTR("Add to Group")); + while (selected) { Node *node = scene_tree->get_edited_scene_root()->get_node(selected->get_metadata(0)); - node->add_to_group(selected_group, true); + undo_redo->add_do_method(node, "add_to_group", selected_group, true); + undo_redo->add_undo_method(node, "remove_from_group", selected_group); selected = nodes_to_add->get_next_selected(selected); } - _group_selected(); - EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->update_tree(); + undo_redo->add_do_method(this, "_group_selected"); + undo_redo->add_undo_method(this, "_group_selected"); + undo_redo->add_do_method(this, "emit_signal", "group_edited"); + undo_redo->add_undo_method(this, "emit_signal", "group_edited"); + + // To force redraw of scene tree. + undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + + undo_redo->commit_action(); } void GroupDialog::_removed_pressed() { @@ -147,15 +155,26 @@ void GroupDialog::_removed_pressed() { return; } + undo_redo->create_action(TTR("Remove from Group")); + while (selected) { Node *node = scene_tree->get_edited_scene_root()->get_node(selected->get_metadata(0)); - node->remove_from_group(selected_group); + undo_redo->add_do_method(node, "remove_from_group", selected_group); + undo_redo->add_undo_method(node, "add_to_group", selected_group, true); selected = nodes_to_add->get_next_selected(selected); } - _group_selected(); - EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->update_tree(); + undo_redo->add_do_method(this, "_group_selected"); + undo_redo->add_undo_method(this, "_group_selected"); + undo_redo->add_do_method(this, "emit_signal", "group_edited"); + undo_redo->add_undo_method(this, "emit_signal", "group_edited"); + + // To force redraw of scene tree. + undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + + undo_redo->commit_action(); } void GroupDialog::_remove_filter_changed(const String &p_filter) { @@ -166,11 +185,29 @@ void GroupDialog::_add_filter_changed(const String &p_filter) { _group_selected(); } -void GroupDialog::_add_group_pressed() { +void GroupDialog::_add_group_pressed(const String &p_name) { _add_group(add_group_text->get_text()); add_group_text->clear(); } +void GroupDialog::_add_group(String p_name) { + if (!is_visible()) { + return; // No need to edit the dialog if it's not being used. + } + + String name = p_name.strip_edges(); + if (name == "" || groups->search_item_text(name)) { + return; + } + + TreeItem *new_group = groups->create_item(groups_root); + new_group->set_text(0, name); + new_group->add_button(0, get_icon("Remove", "EditorIcons"), 0); + new_group->set_editable(0, true); + new_group->select(0); + groups->ensure_cursor_is_visible(); +} + void GroupDialog::_group_renamed() { TreeItem *renamed_group = groups->get_edited(); if (!renamed_group) { @@ -194,38 +231,51 @@ void GroupDialog::_group_renamed() { return; } + undo_redo->create_action(TTR("Rename Group")); + List<Node *> nodes; scene_tree->get_nodes_in_group(selected_group, &nodes); bool removed_all = true; for (List<Node *>::Element *E = nodes.front(); E; E = E->next()) { Node *node = E->get(); if (_can_edit(node, selected_group)) { - node->remove_from_group(selected_group); - node->add_to_group(name, true); + undo_redo->add_do_method(node, "remove_from_group", selected_group); + undo_redo->add_undo_method(node, "remove_from_group", name); + undo_redo->add_do_method(node, "add_to_group", name, true); + undo_redo->add_undo_method(node, "add_to_group", selected_group, true); } else { removed_all = false; } } if (!removed_all) { - _add_group(selected_group); + undo_redo->add_do_method(this, "_add_group", selected_group); + undo_redo->add_undo_method(this, "_delete_group_item", selected_group); } - selected_group = renamed_group->get_text(0); - _group_selected(); -} + undo_redo->add_do_method(this, "_rename_group_item", selected_group, renamed_group->get_text(0)); + undo_redo->add_undo_method(this, "_rename_group_item", renamed_group->get_text(0), selected_group); + undo_redo->add_do_method(this, "_group_selected"); + undo_redo->add_undo_method(this, "_group_selected"); + undo_redo->add_do_method(this, "emit_signal", "group_edited"); + undo_redo->add_undo_method(this, "emit_signal", "group_edited"); -void GroupDialog::_add_group(String p_name) { + undo_redo->commit_action(); +} - String name = p_name.strip_edges(); - if (name == "" || groups->search_item_text(name)) { - return; +void GroupDialog::_rename_group_item(const String &p_old_name, const String &p_new_name) { + if (!is_visible()) { + return; // No need to edit the dialog if it's not being used. } - TreeItem *new_group = groups->create_item(groups_root); - new_group->set_text(0, name); - new_group->add_button(0, get_icon("Remove", "EditorIcons"), 0); - new_group->set_editable(0, true); + selected_group = p_new_name; + + for (TreeItem *E = groups_root->get_children(); E; E = E->get_next()) { + if (E->get_text(0) == p_old_name) { + E->set_text(0, p_new_name); + return; + } + } } void GroupDialog::_load_groups(Node *p_current) { @@ -251,29 +301,57 @@ void GroupDialog::_delete_group_pressed(Object *p_item, int p_column, int p_id) String name = ti->get_text(0); + undo_redo->create_action(TTR("Delete Group")); + List<Node *> nodes; scene_tree->get_nodes_in_group(name, &nodes); bool removed_all = true; for (List<Node *>::Element *E = nodes.front(); E; E = E->next()) { if (_can_edit(E->get(), name)) { - E->get()->remove_from_group(name); + undo_redo->add_do_method(E->get(), "remove_from_group", name); + undo_redo->add_undo_method(E->get(), "add_to_group", name, true); } else { removed_all = false; } } if (removed_all) { - if (selected_group == name) { - add_filter->clear(); - remove_filter->clear(); - nodes_to_remove->clear(); - nodes_to_add->clear(); - groups->deselect_all(); - selected_group = ""; + undo_redo->add_do_method(this, "_delete_group_item", name); + undo_redo->add_undo_method(this, "_add_group", name); + } + + undo_redo->add_do_method(this, "_group_selected"); + undo_redo->add_undo_method(this, "_group_selected"); + undo_redo->add_do_method(this, "emit_signal", "group_edited"); + undo_redo->add_undo_method(this, "emit_signal", "group_edited"); + + // To force redraw of scene tree. + undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + + undo_redo->commit_action(); +} + +void GroupDialog::_delete_group_item(const String &p_name) { + if (!is_visible()) { + return; // No need to edit the dialog if it's not being used. + } + + if (selected_group == p_name) { + add_filter->clear(); + remove_filter->clear(); + nodes_to_remove->clear(); + nodes_to_add->clear(); + groups->deselect_all(); + selected_group = ""; + } + + for (TreeItem *E = groups_root->get_children(); E; E = E->get_next()) { + if (E->get_text(0) == p_name) { + groups_root->remove_child(E); + return; } - groups_root->remove_child(ti); } - EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->update_tree(); } void GroupDialog::_notification(int p_what) { @@ -291,8 +369,7 @@ void GroupDialog::_notification(int p_what) { } void GroupDialog::edit() { - - popup_centered(Size2(600, 400)); + popup_centered(); groups->clear(); groups_root = groups->create_item(); @@ -308,27 +385,32 @@ void GroupDialog::edit() { } void GroupDialog::_bind_methods() { - ClassDB::bind_method("_cancel", &GroupDialog::_cancel_pressed); - ClassDB::bind_method("_add_pressed", &GroupDialog::_add_pressed); ClassDB::bind_method("_removed_pressed", &GroupDialog::_removed_pressed); ClassDB::bind_method("_delete_group_pressed", &GroupDialog::_delete_group_pressed); + ClassDB::bind_method("_delete_group_item", &GroupDialog::_delete_group_item); ClassDB::bind_method("_group_selected", &GroupDialog::_group_selected); ClassDB::bind_method("_add_group_pressed", &GroupDialog::_add_group_pressed); + ClassDB::bind_method("_add_group", &GroupDialog::_add_group); ClassDB::bind_method("_add_filter_changed", &GroupDialog::_add_filter_changed); ClassDB::bind_method("_remove_filter_changed", &GroupDialog::_remove_filter_changed); ClassDB::bind_method("_group_renamed", &GroupDialog::_group_renamed); + ClassDB::bind_method("_rename_group_item", &GroupDialog::_rename_group_item); + + ADD_SIGNAL(MethodInfo("group_edited")); } GroupDialog::GroupDialog() { + set_custom_minimum_size(Size2(600, 400)); scene_tree = SceneTree::get_singleton(); VBoxContainer *vbc = memnew(VBoxContainer); add_child(vbc); + vbc->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); HBoxContainer *hbc = memnew(HBoxContainer); vbc->add_child(hbc); @@ -345,10 +427,11 @@ GroupDialog::GroupDialog() { groups = memnew(Tree); vbc_left->add_child(groups); groups->set_hide_root(true); - groups->set_v_size_flags(SIZE_EXPAND_FILL); groups->set_select_mode(Tree::SELECT_SINGLE); groups->set_allow_reselect(true); groups->set_allow_rmb_select(true); + groups->set_v_size_flags(SIZE_EXPAND_FILL); + groups->add_constant_override("draw_guides", 1); groups->connect("item_selected", this, "_group_selected"); groups->connect("button_pressed", this, "_delete_group_pressed"); groups->connect("item_edited", this, "_group_renamed"); @@ -360,26 +443,28 @@ GroupDialog::GroupDialog() { add_group_text = memnew(LineEdit); chbc->add_child(add_group_text); add_group_text->set_h_size_flags(SIZE_EXPAND_FILL); + add_group_text->connect("text_entered", this, "_add_group_pressed"); Button *add_group_button = memnew(Button); add_group_button->set_text("Add"); chbc->add_child(add_group_button); - add_group_button->connect("pressed", this, "_add_group_pressed"); + add_group_button->connect("pressed", this, "_add_group_pressed", varray(String())); VBoxContainer *vbc_add = memnew(VBoxContainer); hbc->add_child(vbc_add); vbc_add->set_h_size_flags(SIZE_EXPAND_FILL); Label *out_of_group_title = memnew(Label); - out_of_group_title->set_text(TTR("Nodes not in Group")); + out_of_group_title->set_text(TTR("Nodes Not in Group")); vbc_add->add_child(out_of_group_title); nodes_to_add = memnew(Tree); vbc_add->add_child(nodes_to_add); nodes_to_add->set_hide_root(true); nodes_to_add->set_hide_folding(true); - nodes_to_add->set_v_size_flags(SIZE_EXPAND_FILL); nodes_to_add->set_select_mode(Tree::SELECT_MULTI); + nodes_to_add->set_v_size_flags(SIZE_EXPAND_FILL); + nodes_to_add->add_constant_override("draw_guides", 1); nodes_to_add->connect("item_selected", this, "_nodes_to_add_selected"); HBoxContainer *add_filter_hbc = memnew(HBoxContainer); @@ -426,6 +511,7 @@ GroupDialog::GroupDialog() { nodes_to_remove->set_hide_root(true); nodes_to_remove->set_hide_folding(true); nodes_to_remove->set_select_mode(Tree::SELECT_MULTI); + nodes_to_remove->add_constant_override("draw_guides", 1); nodes_to_remove->connect("item_selected", this, "_node_to_remove_selected"); HBoxContainer *remove_filter_hbc = memnew(HBoxContainer); @@ -438,8 +524,15 @@ GroupDialog::GroupDialog() { remove_filter_hbc->add_child(remove_filter); remove_filter->connect("text_changed", this, "_remove_filter_changed"); - set_title("Group Editor"); - get_cancel()->hide(); + group_empty = memnew(Label()); + group_empty->set_text(TTR("Empty groups will be automatically removed.")); + group_empty->set_valign(Label::VALIGN_CENTER); + group_empty->set_align(Label::ALIGN_CENTER); + group_empty->set_autowrap(true); + nodes_to_remove->add_child(group_empty); + group_empty->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); + + set_title(TTR("Group Editor")); set_as_toplevel(true); set_resizable(true); @@ -465,11 +558,13 @@ void GroupsEditor::_add_group(const String &p_group) { undo_redo->create_action(TTR("Add to Group")); undo_redo->add_do_method(node, "add_to_group", name, true); - undo_redo->add_do_method(this, "update_tree"); undo_redo->add_undo_method(node, "remove_from_group", name); + undo_redo->add_do_method(this, "update_tree"); undo_redo->add_undo_method(this, "update_tree"); - undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); //to force redraw of scene tree - undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); //to force redraw of scene tree + + // To force redraw of scene tree. + undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); undo_redo->commit_action(); @@ -490,11 +585,13 @@ void GroupsEditor::_remove_group(Object *p_item, int p_column, int p_id) { undo_redo->create_action(TTR("Remove from Group")); undo_redo->add_do_method(node, "remove_from_group", name); - undo_redo->add_do_method(this, "update_tree"); undo_redo->add_undo_method(node, "add_to_group", name, true); + undo_redo->add_do_method(this, "update_tree"); undo_redo->add_undo_method(this, "update_tree"); - undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); //to force redraw of scene tree - undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); //to force redraw of scene tree + + // To force redraw of scene tree. + undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); undo_redo->commit_action(); } @@ -562,11 +659,9 @@ void GroupsEditor::set_current(Node *p_node) { } void GroupsEditor::_show_group_dialog() { - group_dialog->edit(); -} -void GroupsEditor::_group_dialog_closed() { - update_tree(); + group_dialog->edit(); + group_dialog->set_undo_redo(undo_redo); } void GroupsEditor::_bind_methods() { @@ -576,7 +671,6 @@ void GroupsEditor::_bind_methods() { ClassDB::bind_method("update_tree", &GroupsEditor::update_tree); ClassDB::bind_method("_show_group_dialog", &GroupsEditor::_show_group_dialog); - ClassDB::bind_method("_group_dialog_closed", &GroupsEditor::_group_dialog_closed); } GroupsEditor::GroupsEditor() { @@ -588,7 +682,7 @@ GroupsEditor::GroupsEditor() { group_dialog = memnew(GroupDialog); group_dialog->set_as_toplevel(true); add_child(group_dialog); - group_dialog->connect("popup_hide", this, "_group_dialog_closed"); + group_dialog->connect("group_edited", this, "update_tree"); Button *group_dialog_button = memnew(Button); group_dialog_button->set_text(TTR("Manage Groups")); @@ -613,6 +707,7 @@ GroupsEditor::GroupsEditor() { tree->set_v_size_flags(SIZE_EXPAND_FILL); vbc->add_child(tree); tree->connect("button_pressed", this, "_remove_group"); + tree->add_constant_override("draw_guides", 1); add_constant_override("separation", 3 * EDSCALE); } diff --git a/editor/groups_editor.h b/editor/groups_editor.h index 4ffeea84e7..78ef99d5c8 100644 --- a/editor/groups_editor.h +++ b/editor/groups_editor.h @@ -41,13 +41,9 @@ #include "scene/gui/tool_button.h" #include "scene/gui/tree.h" -/** -@author Juan Linietsky <reduzio@gmail.com> -*/ +class GroupDialog : public WindowDialog { -class GroupDialog : public ConfirmationDialog { - - GDCLASS(GroupDialog, ConfirmationDialog); + GDCLASS(GroupDialog, WindowDialog); ConfirmationDialog *error; @@ -66,13 +62,15 @@ class GroupDialog : public ConfirmationDialog { TreeItem *remove_node_root; LineEdit *remove_filter; + Label *group_empty; + ToolButton *add_button; ToolButton *remove_button; String selected_group; - void ok_pressed(); - void _cancel_pressed(); + UndoRedo *undo_redo; + void _group_selected(); void _remove_filter_changed(const String &p_filter); @@ -80,12 +78,14 @@ class GroupDialog : public ConfirmationDialog { void _add_pressed(); void _removed_pressed(); - void _add_group_pressed(); + void _add_group_pressed(const String &p_name); void _group_renamed(); + void _rename_group_item(const String &p_old_name, const String &p_new_name); void _add_group(String p_name); void _delete_group_pressed(Object *p_item, int p_column, int p_id); + void _delete_group_item(const String &p_name); bool _can_edit(Node *p_node, String p_group); @@ -98,6 +98,7 @@ protected: public: void edit(); + void set_undo_redo(UndoRedo *p_undoredo) { undo_redo = p_undoredo; } GroupDialog(); }; @@ -122,7 +123,6 @@ class GroupsEditor : public VBoxContainer { void _close(); void _show_group_dialog(); - void _group_dialog_closed(); protected: static void _bind_methods(); diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 8e6a56a929..64994e21b0 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -960,7 +960,7 @@ void ResourceImporterScene::_find_meshes(Node *p_node, Map<Ref<ArrayMesh>, Trans } } -void ResourceImporterScene::_make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_keep_animations, bool p_make_materials, bool p_keep_materials, bool p_make_meshes, Map<Ref<Animation>, Ref<Animation> > &p_animations, Map<Ref<Material>, Ref<Material> > &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh> > &p_meshes) { +void ResourceImporterScene::_make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_animations_as_text, bool p_keep_animations, bool p_make_materials, bool p_materials_as_text, bool p_keep_materials, bool p_make_meshes, bool p_meshes_as_text, Map<Ref<Animation>, Ref<Animation> > &p_animations, Map<Ref<Material>, Ref<Material> > &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh> > &p_meshes) { List<PropertyInfo> pi; @@ -982,7 +982,14 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String anim->track_set_imported(i, true); } - String ext_name = p_base_path.plus_file(_make_extname(E->get()) + ".anim"); + String ext_name; + + if (p_animations_as_text) { + ext_name = p_base_path.plus_file(_make_extname(E->get()) + ".tres"); + } else { + ext_name = p_base_path.plus_file(_make_extname(E->get()) + ".anim"); + } + if (FileAccess::exists(ext_name) && p_keep_animations) { //try to keep custom animation tracks Ref<Animation> old_anim = ResourceLoader::load(ext_name, "Animation", true); @@ -1017,7 +1024,14 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String if (!p_materials.has(mat)) { - String ext_name = p_base_path.plus_file(_make_extname(mat->get_name()) + ".material"); + String ext_name; + + if (p_materials_as_text) { + ext_name = p_base_path.plus_file(_make_extname(mat->get_name()) + ".tres"); + } else { + ext_name = p_base_path.plus_file(_make_extname(mat->get_name()) + ".material"); + } + if (p_keep_materials && FileAccess::exists(ext_name)) { //if exists, use it p_materials[mat] = ResourceLoader::load(ext_name); @@ -1045,7 +1059,13 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String if (!p_meshes.has(mesh)) { //meshes are always overwritten, keeping them is not practical - String ext_name = p_base_path.plus_file(_make_extname(mesh->get_name()) + ".mesh"); + String ext_name; + + if (p_meshes_as_text) { + ext_name = p_base_path.plus_file(_make_extname(mesh->get_name()) + ".tres"); + } else { + ext_name = p_base_path.plus_file(_make_extname(mesh->get_name()) + ".mesh"); + } ResourceSaver::save(ext_name, mesh, ResourceSaver::FLAG_CHANGE_PATH); p_meshes[mesh] = ResourceLoader::load(ext_name); @@ -1067,9 +1087,14 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String continue; if (!p_materials.has(mat)) { + String ext_name; + + if (p_materials_as_text) { + ext_name = p_base_path.plus_file(_make_extname(mat->get_name()) + ".tres"); + } else { + ext_name = p_base_path.plus_file(_make_extname(mat->get_name()) + ".material"); + } - String ext_name = p_base_path.plus_file(_make_extname(mat->get_name()) + ".material"); - ; if (p_keep_materials && FileAccess::exists(ext_name)) { //if exists, use it p_materials[mat] = ResourceLoader::load(ext_name); @@ -1086,7 +1111,15 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String //re-save the mesh since a material is now assigned if (p_make_meshes) { - String ext_name = p_base_path.plus_file(_make_extname(mesh->get_name()) + ".mesh"); + + String ext_name; + + if (p_meshes_as_text) { + ext_name = p_base_path.plus_file(_make_extname(mesh->get_name()) + ".tres"); + } else { + ext_name = p_base_path.plus_file(_make_extname(mesh->get_name()) + ".mesh"); + } + ResourceSaver::save(ext_name, mesh, ResourceSaver::FLAG_CHANGE_PATH); p_meshes[mesh] = ResourceLoader::load(ext_name); } @@ -1105,7 +1138,7 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String for (int i = 0; i < p_node->get_child_count(); i++) { - _make_external_resources(p_node->get_child(i), p_base_path, p_make_animations, p_keep_animations, p_make_materials, p_keep_materials, p_make_meshes, p_animations, p_materials, p_meshes); + _make_external_resources(p_node->get_child(i), p_base_path, p_make_animations, p_animations_as_text, p_keep_animations, p_make_materials, p_materials_as_text, p_keep_materials, p_make_meshes, p_meshes_as_text, p_animations, p_materials, p_meshes); } } @@ -1134,18 +1167,18 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/custom_script", PROPERTY_HINT_FILE, script_ext_hint), "")); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "nodes/storage", PROPERTY_HINT_ENUM, "Single Scene,Instanced Sub-Scenes"), scenes_out ? 1 : 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "materials/location", PROPERTY_HINT_ENUM, "Node,Mesh"), (meshes_out || materials_out) ? 1 : 0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "materials/storage", PROPERTY_HINT_ENUM, "Built-In,Files", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), materials_out ? 1 : 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "materials/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.material),Files (.tres)", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), materials_out ? 1 : 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "materials/keep_on_reimport"), materials_out)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/compress"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/ensure_tangents"), true)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/storage", PROPERTY_HINT_ENUM, "Built-In,Files"), meshes_out ? 1 : 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.mesh),Files (.tres)"), meshes_out ? 1 : 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Enable,Gen Lightmaps", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.1)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "external_files/store_in_subdir"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 15)); r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "animation/filter_script", PROPERTY_HINT_MULTILINE_TEXT), "")); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "animation/storage", PROPERTY_HINT_ENUM, "Built-In,Files", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), animations_out)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "animation/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.anim),Files (.tres)"), animations_out ? true : false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/keep_custom_tracks"), animations_out)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/optimizer/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "animation/optimizer/max_linear_error"), 0.05)); @@ -1367,10 +1400,13 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p _filter_tracks(scene, animation_filter); } - bool external_animations = int(p_options["animation/storage"]) == 1; + bool external_animations = int(p_options["animation/storage"]) == 1 || int(p_options["animation/storage"]) == 2; + bool external_animations_as_text = int(p_options["animation/storage"]) == 2; bool keep_custom_tracks = p_options["animation/keep_custom_tracks"]; - bool external_materials = p_options["materials/storage"]; - bool external_meshes = p_options["meshes/storage"]; + bool external_materials = int(p_options["materials/storage"]) == 1 || int(p_options["materials/storage"]) == 2; + bool external_materials_as_text = int(p_options["materials/storage"]) == 2; + bool external_meshes = int(p_options["meshes/storage"]) == 1 || int(p_options["meshes/storage"]) == 2; + bool external_meshes_as_text = int(p_options["meshes/storage"]) == 2; bool external_scenes = int(p_options["nodes/storage"]) == 1; String base_path = p_source_file.get_base_dir(); @@ -1425,7 +1461,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p bool keep_materials = bool(p_options["materials/keep_on_reimport"]); - _make_external_resources(scene, base_path, external_animations, keep_custom_tracks, external_materials, keep_materials, external_meshes, anim_map, mat_map, mesh_map); + _make_external_resources(scene, base_path, external_animations, external_animations_as_text, keep_custom_tracks, external_materials, external_materials_as_text, keep_materials, external_meshes, external_meshes_as_text, anim_map, mat_map, mesh_map); } progress.step(TTR("Running Custom Script..."), 2); diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index 498e0f6fb8..ef9a77917f 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -144,7 +144,7 @@ public: void _find_meshes(Node *p_node, Map<Ref<ArrayMesh>, Transform> &meshes); - void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_keep_animations, bool p_make_materials, bool p_keep_materials, bool p_make_meshes, Map<Ref<Animation>, Ref<Animation> > &p_animations, Map<Ref<Material>, Ref<Material> > &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh> > &p_meshes); + void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_animations_as_text, bool p_keep_animations, bool p_make_materials, bool p_materials_as_text, bool p_keep_materials, bool p_make_meshes, bool p_meshes_as_text, Map<Ref<Animation>, Ref<Animation> > &p_animations, Map<Ref<Material>, Ref<Material> > &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh> > &p_meshes); Node *_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape> > > &collision_map, LightBakeMode p_light_bake_mode); diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 132bf3973e..cb68f5eaaf 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -101,7 +101,7 @@ EditorAssetLibraryItem::EditorAssetLibraryItem() { add_style_override("panel", border); HBoxContainer *hb = memnew(HBoxContainer); - // Add some spacing to visually separate the icon from the asset details + // Add some spacing to visually separate the icon from the asset details. hb->add_constant_override("separation", 15 * EDSCALE); add_child(hb); @@ -118,25 +118,21 @@ EditorAssetLibraryItem::EditorAssetLibraryItem() { vb->set_h_size_flags(SIZE_EXPAND_FILL); title = memnew(LinkButton); - title->set_text("My Awesome Addon"); title->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER); title->connect("pressed", this, "_asset_clicked"); vb->add_child(title); category = memnew(LinkButton); - category->set_text("Editor Tools"); category->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER); category->connect("pressed", this, "_category_clicked"); vb->add_child(category); author = memnew(LinkButton); - author->set_text("Johny Tolengo"); author->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER); author->connect("pressed", this, "_author_clicked"); vb->add_child(author); price = memnew(Label); - price->set_text(TTR("Free")); vb->add_child(price); set_custom_minimum_size(Size2(250, 100) * EDSCALE); @@ -200,14 +196,15 @@ void EditorAssetLibraryItemDescription::set_image(int p_type, int p_index, const } break; } } + void EditorAssetLibraryItemDescription::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { previews_bg->add_style_override("panel", get_stylebox("normal", "TextEdit")); - desc_bg->add_style_override("panel", get_stylebox("normal", "TextEdit")); } break; } } + void EditorAssetLibraryItemDescription::_bind_methods() { ClassDB::bind_method(D_METHOD("set_image"), &EditorAssetLibraryItemDescription::set_image); ClassDB::bind_method(D_METHOD("_link_click"), &EditorAssetLibraryItemDescription::_link_click); @@ -278,12 +275,8 @@ void EditorAssetLibraryItemDescription::add_preview(int p_id, bool p_video, cons EditorAssetLibraryItemDescription::EditorAssetLibraryItemDescription() { - VBoxContainer *vbox = memnew(VBoxContainer); - add_child(vbox); - HBoxContainer *hbox = memnew(HBoxContainer); - vbox->add_child(hbox); - vbox->add_constant_override("separation", 15 * EDSCALE); + add_child(hbox); VBoxContainer *desc_vbox = memnew(VBoxContainer); hbox->add_child(desc_vbox); hbox->add_constant_override("separation", 15 * EDSCALE); @@ -291,24 +284,23 @@ EditorAssetLibraryItemDescription::EditorAssetLibraryItemDescription() { item = memnew(EditorAssetLibraryItem); desc_vbox->add_child(item); - desc_vbox->set_custom_minimum_size(Size2(300 * EDSCALE, 0)); - - desc_bg = memnew(PanelContainer); - desc_vbox->add_child(desc_bg); - desc_bg->set_v_size_flags(SIZE_EXPAND_FILL); + desc_vbox->set_custom_minimum_size(Size2(440 * EDSCALE, 0)); description = memnew(RichTextLabel); + desc_vbox->add_child(description); + description->set_v_size_flags(SIZE_EXPAND_FILL); description->connect("meta_clicked", this, "_link_click"); - description->set_custom_minimum_size(Size2(440 * EDSCALE, 300 * EDSCALE)); - desc_bg->add_child(description); VBoxContainer *previews_vbox = memnew(VBoxContainer); hbox->add_child(previews_vbox); previews_vbox->add_constant_override("separation", 15 * EDSCALE); + previews_vbox->set_v_size_flags(SIZE_EXPAND_FILL); preview = memnew(TextureRect); - preview->set_custom_minimum_size(Size2(640 * EDSCALE, 345 * EDSCALE)); previews_vbox->add_child(preview); + preview->set_expand(true); + preview->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED); + preview->set_custom_minimum_size(Size2(640 * EDSCALE, 345 * EDSCALE)); previews_bg = memnew(PanelContainer); previews_vbox->add_child(previews_bg); @@ -392,7 +384,7 @@ void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int install->set_disabled(false); status->set_text(TTR("Success!")); - // Make the progress bar invisible but don't reflow other Controls around it + // Make the progress bar invisible but don't reflow other Controls around it. progress->set_modulate(Color(0, 0, 0, 0)); set_process(false); @@ -404,7 +396,7 @@ void EditorAssetLibraryItemDownload::configure(const String &p_title, int p_asse icon->set_texture(p_preview); asset_id = p_asset_id; if (!p_preview.is_valid()) - icon->set_texture(get_icon("DefaultProjectIcon", "EditorIcons")); + icon->set_texture(get_icon("FileBrokenBigThumb", "EditorIcons")); host = p_download_url; sha256 = p_sha256_hash; _make_request(); @@ -600,33 +592,15 @@ void EditorAssetLibrary::_notification(int p_what) { case NOTIFICATION_PROCESS: { HTTPClient::Status s = request->get_http_client_status(); - bool visible = s != HTTPClient::STATUS_DISCONNECTED; + const bool loading = s != HTTPClient::STATUS_DISCONNECTED; - if (visible != load_status->is_visible()) { - load_status->set_visible(visible); - } - - if (visible) { - switch (s) { - - case HTTPClient::STATUS_RESOLVING: { - load_status->set_value(0.1); - } break; - case HTTPClient::STATUS_CONNECTING: { - load_status->set_value(0.2); - } break; - case HTTPClient::STATUS_REQUESTING: { - load_status->set_value(0.3); - } break; - case HTTPClient::STATUS_BODY: { - load_status->set_value(0.4); - } break; - default: { - } - } + if (loading) { + library_scroll->set_modulate(Color(1, 1, 1, 0.5)); + } else { + library_scroll->set_modulate(Color(1, 1, 1, 1)); } - bool no_downloads = downloads_hb->get_child_count() == 0; + const bool no_downloads = downloads_hb->get_child_count() == 0; if (no_downloads == downloads_scroll->is_visible()) { downloads_scroll->set_visible(!no_downloads); } @@ -679,7 +653,7 @@ const char *EditorAssetLibrary::sort_key[SORT_MAX] = { const char *EditorAssetLibrary::sort_text[SORT_MAX] = { "Downloads", "Name", - "License", // "cost" stores the SPDX license name in the Godot Asset Library + "License", // "cost" stores the SPDX license name in the Godot Asset Library. "Updated" }; @@ -691,7 +665,7 @@ const char *EditorAssetLibrary::support_key[SUPPORT_MAX] = { void EditorAssetLibrary::_select_author(int p_id) { - // Open author window + // Open author window. } void EditorAssetLibrary::_select_category(int p_id) { @@ -788,7 +762,7 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PoolByt } if (!image_set && final) { - obj->call("set_image", image_queue[p_queue_id].image_type, image_queue[p_queue_id].image_index, get_icon("DefaultProjectIcon", "EditorIcons")); + obj->call("set_image", image_queue[p_queue_id].image_type, image_queue[p_queue_id].image_index, get_icon("FileBrokenBigThumb", "EditorIcons")); } } } @@ -833,7 +807,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons WARN_PRINTS("Error getting image file from URL: " + image_queue[p_queue_id].image_url); Object *obj = ObjectDB::get_instance(image_queue[p_queue_id].target); if (obj) { - obj->call("set_image", image_queue[p_queue_id].image_type, image_queue[p_queue_id].image_index, get_icon("DefaultProjectIcon", "EditorIcons")); + obj->call("set_image", image_queue[p_queue_id].image_type, image_queue[p_queue_id].image_index, get_icon("FileBrokenBigThumb", "EditorIcons")); } } @@ -845,7 +819,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons void EditorAssetLibrary::_update_image_queue() { - int max_images = 2; + const int max_images = 6; int current_images = 0; List<int> to_delete; @@ -1157,6 +1131,10 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const _search(); } break; case REQUESTING_SEARCH: { + + // The loading text only needs to be displayed before the first page is loaded + library_loading->hide(); + if (asset_items) { memdelete(asset_items); } @@ -1359,7 +1337,6 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { library_main->add_child(search_hb); library_main->add_constant_override("separation", 10 * EDSCALE); - search_hb->add_child(memnew(Label(TTR("Search:") + " "))); filter = memnew(LineEdit); search_hb->add_child(filter); filter->set_h_size_flags(SIZE_EXPAND_FILL); @@ -1372,12 +1349,12 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { search_hb->add_child(memnew(VSeparator)); Button *open_asset = memnew(Button); - open_asset->set_text(TTR("Import")); + open_asset->set_text(TTR("Import...")); search_hb->add_child(open_asset); open_asset->connect("pressed", this, "_asset_open"); Button *plugins = memnew(Button); - plugins->set_text(TTR("Plugins")); + plugins->set_text(TTR("Plugins...")); search_hb->add_child(plugins); plugins->connect("pressed", this, "_manage_plugins"); @@ -1434,7 +1411,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { support = memnew(MenuButton); search_hb2->add_child(support); - support->set_text(TTR("Support...")); + support->set_text(TTR("Support")); support->get_popup()->add_check_item(TTR("Official"), SUPPORT_OFFICIAL); support->get_popup()->add_check_item(TTR("Community"), SUPPORT_COMMUNITY); support->get_popup()->add_check_item(TTR("Testing"), SUPPORT_TESTING); @@ -1472,6 +1449,10 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { library_vb_border->add_child(library_vb); + library_loading = memnew(Label(TTR("Loading..."))); + library_loading->set_align(Label::ALIGN_CENTER); + library_vb->add_child(library_loading); + asset_top_page = memnew(HBoxContainer); library_vb->add_child(asset_top_page); @@ -1494,12 +1475,6 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { library_vb->add_constant_override("separation", 20 * EDSCALE); - load_status = memnew(ProgressBar); - load_status->set_min(0); - load_status->set_max(1); - load_status->set_step(0.001); - library_main->add_child(load_status); - error_hb = memnew(HBoxContainer); library_main->add_child(error_hb); error_label = memnew(Label); diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h index 81288ae831..b17a6dfe54 100644 --- a/editor/plugins/asset_library_editor_plugin.h +++ b/editor/plugins/asset_library_editor_plugin.h @@ -91,7 +91,6 @@ class EditorAssetLibraryItemDescription : public ConfirmationDialog { ScrollContainer *previews; HBoxContainer *preview_hb; PanelContainer *previews_bg; - PanelContainer *desc_bg; struct Preview { int id; @@ -186,13 +185,13 @@ class EditorAssetLibrary : public PanelContainer { PanelContainer *library_scroll_bg; ScrollContainer *library_scroll; VBoxContainer *library_vb; + Label *library_loading; LineEdit *filter; OptionButton *categories; OptionButton *repository; OptionButton *sort; ToolButton *reverse; Button *search; - ProgressBar *load_status; HBoxContainer *error_hb; TextureRect *error_tr; Label *error_label; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 785a1c107a..2daee70474 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -4429,6 +4429,27 @@ void CanvasItemEditor::_popup_callback(int p_op) { } } break; + case CLEAR_GUIDES: { + + if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_") || EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) { + undo_redo->create_action(TTR("Clear Guides")); + if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) { + Array hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_"); + + undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", Array()); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides); + } + if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) { + Array vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_"); + + undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", Array()); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides); + } + undo_redo->add_undo_method(viewport, "update"); + undo_redo->commit_action(); + } + + } break; case VIEW_CENTER_TO_SELECTION: case VIEW_FRAME_TO_SELECTION: { @@ -5159,6 +5180,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p->add_separator(); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), KEY_F), VIEW_CENTER_TO_SELECTION); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KEY_MASK_SHIFT | KEY_F), VIEW_FRAME_TO_SELECTION); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/clear_guides", TTR("Clear Guides")), CLEAR_GUIDES); p->add_separator(); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/preview_canvas_scale", TTR("Preview Canvas Scale"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_P), PREVIEW_CANVAS_SCALE); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index a16d07599a..ac7d612292 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -178,6 +178,7 @@ private: ANIM_COPY_POSE, ANIM_PASTE_POSE, ANIM_CLEAR_POSE, + CLEAR_GUIDES, VIEW_CENTER_TO_SELECTION, VIEW_FRAME_TO_SELECTION, PREVIEW_CANVAS_SCALE, diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 04820b8a8f..938dc8a1e7 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -55,6 +55,7 @@ void ShaderTextEditor::set_edited_shader(const Ref<Shader> &p_shader) { _load_theme_settings(); get_text_edit()->set_text(p_shader->get_code()); + get_text_edit()->clear_undo_history(); _validate_script(); _line_col_changed(); diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index c1e85788f8..9096a0e0be 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -176,6 +176,86 @@ Error TileSetEditor::update_library_file(Node *p_base_scene, Ref<TileSet> ml, bo return OK; } +Variant TileSetEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) { + + return false; +} + +bool TileSetEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { + + Dictionary d = p_data; + + if (!d.has("type")) + return false; + + if (d.has("from") && (Object *)(d["from"]) == texture_list) + return false; + + if (String(d["type"]) == "resource" && d.has("resource")) { + RES r = d["resource"]; + + Ref<Texture> texture = r; + + if (texture.is_valid()) { + + return true; + } + } + + if (String(d["type"]) == "files") { + + Vector<String> files = d["files"]; + + if (files.size() == 0) + return false; + + for (int i = 0; i < files.size(); i++) { + String file = files[i]; + String ftype = EditorFileSystem::get_singleton()->get_file_type(file); + + if (!ClassDB::is_parent_class(ftype, "Texture")) { + return false; + } + } + + return true; + } + return false; +} + +void TileSetEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { + + if (!can_drop_data_fw(p_point, p_data, p_from)) + return; + + Dictionary d = p_data; + + if (!d.has("type")) + return; + + if (String(d["type"]) == "resource" && d.has("resource")) { + RES r = d["resource"]; + + Ref<Texture> texture = r; + + if (texture.is_valid()) + add_texture(texture); + + if (texture_list->get_item_count() > 0) { + update_texture_list_icon(); + texture_list->select(texture_list->get_item_count() - 1); + _on_texture_list_selected(texture_list->get_item_count() - 1); + } + } + + if (String(d["type"]) == "files") { + + PoolVector<String> files = d["files"]; + + _on_textures_added(files); + } +} + void TileSetEditor::_bind_methods() { ClassDB::bind_method("_undo_redo_import_scene", &TileSetEditor::_undo_redo_import_scene); @@ -203,6 +283,10 @@ void TileSetEditor::_bind_methods() { ClassDB::bind_method("_select_edited_shape_coord", &TileSetEditor::_select_edited_shape_coord); ClassDB::bind_method("_sort_tiles", &TileSetEditor::_sort_tiles); + ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &TileSetEditor::get_drag_data_fw); + ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &TileSetEditor::can_drop_data_fw); + ClassDB::bind_method(D_METHOD("drop_data_fw"), &TileSetEditor::drop_data_fw); + ClassDB::bind_method("edit", &TileSetEditor::edit); ClassDB::bind_method("add_texture", &TileSetEditor::add_texture); ClassDB::bind_method("remove_texture", &TileSetEditor::remove_texture); @@ -274,6 +358,7 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { texture_list->set_v_size_flags(SIZE_EXPAND_FILL); texture_list->set_custom_minimum_size(Size2(200, 0)); texture_list->connect("item_selected", this, "_on_texture_list_selected"); + texture_list->set_drag_forwarding(this); HBoxContainer *tileset_toolbar_container = memnew(HBoxContainer); left_container->add_child(tileset_toolbar_container); diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h index 69ad8205a4..fff9ef7731 100644 --- a/editor/plugins/tile_set_editor_plugin.h +++ b/editor/plugins/tile_set_editor_plugin.h @@ -173,6 +173,12 @@ class TileSetEditor : public HSplitContainer { static void _import_scene(Node *p_scene, Ref<TileSet> p_library, bool p_merge); void _undo_redo_import_scene(Node *p_scene, bool p_merge); + bool _is_drop_valid(const Dictionary &p_drag_data, const Dictionary &p_item_data) const; + Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); + bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; + void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); + void _file_load_request(const PoolVector<String> &p_path, int p_at_pos = -1); + protected: static void _bind_methods(); void _notification(int p_what); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 589964f620..66fbc32b1c 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -41,6 +41,7 @@ #include "scene/gui/panel.h" #include "scene/main/viewport.h" #include "scene/resources/visual_shader_nodes.h" +#include "servers/visual/shader_types.h" Control *VisualShaderNodePlugin::create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node) { @@ -229,6 +230,14 @@ void VisualShaderEditor::_update_custom_nodes() { } } +String VisualShaderEditor::_get_description(int p_idx) { + if (add_options[p_idx].highend) { + return TTR("(GLES3 only)") + " " + add_options[p_idx].description; // TODO: change it to (Vulkan Only) when its ready + } else { + return add_options[p_idx].description; + } +} + void VisualShaderEditor::_update_options_menu() { node_desc->set_text(""); @@ -332,11 +341,10 @@ void VisualShaderEditor::_update_options_menu() { else if (add_options[i].highend) item->set_custom_color(0, supported_color); item->set_text(0, add_options[i].name); - if (p_category == sub_category) { - if (is_first_item) { - item->select(0); - is_first_item = false; - } + if (is_first_item && use_filter) { + item->select(0); + node_desc->set_text(_get_description(i)); + is_first_item = false; } switch (add_options[i].return_type) { case VisualShaderNode::PORT_TYPE_SCALAR: @@ -1598,6 +1606,9 @@ void VisualShaderEditor::_notification(int p_what) { preview_text->add_color_override("symbol_color", symbol_color); preview_text->add_color_region("/*", "*/", comment_color, false); preview_text->add_color_region("//", "", comment_color, false); + + error_text->add_font_override("font", get_font("status_source", "EditorFonts")); + error_text->add_color_override("font_color", get_color("error_color", "Editor")); } tools->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Tools", "EditorIcons")); @@ -1926,11 +1937,7 @@ void VisualShaderEditor::_member_selected() { if (item != NULL && item->has_meta("id")) { members_dialog->get_ok()->set_disabled(false); - if (add_options[item->get_meta("id")].highend) { - node_desc->set_text(TTR("(GLES3 only)") + " " + add_options[item->get_meta("id")].description); // TODO: change it to (Vulkan Only) when its ready - } else { - node_desc->set_text(add_options[item->get_meta("id")].description); - } + node_desc->set_text(_get_description(item->get_meta("id"))); } else { members_dialog->get_ok()->set_disabled(true); node_desc->set_text(""); @@ -2052,11 +2059,44 @@ void VisualShaderEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da void VisualShaderEditor::_show_preview_text() { preview_showed = !preview_showed; - preview_text->set_visible(preview_showed); + preview_vbox->set_visible(preview_showed); + if (preview_showed) { + if (pending_update_preview) { + _update_preview(); + pending_update_preview = false; + } + } } void VisualShaderEditor::_update_preview() { - preview_text->set_text(visual_shader->get_code()); + + if (!preview_showed) { + pending_update_preview = true; + return; + } + + String code = visual_shader->get_code(); + + preview_text->set_text(code); + + ShaderLanguage sl; + + Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_types()); + + for (int i = 0; i < preview_text->get_line_count(); i++) { + preview_text->set_line_as_marked(i, false); + } + if (err != OK) { + preview_text->set_line_as_marked(sl.get_error_line() - 1, true); + error_text->set_visible(true); + + String text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text(); + error_text->set_text(text); + shader_error = true; + } else { + error_text->set_visible(false); + shader_error = false; + } } void VisualShaderEditor::_bind_methods() { @@ -2127,6 +2167,8 @@ VisualShaderEditor::VisualShaderEditor() { ShaderLanguage::get_keyword_list(&keyword_list); preview_showed = false; + pending_update_preview = false; + shader_error = false; to_node = -1; to_slot = -1; @@ -2201,15 +2243,22 @@ VisualShaderEditor::VisualShaderEditor() { // PREVIEW PANEL /////////////////////////////////////// + preview_vbox = memnew(VBoxContainer); + preview_vbox->set_visible(preview_showed); + main_box->add_child(preview_vbox); preview_text = memnew(TextEdit); - main_box->add_child(preview_text); + preview_vbox->add_child(preview_text); preview_text->set_h_size_flags(SIZE_EXPAND_FILL); preview_text->set_v_size_flags(SIZE_EXPAND_FILL); - preview_text->set_visible(preview_showed); preview_text->set_custom_minimum_size(Size2(400 * EDSCALE, 0)); preview_text->set_syntax_coloring(true); + preview_text->set_show_line_numbers(true); preview_text->set_readonly(true); + error_text = memnew(Label); + preview_vbox->add_child(error_text); + error_text->set_visible(false); + /////////////////////////////////////// // SHADER NODES TREE /////////////////////////////////////// @@ -2520,7 +2569,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("TransformDecompose", "Transform", "Composition", "VisualShaderNodeTransformDecompose", TTR("Decomposes transform to four vectors."))); add_options.push_back(AddOption("Determinant", "Transform", "Functions", "VisualShaderNodeDeterminant", TTR("Calculates the determinant of a transform."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); - add_options.push_back(AddOption("Inverse", "Transform", "Functions", "VisualShaderNodeTransformFunc", TTR("Calculates the inverse of a transform."), VisualShaderNodeTransformFunc::FUNC_INVERSE, VisualShaderNode::PORT_TYPE_TRANSFORM, -1, -1, -1, true)); + add_options.push_back(AddOption("Inverse", "Transform", "Functions", "VisualShaderNodeTransformFunc", TTR("Calculates the inverse of a transform."), VisualShaderNodeTransformFunc::FUNC_INVERSE, VisualShaderNode::PORT_TYPE_TRANSFORM)); add_options.push_back(AddOption("Transpose", "Transform", "Functions", "VisualShaderNodeTransformFunc", TTR("Calculates the transpose of a transform."), VisualShaderNodeTransformFunc::FUNC_TRANSPOSE, VisualShaderNode::PORT_TYPE_TRANSFORM)); add_options.push_back(AddOption("TransformMult", "Transform", "Operators", "VisualShaderNodeTransformMult", TTR("Multiplies transform by transform."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM)); diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index 1556c7cd43..cd5efc366b 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -70,7 +70,11 @@ class VisualShaderEditor : public VBoxContainer { PanelContainer *error_panel; Label *error_label; + bool pending_update_preview; + bool shader_error; + VBoxContainer *preview_vbox; TextEdit *preview_text; + Label *error_text; UndoRedo *undo_redo; Point2 saved_node_pos; @@ -154,6 +158,7 @@ class VisualShaderEditor : public VBoxContainer { void _show_preview_text(); void _update_preview(); + String _get_description(int p_idx); static VisualShaderEditor *singleton; diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 5709bdc3fa..23aba06956 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -946,6 +946,11 @@ public: static const char *SIGNAL_SELECTION_CHANGED; static const char *SIGNAL_PROJECT_ASK_OPEN; + enum MenuOptions { + GLOBAL_NEW_WINDOW, + GLOBAL_OPEN_PROJECT + }; + // Can often be passed by copy struct Item { String project_key; @@ -1181,6 +1186,7 @@ void ProjectList::load_projects() { _projects.clear(); _last_clicked = ""; _selected_project_keys.clear(); + OS::get_singleton()->global_menu_clear("_dock"); // Load data // TODO Would be nice to change how projects and favourites are stored... it complicates things a bit. @@ -1218,6 +1224,9 @@ void ProjectList::load_projects() { create_project_item_control(i); } + OS::get_singleton()->global_menu_add_separator("_dock"); + OS::get_singleton()->global_menu_add_item("_dock", TTR("New Window"), GLOBAL_NEW_WINDOW, Variant()); + sort_projects(); set_v_scroll(0); @@ -1305,6 +1314,7 @@ void ProjectList::create_project_item_control(int p_index) { fpath->set_clip_text(true); _scroll_children->add_child(hb); + OS::get_singleton()->global_menu_add_item("_dock", item.project_name + " ( " + item.path + " )", GLOBAL_OPEN_PROJECT, Variant(item.path.plus_file("project.godot"))); item.control = hb; } @@ -1822,7 +1832,7 @@ void ProjectManager::_unhandled_input(const Ref<InputEvent> &p_ev) { break; int index = _project_list->get_single_selected_index(); - if (index - 1 > 0) { + if (index > 0) { _project_list->select_project(index - 1); _project_list->ensure_project_visible(index - 1); _update_project_buttons(); @@ -1894,6 +1904,29 @@ void ProjectManager::_confirm_update_settings() { _open_selected_projects(); } +void ProjectManager::_global_menu_action(const Variant &p_id, const Variant &p_meta) { + + int id = (int)p_id; + if (id == ProjectList::GLOBAL_NEW_WINDOW) { + List<String> args; + String exec = OS::get_singleton()->get_executable_path(); + + OS::ProcessID pid = 0; + OS::get_singleton()->execute(exec, args, false, &pid); + } else if (id == ProjectList::GLOBAL_OPEN_PROJECT) { + String conf = (String)p_meta; + + if (conf != String()) { + List<String> args; + args.push_back(conf); + String exec = OS::get_singleton()->get_executable_path(); + + OS::ProcessID pid = 0; + OS::get_singleton()->execute(exec, args, false, &pid); + } + } +} + void ProjectManager::_open_selected_projects() { const Set<String> &selected_list = _project_list->get_selected_project_keys(); @@ -2236,6 +2269,7 @@ void ProjectManager::_bind_methods() { ClassDB::bind_method("_open_selected_projects_ask", &ProjectManager::_open_selected_projects_ask); ClassDB::bind_method("_open_selected_projects", &ProjectManager::_open_selected_projects); + ClassDB::bind_method(D_METHOD("_global_menu_action"), &ProjectManager::_global_menu_action, DEFVAL(Variant())); ClassDB::bind_method("_run_project", &ProjectManager::_run_project); ClassDB::bind_method("_run_project_confirm", &ProjectManager::_run_project_confirm); ClassDB::bind_method("_scan_projects", &ProjectManager::_scan_projects); @@ -2561,6 +2595,7 @@ ProjectManager::ProjectManager() { } SceneTree::get_singleton()->connect("files_dropped", this, "_files_dropped"); + SceneTree::get_singleton()->connect("global_menu_action", this, "_global_menu_action"); run_error_diag = memnew(AcceptDialog); gui_base->add_child(run_error_diag); diff --git a/editor/project_manager.h b/editor/project_manager.h index 2a5fd02892..cf0b8b8801 100644 --- a/editor/project_manager.h +++ b/editor/project_manager.h @@ -43,6 +43,7 @@ class ProjectList; class ProjectListFilter; class ProjectManager : public Control { + GDCLASS(ProjectManager, Control); Button *erase_btn; @@ -96,6 +97,7 @@ class ProjectManager : public Control { void _restart_confirm(); void _exit_dialog(); void _scan_begin(const String &p_base); + void _global_menu_action(const Variant &p_id, const Variant &p_meta); void _confirm_update_settings(); |