diff options
Diffstat (limited to 'editor')
91 files changed, 2481 insertions, 1829 deletions
diff --git a/editor/SCsub b/editor/SCsub index 82b982eef2..82a4ecb6c0 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -1,6 +1,7 @@ #!/usr/bin/env python Import('env') + env.editor_sources = [] import os @@ -78,7 +79,9 @@ if env['tools']: env.CommandNoCache('#editor/builtin_fonts.gen.h', flist, run_in_subprocess(editor_builders.make_fonts_header)) env.add_source_files(env.editor_sources, "*.cpp") - env.add_source_files(env.editor_sources, ["#thirdparty/misc/clipper.cpp"]) + env_thirdparty = env.Clone() + env_thirdparty.disable_warnings() + env_thirdparty.add_source_files(env.editor_sources, ["#thirdparty/misc/clipper.cpp"]) SConscript('collada/SCsub') SConscript('doc/SCsub') @@ -89,5 +92,3 @@ if env['tools']: lib = env.add_library("editor", env.editor_sources) env.Prepend(LIBS=[lib]) - - Export('env') diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index ac28fb9b99..77be561477 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "animation_track_editor.h" + #include "animation_track_editor_plugins.h" #include "core/os/keyboard.h" #include "editor/animation_bezier_editor.h" @@ -772,9 +773,6 @@ void AnimationTimelineEdit::_notification(int p_what) { hsize_rect = Rect2(get_name_limit() - hsize_icon->get_width() - 2 * EDSCALE, (get_size().height - hsize_icon->get_height()) / 2, hsize_icon->get_width(), hsize_icon->get_height()); draw_texture(hsize_icon, hsize_rect.position); - float keys_from = get_value(); - float keys_to = keys_from + zoomw / scale; - { float time_min = 0; float time_max = animation->get_length(); @@ -4923,8 +4921,8 @@ AnimationTrackEditor::AnimationTrackEditor() { //this shortcut will be checked from the track itself. so no need to enable it here (will conflict with scenetree dock) edit->get_popup()->add_separator(); - edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_next_step", TTR("Goto Next Step"), KEY_MASK_CMD | KEY_RIGHT), EDIT_GOTO_NEXT_STEP); - edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_prev_step", TTR("Goto Prev Step"), KEY_MASK_CMD | KEY_LEFT), EDIT_GOTO_PREV_STEP); + edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_next_step", TTR("Go to Next Step"), KEY_MASK_CMD | KEY_RIGHT), EDIT_GOTO_NEXT_STEP); + edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_prev_step", TTR("Go to Previous Step"), KEY_MASK_CMD | KEY_LEFT), EDIT_GOTO_PREV_STEP); edit->get_popup()->add_separator(); edit->get_popup()->add_item(TTR("Optimize Animation"), EDIT_OPTIMIZE_ANIMATION); edit->get_popup()->add_item(TTR("Clean-Up Animation"), EDIT_CLEAN_UP_ANIMATION); diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 33d36e5e9c..79c22f667a 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -44,7 +44,7 @@ void GotoLineDialog::popup_find_line(TextEdit *p_edit) { line->set_text(itos(text_editor->cursor_get_line())); line->select_all(); - popup_centered(Size2(180, 80)); + popup_centered(Size2(180, 80) * EDSCALE); line->grab_focus(); } @@ -65,16 +65,20 @@ void GotoLineDialog::ok_pressed() { GotoLineDialog::GotoLineDialog() { set_title(TTR("Go to Line")); + + VBoxContainer *vbc = memnew(VBoxContainer); + vbc->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 8 * EDSCALE); + vbc->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 8 * EDSCALE); + vbc->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -8 * EDSCALE); + vbc->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -8 * EDSCALE); + add_child(vbc); + Label *l = memnew(Label); l->set_text(TTR("Line Number:")); - l->set_position(Point2(5, 5)); - add_child(l); + vbc->add_child(l); line = memnew(LineEdit); - line->set_anchor(MARGIN_RIGHT, ANCHOR_END); - line->set_begin(Point2(15, 22)); - line->set_end(Point2(-15, 35)); - add_child(line); + vbc->add_child(line); register_text_enter(line); text_editor = NULL; diff --git a/editor/collada/SCsub b/editor/collada/SCsub index 04c9a827ef..2b1e889fb0 100644 --- a/editor/collada/SCsub +++ b/editor/collada/SCsub @@ -3,5 +3,3 @@ Import('env') env.add_source_files(env.editor_sources, "*.cpp") - -Export('env') diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index 037543f45c..d64b02a605 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -504,7 +504,7 @@ void DependencyRemoveDialog::ok_pressed() { } if (dirs_to_delete.size() == 0) { - //If we only deleted files we should only need to tell the file system about the files we touched. + // If we only deleted files we should only need to tell the file system about the files we touched. for (int i = 0; i < files_to_delete.size(); ++i) EditorFileSystem::get_singleton()->update_file(files_to_delete[i]); } else { @@ -518,21 +518,25 @@ void DependencyRemoveDialog::ok_pressed() { } } - // if some dirs would be deleted, favorite dirs need to be updated - Vector<String> previous_favorite_dirs = EditorSettings::get_singleton()->get_favorite_dirs(); - Vector<String> new_favorite_dirs; + EditorFileSystem::get_singleton()->scan_changes(); + } - for (int i = 0; i < previous_favorite_dirs.size(); ++i) { - if (dirs_to_delete.find(previous_favorite_dirs[i] + "/") < 0) { - new_favorite_dirs.push_back(previous_favorite_dirs[i]); - } - } + // If some files/dirs would be deleted, favorite dirs need to be updated + Vector<String> previous_favorites = EditorSettings::get_singleton()->get_favorites(); + Vector<String> new_favorites; - if (new_favorite_dirs.size() < previous_favorite_dirs.size()) { - EditorSettings::get_singleton()->set_favorite_dirs(new_favorite_dirs); + for (int i = 0; i < previous_favorites.size(); ++i) { + if (previous_favorites[i].ends_with("/")) { + if (dirs_to_delete.find(previous_favorites[i]) < 0) + new_favorites.push_back(previous_favorites[i]); + } else { + if (files_to_delete.find(previous_favorites[i]) < 0) + new_favorites.push_back(previous_favorites[i]); } + } - EditorFileSystem::get_singleton()->scan_changes(); + if (new_favorites.size() < previous_favorites.size()) { + EditorSettings::get_singleton()->set_favorites(new_favorites); } } diff --git a/editor/doc/SCsub b/editor/doc/SCsub index 04c9a827ef..2b1e889fb0 100644 --- a/editor/doc/SCsub +++ b/editor/doc/SCsub @@ -3,5 +3,3 @@ Import('env') env.add_source_files(env.editor_sources, "*.cpp") - -Export('env') diff --git a/editor/editor_export.h b/editor/editor_export.h index 420f383f95..b4ee5b89e7 100644 --- a/editor/editor_export.h +++ b/editor/editor_export.h @@ -37,10 +37,10 @@ #include "scene/main/timer.h" #include "scene/resources/texture.h" -class EditorProgress; class FileAccess; class EditorExportPlatform; class EditorFileSystemDirectory; +struct EditorProgress; class EditorExportPreset : public Reference { diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 3659a06bb7..38bdba31ea 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -198,8 +198,22 @@ void EditorFileDialog::update_dir() { dir->set_text(dir_access->get_current_dir()); - // Disable "Open" button only when we in selecting file(s) mode or open dir mode. + // Disable "Open" button only when selecting file(s) mode. get_ok()->set_disabled(_is_open_should_be_disabled()); + switch (mode) { + + case MODE_OPEN_FILE: + case MODE_OPEN_FILES: + get_ok()->set_text(TTR("Open")); + break; + case MODE_OPEN_DIR: + get_ok()->set_text(TTR("Select Current Folder")); + break; + case MODE_OPEN_ANY: + case MODE_SAVE_FILE: + // FIXME: Implement, or refactor to avoid duplication with set_mode + break; + } } void EditorFileDialog::_dir_entered(String p_dir) { @@ -269,7 +283,7 @@ void EditorFileDialog::_post_popup() { set_process_unhandled_input(true); } -void EditorFileDialog::_thumbnail_result(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata) { +void EditorFileDialog::_thumbnail_result(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata) { if (display_mode == DISPLAY_LIST || p_preview.is_null()) return; @@ -284,7 +298,7 @@ void EditorFileDialog::_thumbnail_result(const String &p_path, const Ref<Texture } } -void EditorFileDialog::_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata) { +void EditorFileDialog::_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata) { set_process(false); preview_waiting = false; @@ -453,6 +467,8 @@ void EditorFileDialog::_item_selected(int p_item) { file->set_text(d["name"]); _request_single_thumbnail(get_current_dir().plus_file(get_current_file())); + } else if (mode == MODE_OPEN_DIR) { + get_ok()->set_text(TTR("Select This Folder")); } get_ok()->set_disabled(_is_open_should_be_disabled()); @@ -492,6 +508,11 @@ void EditorFileDialog::_items_clear_selection() { get_ok()->set_disabled(false); get_ok()->set_text(TTR("Select Current Folder")); break; + + case MODE_OPEN_ANY: + case MODE_SAVE_FILE: + // FIXME: Implement, or refactor to avoid duplication with set_mode + break; } } @@ -637,7 +658,7 @@ bool EditorFileDialog::_is_open_should_be_disabled() { Vector<int> items = item_list->get_selected_items(); if (items.size() == 0) - return true; + return mode != MODE_OPEN_DIR; // In "Open folder" mode, having nothing selected picks the current folder. for (int i = 0; i < items.size(); i++) { @@ -1115,7 +1136,7 @@ void EditorFileDialog::_update_drives() { void EditorFileDialog::_favorite_selected(int p_idx) { - Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs(); + Vector<String> favorited = EditorSettings::get_singleton()->get_favorites(); ERR_FAIL_INDEX(p_idx, favorited.size()); dir_access->change_dir(favorited[p_idx]); @@ -1130,7 +1151,7 @@ void EditorFileDialog::_favorite_move_up() { int current = favorites->get_current(); if (current > 0 && current < favorites->get_item_count()) { - Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs(); + Vector<String> favorited = EditorSettings::get_singleton()->get_favorites(); int a_idx = favorited.find(String(favorites->get_item_metadata(current - 1))); int b_idx = favorited.find(String(favorites->get_item_metadata(current))); @@ -1139,7 +1160,7 @@ void EditorFileDialog::_favorite_move_up() { return; SWAP(favorited.write[a_idx], favorited.write[b_idx]); - EditorSettings::get_singleton()->set_favorite_dirs(favorited); + EditorSettings::get_singleton()->set_favorites(favorited); _update_favorites(); update_file_list(); @@ -1150,7 +1171,7 @@ void EditorFileDialog::_favorite_move_down() { int current = favorites->get_current(); if (current >= 0 && current < favorites->get_item_count() - 1) { - Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs(); + Vector<String> favorited = EditorSettings::get_singleton()->get_favorites(); int a_idx = favorited.find(String(favorites->get_item_metadata(current + 1))); int b_idx = favorited.find(String(favorites->get_item_metadata(current))); @@ -1159,7 +1180,7 @@ void EditorFileDialog::_favorite_move_down() { return; SWAP(favorited.write[a_idx], favorited.write[b_idx]); - EditorSettings::get_singleton()->set_favorite_dirs(favorited); + EditorSettings::get_singleton()->set_favorites(favorited); _update_favorites(); update_file_list(); @@ -1176,7 +1197,7 @@ void EditorFileDialog::_update_favorites() { favorite->set_pressed(false); - Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs(); + Vector<String> favorited = EditorSettings::get_singleton()->get_favorites(); for (int i = 0; i < favorited.size(); i++) { bool cres = favorited[i].begins_with("res://"); if (cres != res) @@ -1206,7 +1227,7 @@ void EditorFileDialog::_favorite_toggled(bool p_toggle) { String cd = get_current_dir(); - Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs(); + Vector<String> favorited = EditorSettings::get_singleton()->get_favorites(); bool found = false; for (int i = 0; i < favorited.size(); i++) { @@ -1228,7 +1249,7 @@ void EditorFileDialog::_favorite_toggled(bool p_toggle) { favorite->set_pressed(true); } - EditorSettings::get_singleton()->set_favorite_dirs(favorited); + EditorSettings::get_singleton()->set_favorites(favorited); _update_favorites(); } diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h index 61eeff9162..56cefb9a47 100644 --- a/editor/editor_file_dialog.h +++ b/editor/editor_file_dialog.h @@ -190,8 +190,8 @@ private: void _save_to_recent(); //callback function is callback(String p_path,Ref<Texture> preview,Variant udata) preview null if could not load - void _thumbnail_result(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata); - void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata); + void _thumbnail_result(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata); + void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata); void _request_single_thumbnail(const String &p_path); void _unhandled_input(const Ref<InputEvent> &p_event); diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index ea99c882e4..8b1818b595 100644 --- a/editor/editor_fonts.cpp +++ b/editor/editor_fonts.cpp @@ -37,33 +37,6 @@ #include "scene/resources/default_theme/default_theme.h" #include "scene/resources/dynamic_font.h" -static Ref<BitmapFont> make_font(int p_height, int p_ascent, int p_valign, int p_charcount, const int *p_chars, const Ref<Texture> &p_texture) { - - Ref<BitmapFont> font(memnew(BitmapFont)); - font->add_texture(p_texture); - - for (int i = 0; i < p_charcount; i++) { - - const int *c = &p_chars[i * 8]; - - int chr = c[0]; - Rect2 frect; - frect.position.x = c[1]; - frect.position.y = c[2]; - frect.size.x = c[3]; - frect.size.y = c[4]; - Point2 align(c[5], c[6] + p_valign); - int advance = c[7]; - - font->add_char(chr, 0, frect, align, advance); - } - - font->set_height(p_height); - font->set_ascent(p_ascent); - - return font; -} - #define MAKE_FALLBACKS(m_name) \ m_name->add_fallback(FontArabic); \ m_name->add_fallback(FontHebrew); \ diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 60040f641b..80dd5aa114 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -40,7 +40,7 @@ #define CONTRIBUTE2_URL "https://github.com/godotengine/godot-docs" #define REQUEST_URL "https://github.com/godotengine/godot-docs/issues/new" -void EditorHelpSearch::popup() { +void EditorHelpSearch::popup_dialog() { popup_centered(Size2(700, 600) * EDSCALE); if (search_box->get_text() != "") { @@ -50,15 +50,16 @@ void EditorHelpSearch::popup() { search_box->grab_focus(); } -void EditorHelpSearch::popup(const String &p_term) { +void EditorHelpSearch::popup_dialog(const String &p_term) { popup_centered(Size2(700, 600) * EDSCALE); if (p_term != "") { search_box->set_text(p_term); search_box->select_all(); _update_search(); - } else + } else { search_box->clear(); + } search_box->grab_focus(); } @@ -362,7 +363,7 @@ void EditorHelpIndex::select_class(const String &p_class) { class_list->ensure_cursor_is_visible(); } -void EditorHelpIndex::popup() { +void EditorHelpIndex::popup_dialog() { popup_centered(Size2(500, 600) * EDSCALE); diff --git a/editor/editor_help.h b/editor/editor_help.h index ad81a39945..25db68b42d 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -92,8 +92,8 @@ protected: static void _bind_methods(); public: - void popup(); - void popup(const String &p_term); + void popup_dialog(); + void popup_dialog(const String &p_term); EditorHelpSearch(); }; @@ -120,7 +120,7 @@ protected: public: void select_class(const String &p_class); - void popup(); + void popup_dialog(); EditorHelpIndex(); }; diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 36c3102840..2c4168f1a0 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -36,9 +36,6 @@ #include "multi_node_edit.h" #include "scene/resources/packed_scene.h" -// TODO: -// arrays and dictionary - Size2 EditorProperty::get_minimum_size() const { Size2 ms; @@ -267,11 +264,6 @@ void EditorProperty::_notification(int p_what) { } else { keying_rect = Rect2(); } - - //int vs = get_constant("vseparation", "Tree"); - Color guide_color = get_color("guide_color", "Tree"); - int vs_height = get_size().height; // vs / 2; - // draw_line(Point2(0, vs_height), Point2(get_size().width, vs_height), guide_color); } } @@ -1454,6 +1446,9 @@ void EditorInspector::update_tree() { } else if (!(p.usage & PROPERTY_USAGE_EDITOR)) continue; + if (p.usage & PROPERTY_USAGE_HIGH_END_GFX && VS::get_singleton()->is_low_end()) + continue; //do not show this property in low end gfx + if (p.name == "script" && (hide_script || bool(object->call("_hide_script_from_inspector")))) { continue; } @@ -1986,7 +1981,7 @@ void EditorInspector::_property_keyed(const String &p_path) { if (!object) return; - emit_signal("property_keyed", p_path, object->get(p_path), false); //second param is deprecated + emit_signal("property_keyed", p_path, object->get(p_path), true); //second param is deprecated } void EditorInspector::_property_keyed_with_value(const String &p_path, const Variant &p_value) { diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 3fc35810df..5f5c46f4a7 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -49,11 +49,6 @@ void EditorLog::_error_handler(void *p_self, const char *p_func, const char *p_f err_str = String(p_file) + ":" + itos(p_line) + " - " + String(p_error); } - /* - if (!self->is_visible_in_tree()) - self->emit_signal("show_request"); - */ - if (p_type == ERR_HANDLER_WARNING) { self->add_message(err_str, MSG_TYPE_WARNING); } else { @@ -76,17 +71,6 @@ void EditorLog::_notification(int p_what) { } } } - - /*if (p_what==NOTIFICATION_DRAW) { - - RID ci = get_canvas_item(); - get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size())); - int top_ofs = 20; - int border_ofs=4; - Ref<StyleBox> style = get_stylebox("normal","TextEdit"); - - style->draw(ci,Rect2( Point2(border_ofs,top_ofs),get_size()-Size2(border_ofs*2,top_ofs+border_ofs))); - }*/ } void EditorLog::_clear_request() { @@ -105,6 +89,8 @@ void EditorLog::add_message(const String &p_msg, MessageType p_type) { bool restore = p_type != MSG_TYPE_STD; switch (p_type) { + case MSG_TYPE_STD: { + } break; case MSG_TYPE_ERROR: { log->push_color(get_color("error_color", "Editor")); Ref<Texture> icon = get_icon("Error", "EditorIcons"); @@ -122,7 +108,6 @@ void EditorLog::add_message(const String &p_msg, MessageType p_type) { } log->add_text(p_msg); - //button->set_text(p_msg); if (restore) log->pop(); @@ -132,21 +117,6 @@ void EditorLog::set_tool_button(ToolButton *p_tool_button) { tool_button = p_tool_button; } -/* -void EditorLog::_dragged(const Point2& p_ofs) { - - int ofs = ec->get_minsize().height; - ofs = ofs-p_ofs.y; - if (ofs<50) - ofs=50; - if (ofs>300) - ofs=300; - ec->set_minsize(Size2(ec->get_minsize().width,ofs)); - minimum_size_changed(); - -} -*/ - void EditorLog::_undo_redo_cbk(void *p_self, const String &p_name) { EditorLog *self = (EditorLog *)p_self; @@ -156,7 +126,6 @@ void EditorLog::_undo_redo_cbk(void *p_self, const String &p_name) { void EditorLog::_bind_methods() { ClassDB::bind_method(D_METHOD("_clear_request"), &EditorLog::_clear_request); - //ClassDB::bind_method(D_METHOD("_dragged"),&EditorLog::_dragged ); ADD_SIGNAL(MethodInfo("clear_request")); } @@ -187,7 +156,6 @@ EditorLog::EditorLog() { log->set_h_size_flags(SIZE_EXPAND_FILL); vb->add_child(log); add_message(VERSION_FULL_NAME " (c) 2007-2018 Juan Linietsky, Ariel Manzur & Godot Contributors."); - //log->add_text("Initialization Complete.\n"); //because it looks cool. eh.errfunc = _error_handler; eh.userdata = this; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 0ba1ef3b18..790e38afca 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -36,7 +36,6 @@ #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" #include "core/io/stream_peer_ssl.h" -#include "core/io/zip_io.h" #include "core/message_queue.h" #include "core/os/file_access.h" #include "core/os/input.h" @@ -1739,13 +1738,13 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; case FILE_QUICK_OPEN_SCENE: { - quick_open->popup("PackedScene", true); + quick_open->popup_dialog("PackedScene", true); quick_open->set_title(TTR("Quick Open Scene...")); } break; case FILE_QUICK_OPEN_SCRIPT: { - quick_open->popup("Script", true); + quick_open->popup_dialog("Script", true); quick_open->set_title(TTR("Quick Open Script...")); } break; @@ -2003,7 +2002,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { case RUN_PLAY_CUSTOM_SCENE: { if (run_custom_filename.empty() || editor_run.get_status() == EditorRun::STATUS_STOP) { _menu_option_confirm(RUN_STOP, true); - quick_run->popup("PackedScene", true); + quick_run->popup_dialog("PackedScene", true); quick_run->set_title(TTR("Quick Run Scene...")); play_custom_scene_button->set_pressed(false); } else { @@ -2039,6 +2038,14 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { emit_signal("stop_pressed"); } break; + + case FILE_SHOW_IN_FILESYSTEM: { + String path = editor_data.get_scene_path(editor_data.get_edited_scene()); + if (path != String()) { + filesystem_dock->navigate_to_path(path); + } + } break; + case RUN_PLAY_SCENE: { _save_default_environment(); @@ -3194,7 +3201,7 @@ Ref<Texture> EditorNode::get_class_icon(const String &p_class, const String &p_f } } - if (p_fallback.length()) + if (p_fallback.length() && gui_base->has_icon(p_fallback, "EditorIcons")) return gui_base->get_icon(p_fallback, "EditorIcons"); return NULL; @@ -3357,19 +3364,12 @@ void EditorNode::_dock_select_input(const Ref<InputEvent> &p_input) { dock_slot[nrect]->show(); dock_select->update(); - VSplitContainer *splits[DOCK_SLOT_MAX / 2] = { - left_l_vsplit, - left_r_vsplit, - right_l_vsplit, - right_r_vsplit, - }; - - for (int i = 0; i < 4; i++) { + for (int i = 0; i < vsplits.size(); i++) { bool in_use = dock_slot[i * 2 + 0]->get_tab_count() || dock_slot[i * 2 + 1]->get_tab_count(); if (in_use) - splits[i]->show(); + vsplits[i]->show(); else - splits[i]->hide(); + vsplits[i]->hide(); } if (right_l_vsplit->is_visible() || right_r_vsplit->is_visible()) @@ -3541,30 +3541,16 @@ void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String &p p_layout->set_value(p_section, "dock_filesystem_split", filesystem_dock->get_split_offset()); - VSplitContainer *splits[DOCK_SLOT_MAX / 2] = { - left_l_vsplit, - left_r_vsplit, - right_l_vsplit, - right_r_vsplit, - }; - - for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) { + for (int i = 0; i < vsplits.size(); i++) { - if (splits[i]->is_visible_in_tree()) { - p_layout->set_value(p_section, "dock_split_" + itos(i + 1), splits[i]->get_split_offset()); + if (vsplits[i]->is_visible_in_tree()) { + p_layout->set_value(p_section, "dock_split_" + itos(i + 1), vsplits[i]->get_split_offset()); } } - HSplitContainer *h_splits[4] = { - left_l_hsplit, - left_r_hsplit, - main_hsplit, - right_hsplit, - }; + for (int i = 0; i < hsplits.size(); i++) { - for (int i = 0; i < 4; i++) { - - p_layout->set_value(p_section, "dock_hsplit_" + itos(i + 1), h_splits[i]->get_split_offset()); + p_layout->set_value(p_section, "dock_hsplit_" + itos(i + 1), hsplits[i]->get_split_offset()); } } @@ -3610,21 +3596,14 @@ void EditorNode::_load_docks() { void EditorNode::_update_dock_slots_visibility() { - VSplitContainer *splits[DOCK_SLOT_MAX / 2] = { - left_l_vsplit, - left_r_vsplit, - right_l_vsplit, - right_r_vsplit, - }; - if (!docks_visible) { for (int i = 0; i < DOCK_SLOT_MAX; i++) { dock_slot[i]->hide(); } - for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) { - splits[i]->hide(); + for (int i = 0; i < vsplits.size(); i++) { + vsplits[i]->hide(); } right_hsplit->hide(); @@ -3638,12 +3617,12 @@ void EditorNode::_update_dock_slots_visibility() { dock_slot[i]->hide(); } - for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) { + for (int i = 0; i < vsplits.size(); i++) { bool in_use = dock_slot[i * 2 + 0]->get_tab_count() || dock_slot[i * 2 + 1]->get_tab_count(); if (in_use) - splits[i]->show(); + vsplits[i]->show(); else - splits[i]->hide(); + vsplits[i]->hide(); } for (int i = 0; i < DOCK_SLOT_MAX; i++) { @@ -3664,12 +3643,6 @@ void EditorNode::_update_dock_slots_visibility() { void EditorNode::_dock_tab_changed(int p_tab) { // update visibility but don't set current tab - VSplitContainer *splits[DOCK_SLOT_MAX / 2] = { - left_l_vsplit, - left_r_vsplit, - right_l_vsplit, - right_r_vsplit, - }; if (!docks_visible) { @@ -3677,8 +3650,8 @@ void EditorNode::_dock_tab_changed(int p_tab) { dock_slot[i]->hide(); } - for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) { - splits[i]->hide(); + for (int i = 0; i < vsplits.size(); i++) { + vsplits[i]->hide(); } right_hsplit->hide(); @@ -3692,12 +3665,12 @@ void EditorNode::_dock_tab_changed(int p_tab) { dock_slot[i]->hide(); } - for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) { + for (int i = 0; i < vsplits.size(); i++) { bool in_use = dock_slot[i * 2 + 0]->get_tab_count() || dock_slot[i * 2 + 1]->get_tab_count(); if (in_use) - splits[i]->show(); + vsplits[i]->show(); else - splits[i]->hide(); + vsplits[i]->hide(); } bottom_panel->show(); @@ -3756,42 +3729,28 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String } filesystem_dock->set_split_offset(fs_split_ofs); - VSplitContainer *splits[DOCK_SLOT_MAX / 2] = { - left_l_vsplit, - left_r_vsplit, - right_l_vsplit, - right_r_vsplit, - }; - - for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) { + for (int i = 0; i < vsplits.size(); i++) { if (!p_layout->has_section_key(p_section, "dock_split_" + itos(i + 1))) continue; int ofs = p_layout->get_value(p_section, "dock_split_" + itos(i + 1)); - splits[i]->set_split_offset(ofs); + vsplits[i]->set_split_offset(ofs); } - HSplitContainer *h_splits[4] = { - left_l_hsplit, - left_r_hsplit, - main_hsplit, - right_hsplit, - }; - - for (int i = 0; i < 4; i++) { + for (int i = 0; i < hsplits.size(); i++) { if (!p_layout->has_section_key(p_section, "dock_hsplit_" + itos(i + 1))) continue; int ofs = p_layout->get_value(p_section, "dock_hsplit_" + itos(i + 1)); - h_splits[i]->set_split_offset(ofs); + hsplits[i]->set_split_offset(ofs); } - for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) { + for (int i = 0; i < vsplits.size(); i++) { bool in_use = dock_slot[i * 2 + 0]->get_tab_count() || dock_slot[i * 2 + 1]->get_tab_count(); if (in_use) - splits[i]->show(); + vsplits[i]->show(); else - splits[i]->hide(); + vsplits[i]->hide(); } if (right_l_vsplit->is_visible() || right_r_vsplit->is_visible()) @@ -3975,6 +3934,7 @@ void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) { scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_all_scenes"), FILE_SAVE_ALL_SCENES); if (scene_tabs->get_hovered_tab() >= 0) { scene_tabs_context_menu->add_separator(); + scene_tabs_context_menu->add_item(TTR("Show in filesystem"), FILE_SHOW_IN_FILESYSTEM); scene_tabs_context_menu->add_item(TTR("Play This Scene"), RUN_PLAY_SCENE); scene_tabs_context_menu->add_item(TTR("Close Tab"), FILE_CLOSE); } @@ -3989,7 +3949,7 @@ void EditorNode::_reposition_active_tab(int idx_to) { _update_scene_tabs(); } -void EditorNode::_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata) { +void EditorNode::_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata) { int p_tab = p_udata.operator signed int(); if (p_preview.is_valid()) { Rect2 rect = scene_tabs->get_tab_rect(p_tab); @@ -4562,6 +4522,16 @@ void EditorNode::_bottom_panel_raise_toggled(bool p_pressed) { } } +void EditorNode::_update_video_driver_color() { + + //todo probably should de-harcode this and add to editor settings + if (video_driver->get_text() == "GLES2") { + video_driver->add_color_override("font_color", Color::hex(0x5586a4ff)); + } else if (video_driver->get_text() == "GLES3") { + video_driver->add_color_override("font_color", Color::hex(0xa5557dff)); + } +} + void EditorNode::_video_driver_selected(int p_which) { String driver = video_driver->get_item_metadata(p_which); @@ -4575,6 +4545,7 @@ void EditorNode::_video_driver_selected(int p_which) { video_driver_request = driver; video_restart_dialog->popup_centered_minsize(); video_driver->select(video_driver_current); + _update_video_driver_color(); } void EditorNode::_bind_methods() { @@ -4878,7 +4849,7 @@ EditorNode::EditorNode() { EDITOR_DEF_RST("interface/inspector/capitalize_properties", true); EDITOR_DEF_RST("interface/inspector/disable_folding", false); EDITOR_DEF("interface/inspector/horizontal_vector2_editing", false); - EDITOR_DEF("interface/inspector/horizontal_vector3_editing", true); + EDITOR_DEF("interface/inspector/horizontal_vector_types_editing", true); EDITOR_DEF("interface/inspector/open_resources_in_current_inspector", true); EDITOR_DEF("interface/inspector/resources_types_to_open_in_new_inspector", "SpatialMaterial,Script"); EDITOR_DEF("run/auto_save/save_before_running", true); @@ -4925,9 +4896,6 @@ EditorNode::EditorNode() { left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_UL]); dock_slot[DOCK_SLOT_LEFT_BL] = memnew(TabContainer); left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_BL]); - left_l_vsplit->hide(); - dock_slot[DOCK_SLOT_LEFT_UL]->hide(); - dock_slot[DOCK_SLOT_LEFT_BL]->hide(); left_r_hsplit = memnew(HSplitContainer); left_l_hsplit->add_child(left_r_hsplit); @@ -4965,19 +4933,22 @@ EditorNode::EditorNode() { right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_UR]); dock_slot[DOCK_SLOT_RIGHT_BR] = memnew(TabContainer); right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_BR]); - right_r_vsplit->hide(); - dock_slot[DOCK_SLOT_RIGHT_UR]->hide(); - dock_slot[DOCK_SLOT_RIGHT_BR]->hide(); - left_l_vsplit->connect("dragged", this, "_dock_split_dragged"); - left_r_vsplit->connect("dragged", this, "_dock_split_dragged"); - right_l_vsplit->connect("dragged", this, "_dock_split_dragged"); - right_r_vsplit->connect("dragged", this, "_dock_split_dragged"); + // Store them for easier access + vsplits.push_back(left_l_vsplit); + vsplits.push_back(left_r_vsplit); + vsplits.push_back(right_l_vsplit); + vsplits.push_back(right_r_vsplit); - left_l_hsplit->connect("dragged", this, "_dock_split_dragged"); - left_r_hsplit->connect("dragged", this, "_dock_split_dragged"); - main_hsplit->connect("dragged", this, "_dock_split_dragged"); - right_hsplit->connect("dragged", this, "_dock_split_dragged"); + hsplits.push_back(left_l_hsplit); + hsplits.push_back(left_r_hsplit); + hsplits.push_back(main_hsplit); + hsplits.push_back(right_hsplit); + + for (int i = 0; i < vsplits.size(); i++) { + vsplits[i]->connect("dragged", this, "_dock_split_dragged"); + hsplits[i]->connect("dragged", this, "_dock_split_dragged"); + } dock_select_popup = memnew(PopupPanel); gui_base->add_child(dock_select_popup); @@ -5437,6 +5408,7 @@ EditorNode::EditorNode() { video_driver->set_focus_mode(Control::FOCUS_NONE); video_driver->set_v_size_flags(Control::SIZE_SHRINK_CENTER); video_driver->connect("item_selected", this, "_video_driver_selected"); + video_driver->add_font_override("font", gui_base->get_font("bold", "EditorFonts")); menu_hb->add_child(video_driver); String video_drivers = ProjectSettings::get_singleton()->get_custom_property_info()["rendering/quality/driver/driver_name"].hint_string; @@ -5453,6 +5425,8 @@ EditorNode::EditorNode() { } } + _update_video_driver_color(); + video_restart_dialog = memnew(ConfirmationDialog); video_restart_dialog->set_text(TTR("Changing the video driver requires restarting the editor.")); video_restart_dialog->get_ok()->set_text(TTR("Save & Restart")); @@ -5487,63 +5461,72 @@ EditorNode::EditorNode() { _menu_option(SETTINGS_UPDATE_SPINNER_HIDE); } - scene_tree_dock = memnew(SceneTreeDock(this, scene_root, editor_selection, editor_data)); - dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(scene_tree_dock); - dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(scene_tree_dock->get_index(), TTR("Scene")); - dock_slot[DOCK_SLOT_LEFT_BR]->hide(); + // Instantiate and place editor docks + scene_tree_dock = memnew(SceneTreeDock(this, scene_root, editor_selection, editor_data)); inspector_dock = memnew(InspectorDock(this, editor_data)); - dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(inspector_dock); - dock_slot[DOCK_SLOT_RIGHT_BL]->set_tab_title(inspector_dock->get_index(), TTR("Inspector")); - - Button *property_editable_warning; - import_dock = memnew(ImportDock); - dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(import_dock); - dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(import_dock->get_index(), TTR("Import")); - - bool use_single_dock_column = (OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x < 1200); - node_dock = memnew(NodeDock); - if (use_single_dock_column) { - dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(node_dock); - dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(node_dock->get_index(), TTR("Node")); - } else { - dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(node_dock); - dock_slot[DOCK_SLOT_RIGHT_BL]->set_tab_title(node_dock->get_index(), TTR("Node")); - } filesystem_dock = memnew(FileSystemDock(this)); - filesystem_dock->set_file_list_display_mode(int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode"))); - - if (use_single_dock_column) { - dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(filesystem_dock); - dock_slot[DOCK_SLOT_RIGHT_BL]->set_tab_title(filesystem_dock->get_index(), TTR("FileSystem")); - left_r_vsplit->hide(); - dock_slot[DOCK_SLOT_LEFT_UR]->hide(); - dock_slot[DOCK_SLOT_LEFT_BR]->hide(); - } else { - dock_slot[DOCK_SLOT_LEFT_UR]->add_child(filesystem_dock); - dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(filesystem_dock->get_index(), TTR("FileSystem")); - } + filesystem_dock->set_file_list_display_mode(int(EditorSettings::get_singleton()->get("docks/filesystem/files_display_mode"))); filesystem_dock->connect("open", this, "open_request"); filesystem_dock->connect("instance", this, "_instance_request"); - const String docks_section = "docks"; + // Scene: Top left + dock_slot[DOCK_SLOT_LEFT_UR]->add_child(scene_tree_dock); + dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(scene_tree_dock->get_index(), TTR("Scene")); + + // Import: Top left, behind Scene + dock_slot[DOCK_SLOT_LEFT_UR]->add_child(import_dock); + dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(import_dock->get_index(), TTR("Import")); + + // FileSystem: Bottom left + dock_slot[DOCK_SLOT_LEFT_BR]->add_child(filesystem_dock); + dock_slot[DOCK_SLOT_LEFT_BR]->set_tab_title(filesystem_dock->get_index(), TTR("FileSystem")); + + // Inspector: Full height right + dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(inspector_dock); + dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(inspector_dock->get_index(), TTR("Inspector")); + + // Node: Full height right, behind Inspector + dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(node_dock); + dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(node_dock->get_index(), TTR("Node")); + + // Hide unused dock slots and vsplits + dock_slot[DOCK_SLOT_LEFT_UL]->hide(); + dock_slot[DOCK_SLOT_LEFT_BL]->hide(); + dock_slot[DOCK_SLOT_RIGHT_BL]->hide(); + dock_slot[DOCK_SLOT_RIGHT_UR]->hide(); + dock_slot[DOCK_SLOT_RIGHT_BR]->hide(); + left_l_vsplit->hide(); + right_r_vsplit->hide(); + + // Add some offsets to left_r and main hsplits to make LEFT_R and RIGHT_L docks wider than minsize + left_r_hsplit->set_split_offset(40 * EDSCALE); + main_hsplit->set_split_offset(-40 * EDSCALE); + // Define corresponding default layout + + const String docks_section = "docks"; overridden_default_layout = -1; default_layout.instance(); - default_layout->set_value(docks_section, "dock_3", "FileSystem"); - default_layout->set_value(docks_section, "dock_5", "Scene,Import"); - default_layout->set_value(docks_section, "dock_6", "Inspector,Node"); + // Dock numbers are based on DockSlot enum value + 1 + default_layout->set_value(docks_section, "dock_3", "Scene,Import"); + default_layout->set_value(docks_section, "dock_4", "FileSystem"); + default_layout->set_value(docks_section, "dock_5", "Inspector,Node"); - for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) - default_layout->set_value(docks_section, "dock_hsplit_" + itos(i + 1), 0); - for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) + for (int i = 0; i < vsplits.size(); i++) default_layout->set_value(docks_section, "dock_split_" + itos(i + 1), 0); + default_layout->set_value(docks_section, "dock_hsplit_1", 0); + default_layout->set_value(docks_section, "dock_hsplit_2", 40 * EDSCALE); + default_layout->set_value(docks_section, "dock_hsplit_3", -40 * EDSCALE); + default_layout->set_value(docks_section, "dock_hsplit_4", 0); _update_layouts_menu(); + // Bottom panels + bottom_panel = memnew(PanelContainer); bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer")); center_split->add_child(bottom_panel); @@ -5928,17 +5911,31 @@ bool EditorPluginList::forward_spatial_gui_input(Camera *p_camera, const Ref<Inp return discard; } -void EditorPluginList::forward_draw_over_viewport(Control *p_overlay) { +void EditorPluginList::forward_canvas_draw_over_viewport(Control *p_overlay) { + + for (int i = 0; i < plugins_list.size(); i++) { + plugins_list[i]->forward_canvas_draw_over_viewport(p_overlay); + } +} + +void EditorPluginList::forward_canvas_force_draw_over_viewport(Control *p_overlay) { + + for (int i = 0; i < plugins_list.size(); i++) { + plugins_list[i]->forward_canvas_force_draw_over_viewport(p_overlay); + } +} + +void EditorPluginList::forward_spatial_draw_over_viewport(Control *p_overlay) { for (int i = 0; i < plugins_list.size(); i++) { - plugins_list[i]->forward_draw_over_viewport(p_overlay); + plugins_list[i]->forward_spatial_draw_over_viewport(p_overlay); } } -void EditorPluginList::forward_force_draw_over_viewport(Control *p_overlay) { +void EditorPluginList::forward_spatial_force_draw_over_viewport(Control *p_overlay) { for (int i = 0; i < plugins_list.size(); i++) { - plugins_list[i]->forward_force_draw_over_viewport(p_overlay); + plugins_list[i]->forward_spatial_force_draw_over_viewport(p_overlay); } } diff --git a/editor/editor_node.h b/editor/editor_node.h index 7409c64a64..0096748ed1 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -125,6 +125,7 @@ private: FILE_SAVE_ALL_SCENES, FILE_SAVE_BEFORE_RUN, FILE_SAVE_AND_RUN, + FILE_SHOW_IN_FILESYSTEM, FILE_IMPORT_SUBSCENE, FILE_EXPORT_PROJECT, FILE_EXPORT_MESH_LIBRARY, @@ -207,8 +208,9 @@ private: int video_driver_current; String video_driver_request; void _video_driver_selected(int); + void _update_video_driver_color(); - //split + // Split containers HSplitContainer *left_l_hsplit; VSplitContainer *left_l_vsplit; @@ -221,7 +223,11 @@ private: VSplitContainer *center_split; - //main tabs + // To access those easily by index + Vector<VSplitContainer *> vsplits; + Vector<HSplitContainer *> hsplits; + + // Main tabs Tabs *scene_tabs; PopupMenu *scene_tabs_context_menu; @@ -535,7 +541,7 @@ private: void _scene_tab_exit(); void _scene_tab_input(const Ref<InputEvent> &p_input); void _reposition_active_tab(int idx_to); - void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata); + void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata); void _scene_tab_script_edited(int p_tab); Dictionary _get_main_scene_state(); @@ -812,9 +818,11 @@ public: void make_visible(bool p_visible); void edit(Object *p_object); bool forward_gui_input(const Ref<InputEvent> &p_event); + void forward_canvas_draw_over_viewport(Control *p_overlay); + void forward_canvas_force_draw_over_viewport(Control *p_overlay); bool forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event, bool serve_when_force_input_enabled); - void forward_draw_over_viewport(Control *p_overlay); - void forward_force_draw_over_viewport(Control *p_overlay); + void forward_spatial_draw_over_viewport(Control *p_overlay); + void forward_spatial_force_draw_over_viewport(Control *p_overlay); void add_plugin(EditorPlugin *p_plugin); void clear(); bool empty(); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 1f2e73654c..dd3a8aa307 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -39,6 +39,7 @@ #include "scene/3d/camera.h" #include "scene/gui/popup_menu.h" #include "servers/visual_server.h" + Array EditorInterface::_make_mesh_previews(const Array &p_meshes, int p_preview_size) { Vector<Ref<Mesh> > meshes; @@ -503,17 +504,17 @@ bool EditorPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return false; } -void EditorPlugin::forward_draw_over_viewport(Control *p_overlay) { +void EditorPlugin::forward_canvas_draw_over_viewport(Control *p_overlay) { - if (get_script_instance() && get_script_instance()->has_method("forward_draw_over_viewport")) { - get_script_instance()->call("forward_draw_over_viewport", p_overlay); + if (get_script_instance() && get_script_instance()->has_method("forward_canvas_draw_over_viewport")) { + get_script_instance()->call("forward_canvas_draw_over_viewport", p_overlay); } } -void EditorPlugin::forward_force_draw_over_viewport(Control *p_overlay) { +void EditorPlugin::forward_canvas_force_draw_over_viewport(Control *p_overlay) { - if (get_script_instance() && get_script_instance()->has_method("forward_force_draw_over_viewport")) { - get_script_instance()->call("forward_force_draw_over_viewport", p_overlay); + if (get_script_instance() && get_script_instance()->has_method("forward_canvas_force_draw_over_viewport")) { + get_script_instance()->call("forward_canvas_force_draw_over_viewport", p_overlay); } } @@ -522,7 +523,7 @@ int EditorPlugin::update_overlays() const { if (SpatialEditor::get_singleton()->is_visible()) { int count = 0; - for (int i = 0; i < SpatialEditor::VIEWPORTS_COUNT; i++) { + for (uint32_t i = 0; i < SpatialEditor::VIEWPORTS_COUNT; i++) { SpatialEditorViewport *vp = SpatialEditor::get_singleton()->get_editor_viewport(i); if (vp->is_visible()) { vp->update_surface(); @@ -545,6 +546,20 @@ bool EditorPlugin::forward_spatial_gui_input(Camera *p_camera, const Ref<InputEv return false; } + +void EditorPlugin::forward_spatial_draw_over_viewport(Control *p_overlay) { + + if (get_script_instance() && get_script_instance()->has_method("forward_spatial_draw_over_viewport")) { + get_script_instance()->call("forward_spatial_draw_over_viewport", p_overlay); + } +} + +void EditorPlugin::forward_spatial_force_draw_over_viewport(Control *p_overlay) { + + if (get_script_instance() && get_script_instance()->has_method("forward_spatial_force_draw_over_viewport")) { + get_script_instance()->call("forward_spatial_force_draw_over_viewport", p_overlay); + } +} String EditorPlugin::get_name() const { if (get_script_instance() && get_script_instance()->has_method("get_plugin_name")) { @@ -769,8 +784,8 @@ void EditorPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("get_script_create_dialog"), &EditorPlugin::get_script_create_dialog); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "forward_canvas_gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); - ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control"))); - ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_force_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control"))); + ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_canvas_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control"))); + ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_canvas_force_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "forward_spatial_gui_input", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_plugin_name")); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::OBJECT, "get_plugin_icon")); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 6c385abf9b..e03aeb5d30 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -174,9 +174,13 @@ public: void notify_resource_saved(const Ref<Resource> &p_resource); virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event); - virtual void forward_draw_over_viewport(Control *p_overlay); - virtual void forward_force_draw_over_viewport(Control *p_overlay); + virtual void forward_canvas_draw_over_viewport(Control *p_overlay); + virtual void forward_canvas_force_draw_over_viewport(Control *p_overlay); + virtual bool forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event); + virtual void forward_spatial_draw_over_viewport(Control *p_overlay); + virtual void forward_spatial_force_draw_over_viewport(Control *p_overlay); + virtual String get_name() const; virtual const Ref<Texture> get_icon() const; virtual bool has_main_screen() const; diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 3439133809..c5c78b2590 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -108,6 +108,7 @@ void EditorPropertyMultilineText::_open_big_text() { if (!big_text_dialog) { big_text = memnew(TextEdit); big_text->connect("text_changed", this, "_big_text_changed"); + big_text->set_wrap_enabled(true); big_text_dialog = memnew(AcceptDialog); big_text_dialog->add_child(big_text); big_text_dialog->set_title("Edit Text:"); @@ -152,6 +153,7 @@ EditorPropertyMultilineText::EditorPropertyMultilineText() { set_bottom_editor(hb); text = memnew(TextEdit); text->connect("text_changed", this, "_text_changed"); + text->set_wrap_enabled(true); add_focusable(text); hb->add_child(text); text->set_h_size_flags(SIZE_EXPAND_FILL); @@ -817,10 +819,10 @@ void EditorPropertyInteger::_bind_methods() { ClassDB::bind_method(D_METHOD("_value_changed"), &EditorPropertyInteger::_value_changed); } -void EditorPropertyInteger::setup(int p_min, int p_max, bool p_allow_greater, bool p_allow_lesser) { +void EditorPropertyInteger::setup(int p_min, int p_max, int p_step, bool p_allow_greater, bool p_allow_lesser) { spin->set_min(p_min); spin->set_max(p_max); - spin->set_step(1); + spin->set_step(p_step); spin->set_allow_greater(p_allow_greater); spin->set_allow_lesser(p_allow_lesser); } @@ -1183,21 +1185,39 @@ void EditorPropertyRect2::setup(double p_min, double p_max, double p_step, bool } EditorPropertyRect2::EditorPropertyRect2() { - VBoxContainer *vb = memnew(VBoxContainer); - add_child(vb); + + bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing"); + + BoxContainer *bc; + + if (horizontal) { + bc = memnew(HBoxContainer); + add_child(bc); + set_bottom_editor(bc); + } else { + bc = memnew(VBoxContainer); + add_child(bc); + } + static const char *desc[4] = { "x", "y", "w", "h" }; for (int i = 0; i < 4; i++) { spin[i] = memnew(EditorSpinSlider); spin[i]->set_label(desc[i]); spin[i]->set_flat(true); - - vb->add_child(spin[i]); + bc->add_child(spin[i]); add_focusable(spin[i]); spin[i]->connect("value_changed", this, "_value_changed"); + if (horizontal) { + spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); + } + } + + if (!horizontal) { + set_label_reference(spin[0]); //show text and buttons around this } - set_label_reference(spin[0]); //show text and buttons around this setting = false; } + ///////////////////// VECTOR3 ///////////////////////// void EditorPropertyVector3::_value_changed(double val) { @@ -1245,7 +1265,7 @@ void EditorPropertyVector3::setup(double p_min, double p_max, double p_step, boo } EditorPropertyVector3::EditorPropertyVector3() { - bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector3_editing"); + bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing"); BoxContainer *bc; @@ -1326,7 +1346,7 @@ void EditorPropertyPlane::setup(double p_min, double p_max, double p_step, bool EditorPropertyPlane::EditorPropertyPlane() { - bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector3_editing"); + bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing"); BoxContainer *bc; @@ -1407,7 +1427,7 @@ void EditorPropertyQuat::setup(double p_min, double p_max, double p_step, bool p } EditorPropertyQuat::EditorPropertyQuat() { - bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector3_editing"); + bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing"); BoxContainer *bc; @@ -1759,7 +1779,7 @@ void EditorPropertyColor::_color_changed(const Color &p_color) { void EditorPropertyColor::_popup_closed() { - emit_signal("property_changed", get_edited_property(), picker->get_pick_color(), false); + emit_signal("property_changed", get_edited_property(), picker->get_pick_color(), true); } void EditorPropertyColor::_bind_methods() { @@ -2636,7 +2656,7 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ } else if (p_hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || p_hint == PROPERTY_HINT_LAYERS_2D_RENDER || p_hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || p_hint == PROPERTY_HINT_LAYERS_3D_RENDER) { - EditorPropertyLayers::LayerType lt; + EditorPropertyLayers::LayerType lt = EditorPropertyLayers::LAYER_RENDER_2D; switch (p_hint) { case PROPERTY_HINT_LAYERS_2D_RENDER: lt = EditorPropertyLayers::LAYER_RENDER_2D; @@ -2663,7 +2683,7 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ } else { EditorPropertyInteger *editor = memnew(EditorPropertyInteger); - int min = 0, max = 65535; + int min = 0, max = 65535, step = 1; bool greater = true, lesser = true; if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) { @@ -2671,6 +2691,11 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ lesser = false; min = p_hint_text.get_slice(",", 0).to_int(); max = p_hint_text.get_slice(",", 1).to_int(); + + if (p_hint_text.get_slice_count(",") >= 3) { + step = p_hint_text.get_slice(",", 2).to_int(); + } + for (int i = 2; i < p_hint_text.get_slice_count(","); i++) { String slice = p_hint_text.get_slice(",", i).strip_edges(); if (slice == "or_greater") { @@ -2682,7 +2707,7 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ } } - editor->setup(min, max, greater, lesser); + editor->setup(min, max, step, greater, lesser); add_property_editor(p_path, editor); } diff --git a/editor/editor_properties.h b/editor/editor_properties.h index cfc433b880..18e70345aa 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -265,7 +265,7 @@ protected: public: virtual void update_property(); - void setup(int p_min, int p_max, bool p_allow_greater, bool p_allow_lesser); + void setup(int p_min, int p_max, int p_step, bool p_allow_greater, bool p_allow_lesser); EditorPropertyInteger(); }; diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index 808a8ac2f8..24360813a2 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -337,7 +337,7 @@ void EditorPropertyArray::update_property() { } break; case Variant::INT: { EditorPropertyInteger *editor = memnew(EditorPropertyInteger); - editor->setup(-100000, 100000, true, true); + editor->setup(-100000, 100000, 1, true, true); prop = editor; } break; @@ -744,7 +744,7 @@ void EditorPropertyDictionary::update_property() { page->connect("value_changed", this, "_page_changed"); } else { // Queue childs for deletion, delete immediately might cause errors. - for (size_t i = 1; i < vbox->get_child_count(); i++) { + for (int i = 1; i < vbox->get_child_count(); i++) { vbox->get_child(i)->queue_delete(); } } @@ -800,7 +800,7 @@ void EditorPropertyDictionary::update_property() { } break; case Variant::INT: { EditorPropertyInteger *editor = memnew(EditorPropertyInteger); - editor->setup(-100000, 100000, true, true); + editor->setup(-100000, 100000, 1, true, true); prop = editor; } break; @@ -969,7 +969,7 @@ void EditorPropertyDictionary::update_property() { pc->add_child(add_vbox); } prop->set_object_and_property(object.ptr(), prop_name); - int change_index; + int change_index = 0; if (i < amount) { String cs = key.get_construct_string(); diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index edfee595ea..310c3b3a52 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -30,11 +30,14 @@ #include "editor_resource_preview.h" +#include "core/method_bind_ext.gen.inc" + #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" #include "core/message_queue.h" #include "core/os/file_access.h" #include "core/project_settings.h" +#include "editor_node.h" #include "editor_scale.h" #include "editor_settings.h" @@ -46,32 +49,37 @@ bool EditorResourcePreviewGenerator::handles(const String &p_type) const { ERR_EXPLAIN("EditorResourcePreviewGenerator::handles needs to be overridden"); ERR_FAIL_V(false); } -Ref<Texture> EditorResourcePreviewGenerator::generate(const RES &p_from) const { + +Ref<Texture> EditorResourcePreviewGenerator::generate(const RES &p_from, const Size2 p_size) const { if (get_script_instance() && get_script_instance()->has_method("generate")) { - return get_script_instance()->call("generate", p_from); + return get_script_instance()->call("generate", p_from, p_size); } ERR_EXPLAIN("EditorResourcePreviewGenerator::generate needs to be overridden"); ERR_FAIL_V(Ref<Texture>()); } -Ref<Texture> EditorResourcePreviewGenerator::generate_from_path(const String &p_path) const { +Ref<Texture> EditorResourcePreviewGenerator::generate_from_path(const String &p_path, const Size2 p_size) const { if (get_script_instance() && get_script_instance()->has_method("generate_from_path")) { - return get_script_instance()->call("generate_from_path", p_path); + return get_script_instance()->call("generate_from_path", p_path, p_size); } RES res = ResourceLoader::load(p_path); if (!res.is_valid()) return res; - return generate(res); + return generate(res, p_size); +} + +bool EditorResourcePreviewGenerator::should_generate_small_preview() const { + return false; } void EditorResourcePreviewGenerator::_bind_methods() { ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "handles", PropertyInfo(Variant::STRING, "type"))); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(CLASS_INFO(Texture), "generate", PropertyInfo(Variant::OBJECT, "from", PROPERTY_HINT_RESOURCE_TYPE, "Resource"))); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(CLASS_INFO(Texture), "generate_from_path", PropertyInfo(Variant::STRING, "path", PROPERTY_HINT_FILE))); + ClassDB::add_virtual_method(get_class_static(), MethodInfo(CLASS_INFO(Texture), "generate", PropertyInfo(Variant::OBJECT, "from", PROPERTY_HINT_RESOURCE_TYPE, "Resource"), PropertyInfo(Variant::VECTOR2, "size"))); + ClassDB::add_virtual_method(get_class_static(), MethodInfo(CLASS_INFO(Texture), "generate_from_path", PropertyInfo(Variant::STRING, "path", PROPERTY_HINT_FILE), PropertyInfo(Variant::VECTOR2, "size"))); } EditorResourcePreviewGenerator::EditorResourcePreviewGenerator() { @@ -85,7 +93,7 @@ void EditorResourcePreview::_thread_func(void *ud) { erp->_thread(); } -void EditorResourcePreview::_preview_ready(const String &p_str, const Ref<Texture> &p_texture, ObjectID id, const StringName &p_func, const Variant &p_ud) { +void EditorResourcePreview::_preview_ready(const String &p_str, const Ref<Texture> &p_texture, const Ref<Texture> &p_small_texture, ObjectID id, const StringName &p_func, const Variant &p_ud) { preview_mutex->lock(); @@ -103,6 +111,7 @@ void EditorResourcePreview::_preview_ready(const String &p_str, const Ref<Textur Item item; item.order = order++; item.preview = p_texture; + item.small_preview = p_small_texture; item.last_hash = hash; item.modified_time = modified_time; @@ -110,11 +119,10 @@ void EditorResourcePreview::_preview_ready(const String &p_str, const Ref<Textur preview_mutex->unlock(); - MessageQueue::get_singleton()->push_call(id, p_func, path, p_texture, p_ud); + MessageQueue::get_singleton()->push_call(id, p_func, path, p_texture, p_small_texture, p_ud); } -Ref<Texture> EditorResourcePreview::_generate_preview(const QueueItem &p_item, const String &cache_base) { - +void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<ImageTexture> &r_small_texture, const QueueItem &p_item, const String &cache_base) { String type; if (p_item.resource.is_valid()) @@ -122,40 +130,59 @@ Ref<Texture> EditorResourcePreview::_generate_preview(const QueueItem &p_item, c else type = ResourceLoader::get_resource_type(p_item.path); - if (type == "") - return Ref<Texture>(); //could not guess type + if (type == "") { + r_texture = Ref<ImageTexture>(); + r_small_texture = Ref<ImageTexture>(); + return; //could not guess type + } - Ref<Texture> generated; + int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); + thumbnail_size *= EDSCALE; - for (int i = 0; i < preview_generators.size(); i++) { + r_texture = Ref<ImageTexture>(); + r_small_texture = Ref<ImageTexture>(); + for (int i = 0; i < preview_generators.size(); i++) { if (!preview_generators[i]->handles(type)) continue; + + Ref<Texture> generated; if (p_item.resource.is_valid()) { - generated = preview_generators[i]->generate(p_item.resource); + generated = preview_generators[i]->generate(p_item.resource, Vector2(thumbnail_size, thumbnail_size)); } else { - generated = preview_generators[i]->generate_from_path(p_item.path); + generated = preview_generators[i]->generate_from_path(p_item.path, Vector2(thumbnail_size, thumbnail_size)); } + r_texture = generated; + if (r_texture.is_valid() && preview_generators[i]->should_generate_small_preview()) { + int small_thumbnail_size = EditorNode::get_singleton()->get_theme_base()->get_icon("Object", "EditorIcons")->get_width(); // Kind of a workaround to retreive the default icon size + small_thumbnail_size *= EDSCALE; + + Ref<Image> small_image = r_texture->get_data(); + small_image->resize(small_thumbnail_size, small_thumbnail_size, Image::INTERPOLATE_CUBIC); + r_small_texture.instance(); + r_small_texture->create_from_image(small_image); + } break; } if (!p_item.resource.is_valid()) { // cache the preview in case it's a resource on disk - if (generated.is_valid()) { - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; + if (r_texture.is_valid()) { //wow it generated a preview... save cache - ResourceSaver::save(cache_base + ".png", generated); + bool has_small_texture = r_small_texture.is_valid(); + ResourceSaver::save(cache_base + ".png", r_texture); + if (has_small_texture) { + ResourceSaver::save(cache_base + "_small.png", r_small_texture); + } FileAccess *f = FileAccess::open(cache_base + ".txt", FileAccess::WRITE); f->store_line(itos(thumbnail_size)); + f->store_line(itos(has_small_texture)); f->store_line(itos(FileAccess::get_modified_time(p_item.path))); f->store_line(FileAccess::get_md5(p_item.path)); memdelete(f); } } - - return generated; } void EditorResourcePreview::_thread() { @@ -177,7 +204,7 @@ void EditorResourcePreview::_thread() { path += ":" + itos(cache[item.path].last_hash); //keep last hash (see description of what this is in condition below) } - _preview_ready(path, cache[item.path].preview, item.id, item.function, item.userdata); + _preview_ready(path, cache[item.path].preview, cache[item.path].small_preview, item.id, item.function, item.userdata); preview_mutex->unlock(); } else { @@ -185,15 +212,17 @@ void EditorResourcePreview::_thread() { preview_mutex->unlock(); Ref<ImageTexture> texture; + Ref<ImageTexture> small_texture; int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); thumbnail_size *= EDSCALE; if (item.resource.is_valid()) { - texture = _generate_preview(item, String()); + _generate_preview(texture, small_texture, item, String()); + //adding hash to the end of path (should be ID:<objid>:<hash>) because of 5 argument limit to call_deferred - _preview_ready(item.path + ":" + itos(item.resource->hash_edited_version()), texture, item.id, item.function, item.userdata); + _preview_ready(item.path + ":" + itos(item.resource->hash_edited_version()), texture, small_texture, item.id, item.function, item.userdata); } else { @@ -207,12 +236,13 @@ void EditorResourcePreview::_thread() { FileAccess *f = FileAccess::open(file, FileAccess::READ); if (!f) { - //generate - texture = _generate_preview(item, cache_base); + // No cache found, generate + _generate_preview(texture, small_texture, item, cache_base); } else { uint64_t modtime = FileAccess::get_modified_time(item.path); int tsize = f->get_line().to_int64(); + bool has_small_texture = f->get_line().to_int(); uint64_t last_modtime = f->get_line().to_int64(); bool cache_valid = true; @@ -236,6 +266,7 @@ void EditorResourcePreview::_thread() { f = FileAccess::open(file, FileAccess::WRITE); f->store_line(itos(modtime)); + f->store_line(itos(has_small_texture)); f->store_line(md5); memdelete(f); } @@ -243,12 +274,12 @@ void EditorResourcePreview::_thread() { memdelete(f); } - //cache_valid = false; - if (cache_valid) { Ref<Image> img; img.instance(); + Ref<Image> small_img; + small_img.instance(); if (img->load(cache_base + ".png") != OK) { cache_valid = false; @@ -256,16 +287,24 @@ void EditorResourcePreview::_thread() { texture.instance(); texture->create_from_image(img, Texture::FLAG_FILTER); + + if (has_small_texture) { + if (small_img->load(cache_base + "_small.png") != OK) { + cache_valid = false; + } else { + small_texture.instance(); + small_texture->create_from_image(small_img, Texture::FLAG_FILTER); + } + } } } if (!cache_valid) { - texture = _generate_preview(item, cache_base); + _generate_preview(texture, small_texture, item, cache_base); } } - - _preview_ready(item.path, texture, item.id, item.function, item.userdata); + _preview_ready(item.path, texture, small_texture, item.id, item.function, item.userdata); } } @@ -287,7 +326,7 @@ void EditorResourcePreview::queue_edited_resource_preview(const Ref<Resource> &p if (cache.has(path_id) && cache[path_id].last_hash == p_res->hash_edited_version()) { cache[path_id].order = order++; - p_receiver->call_deferred(p_receiver_func, path_id, cache[path_id].preview, p_userdata); + p_receiver->call_deferred(p_receiver_func, path_id, cache[path_id].preview, cache[path_id].small_preview, p_userdata); preview_mutex->unlock(); return; } @@ -312,7 +351,7 @@ void EditorResourcePreview::queue_resource_preview(const String &p_path, Object preview_mutex->lock(); if (cache.has(p_path)) { cache[p_path].order = order++; - p_receiver->call_deferred(p_receiver_func, p_path, cache[p_path].preview, p_userdata); + p_receiver->call_deferred(p_receiver_func, p_path, cache[p_path].preview, cache[p_path].small_preview, p_userdata); preview_mutex->unlock(); return; } diff --git a/editor/editor_resource_preview.h b/editor/editor_resource_preview.h index 434b26e901..a3417cdf60 100644 --- a/editor/editor_resource_preview.h +++ b/editor/editor_resource_preview.h @@ -63,8 +63,10 @@ protected: public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; - virtual Ref<Texture> generate_from_path(const String &p_path) const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; + virtual Ref<Texture> generate_from_path(const String &p_path, const Size2 p_size) const; + + virtual bool should_generate_small_preview() const; EditorResourcePreviewGenerator(); }; @@ -92,6 +94,7 @@ class EditorResourcePreview : public Node { struct Item { Ref<Texture> preview; + Ref<Texture> small_preview; int order; uint32_t last_hash; uint64_t modified_time; @@ -101,8 +104,8 @@ class EditorResourcePreview : public Node { Map<String, Item> cache; - void _preview_ready(const String &p_str, const Ref<Texture> &p_texture, ObjectID id, const StringName &p_func, const Variant &p_ud); - Ref<Texture> _generate_preview(const QueueItem &p_item, const String &cache_base); + void _preview_ready(const String &p_str, const Ref<Texture> &p_texture, const Ref<Texture> &p_small_texture, ObjectID id, const StringName &p_func, const Variant &p_ud); + void _generate_preview(Ref<ImageTexture> &r_texture, Ref<ImageTexture> &r_small_texture, const QueueItem &p_item, const String &cache_base); static void _thread_func(void *ud); void _thread(); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 3e959731fc..2dec21fffb 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -485,6 +485,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("editors/2d/bone_outline_color", Color(0.35, 0.35, 0.35)); _initial_set("editors/2d/bone_outline_size", 2); _initial_set("editors/2d/keep_margins_when_changing_anchors", false); + _initial_set("editors/2d/viewport_border_color", Color(0.4, 0.4, 1.0, 0.4)); _initial_set("editors/2d/warped_mouse_panning", true); _initial_set("editors/2d/simple_spacebar_panning", false); _initial_set("editors/2d/scroll_to_pan", false); @@ -511,17 +512,16 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("filesystem/file_dialog/show_hidden_files", false); _initial_set("filesystem/file_dialog/display_mode", 0); hints["filesystem/file_dialog/display_mode"] = PropertyInfo(Variant::INT, "filesystem/file_dialog/display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List"); + _initial_set("filesystem/file_dialog/thumbnail_size", 64); hints["filesystem/file_dialog/thumbnail_size"] = PropertyInfo(Variant::INT, "filesystem/file_dialog/thumbnail_size", PROPERTY_HINT_RANGE, "32,128,16"); - _initial_set("docks/filesystem/disable_split", false); - _initial_set("docks/filesystem/split_mode_minimum_height", 600); _initial_set("docks/filesystem/display_mode", 0); - hints["docks/filesystem/display_mode"] = PropertyInfo(Variant::INT, "docks/filesystem/display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List"); + hints["docks/filesystem/display_mode"] = PropertyInfo(Variant::INT, "docks/filesystem/display_mode", PROPERTY_HINT_ENUM, "Tree only, Split"); _initial_set("docks/filesystem/thumbnail_size", 64); hints["docks/filesystem/thumbnail_size"] = PropertyInfo(Variant::INT, "docks/filesystem/thumbnail_size", PROPERTY_HINT_RANGE, "32,128,16"); - _initial_set("docks/filesystem/display_mode", 0); - hints["docks/filesystem/display_mode"] = PropertyInfo(Variant::INT, "docks/filesystem/display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List"); + _initial_set("docks/filesystem/files_display_mode", 0); + hints["docks/filesystem/files_display_mode"] = PropertyInfo(Variant::INT, "docks/filesystem/files_display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List"); _initial_set("docks/filesystem/always_show_folders", true); _initial_set("editors/animation/autorename_animation_tracks", true); @@ -1152,20 +1152,20 @@ Variant EditorSettings::get_project_metadata(const String &p_section, const Stri return cf->get_value(p_section, p_key, p_default); } -void EditorSettings::set_favorite_dirs(const Vector<String> &p_favorites_dirs) { +void EditorSettings::set_favorites(const Vector<String> &p_favorites) { - favorite_dirs = p_favorites_dirs; - FileAccess *f = FileAccess::open(get_project_settings_dir().plus_file("favorite_dirs"), FileAccess::WRITE); + favorites = p_favorites; + FileAccess *f = FileAccess::open(get_project_settings_dir().plus_file("favorites"), FileAccess::WRITE); if (f) { - for (int i = 0; i < favorite_dirs.size(); i++) - f->store_line(favorite_dirs[i]); + for (int i = 0; i < favorites.size(); i++) + f->store_line(favorites[i]); memdelete(f); } } -Vector<String> EditorSettings::get_favorite_dirs() const { +Vector<String> EditorSettings::get_favorites() const { - return favorite_dirs; + return favorites; } void EditorSettings::set_recent_dirs(const Vector<String> &p_recent_dirs) { @@ -1186,11 +1186,11 @@ Vector<String> EditorSettings::get_recent_dirs() const { void EditorSettings::load_favorites() { - FileAccess *f = FileAccess::open(get_project_settings_dir().plus_file("favorite_dirs"), FileAccess::READ); + FileAccess *f = FileAccess::open(get_project_settings_dir().plus_file("favorites"), FileAccess::READ); if (f) { String line = f->get_line().strip_edges(); while (line != "") { - favorite_dirs.push_back(line); + favorites.push_back(line); line = f->get_line().strip_edges(); } memdelete(f); @@ -1217,18 +1217,25 @@ bool EditorSettings::is_dark_theme() { void EditorSettings::list_text_editor_themes() { String themes = "Adaptive,Default,Custom"; + DirAccess *d = DirAccess::open(get_text_editor_themes_dir()); if (d) { + List<String> custom_themes; d->list_dir_begin(); String file = d->get_next(); while (file != String()) { if (file.get_extension() == "tet" && file.get_basename().to_lower() != "default" && file.get_basename().to_lower() != "adaptive" && file.get_basename().to_lower() != "custom") { - themes += "," + file.get_basename(); + custom_themes.push_back(file.get_basename()); } file = d->get_next(); } d->list_dir_end(); memdelete(d); + + custom_themes.sort(); + for (List<String>::Element *E = custom_themes.front(); E; E = E->next()) { + themes += "," + E->get(); + } } add_property_hint(PropertyInfo(Variant::STRING, "text_editor/theme/color_theme", PROPERTY_HINT_ENUM, themes)); } @@ -1471,8 +1478,8 @@ void EditorSettings::_bind_methods() { ClassDB::bind_method(D_METHOD("set_project_metadata", "section", "key", "data"), &EditorSettings::set_project_metadata); ClassDB::bind_method(D_METHOD("get_project_metadata", "section", "key", "default"), &EditorSettings::get_project_metadata, DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("set_favorite_dirs", "dirs"), &EditorSettings::set_favorite_dirs); - ClassDB::bind_method(D_METHOD("get_favorite_dirs"), &EditorSettings::get_favorite_dirs); + ClassDB::bind_method(D_METHOD("set_favorites", "dirs"), &EditorSettings::set_favorites); + ClassDB::bind_method(D_METHOD("get_favorites"), &EditorSettings::get_favorites); ClassDB::bind_method(D_METHOD("set_recent_dirs", "dirs"), &EditorSettings::set_recent_dirs); ClassDB::bind_method(D_METHOD("get_recent_dirs"), &EditorSettings::get_recent_dirs); diff --git a/editor/editor_settings.h b/editor/editor_settings.h index 8165c36e67..7b0de9617c 100644 --- a/editor/editor_settings.h +++ b/editor/editor_settings.h @@ -107,7 +107,7 @@ private: String config_file_path; String project_config_dir; - Vector<String> favorite_dirs; + Vector<String> favorites; Vector<String> recent_dirs; bool save_changed_setting; @@ -173,8 +173,8 @@ public: void set_project_metadata(const String &p_section, const String &p_key, Variant p_data); Variant get_project_metadata(const String &p_section, const String &p_key, Variant p_default) const; - void set_favorite_dirs(const Vector<String> &p_favorites_dirs); - Vector<String> get_favorite_dirs() const; + void set_favorites(const Vector<String> &p_favorites); + Vector<String> get_favorites() const; void set_recent_dirs(const Vector<String> &p_recent_dirs); Vector<String> get_recent_dirs() const; void load_favorites(); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 7ed7b920d9..9e81051dc2 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -36,7 +36,6 @@ #include "editor_scale.h" #include "editor_settings.h" #include "modules/svg/image_loader_svg.h" -#include "time.h" static Ref<StyleBoxTexture> make_stylebox(Ref<Texture> p_texture, float p_left, float p_top, float p_right, float p_botton, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_botton = -1, bool p_draw_center = true) { Ref<StyleBoxTexture> style(memnew(StyleBoxTexture)); @@ -82,12 +81,6 @@ static Ref<StyleBoxLine> make_line_stylebox(Color p_color, int p_thickness = 1, return style; } -static Ref<StyleBoxFlat> change_border_color(Ref<StyleBoxFlat> p_style, Color p_color) { - Ref<StyleBoxFlat> style = p_style->duplicate(); - style->set_border_color_all(p_color); - return style; -} - Ref<ImageTexture> editor_generate_icon(int p_index, bool p_convert_color, float p_scale = EDSCALE, bool p_force_filter = false) { Ref<ImageTexture> icon = memnew(ImageTexture); @@ -199,8 +192,6 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = exceptions.push_back("StatusWarning"); exceptions.push_back("NodeWarning"); - clock_t begin_time = clock(); - ImageLoaderSVG::set_convert_colors(&dark_icon_color_dictionary); // generate icons @@ -235,8 +226,6 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = } ImageLoaderSVG::set_convert_colors(NULL); - - clock_t end_time = clock(); #else print_line("SVG support disabled, editor icons won't be rendered."); #endif @@ -260,8 +249,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { bool use_gn_headers = EDITOR_DEF("interface/theme/use_graph_node_headers", false); - Color script_bg_color = EDITOR_DEF("text_editor/highlighting/background_color", Color(0, 0, 0, 0)); - Color preset_accent_color; Color preset_base_color; float preset_contrast; @@ -491,8 +478,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { style_tab_selected->set_bg_color(tab_color); Ref<StyleBoxFlat> style_tab_unselected = style_tab_selected->duplicate(); - style_tab_unselected->set_draw_center(false); - style_tab_unselected->set_border_width_all(0); + style_tab_unselected->set_bg_color(dark_color_1); + style_tab_unselected->set_border_color_all(dark_color_2); // Editor background theme->set_stylebox("Background", "EditorStyles", make_flat_stylebox(background_color, default_margin_size, default_margin_size, default_margin_size, default_margin_size)); @@ -945,6 +932,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // TooltipPanel Ref<StyleBoxFlat> style_tooltip = style_popup->duplicate(); + float v = MAX(border_size * EDSCALE, 1.0); + style_tooltip->set_default_margin(MARGIN_LEFT, v); + style_tooltip->set_default_margin(MARGIN_TOP, v); + style_tooltip->set_default_margin(MARGIN_RIGHT, v); + style_tooltip->set_default_margin(MARGIN_BOTTOM, v); style_tooltip->set_bg_color(Color(mono_color.r, mono_color.g, mono_color.b, 0.9)); style_tooltip->set_border_width_all(border_width); style_tooltip->set_border_color_all(mono_color); @@ -1064,8 +1056,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const float mono_value = mono_color.r; const Color alpha1 = Color(mono_value, mono_value, mono_value, 0.07); const Color alpha2 = Color(mono_value, mono_value, mono_value, 0.14); - const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.5); - const Color alpha4 = Color(mono_value, mono_value, mono_value, 0.7); + const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.7); // editor main color const Color main_color = Color::html(dark_theme ? "#57b3ff" : "#0480ff"); @@ -1099,9 +1090,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const Color member_variable_color = main_color.linear_interpolate(mono_color, 0.6); const Color mark_color = Color(error_color.r, error_color.g, error_color.b, 0.3); const Color breakpoint_color = error_color; - const Color code_folding_color = alpha4; + const Color code_folding_color = alpha3; const Color search_result_color = alpha1; - const Color search_result_border_color = alpha4; + const Color search_result_border_color = alpha3; EditorSettings *setting = EditorSettings::get_singleton(); String text_editor_color_theme = setting->get("text_editor/theme/color_theme"); diff --git a/editor/fileserver/SCsub b/editor/fileserver/SCsub index f1fa50148f..2b1e889fb0 100644 --- a/editor/fileserver/SCsub +++ b/editor/fileserver/SCsub @@ -1,5 +1,5 @@ #!/usr/bin/env python Import('env') -Export('env') + env.add_source_files(env.editor_sources, "*.cpp") diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 3a55966e7b..2c69909f23 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -40,52 +40,103 @@ #include "editor_settings.h" #include "scene/main/viewport.h" +Ref<Texture> FileSystemDock::_get_tree_item_icon(EditorFileSystemDirectory *p_dir, int p_idx) { + Ref<Texture> file_icon; + if (!p_dir->get_file_import_is_valid(p_idx)) { + file_icon = get_icon("ImportFail", "EditorIcons"); + } else { + String file_type = p_dir->get_file_type(p_idx); + file_icon = (has_icon(file_type, "EditorIcons")) ? get_icon(file_type, "EditorIcons") : get_icon("File", "EditorIcons"); + } + return file_icon; +} + bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths) { - TreeItem *item = tree->create_item(p_parent); + bool parent_should_expand = false; + + // Create a tree item for the subdirectory + TreeItem *subdirectory_item = tree->create_item(p_parent); String dname = p_dir->get_name(); if (dname == "") dname = "res://"; - item->set_text(0, dname); - item->set_icon(0, get_icon("Folder", "EditorIcons")); - item->set_selectable(0, true); + subdirectory_item->set_text(0, dname); + subdirectory_item->set_icon(0, get_icon("Folder", "EditorIcons")); + subdirectory_item->set_selectable(0, true); String lpath = p_dir->get_path(); - if (lpath != "res://" && lpath.ends_with("/")) { - lpath = lpath.substr(0, lpath.length() - 1); - } - item->set_metadata(0, lpath); - if (lpath == path) { - item->select(0); + subdirectory_item->set_metadata(0, lpath); + if (path == lpath || ((display_mode_setting == DISPLAY_MODE_SETTING_SPLIT) && path.get_base_dir() == lpath)) { + subdirectory_item->select(0); } if ((path.begins_with(lpath) && path != lpath)) { - item->set_collapsed(false); + subdirectory_item->set_collapsed(false); } else { - bool is_collapsed = true; - for (int i = 0; i < uncollapsed_paths.size(); i++) { - if (lpath == uncollapsed_paths[i]) { - is_collapsed = false; - break; + subdirectory_item->set_collapsed(uncollapsed_paths.find(lpath) < 0); + } + if (searched_string.length() > 0 && dname.to_lower().find(searched_string) >= 0) { + parent_should_expand = true; + } + + // Create items for all subdirectories + for (int i = 0; i < p_dir->get_subdir_count(); i++) + parent_should_expand = (_create_tree(subdirectory_item, p_dir->get_subdir(i), uncollapsed_paths) || parent_should_expand); + + // Create all items for the files in the subdirectory + if (display_mode_setting == DISPLAY_MODE_SETTING_TREE_ONLY) { + for (int i = 0; i < p_dir->get_file_count(); i++) { + String file_name = p_dir->get_file(i); + + if (searched_string.length() > 0) { + if (file_name.to_lower().find(searched_string) < 0) { + // The seached string is not in the file name, we skip it + continue; + } else { + // We expand all parents + parent_should_expand = true; + } + } + + TreeItem *file_item = tree->create_item(subdirectory_item); + file_item->set_text(0, file_name); + file_item->set_icon(0, _get_tree_item_icon(p_dir, i)); + String file_metadata = lpath.plus_file(file_name); + file_item->set_metadata(0, file_metadata); + if (path == file_metadata) { + file_item->select(0); + file_item->set_as_cursor(0); } + Array udata; + udata.push_back(tree_update_id); + udata.push_back(file_item); + EditorResourcePreview::get_singleton()->queue_resource_preview(file_metadata, this, "_tree_thumbnail_done", udata); } - item->set_collapsed(is_collapsed); } - for (int i = 0; i < p_dir->get_subdir_count(); i++) - _create_tree(item, p_dir->get_subdir(i), uncollapsed_paths); + if (searched_string.length() > 0) { + if (parent_should_expand) { + subdirectory_item->set_collapsed(false); + } else if (dname != "res://") { + subdirectory_item->get_parent()->remove_child(subdirectory_item); + } + } - return true; + return parent_should_expand; } -void FileSystemDock::_update_tree(bool keep_collapse_state, bool p_uncollapse_root) { - +Vector<String> FileSystemDock::_compute_uncollapsed_paths() { + // Register currently collapsed paths Vector<String> uncollapsed_paths; - if (keep_collapse_state) { - TreeItem *root = tree->get_root(); - if (root) { - TreeItem *resTree = root->get_children()->get_next(); + TreeItem *root = tree->get_root(); + if (root) { + TreeItem *favorites_item = root->get_children(); + if (!favorites_item->is_collapsed()) { + uncollapsed_paths.push_back(favorites_item->get_metadata(0)); + } + TreeItem *resTree = root->get_children()->get_next(); + if (resTree) { Vector<TreeItem *> needs_check; needs_check.push_back(resTree); @@ -102,84 +153,126 @@ void FileSystemDock::_update_tree(bool keep_collapse_state, bool p_uncollapse_ro } } } + return uncollapsed_paths; +} + +void FileSystemDock::_update_tree(const Vector<String> p_uncollapsed_paths, bool p_uncollapse_root) { + // Recreate the tree tree->clear(); + tree_update_id++; updating_tree = true; - TreeItem *root = tree->create_item(); + + // Handles the favorites TreeItem *favorites = tree->create_item(root); favorites->set_icon(0, get_icon("Favorites", "EditorIcons")); favorites->set_text(0, TTR("Favorites:")); - favorites->set_selectable(0, false); + favorites->set_metadata(0, "Favorites"); + favorites->set_collapsed(p_uncollapsed_paths.find("Favorites") < 0); - Vector<String> favorite_paths = EditorSettings::get_singleton()->get_favorite_dirs(); - String res_path = "res://"; - Ref<Texture> folder_icon = get_icon("Folder", "EditorIcons"); + Vector<String> favorite_paths = EditorSettings::get_singleton()->get_favorites(); for (int i = 0; i < favorite_paths.size(); i++) { String fave = favorite_paths[i]; - if (!fave.begins_with(res_path)) + if (!fave.begins_with("res://")) continue; - TreeItem *ti = tree->create_item(favorites); - if (fave == res_path) - ti->set_text(0, "/"); - else - ti->set_text(0, fave.get_file()); - ti->set_icon(0, folder_icon); - ti->set_selectable(0, true); - ti->set_metadata(0, fave); + Ref<Texture> folder_icon = get_icon("Folder", "EditorIcons"); + + String text; + Ref<Texture> icon; + if (fave == "res://") { + text = "/"; + icon = folder_icon; + } else if (fave.ends_with("/")) { + text = fave.substr(0, fave.length() - 1).get_file(); + icon = folder_icon; + } else { + text = fave.get_file(); + int index; + EditorFileSystemDirectory *dir = EditorFileSystem::get_singleton()->find_file(fave, &index); + if (dir) { + icon = _get_tree_item_icon(dir, index); + } else { + icon = get_icon("File", "EditorIcons"); + } + } + + if (searched_string.length() == 0 || text.to_lower().find(searched_string) >= 0) { + TreeItem *ti = tree->create_item(favorites); + ti->set_text(0, text); + ti->set_icon(0, icon); + ti->set_tooltip(0, fave); + ti->set_selectable(0, true); + ti->set_metadata(0, fave); + if (!fave.ends_with("/")) { + Array udata; + udata.push_back(tree_update_id); + udata.push_back(ti); + EditorResourcePreview::get_singleton()->queue_resource_preview(fave, this, "_tree_thumbnail_done", udata); + } + } } + Vector<String> uncollapsed_paths = p_uncollapsed_paths; if (p_uncollapse_root) { uncollapsed_paths.push_back("res://"); } + // Create the remaining of the tree _create_tree(root, EditorFileSystem::get_singleton()->get_filesystem(), uncollapsed_paths); tree->ensure_cursor_is_visible(); updating_tree = false; } void FileSystemDock::_update_display_mode() { - - bool disable_split = bool(EditorSettings::get_singleton()->get("docks/filesystem/disable_split")); - bool compact_mode = get_size().height < int(EditorSettings::get_singleton()->get("docks/filesystem/split_mode_minimum_height")); - DisplayMode new_mode; - if (disable_split || compact_mode) { - new_mode = file_list_view ? DISPLAY_FILE_LIST_ONLY : DISPLAY_TREE_ONLY; + // Compute the new display mode + DisplayMode new_display_mode; + if (display_mode_setting == DISPLAY_MODE_SETTING_TREE_ONLY) { + new_display_mode = file_list_view ? DISPLAY_MODE_FILE_LIST_ONLY : DISPLAY_MODE_TREE_ONLY; } else { - new_mode = DISPLAY_SPLIT; + new_display_mode = DISPLAY_MODE_SPLIT; } - if (new_mode != display_mode) { - switch (new_mode) { - case DISPLAY_TREE_ONLY: + if (new_display_mode != display_mode || old_display_mode_setting != display_mode_setting) { + display_mode = new_display_mode; + old_display_mode_setting = display_mode_setting; + button_toggle_display_mode->set_pressed(display_mode_setting == DISPLAY_MODE_SETTING_SPLIT ? true : false); + switch (display_mode) { + case DISPLAY_MODE_TREE_ONLY: tree->show(); tree->set_v_size_flags(SIZE_EXPAND_FILL); - _update_tree(true); + if (display_mode_setting == DISPLAY_MODE_SETTING_TREE_ONLY) { + tree_search_box->show(); + } else { + tree_search_box->hide(); + } + _update_tree(_compute_uncollapsed_paths()); file_list_vb->hide(); break; - case DISPLAY_FILE_LIST_ONLY: + case DISPLAY_MODE_FILE_LIST_ONLY: tree->hide(); + tree_search_box->hide(); button_tree->show(); file_list_vb->show(); - _update_files(true); + _update_file_list(true); break; - case DISPLAY_SPLIT: + case DISPLAY_MODE_SPLIT: tree->show(); tree->set_v_size_flags(SIZE_EXPAND_FILL); button_tree->hide(); tree->ensure_cursor_is_visible(); - _update_tree(true); + tree_search_box->hide(); + _update_tree(_compute_uncollapsed_paths()); file_list_vb->show(); - _update_files(true); + _update_file_list(true); break; } - display_mode = new_mode; } } @@ -201,34 +294,36 @@ void FileSystemDock::_notification(int p_what) { String ei = "EditorIcons"; button_reload->set_icon(get_icon("Reload", ei)); - button_favorite->set_icon(get_icon("Favorites", ei)); - //button_instance->set_icon(get_icon("Add", ei)); - //button_open->set_icon(get_icon("Folder", ei)); + button_toggle_display_mode->set_icon(get_icon("Panels2", ei)); button_tree->set_icon(get_icon("Filesystem", ei)); _update_file_list_display_mode_button(); button_file_list_display_mode->connect("pressed", this, "_change_file_display"); - //file_options->set_icon( get_icon("Tools","ei")); - files->connect("item_activated", this, "_select_file"); + + files->connect("item_activated", this, "_file_list_activate_file"); button_hist_next->connect("pressed", this, "_fw_history"); button_hist_prev->connect("pressed", this, "_bw_history"); - search_box->set_right_icon(get_icon("Search", ei)); - search_box->set_clear_button_enabled(true); + tree_search_box->set_right_icon(get_icon("Search", ei)); + tree_search_box->set_clear_button_enabled(true); + file_list_search_box->set_right_icon(get_icon("Search", ei)); + file_list_search_box->set_clear_button_enabled(true); button_hist_next->set_icon(get_icon("Forward", ei)); button_hist_prev->set_icon(get_icon("Back", ei)); - button_show->set_icon(get_icon("GuiVisibilityVisible", "EditorIcons")); - file_options->connect("id_pressed", this, "_file_option"); - folder_options->connect("id_pressed", this, "_folder_option"); + file_list_popup->connect("id_pressed", this, "_file_list_rmb_option"); + tree_popup->connect("id_pressed", this, "_tree_rmb_option"); button_tree->connect("pressed", this, "_go_to_tree", varray(), CONNECT_DEFERRED); current_path->connect("text_entered", this, "navigate_to_path"); + display_mode_setting = DisplayModeSetting(int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode"))); + always_show_folders = bool(EditorSettings::get_singleton()->get("docks/filesystem/always_show_folders")); + _update_display_mode(); if (EditorFileSystem::get_singleton()->is_scanning()) { _set_scanning_mode(); } else { - _update_tree(false, true); + _update_tree(Vector<String>(), true); } } break; @@ -245,7 +340,7 @@ void FileSystemDock::_notification(int p_what) { Dictionary dd = get_viewport()->gui_get_drag_data(); if (tree->is_visible_in_tree() && dd.has("type")) { if ((String(dd["type"]) == "files") || (String(dd["type"]) == "files_and_dirs") || (String(dd["type"]) == "resource")) { - tree->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM); + tree->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM | Tree::DROP_MODE_INBETWEEN); } else if ((String(dd["type"]) == "favorite")) { tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN); } @@ -261,21 +356,38 @@ void FileSystemDock::_notification(int p_what) { // Update icons String ei = "EditorIcons"; button_reload->set_icon(get_icon("Reload", ei)); - button_favorite->set_icon(get_icon("Favorites", ei)); + button_toggle_display_mode->set_icon(get_icon("Panels2", ei)); button_tree->set_icon(get_icon("Filesystem", ei)); button_hist_next->set_icon(get_icon("Forward", ei)); button_hist_prev->set_icon(get_icon("Back", ei)); - search_box->set_right_icon(get_icon("Search", ei)); - search_box->set_clear_button_enabled(true); + tree_search_box->set_right_icon(get_icon("Search", ei)); + tree_search_box->set_clear_button_enabled(true); + file_list_search_box->set_right_icon(get_icon("Search", ei)); + file_list_search_box->set_clear_button_enabled(true); + + bool should_update_files = false; - // Change size mode - int new_file_list_mode = int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode")); + // Update file list display mode + int new_file_list_mode = int(EditorSettings::get_singleton()->get("docks/filesystem/files_display_mode")); if (new_file_list_mode != file_list_display_mode) { set_file_list_display_mode(new_file_list_mode); - } else { _update_file_list_display_mode_button(); - _update_files(true); + should_update_files = true; + } + + // Update display of files in tree + display_mode_setting = DisplayModeSetting(int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode"))); + + // Update allways showfolders + bool new_always_show_folders = bool(EditorSettings::get_singleton()->get("docks/filesystem/always_show_folders")); + if (new_always_show_folders != always_show_folders) { + always_show_folders = new_always_show_folders; + should_update_files = true; + } + + if (should_update_files) { + _update_file_list(true); } // Change full tree mode @@ -285,74 +397,44 @@ void FileSystemDock::_notification(int p_what) { } } -void FileSystemDock::_dir_selected() { +void FileSystemDock::_tree_multi_selected(Object *p_item, int p_column, bool p_selected) { + // Update the import dock + import_dock_needs_update = true; + call_deferred("_update_import_dock"); - TreeItem *sel = tree->get_selected(); - if (!sel) + // Return if we don't select something new + if (!p_selected) return; - path = sel->get_metadata(0); - - bool found = false; - Vector<String> favorites = EditorSettings::get_singleton()->get_favorite_dirs(); - for (int i = 0; i < favorites.size(); i++) { - - if (favorites[i] == path) { - found = true; - break; - } - } - button_favorite->set_pressed(found); - current_path->set_text(path); - _push_to_history(); - - if (display_mode == DISPLAY_SPLIT) { - _update_files(false); - } -} - -void FileSystemDock::_favorites_pressed() { - - TreeItem *sel = tree->get_selected(); - if (!sel) + // Tree item selected + TreeItem *selected = tree->get_selected(); + if (!selected) return; - path = sel->get_metadata(0); - int idx = -1; - Vector<String> favorites = EditorSettings::get_singleton()->get_favorite_dirs(); - for (int i = 0; i < favorites.size(); i++) { - - if (favorites[i] == path) { - idx = i; - break; - } - } - - if (idx == -1) { - favorites.push_back(path); + TreeItem *favorites_item = tree->get_root()->get_children(); + if (selected->get_parent() == favorites_item) { + // Go to the favorites if we click in the favorites and the path has changed + path = "Favorites"; } else { - favorites.remove(idx); + path = selected->get_metadata(0); + // Note: the "Favorites" item also leads to this path } - EditorSettings::get_singleton()->set_favorite_dirs(favorites); - _update_tree(true); -} -void FileSystemDock::_show_current_scene_file() { + // Set the current path + _set_current_path_text(path); + _push_to_history(); - int index = EditorNode::get_editor_data().get_edited_scene(); - String path = EditorNode::get_editor_data().get_scene_path(index); - if (path != String()) { - navigate_to_path(path); + // Update the file list + if (!updating_tree && display_mode == DISPLAY_MODE_SPLIT) { + _update_file_list(false); } } String FileSystemDock::get_selected_path() const { - - TreeItem *sel = tree->get_selected(); - if (!sel) - return ""; - - return sel->get_metadata(0); + if (path.ends_with("/")) + return path; + else + return path.get_base_dir(); } String FileSystemDock::get_current_path() const { @@ -360,30 +442,55 @@ String FileSystemDock::get_current_path() const { return path; } +void FileSystemDock::_set_current_path_text(const String &p_path) { + if (p_path == "Favorites") { + current_path->set_text(TTR("Favorites")); + } else { + current_path->set_text(path); + } +} + void FileSystemDock::navigate_to_path(const String &p_path) { - // If the path is a file, do not only go to the directory in the tree, also select the file in the file list. - String file_name = ""; - DirAccess *dirAccess = DirAccess::open("res://"); - if (dirAccess->file_exists(p_path)) { - path = p_path.get_base_dir(); - file_name = p_path.get_file(); - } else if (dirAccess->dir_exists(p_path)) { + + if (p_path == "Favorites") { path = p_path; } else { - ERR_EXPLAIN(vformat(TTR("Cannot navigate to '%s' as it has not been found in the file system!"), p_path)); - ERR_FAIL(); + String target_path = p_path; + // If the path is a file, do not only go to the directory in the tree, also select the file in the file list. + if (target_path.ends_with("/")) { + target_path = target_path.substr(0, target_path.length() - 1); + } + DirAccess *dirAccess = DirAccess::open("res://"); + if (dirAccess->file_exists(p_path)) { + path = target_path; + } else if (dirAccess->dir_exists(p_path)) { + path = target_path + "/"; + } else { + ERR_EXPLAIN(vformat(TTR("Cannot navigate to '%s' as it has not been found in the file system!"), p_path)); + ERR_FAIL(); + } } - current_path->set_text(path); + _set_current_path_text(path); _push_to_history(); - if (display_mode == DISPLAY_SPLIT) { - _update_tree(true); - _update_files(false); - } else { - _go_to_file_list(); + if (display_mode == DISPLAY_MODE_SPLIT) { + if (path.ends_with("/") || path == "Favorites") { + _go_to_file_list(); + } + _update_tree(_compute_uncollapsed_paths()); + _update_file_list(false); + } else if (display_mode == DISPLAY_MODE_TREE_ONLY) { + if (path.ends_with("/") || path == "Favorites") { + _go_to_file_list(); + } else { + _update_tree(_compute_uncollapsed_paths()); + } + } else { // DISPLAY_MODE_FILE_LIST_ONLY + _update_file_list(true); } + String file_name = p_path.get_file(); if (!file_name.empty()) { for (int i = 0; i < files->get_item_count(); i++) { if (files->get_item_text(i) == file_name) { @@ -395,15 +502,32 @@ void FileSystemDock::navigate_to_path(const String &p_path) { } } -void FileSystemDock::_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata) { +void FileSystemDock::_file_list_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata) { if ((file_list_vb->is_visible_in_tree() || path == p_path.get_base_dir()) && p_preview.is_valid()) { - Array uarr = p_udata; int idx = uarr[0]; String file = uarr[1]; - if (idx < files->get_item_count() && files->get_item_text(idx) == file && files->get_item_metadata(idx) == p_path) - files->set_item_icon(idx, p_preview); + if (idx < files->get_item_count() && files->get_item_text(idx) == file && files->get_item_metadata(idx) == p_path) { + if (file_list_display_mode == FILE_LIST_DISPLAY_LIST) { + if (p_small_preview.is_valid()) + files->set_item_icon(idx, p_small_preview); + } else { + files->set_item_icon(idx, p_preview); + } + } + } +} + +void FileSystemDock::_tree_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata) { + if (p_small_preview.is_valid()) { + Array uarr = p_udata; + if (tree_update_id == (int)uarr[0]) { + TreeItem *file_item = Object::cast_to<TreeItem>(uarr[1]); + if (file_item) { + file_item->set_icon(0, p_small_preview); + } + } } } @@ -424,9 +548,9 @@ void FileSystemDock::_change_file_display() { _update_file_list_display_mode_button(); - EditorSettings::get_singleton()->set("docks/filesystem/display_mode", file_list_display_mode); + EditorSettings::get_singleton()->set("docks/filesystem/files_display_mode", file_list_display_mode); - _update_files(true); + _update_file_list(true); } void FileSystemDock::_search(EditorFileSystemDirectory *p_path, List<FileInfo> *matches, int p_max_items) { @@ -438,12 +562,10 @@ void FileSystemDock::_search(EditorFileSystemDirectory *p_path, List<FileInfo> * _search(p_path->get_subdir(i), matches, p_max_items); } - String match = search_box->get_text().to_lower(); - for (int i = 0; i < p_path->get_file_count(); i++) { String file = p_path->get_file(i); - if (file.to_lower().find(match) != -1) { + if (file.to_lower().find(searched_string) != -1) { FileInfo fi; fi.name = file; @@ -459,14 +581,12 @@ void FileSystemDock::_search(EditorFileSystemDirectory *p_path, List<FileInfo> * } } -void FileSystemDock::_update_files(bool p_keep_selection) { +void FileSystemDock::_update_file_list(bool p_keep_selection) { + // Register the previously selected items Set<String> cselection; - if (p_keep_selection) { - for (int i = 0; i < files->get_item_count(); i++) { - if (files->is_selected(i)) cselection.insert(files->get_item_text(i)); } @@ -474,11 +594,10 @@ void FileSystemDock::_update_files(bool p_keep_selection) { files->clear(); - current_path->set_text(path); + _set_current_path_text(path); - EditorFileSystemDirectory *efd = EditorFileSystem::get_singleton()->get_filesystem_path(path); - if (!efd) - return; + String directory = path; + String file = ""; String ei = "EditorIcons"; int thumbnail_size = EditorSettings::get_singleton()->get("docks/filesystem/thumbnail_size"); @@ -487,13 +606,10 @@ void FileSystemDock::_update_files(bool p_keep_selection) { Ref<Texture> file_thumbnail; Ref<Texture> file_thumbnail_broken; - bool always_show_folders = EditorSettings::get_singleton()->get("docks/filesystem/always_show_folders"); - bool use_thumbnails = (file_list_display_mode == FILE_LIST_DISPLAY_THUMBNAILS); - bool use_folders = search_box->get_text().length() == 0 && ((display_mode == DISPLAY_FILE_LIST_ONLY || display_mode == DISPLAY_TREE_ONLY) || always_show_folders); if (use_thumbnails) { - + // Thumbnails mode files->set_max_columns(0); files->set_icon_mode(ItemList::ICON_MODE_TOP); files->set_fixed_column_width(thumbnail_size * 3 / 2); @@ -511,6 +627,7 @@ void FileSystemDock::_update_files(bool p_keep_selection) { } } else { + // No thumbnails files->set_icon_mode(ItemList::ICON_MODE_LEFT); files->set_max_columns(1); files->set_max_text_lines(1); @@ -518,55 +635,117 @@ void FileSystemDock::_update_files(bool p_keep_selection) { files->set_fixed_icon_size(Size2()); } - if (use_folders) { - Ref<Texture> folderIcon = (use_thumbnails) ? folder_thumbnail : get_icon("folder", "FileDialog"); + Ref<Texture> folder_icon = (use_thumbnails) ? folder_thumbnail : get_icon("folder", "FileDialog"); - if (path != "res://") { - files->add_item("..", folderIcon, true); + // Build the FileInfo list + List<FileInfo> filelist; + if (path == "Favorites") { + // Display the favorites + Vector<String> favorites = EditorSettings::get_singleton()->get_favorites(); + for (int i = 0; i < favorites.size(); i++) { + String favorite = favorites[i]; + String text; + Ref<Texture> icon; + if (favorite == "res://") { + text = "/"; + icon = folder_icon; + if (searched_string.length() == 0 || text.to_lower().find(searched_string) >= 0) { + files->add_item(text, icon, true); + files->set_item_metadata(files->get_item_count() - 1, favorite); + } + } else if (favorite.ends_with("/")) { + text = favorite.substr(0, favorite.length() - 1).get_file(); + icon = folder_icon; + if (searched_string.length() == 0 || text.to_lower().find(searched_string) >= 0) { + files->add_item(text, icon, true); + files->set_item_metadata(files->get_item_count() - 1, favorite); + } + } else { + int index; + EditorFileSystemDirectory *efd = EditorFileSystem::get_singleton()->find_file(favorite, &index); + + FileInfo fi; + fi.name = favorite.get_file(); + fi.path = favorite; + if (efd) { + fi.type = efd->get_file_type(index); + fi.import_broken = !efd->get_file_import_is_valid(index); + } else { + fi.type = ""; + fi.import_broken = true; + } + fi.import_status = 0; - String bd = path.get_base_dir(); - if (bd != "res://" && !bd.ends_with("/")) - bd += "/"; + if (searched_string.length() == 0 || fi.name.to_lower().find(searched_string) >= 0) { + filelist.push_back(fi); + } + } + } + } else { - files->set_item_metadata(files->get_item_count() - 1, bd); + // Get infos on the directory + file + if (directory.ends_with("/") && directory != "res://") { + directory = directory.substr(0, directory.length() - 1); + } + EditorFileSystemDirectory *efd = EditorFileSystem::get_singleton()->get_filesystem_path(directory); + if (!efd) { + directory = path.get_base_dir(); + file = path.get_file(); + efd = EditorFileSystem::get_singleton()->get_filesystem_path(directory); } + if (!efd) + return; - for (int i = 0; i < efd->get_subdir_count(); i++) { + if (searched_string.length() > 0) { + // Display the search results + _search(EditorFileSystem::get_singleton()->get_filesystem(), &filelist, 128); + } else { - String dname = efd->get_subdir(i)->get_name(); + if ((display_mode == DISPLAY_MODE_FILE_LIST_ONLY || display_mode == DISPLAY_MODE_TREE_ONLY) || always_show_folders) { + // Display folders in the list - files->add_item(dname, folderIcon, true); - files->set_item_metadata(files->get_item_count() - 1, path.plus_file(dname) + "/"); + if (directory != "res://") { + files->add_item("..", folder_icon, true); - if (cselection.has(dname)) - files->select(files->get_item_count() - 1, false); - } - } + String bd = directory.get_base_dir(); + if (bd != "res://" && !bd.ends_with("/")) + bd += "/"; - List<FileInfo> filelist; + files->set_item_metadata(files->get_item_count() - 1, bd); + files->set_item_selectable(files->get_item_count() - 1, false); + } - if (search_box->get_text().length() > 0) { + for (int i = 0; i < efd->get_subdir_count(); i++) { - _search(EditorFileSystem::get_singleton()->get_filesystem(), &filelist, 128); - filelist.sort(); - } else { + String dname = efd->get_subdir(i)->get_name(); - for (int i = 0; i < efd->get_file_count(); i++) { + files->add_item(dname, folder_icon, true); + files->set_item_metadata(files->get_item_count() - 1, directory.plus_file(dname) + "/"); - FileInfo fi; - fi.name = efd->get_file(i); - fi.path = path.plus_file(fi.name); - fi.type = efd->get_file_type(i); - fi.import_broken = !efd->get_file_import_is_valid(i); - fi.import_status = 0; + if (cselection.has(dname)) { + files->select(files->get_item_count() - 1, false); + } + } + } + + // Display the folder content + for (int i = 0; i < efd->get_file_count(); i++) { - filelist.push_back(fi); + FileInfo fi; + fi.name = efd->get_file(i); + fi.path = directory.plus_file(fi.name); + fi.type = efd->get_file_type(i); + fi.import_broken = !efd->get_file_import_is_valid(i); + fi.import_status = 0; + + filelist.push_back(fi); + } } filelist.sort(); } + // Fills the ItemList control node from the FileInfos String oi = "Object"; - for (List<FileInfo>::Element *E = filelist.front(); E; E = E->next()) { FileInfo *finfo = &(E->get()); String fname = finfo->name; @@ -578,6 +757,7 @@ void FileSystemDock::_update_files(bool p_keep_selection) { String tooltip = fname; + // Select the icons if (!finfo->import_broken) { type_icon = (has_icon(ftype, ei)) ? get_icon(ftype, ei) : get_icon(oi, ei); big_icon = file_thumbnail; @@ -587,28 +767,39 @@ void FileSystemDock::_update_files(bool p_keep_selection) { tooltip += "\n" + TTR("Status: Import of file failed. Please fix file and reimport manually."); } + // Add the item to the ItemList int item_index; if (use_thumbnails) { files->add_item(fname, big_icon, true); item_index = files->get_item_count() - 1; files->set_item_metadata(item_index, fpath); files->set_item_tag_icon(item_index, type_icon); - if (!finfo->import_broken) { - Array udata; - udata.resize(2); - udata[0] = item_index; - udata[1] = fname; - EditorResourcePreview::get_singleton()->queue_resource_preview(fpath, this, "_thumbnail_done", udata); - } + } else { files->add_item(fname, type_icon, true); item_index = files->get_item_count() - 1; files->set_item_metadata(item_index, fpath); } + // Generate the preview + if (!finfo->import_broken) { + Array udata; + udata.resize(2); + udata[0] = item_index; + udata[1] = fname; + EditorResourcePreview::get_singleton()->queue_resource_preview(fpath, this, "_file_list_thumbnail_done", udata); + } + + // Select the items if (cselection.has(fname)) files->select(item_index, false); + if (!p_keep_selection && file != "" && fname == file) { + files->select(item_index, true); + files->ensure_current_is_visible(); + } + + // Tooltip if (finfo->sources.size()) { for (int j = 0; j < finfo->sources.size(); j++) { tooltip += "\nSource: " + finfo->sources[j]; @@ -618,33 +809,49 @@ void FileSystemDock::_update_files(bool p_keep_selection) { } } -void FileSystemDock::_select_file(int p_idx) { - String fpath = files->get_item_metadata(p_idx); +void FileSystemDock::_select_file(const String p_path) { + String fpath = p_path; if (fpath.ends_with("/")) { if (fpath != "res://") { fpath = fpath.substr(0, fpath.length() - 1); } - navigate_to_path(fpath); - } else { + } else if (fpath != "Favorites") { if (ResourceLoader::get_resource_type(fpath) == "PackedScene") { editor->open_request(fpath); } else { editor->load_resource(fpath); } } + navigate_to_path(fpath); +} + +void FileSystemDock::_tree_activate_file() { + TreeItem *selected = tree->get_selected(); + if (selected) { + call_deferred("_select_file", selected->get_metadata(0)); + } +} + +void FileSystemDock::_file_list_activate_file(int p_idx) { + _select_file(files->get_item_metadata(p_idx)); } void FileSystemDock::_go_to_file_list() { - if (display_mode == DISPLAY_TREE_ONLY) { + if (display_mode == DISPLAY_MODE_TREE_ONLY) { + file_list_view = true; _update_display_mode(); } else { - bool collapsed = tree->get_selected()->is_collapsed(); - tree->get_selected()->set_collapsed(!collapsed); - _update_files(false); + TreeItem *selected = tree->get_selected(); + if (selected) { + bool collapsed = selected->is_collapsed(); + selected->set_collapsed(!collapsed); + } + _update_file_list(false); } } + void FileSystemDock::_go_to_tree() { file_list_view = false; @@ -655,7 +862,7 @@ void FileSystemDock::_go_to_tree() { void FileSystemDock::_preview_invalidated(const String &p_path) { - if (file_list_display_mode == FILE_LIST_DISPLAY_THUMBNAILS && p_path.get_base_dir() == path && search_box->get_text() == String() && file_list_vb->is_visible_in_tree()) { + if (file_list_display_mode == FILE_LIST_DISPLAY_THUMBNAILS && p_path.get_base_dir() == path && searched_string.length() == 0 && file_list_vb->is_visible_in_tree()) { for (int i = 0; i < files->get_item_count(); i++) { @@ -665,7 +872,7 @@ void FileSystemDock::_preview_invalidated(const String &p_path) { udata.resize(2); udata[0] = i; udata[1] = files->get_item_text(i); - EditorResourcePreview::get_singleton()->queue_resource_preview(p_path, this, "_thumbnail_done", udata); + EditorResourcePreview::get_singleton()->queue_resource_preview(p_path, this, "_file_list_thumbnail_done", udata); break; } } @@ -680,11 +887,11 @@ void FileSystemDock::_fs_changed() { split_box->show(); if (tree->is_visible()) { - _update_tree(true); + _update_tree(_compute_uncollapsed_paths()); } if (file_list_vb->is_visible()) { - _update_files(true); + _update_file_list(true); } set_process(false); @@ -721,16 +928,16 @@ void FileSystemDock::_bw_history() { void FileSystemDock::_update_history() { path = history[history_pos]; - current_path->set_text(path); + _set_current_path_text(path); if (tree->is_visible()) { - _update_tree(true); + _update_tree(_compute_uncollapsed_paths()); tree->grab_focus(); tree->ensure_cursor_is_visible(); } if (file_list_vb->is_visible()) { - _update_files(false); + _update_file_list(false); } button_hist_prev->set_disabled(history_pos == 0); @@ -968,23 +1175,23 @@ void FileSystemDock::_update_project_settings_after_move(const Map<String, Strin ProjectSettings::get_singleton()->save(); } -void FileSystemDock::_update_favorite_dirs_list_after_move(const Map<String, String> &p_renames) const { - - Vector<String> favorite_dirs = EditorSettings::get_singleton()->get_favorite_dirs(); - Vector<String> new_favorite_dirs; +void FileSystemDock::_update_favorites_list_after_move(const Map<String, String> &p_files_renames, const Map<String, String> &p_folders_renames) const { - for (int i = 0; i < favorite_dirs.size(); i++) { - String old_path = favorite_dirs[i] + "/"; + Vector<String> favorites = EditorSettings::get_singleton()->get_favorites(); + Vector<String> new_favorites; - if (p_renames.has(old_path)) { - String new_path = p_renames[old_path]; - new_favorite_dirs.push_back(new_path.substr(0, new_path.length() - 1)); + for (int i = 0; i < favorites.size(); i++) { + String old_path = favorites[i]; + if (p_folders_renames.has(old_path)) { + new_favorites.push_back(p_folders_renames[old_path]); + } else if (p_files_renames.has(old_path)) { + new_favorites.push_back(p_files_renames[old_path]); } else { - new_favorite_dirs.push_back(favorite_dirs[i]); + new_favorites.push_back(old_path); } } - EditorSettings::get_singleton()->set_favorite_dirs(new_favorite_dirs); + EditorSettings::get_singleton()->set_favorites(new_favorites); } void FileSystemDock::_make_dir_confirm() { @@ -998,9 +1205,13 @@ void FileSystemDock::_make_dir_confirm() { return; } - print_verbose("Making folder " + dir_name + " in " + path); + String directory = path; + if (!directory.ends_with("/")) { + directory = directory.get_base_dir(); + } + print_verbose("Making folder " + dir_name + " in " + directory); DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); - Error err = da->change_dir(path); + Error err = da->change_dir(directory); if (err == OK) { err = da->make_dir(dir_name); } @@ -1051,7 +1262,7 @@ void FileSystemDock::_rename_operation_confirm() { _update_dependencies_after_move(file_renames); _update_resource_paths_after_move(file_renames); _update_project_settings_after_move(file_renames); - _update_favorite_dirs_list_after_move(folder_renames); + _update_favorites_list_after_move(file_renames, folder_renames); //Rescan everything print_verbose("FileSystem: calling rescan."); @@ -1144,111 +1355,212 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool overw _update_dependencies_after_move(file_renames); _update_resource_paths_after_move(file_renames); _update_project_settings_after_move(file_renames); - _update_favorite_dirs_list_after_move(folder_renames); + _update_favorites_list_after_move(file_renames, folder_renames); print_verbose("FileSystem: calling rescan."); _rescan(); } } -void FileSystemDock::_file_option(int p_option) { +Vector<String> FileSystemDock::_tree_get_selected(bool remove_self_inclusion) { + // Build a list of selected items with the active one at the first position + Vector<String> selected_strings; + + TreeItem *favorites_item = tree->get_root()->get_children(); + TreeItem *active_selected = tree->get_selected(); + if (active_selected && active_selected != favorites_item) { + selected_strings.push_back(active_selected->get_metadata(0)); + } + + TreeItem *selected = tree->get_root(); + selected = tree->get_next_selected(selected); + while (selected) { + if (selected != active_selected && selected != favorites_item) { + selected_strings.push_back(selected->get_metadata(0)); + } + selected = tree->get_next_selected(selected); + } + + // Remove paths or files that are included into another + if (remove_self_inclusion && selected_strings.size() > 1) { + selected_strings.sort_custom<NaturalNoCaseComparator>(); + String last_path = ""; + for (int i = 0; i < selected_strings.size(); i++) { + if (last_path != "" && selected_strings[i].begins_with(last_path)) { + selected_strings.remove(i); + i--; + } + if (selected_strings[i].ends_with("/")) { + last_path = selected_strings[i]; + } + } + } + return selected_strings; +} + +void FileSystemDock::_tree_rmb_option(int p_option) { + + Vector<String> selected_strings = _tree_get_selected(); + + // Execute the current option switch (p_option) { - case FILE_SHOW_IN_EXPLORER: { + case FOLDER_EXPAND_ALL: + case FOLDER_COLLAPSE_ALL: { + // Expand or collapse the folder + if (selected_strings.size() == 1) { + bool is_collapsed = (p_option == FOLDER_COLLAPSE_ALL); + + Vector<TreeItem *> needs_check; + needs_check.push_back(tree->get_selected()); - String path = this->path; + while (needs_check.size()) { + needs_check[0]->set_collapsed(is_collapsed); - // first try to grab directory from selected file, so that it works for searched files - int idx = files->get_current(); + TreeItem *child = needs_check[0]->get_children(); + while (child) { + needs_check.push_back(child); + child = child->get_next(); + } - if (idx >= 0 && idx < files->get_item_count()) { - path = files->get_item_metadata(idx); - path = path.get_base_dir(); + needs_check.remove(0); + } } + } break; + default: { + _file_option(p_option, selected_strings); + } break; + } +} - path = ProjectSettings::get_singleton()->globalize_path(path); - OS::get_singleton()->shell_open(String("file://") + path); +void FileSystemDock::_file_list_rmb_option(int p_option) { + Vector<int> selected_id = files->get_selected_items(); + Vector<String> selected; + for (int i = 0; i < selected_id.size(); i++) { + selected.push_back(files->get_item_metadata(selected_id[i])); + } + _file_option(p_option, selected); +} + +void FileSystemDock::_file_option(int p_option, const Vector<String> p_selected) { + // The first one should be the active item + + switch (p_option) { + case FILE_SHOW_IN_EXPLORER: { + // Show the file / folder in the OS explorer + String fpath = path; + if (!fpath.ends_with("/")) { + fpath = fpath.get_base_dir(); + } + String dir = ProjectSettings::get_singleton()->globalize_path(fpath); + OS::get_singleton()->shell_open(String("file://") + dir); } break; + case FILE_OPEN: { - for (int i = 0; i < files->get_item_count(); i++) { - if (files->is_selected(i)) { - _select_file(i); - } + // Open the file + for (int i = 0; i < p_selected.size(); i++) { + _select_file(p_selected[i]); } } break; - case FILE_INSTANCE: { + case FILE_INSTANCE: { + // Instance all selected scenes Vector<String> paths; - - for (int i = 0; i < files->get_item_count(); i++) { - if (!files->is_selected(i)) - continue; - String fpath = files->get_item_metadata(i); + for (int i = 0; i < p_selected.size(); i++) { + String fpath = p_selected[i]; if (EditorFileSystem::get_singleton()->get_file_type(fpath) == "PackedScene") { paths.push_back(fpath); } } - if (!paths.empty()) { emit_signal("instance", paths); } } break; - case FILE_DEPENDENCIES: { - int idx = files->get_current(); - if (idx < 0 || idx >= files->get_item_count()) - break; - String fpath = files->get_item_metadata(idx); - deps_editor->edit(fpath); + case FILE_ADD_FAVORITE: { + // Add the files from favorites + Vector<String> favorites = EditorSettings::get_singleton()->get_favorites(); + for (int i = 0; i < p_selected.size(); i++) { + if (favorites.find(p_selected[i]) == -1) { + favorites.push_back(p_selected[i]); + } + } + EditorSettings::get_singleton()->set_favorites(favorites); + _update_tree(_compute_uncollapsed_paths()); } break; - case FILE_OWNERS: { - int idx = files->get_current(); - if (idx < 0 || idx >= files->get_item_count()) - break; - String fpath = files->get_item_metadata(idx); - owners_editor->show(fpath); + case FILE_REMOVE_FAVORITE: { + // Remove the files from favorites + Vector<String> favorites = EditorSettings::get_singleton()->get_favorites(); + for (int i = 0; i < p_selected.size(); i++) { + favorites.erase(p_selected[i]); + } + EditorSettings::get_singleton()->set_favorites(favorites); + _update_tree(_compute_uncollapsed_paths()); + if (path == "Favorites") + _update_file_list(true); } break; + + case FILE_DEPENDENCIES: { + // Checkout the file dependencies + if (!p_selected.empty()) { + String fpath = p_selected[0]; + deps_editor->edit(fpath); + } + } break; + + case FILE_OWNERS: { + // Checkout the file owners + if (!p_selected.empty()) { + String fpath = p_selected[0]; + owners_editor->show(fpath); + } + } break; + case FILE_MOVE: { + // Move the files to a given location to_move.clear(); - for (int i = 0; i < files->get_item_count(); i++) { - if (!files->is_selected(i)) - continue; - - String fpath = files->get_item_metadata(i); - to_move.push_back(FileOrFolder(fpath, !fpath.ends_with("/"))); + for (int i = 0; i < p_selected.size(); i++) { + String fpath = p_selected[i]; + if (fpath != "res://") { + to_move.push_back(FileOrFolder(fpath, !fpath.ends_with("/"))); + } } if (to_move.size() > 0) { move_dialog->popup_centered_ratio(); } } break; - case FILE_RENAME: { - int idx = files->get_current(); - if (idx < 0 || idx >= files->get_item_count()) - break; - to_rename.path = files->get_item_metadata(idx); - to_rename.is_file = !to_rename.path.ends_with("/"); - if (to_rename.is_file) { - String name = to_rename.path.get_file(); - rename_dialog->set_title(TTR("Renaming file:") + " " + name); - rename_dialog_text->set_text(name); - rename_dialog_text->select(0, name.find_last(".")); - } else { - String name = to_rename.path.substr(0, to_rename.path.length() - 1).get_file(); - rename_dialog->set_title(TTR("Renaming folder:") + " " + name); - rename_dialog_text->set_text(name); - rename_dialog_text->select(0, name.length()); + case FILE_RENAME: { + // Rename the active file + if (!p_selected.empty()) { + to_rename.path = p_selected[0]; + if (to_rename.path != "res://") { + to_rename.is_file = !to_rename.path.ends_with("/"); + if (to_rename.is_file) { + String name = to_rename.path.get_file(); + rename_dialog->set_title(TTR("Renaming file:") + " " + name); + rename_dialog_text->set_text(name); + rename_dialog_text->select(0, name.find_last(".")); + } else { + String name = to_rename.path.substr(0, to_rename.path.length() - 1).get_file(); + rename_dialog->set_title(TTR("Renaming folder:") + " " + name); + rename_dialog_text->set_text(name); + rename_dialog_text->select(0, name.length()); + } + rename_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE); + rename_dialog_text->grab_focus(); + } } - rename_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE); - rename_dialog_text->grab_focus(); } break; + case FILE_REMOVE: { + // Remove the selected files Vector<String> remove_files; Vector<String> remove_folders; - for (int i = 0; i < files->get_item_count(); i++) { - String fpath = files->get_item_metadata(i); - if (files->is_selected(i) && fpath != "res://") { + for (int i = 0; i < p_selected.size(); i++) { + String fpath = p_selected[i]; + if (fpath != "res://") { if (fpath.ends_with("/")) { remove_folders.push_back(fpath); } else { @@ -1259,166 +1571,77 @@ void FileSystemDock::_file_option(int p_option) { if (remove_files.size() + remove_folders.size() > 0) { remove_dialog->show(remove_folders, remove_files); - //1) find if used - //2) warn } } break; - case FILE_DUPLICATE: { - int idx = files->get_current(); - if (idx < 0 || idx >= files->get_item_count()) - break; - to_duplicate.path = files->get_item_metadata(idx); - to_duplicate.is_file = !to_duplicate.path.ends_with("/"); - if (to_duplicate.is_file) { - String name = to_duplicate.path.get_file(); - duplicate_dialog->set_title(TTR("Duplicating file:") + " " + name); - duplicate_dialog_text->set_text(name); - duplicate_dialog_text->select(0, name.find_last(".")); - } else { - String name = to_duplicate.path.substr(0, to_duplicate.path.length() - 1).get_file(); - duplicate_dialog->set_title(TTR("Duplicating folder:") + " " + name); - duplicate_dialog_text->set_text(name); - duplicate_dialog_text->select(0, name.length()); + case FILE_DUPLICATE: { + // Duplicate the selected files + for (int i = 0; i < p_selected.size(); i++) { + to_duplicate.path = p_selected[i]; + to_duplicate.is_file = !to_duplicate.path.ends_with("/"); + if (to_duplicate.is_file) { + String name = to_duplicate.path.get_file(); + duplicate_dialog->set_title(TTR("Duplicating file:") + " " + name); + duplicate_dialog_text->set_text(name); + duplicate_dialog_text->select(0, name.find_last(".")); + } else { + String name = to_duplicate.path.substr(0, to_duplicate.path.length() - 1).get_file(); + duplicate_dialog->set_title(TTR("Duplicating folder:") + " " + name); + duplicate_dialog_text->set_text(name); + duplicate_dialog_text->select(0, name.length()); + } + duplicate_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE); + duplicate_dialog_text->grab_focus(); } - duplicate_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE); - duplicate_dialog_text->grab_focus(); } break; + case FILE_INFO: { } break; - case FILE_REIMPORT: { + case FILE_REIMPORT: { + // Reimport all selected files Vector<String> reimport; - for (int i = 0; i < files->get_item_count(); i++) { - - if (!files->is_selected(i)) - continue; - - String fpath = files->get_item_metadata(i); - reimport.push_back(fpath); + for (int i = 0; i < p_selected.size(); i++) { + reimport.push_back(p_selected[i]); } ERR_FAIL_COND(reimport.size() == 0); - /* - Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(reimport[0]); - ERR_FAIL_COND(!rimd.is_valid()); - String editor=rimd->get_editor(); - - if (editor.begins_with("texture_")) { //compatibility fix for old texture format - editor="texture"; - } - - Ref<EditorImportPlugin> rimp = EditorImportExport::get_singleton()->get_import_plugin_by_name(editor); - ERR_FAIL_COND(!rimp.is_valid()); - - if (reimport.size()==1) { - rimp->import_dialog(reimport[0]); - } else { - rimp->reimport_multiple_files(reimport); - - } - */ } break; + case FILE_NEW_FOLDER: { + // Create a new folder make_dir_dialog_text->set_text("new folder"); make_dir_dialog_text->select_all(); make_dir_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE); make_dir_dialog_text->grab_focus(); } break; + case FILE_NEW_SCRIPT: { - String tarDir = path; - if (tarDir != "res://" && !tarDir.ends_with("/")) { - tarDir += "/"; + // Create a new script + String fpath = path; + if (!fpath.ends_with("/")) { + fpath = fpath.get_base_dir(); } - - make_script_dialog_text->config("Node", tarDir + "new_script.gd"); + make_script_dialog_text->config("Node", fpath + "new_script.gd", false); make_script_dialog_text->popup_centered(Size2(300, 300) * EDSCALE); } break; + case FILE_COPY_PATH: { - int idx = files->get_current(); - if (idx < 0 || idx >= files->get_item_count()) - break; - String fpath = files->get_item_metadata(idx); - OS::get_singleton()->set_clipboard(fpath); + // Copy the file path + if (!p_selected.empty()) { + String fpath = p_selected[0]; + OS::get_singleton()->set_clipboard(fpath); + } } break; + case FILE_NEW_RESOURCE: { + // Create a new resource new_resource_dialog->popup_create(true); } break; } } -void FileSystemDock::_folder_option(int p_option) { - - TreeItem *selected = tree->get_selected(); - - switch (p_option) { - case FOLDER_EXPAND_ALL: - case FOLDER_COLLAPSE_ALL: { - bool is_collapsed = (p_option == FOLDER_COLLAPSE_ALL); - Vector<TreeItem *> needs_check; - needs_check.push_back(selected); - - while (needs_check.size()) { - needs_check[0]->set_collapsed(is_collapsed); - - TreeItem *child = needs_check[0]->get_children(); - while (child) { - needs_check.push_back(child); - child = child->get_next(); - } - - needs_check.remove(0); - } - } break; - case FOLDER_MOVE: { - to_move.clear(); - String fpath = selected->get_metadata(tree->get_selected_column()); - if (fpath != "res://") { - fpath = fpath.ends_with("/") ? fpath.substr(0, fpath.length() - 1) : fpath; - to_move.push_back(FileOrFolder(fpath, false)); - move_dialog->popup_centered_ratio(); - } - } break; - case FOLDER_RENAME: { - to_rename.path = selected->get_metadata(tree->get_selected_column()); - to_rename.is_file = false; - if (to_rename.path != "res://") { - String name = to_rename.path.ends_with("/") ? to_rename.path.substr(0, to_rename.path.length() - 1).get_file() : to_rename.path.get_file(); - rename_dialog->set_title(TTR("Renaming folder:") + " " + name); - rename_dialog_text->set_text(name); - rename_dialog_text->select(0, name.length()); - rename_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE); - rename_dialog_text->grab_focus(); - } - } break; - case FOLDER_REMOVE: { - Vector<String> remove_folders; - Vector<String> remove_files; - String fpath = selected->get_metadata(tree->get_selected_column()); - if (fpath != "res://") { - remove_folders.push_back(fpath); - remove_dialog->show(remove_folders, remove_files); - } - } break; - case FOLDER_NEW_FOLDER: { - make_dir_dialog_text->set_text("new folder"); - make_dir_dialog_text->select_all(); - make_dir_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE); - make_dir_dialog_text->grab_focus(); - } break; - case FOLDER_COPY_PATH: { - String fpath = selected->get_metadata(tree->get_selected_column()); - OS::get_singleton()->set_clipboard(fpath); - } break; - case FOLDER_SHOW_IN_EXPLORER: { - String fpath = selected->get_metadata(tree->get_selected_column()); - String dir = ProjectSettings::get_singleton()->globalize_path(fpath); - OS::get_singleton()->shell_open(String("file://") + dir); - } break; - } -} - void FileSystemDock::_resource_created() const { Object *c = new_resource_dialog->instance_selected(); @@ -1431,38 +1654,39 @@ void FileSystemDock::_resource_created() const { RES current_res = RES(r); - editor->save_resource_as(current_res, path); -} - -void FileSystemDock::_dir_rmb_pressed(const Vector2 &p_pos) { - folder_options->clear(); - folder_options->set_size(Size2(1, 1)); + String fpath = path; + if (!fpath.ends_with("/")) { + fpath = fpath.get_base_dir(); + } - folder_options->add_item(TTR("Expand all"), FOLDER_EXPAND_ALL); - folder_options->add_item(TTR("Collapse all"), FOLDER_COLLAPSE_ALL); + editor->save_resource_as(current_res, fpath); +} - TreeItem *item = tree->get_selected(); - if (item) { - String fpath = item->get_metadata(tree->get_selected_column()); - folder_options->add_separator(); - folder_options->add_item(TTR("Copy Path"), FOLDER_COPY_PATH); - if (fpath != "res://") { - folder_options->add_item(TTR("Rename..."), FOLDER_RENAME); - folder_options->add_item(TTR("Move To..."), FOLDER_MOVE); - folder_options->add_item(TTR("Delete"), FOLDER_REMOVE); - } - folder_options->add_separator(); - folder_options->add_item(TTR("New Folder..."), FOLDER_NEW_FOLDER); - folder_options->add_item(TTR("Open In File Manager"), FOLDER_SHOW_IN_EXPLORER); +void FileSystemDock::_search_changed(const String &p_text, const Control *p_from) { + if (searched_string.length() == 0 && p_text.length() > 0) { + // Register the uncollapsed paths before they change + uncollapsed_paths_before_search = _compute_uncollapsed_paths(); } - folder_options->set_position(tree->get_global_position() + p_pos); - folder_options->popup(); -} -void FileSystemDock::_search_changed(const String &p_text) { + searched_string = p_text.to_lower(); + + if (p_from == tree_search_box) + file_list_search_box->set_text(searched_string); + else // file_list_search_box + tree_search_box->set_text(searched_string); - if (file_list_vb->is_visible()) - _update_files(false); + switch (display_mode) { + case DISPLAY_MODE_FILE_LIST_ONLY: { + _update_file_list(false); + } break; + case DISPLAY_MODE_TREE_ONLY: { + _update_tree(searched_string.length() == 0 ? uncollapsed_paths_before_search : Vector<String>()); + } break; + case DISPLAY_MODE_SPLIT: { + _update_file_list(false); + _update_tree(searched_string.length() == 0 ? uncollapsed_paths_before_search : Vector<String>()); + } break; + } } void FileSystemDock::_rescan() { @@ -1471,20 +1695,25 @@ void FileSystemDock::_rescan() { EditorFileSystem::get_singleton()->scan(); } +void FileSystemDock::_toggle_split_mode(bool p_active) { + display_mode_setting = p_active ? DISPLAY_MODE_SETTING_SPLIT : DISPLAY_MODE_SETTING_TREE_ONLY; + EditorSettings::get_singleton()->set("docks/filesystem/display_mode", int(display_mode_setting)); + _update_display_mode(); +} + void FileSystemDock::fix_dependencies(const String &p_for_file) { deps_editor->edit(p_for_file); } void FileSystemDock::focus_on_filter() { - if (display_mode == DISPLAY_FILE_LIST_ONLY && tree->is_visible()) { + if (display_mode == DISPLAY_MODE_FILE_LIST_ONLY && tree->is_visible()) { // Tree mode, switch to files list with search box tree->hide(); file_list_vb->show(); - button_favorite->hide(); } - search_box->grab_focus(); + file_list_search_box->grab_focus(); } void FileSystemDock::set_file_list_display_mode(int p_mode) { @@ -1497,33 +1726,49 @@ void FileSystemDock::set_file_list_display_mode(int p_mode) { } Variant FileSystemDock::get_drag_data_fw(const Point2 &p_point, Control *p_from) { - bool is_favorite = false; + bool all_favorites = true; + bool all_not_favorites = true; + Vector<String> paths; if (p_from == tree) { - TreeItem *selected = tree->get_selected(); - if (!selected) - return Variant(); - - String folder = selected->get_metadata(0); - if (folder == String()) - return Variant(); + // Check if the first selected is in favorite + TreeItem *selected = tree->get_next_selected(tree->get_root()); + while (selected) { + TreeItem *favorites_item = tree->get_root()->get_children(); + if (selected == favorites_item) { + // The "Favorites" item is not draggable + return Variant(); + } - paths.push_back(folder.ends_with("/") ? folder : (folder + "/")); - is_favorite = selected->get_parent() != NULL && tree->get_root()->get_children() == selected->get_parent(); + bool is_favorite = selected->get_parent() != NULL && tree->get_root()->get_children() == selected->get_parent(); + all_favorites &= is_favorite; + all_not_favorites &= !is_favorite; + selected = tree->get_next_selected(selected); + } + if (all_favorites) { + paths = _tree_get_selected(false); + } else { + paths = _tree_get_selected(); + } } else if (p_from == files) { for (int i = 0; i < files->get_item_count(); i++) { if (files->is_selected(i)) { paths.push_back(files->get_item_metadata(i)); } } + all_favorites = false; + all_not_favorites = true; } if (paths.empty()) return Variant(); + if (!all_favorites && !all_not_favorites) + return Variant(); + Dictionary drag_data = EditorNode::get_singleton()->drag_files_and_dirs(paths, p_from); - if (is_favorite) { + if (all_favorites) { drag_data["type"] = "favorite"; } return drag_data; @@ -1535,34 +1780,46 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da if (drag_data.has("type") && String(drag_data["type"]) == "favorite") { - //moving favorite around + // Moving favorite around TreeItem *ti = tree->get_item_at_position(p_point); if (!ti) return false; - int what = tree->get_drop_section_at_position(p_point); + int drop_section = tree->get_drop_section_at_position(p_point); + TreeItem *favorites_item = tree->get_root()->get_children(); + + TreeItem *resources_item = favorites_item->get_next(); - if (ti == tree->get_root()->get_children()) { - return (what == 1); //the parent, first fav + if (ti == favorites_item) { + return (drop_section == 1); // The parent, first fav } - if (ti->get_parent() && tree->get_root()->get_children() == ti->get_parent()) { - return true; // a favorite + if (ti->get_parent() && favorites_item == ti->get_parent()) { + return true; // A favorite } - - if (ti == tree->get_root()->get_children()->get_next()) { - return (what == -1); //the tree, last fav + if (ti == resources_item) { + return (drop_section == -1); // The tree, last fav } return false; } if (drag_data.has("type") && String(drag_data["type"]) == "resource") { - String to_dir = _get_drag_target_folder(p_point, p_from); + // Move resources + String to_dir; + bool favorite; + _get_drag_target_folder(to_dir, favorite, p_point, p_from); return !to_dir.empty(); } if (drag_data.has("type") && (String(drag_data["type"]) == "files" || String(drag_data["type"]) == "files_and_dirs")) { - String to_dir = _get_drag_target_folder(p_point, p_from); + // Move files or dir + String to_dir; + bool favorite; + _get_drag_target_folder(to_dir, favorite, p_point, p_from); + + if (favorite) + return true; + if (to_dir.empty()) return false; @@ -1587,71 +1844,70 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data, return; Dictionary drag_data = p_data; - if (drag_data.has("type") && String(drag_data["type"]) == "favorite") { + Vector<String> dirs = EditorSettings::get_singleton()->get_favorites(); - //moving favorite around + if (drag_data.has("type") && String(drag_data["type"]) == "favorite") { + // Moving favorite around TreeItem *ti = tree->get_item_at_position(p_point); if (!ti) return; + int drop_section = tree->get_drop_section_at_position(p_point); + int drop_position; Vector<String> files = drag_data["files"]; - - ERR_FAIL_COND(files.size() != 1); - - String swap = files[0]; - if (swap != "res://" && swap.ends_with("/")) { - swap = swap.substr(0, swap.length() - 1); - } - - int what = tree->get_drop_section_at_position(p_point); - - TreeItem *swap_item = NULL; - - if (ti == tree->get_root()->get_children()) { - swap_item = tree->get_root()->get_children()->get_children(); - - } else if (ti->get_parent() && tree->get_root()->get_children() == ti->get_parent()) { - if (what == -1) { - swap_item = ti; - } else { - swap_item = ti->get_next(); + TreeItem *favorites_item = tree->get_root()->get_children(); + TreeItem *resources_item = favorites_item->get_next(); + + if (ti == favorites_item) { + // Drop on the favorite folder + drop_position = 0; + } else if (ti == resources_item) { + // Drop on the resouce item + drop_position = dirs.size(); + } else { + // Drop in the list + drop_position = dirs.find(ti->get_metadata(0)); + if (drop_section == 1) { + drop_position++; } } - String swap_with; - - if (swap_item) { - swap_with = swap_item->get_metadata(0); - if (swap_with != "res://" && swap_with.ends_with("/")) { - swap_with = swap_with.substr(0, swap_with.length() - 1); + // Remove dragged favorites + Vector<int> to_remove; + int offset = 0; + for (int i = 0; i < files.size(); i++) { + int to_remove_pos = dirs.find(files[i]); + to_remove.push_back(to_remove_pos); + if (to_remove_pos < drop_position) { + offset++; } } + drop_position -= offset; + to_remove.sort(); + for (int i = 0; i < to_remove.size(); i++) { + dirs.remove(to_remove[i] - i); + } - if (swap == swap_with) - return; - - Vector<String> dirs = EditorSettings::get_singleton()->get_favorite_dirs(); - - ERR_FAIL_COND(dirs.find(swap) == -1); - ERR_FAIL_COND(swap_with != String() && dirs.find(swap_with) == -1); - - dirs.erase(swap); - - if (swap_with == String()) { - dirs.push_back(swap); - } else { - int idx = dirs.find(swap_with); - dirs.insert(idx, swap); + // Re-add them at the right position + for (int i = 0; i < files.size(); i++) { + dirs.insert(drop_position, files[i]); + drop_position++; } - EditorSettings::get_singleton()->set_favorite_dirs(dirs); - _update_tree(true); + EditorSettings::get_singleton()->set_favorites(dirs); + _update_tree(_compute_uncollapsed_paths()); + + if (display_mode == DISPLAY_MODE_SPLIT && path == "Favorites") + _update_file_list(true); return; } if (drag_data.has("type") && String(drag_data["type"]) == "resource") { + // Moving resource Ref<Resource> res = drag_data["resource"]; - String to_dir = _get_drag_target_folder(p_point, p_from); + String to_dir; + bool favorite; + _get_drag_target_folder(to_dir, favorite, p_point, p_from); if (res.is_valid() && !to_dir.empty()) { EditorNode::get_singleton()->push_item(res.ptr()); EditorNode::get_singleton()->save_resource_as(res, to_dir); @@ -1659,7 +1915,10 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data, } if (drag_data.has("type") && (String(drag_data["type"]) == "files" || String(drag_data["type"]) == "files_and_dirs")) { - String to_dir = _get_drag_target_folder(p_point, p_from); + // Move files or add to favorites + String to_dir; + bool favorite; + _get_drag_target_folder(to_dir, favorite, p_point, p_from); if (!to_dir.empty()) { Vector<String> fnames = drag_data["files"]; to_move.clear(); @@ -1667,50 +1926,93 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data, to_move.push_back(FileOrFolder(fnames[i], !fnames[i].ends_with("/"))); } _move_operation_confirm(to_dir); + } else if (favorite) { + // Add the files from favorites + Vector<String> fnames = drag_data["files"]; + Vector<String> favorites = EditorSettings::get_singleton()->get_favorites(); + for (int i = 0; i < fnames.size(); i++) { + if (favorites.find(fnames[i]) == -1) { + favorites.push_back(fnames[i]); + } + } + EditorSettings::get_singleton()->set_favorites(favorites); + _update_tree(_compute_uncollapsed_paths()); } } } -String FileSystemDock::_get_drag_target_folder(const Point2 &p_point, Control *p_from) const { +void FileSystemDock::_get_drag_target_folder(String &target, bool &target_favorites, const Point2 &p_point, Control *p_from) const { + target = String(); + target_favorites = false; + + // In the file list if (p_from == files) { int pos = files->get_item_at_position(p_point, true); - if (pos == -1) - return path; + if (pos == -1) { + return; + } - String target = files->get_item_metadata(pos); - return target.ends_with("/") ? target : path; + String ltarget = files->get_item_metadata(pos); + target = ltarget.ends_with("/") ? ltarget : path; + return; } + // In the tree if (p_from == tree) { TreeItem *ti = tree->get_item_at_position(p_point); - if (ti && ti != tree->get_root()->get_children()) - return ti->get_metadata(0); + int section = tree->get_drop_section_at_position(p_point); + if (ti) { + // Check the favorites first + if (ti == tree->get_root()->get_children() && section >= 0) { + target_favorites = true; + return; + } else if (ti->get_parent() == tree->get_root()->get_children()) { + target_favorites = true; + return; + } else { + String fpath = ti->get_metadata(0); + if (section == 0) { + if (fpath.ends_with("/")) { + // We drop on a folder + target = fpath; + return; + } + } else { + if (ti->get_parent() != tree->get_root()->get_children()) { + // Not in the favorite section + if (fpath != "res://") { + // We drop between two files + if (fpath.ends_with("/")) { + fpath = fpath.substr(0, fpath.length() - 1); + } + target = fpath.get_base_dir(); + return; + } + } + } + } + } } - return String(); + return; } -void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) { - - //Right clicking ".." should clear current selection - if (files->get_item_text(p_item) == "..") { - for (int i = 0; i < files->get_item_count(); i++) { - files->unselect(i); - } - } +void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<String> p_paths) { + // Add options for files and folders + ERR_FAIL_COND(p_paths.empty()) Vector<String> filenames; Vector<String> foldernames; + Vector<String> favorites = EditorSettings::get_singleton()->get_favorites(); + bool all_files = true; bool all_files_scenes = true; bool all_folders = true; - for (int i = 0; i < files->get_item_count(); i++) { - if (!files->is_selected(i)) { - continue; - } - - String fpath = files->get_item_metadata(i); + bool all_favorites = true; + bool all_not_favorites = true; + for (int i = 0; i < p_paths.size(); i++) { + String fpath = p_paths[i]; if (fpath.ends_with("/")) { foldernames.push_back(fpath); all_files = false; @@ -1719,68 +2021,135 @@ void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) { all_folders = false; all_files_scenes &= (EditorFileSystem::get_singleton()->get_file_type(fpath) == "PackedScene"); } + + // Check if in favorites + bool found = false; + for (int j = 0; j < favorites.size(); j++) { + if (favorites[j] == fpath) { + found = true; + break; + } + } + if (found) { + all_not_favorites = false; + } else { + all_favorites = false; + } } - file_options->clear(); - file_options->set_size(Size2(1, 1)); if (all_files) { if (all_files_scenes && filenames.size() >= 1) { - file_options->add_item(TTR("Open Scene(s)"), FILE_OPEN); - file_options->add_item(TTR("Instance"), FILE_INSTANCE); - file_options->add_separator(); + p_popup->add_item(TTR("Open Scene(s)"), FILE_OPEN); + p_popup->add_item(TTR("Instance"), FILE_INSTANCE); + p_popup->add_separator(); } if (!all_files_scenes && filenames.size() == 1) { - file_options->add_item(TTR("Open"), FILE_OPEN); - file_options->add_separator(); + p_popup->add_item(TTR("Open"), FILE_OPEN); + p_popup->add_separator(); } + } + if (p_paths.size() >= 1) { + if (!all_favorites) { + p_popup->add_item(TTR("Add to favorites"), FILE_ADD_FAVORITE); + } + if (!all_not_favorites) { + p_popup->add_item(TTR("Remove from favorites"), FILE_REMOVE_FAVORITE); + } + p_popup->add_separator(); + } + + if (all_files) { if (filenames.size() == 1) { - file_options->add_item(TTR("Edit Dependencies..."), FILE_DEPENDENCIES); - file_options->add_item(TTR("View Owners..."), FILE_OWNERS); - file_options->add_separator(); + p_popup->add_item(TTR("Edit Dependencies..."), FILE_DEPENDENCIES); + p_popup->add_item(TTR("View Owners..."), FILE_OWNERS); + p_popup->add_separator(); } } else if (all_folders && foldernames.size() > 0) { - file_options->add_item(TTR("Open"), FILE_OPEN); - file_options->add_separator(); + p_popup->add_item(TTR("Open"), FILE_OPEN); + p_popup->add_separator(); } - int num_items = filenames.size() + foldernames.size(); - if (num_items >= 1) { - if (num_items == 1) { - file_options->add_item(TTR("Copy Path"), FILE_COPY_PATH); - file_options->add_item(TTR("Rename..."), FILE_RENAME); - file_options->add_item(TTR("Duplicate..."), FILE_DUPLICATE); - } - file_options->add_item(TTR("Move To..."), FILE_MOVE); - file_options->add_item(TTR("Delete"), FILE_REMOVE); - file_options->add_separator(); + if (p_paths.size() == 1) { + p_popup->add_item(TTR("Copy Path"), FILE_COPY_PATH); + p_popup->add_item(TTR("Rename..."), FILE_RENAME); + p_popup->add_item(TTR("Duplicate..."), FILE_DUPLICATE); } - file_options->add_item(TTR("New Folder..."), FILE_NEW_FOLDER); - file_options->add_item(TTR("New Script..."), FILE_NEW_SCRIPT); - file_options->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE); + p_popup->add_item(TTR("Move To..."), FILE_MOVE); + p_popup->add_item(TTR("Delete"), FILE_REMOVE); + + if (p_paths.size() == 1) { + p_popup->add_separator(); + p_popup->add_item(TTR("New Folder..."), FILE_NEW_FOLDER); + p_popup->add_item(TTR("New Script..."), FILE_NEW_SCRIPT); + p_popup->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE); - String fpath = files->get_item_metadata(p_item); - String item_text = fpath.ends_with("/") ? TTR("Open In File Manager") : TTR("Show In File Manager"); - file_options->add_item(item_text, FILE_SHOW_IN_EXPLORER); + String fpath = p_paths[0]; + String item_text = fpath.ends_with("/") ? TTR("Open In File Manager") : TTR("Show In File Manager"); + p_popup->add_item(item_text, FILE_SHOW_IN_EXPLORER); + } +} + +void FileSystemDock::_tree_rmb_select(const Vector2 &p_pos) { + // Right click is pressed in the tree + Vector<String> paths = _tree_get_selected(); + + if (paths.size() == 1) { + if (paths[0].ends_with("/")) { + tree_popup->add_item(TTR("Expand all"), FOLDER_EXPAND_ALL); + tree_popup->add_item(TTR("Collapse all"), FOLDER_COLLAPSE_ALL); + tree_popup->add_separator(); + } + } - file_options->set_position(files->get_global_position() + p_pos); - file_options->popup(); + // Popup + if (!paths.empty()) { + tree_popup->clear(); + tree_popup->set_size(Size2(1, 1)); + _file_and_folders_fill_popup(tree_popup, paths); + tree_popup->set_position(tree->get_global_position() + p_pos); + tree_popup->popup(); + } } -void FileSystemDock::_rmb_pressed(const Vector2 &p_pos) { - file_options->clear(); - file_options->set_size(Size2(1, 1)); +void FileSystemDock::_file_list_rmb_select(int p_item, const Vector2 &p_pos) { + // Right click is pressed in the file list + Vector<String> paths; + for (int i = 0; i < files->get_item_count(); i++) { + if (!files->is_selected(i)) + continue; + if (files->get_item_text(p_item) == "..") { + files->unselect(i); + continue; + } + paths.push_back(files->get_item_metadata(i)); + } + + // Popup + if (!paths.empty()) { + file_list_popup->clear(); + file_list_popup->set_size(Size2(1, 1)); + _file_and_folders_fill_popup(file_list_popup, paths); + file_list_popup->set_position(files->get_global_position() + p_pos); + file_list_popup->popup(); + } +} - file_options->add_item(TTR("New Folder..."), FILE_NEW_FOLDER); - file_options->add_item(TTR("New Script..."), FILE_NEW_SCRIPT); - file_options->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE); - file_options->add_item(TTR("Show In File Manager"), FILE_SHOW_IN_EXPLORER); - file_options->set_position(files->get_global_position() + p_pos); - file_options->popup(); +void FileSystemDock::_file_list_rmb_pressed(const Vector2 &p_pos) { + // Right click on empty space for file list + file_list_popup->clear(); + file_list_popup->set_size(Size2(1, 1)); + + file_list_popup->add_item(TTR("New Folder..."), FILE_NEW_FOLDER); + file_list_popup->add_item(TTR("New Script..."), FILE_NEW_SCRIPT); + file_list_popup->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE); + file_list_popup->add_item(TTR("Show In File Manager"), FILE_SHOW_IN_EXPLORER); + file_list_popup->set_position(files->get_global_position() + p_pos); + file_list_popup->popup(); } void FileSystemDock::select_file(const String &p_file) { @@ -1790,11 +2159,24 @@ void FileSystemDock::select_file(const String &p_file) { void FileSystemDock::_file_multi_selected(int p_index, bool p_selected) { + // Set the path to the current focussed item + int current = files->get_current(); + if (current == p_index) { + String fpath = files->get_item_metadata(current); + if (!fpath.ends_with("/")) { + path = fpath; + if (display_mode == DISPLAY_MODE_SPLIT) { + _update_tree(_compute_uncollapsed_paths()); + } + } + } + + // Update the import dock import_dock_needs_update = true; call_deferred("_update_import_dock"); } -void FileSystemDock::_files_gui_input(Ref<InputEvent> p_event) { +void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) { if (get_viewport()->get_modal_stack_top()) return; //ignore because of modal window @@ -1802,21 +2184,34 @@ void FileSystemDock::_files_gui_input(Ref<InputEvent> p_event) { Ref<InputEventKey> key = p_event; if (key.is_valid() && key->is_pressed() && !key->is_echo()) { if (ED_IS_SHORTCUT("filesystem_dock/duplicate", p_event)) { - _file_option(FILE_DUPLICATE); + _tree_rmb_option(FILE_DUPLICATE); } else if (ED_IS_SHORTCUT("filesystem_dock/copy_path", p_event)) { - _file_option(FILE_COPY_PATH); + _tree_rmb_option(FILE_COPY_PATH); } else if (ED_IS_SHORTCUT("filesystem_dock/delete", p_event)) { - _file_option(FILE_REMOVE); + _tree_rmb_option(FILE_REMOVE); } else if (ED_IS_SHORTCUT("filesystem_dock/rename", p_event)) { - _file_option(FILE_RENAME); + _tree_rmb_option(FILE_RENAME); } } } -void FileSystemDock::_file_selected() { +void FileSystemDock::_file_list_gui_input(Ref<InputEvent> p_event) { - import_dock_needs_update = true; - _update_import_dock(); + if (get_viewport()->get_modal_stack_top()) + return; //ignore because of modal window + + Ref<InputEventKey> key = p_event; + if (key.is_valid() && key->is_pressed() && !key->is_echo()) { + if (ED_IS_SHORTCUT("filesystem_dock/duplicate", p_event)) { + _file_list_rmb_option(FILE_DUPLICATE); + } else if (ED_IS_SHORTCUT("filesystem_dock/copy_path", p_event)) { + _file_list_rmb_option(FILE_COPY_PATH); + } else if (ED_IS_SHORTCUT("filesystem_dock/delete", p_event)) { + _file_list_rmb_option(FILE_REMOVE); + } else if (ED_IS_SHORTCUT("filesystem_dock/rename", p_event)) { + _file_list_rmb_option(FILE_RENAME); + } + } } void FileSystemDock::_update_import_dock() { @@ -1824,15 +2219,33 @@ void FileSystemDock::_update_import_dock() { if (!import_dock_needs_update) return; - //check import + // List selected + Vector<String> selected; + if (display_mode_setting == DISPLAY_MODE_SETTING_TREE_ONLY) { + // Use the tree + selected = _tree_get_selected(); + + } else { + // Use the file list + for (int i = 0; i < files->get_item_count(); i++) { + if (!files->is_selected(i)) + continue; + + selected.push_back(files->get_item_metadata(i)); + } + } + + // Check import Vector<String> imports; String import_type; + for (int i = 0; i < selected.size(); i++) { + String fpath = selected[i]; - for (int i = 0; i < files->get_item_count(); i++) { - if (!files->is_selected(i)) - continue; + if (fpath.ends_with("/")) { + imports.clear(); + break; + } - String fpath = files->get_item_metadata(i); if (!FileAccess::exists(fpath + ".import")) { imports.clear(); break; @@ -1869,16 +2282,25 @@ void FileSystemDock::_update_import_dock() { void FileSystemDock::_bind_methods() { - ClassDB::bind_method(D_METHOD("_files_gui_input"), &FileSystemDock::_files_gui_input); + ClassDB::bind_method(D_METHOD("_file_list_gui_input"), &FileSystemDock::_file_list_gui_input); + ClassDB::bind_method(D_METHOD("_tree_gui_input"), &FileSystemDock::_tree_gui_input); + ClassDB::bind_method(D_METHOD("_update_tree"), &FileSystemDock::_update_tree); ClassDB::bind_method(D_METHOD("_rescan"), &FileSystemDock::_rescan); - ClassDB::bind_method(D_METHOD("_favorites_pressed"), &FileSystemDock::_favorites_pressed); - ClassDB::bind_method(D_METHOD("_show_current_scene_file"), &FileSystemDock::_show_current_scene_file); - //ClassDB::bind_method(D_METHOD("_instance_pressed"),&ScenesDock::_instance_pressed); - ClassDB::bind_method(D_METHOD("_go_to_file_list"), &FileSystemDock::_go_to_file_list); - ClassDB::bind_method(D_METHOD("_dir_rmb_pressed"), &FileSystemDock::_dir_rmb_pressed); - ClassDB::bind_method(D_METHOD("_thumbnail_done"), &FileSystemDock::_thumbnail_done); + ClassDB::bind_method(D_METHOD("_toggle_split_mode"), &FileSystemDock::_toggle_split_mode); + + ClassDB::bind_method(D_METHOD("_tree_rmb_option", "option"), &FileSystemDock::_tree_rmb_option); + ClassDB::bind_method(D_METHOD("_file_list_rmb_option", "option"), &FileSystemDock::_file_list_rmb_option); + + ClassDB::bind_method(D_METHOD("_tree_rmb_select"), &FileSystemDock::_tree_rmb_select); + ClassDB::bind_method(D_METHOD("_file_list_rmb_select"), &FileSystemDock::_file_list_rmb_select); + ClassDB::bind_method(D_METHOD("_file_list_rmb_pressed"), &FileSystemDock::_file_list_rmb_pressed); + + ClassDB::bind_method(D_METHOD("_file_list_thumbnail_done"), &FileSystemDock::_file_list_thumbnail_done); + ClassDB::bind_method(D_METHOD("_tree_thumbnail_done"), &FileSystemDock::_tree_thumbnail_done); + ClassDB::bind_method(D_METHOD("_file_list_activate_file"), &FileSystemDock::_file_list_activate_file); + ClassDB::bind_method(D_METHOD("_tree_activate_file"), &FileSystemDock::_tree_activate_file); ClassDB::bind_method(D_METHOD("_select_file"), &FileSystemDock::_select_file); ClassDB::bind_method(D_METHOD("_go_to_tree"), &FileSystemDock::_go_to_tree); ClassDB::bind_method(D_METHOD("navigate_to_path"), &FileSystemDock::navigate_to_path); @@ -1886,9 +2308,7 @@ void FileSystemDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_fw_history"), &FileSystemDock::_fw_history); ClassDB::bind_method(D_METHOD("_bw_history"), &FileSystemDock::_bw_history); ClassDB::bind_method(D_METHOD("_fs_changed"), &FileSystemDock::_fs_changed); - ClassDB::bind_method(D_METHOD("_dir_selected"), &FileSystemDock::_dir_selected); - ClassDB::bind_method(D_METHOD("_file_option"), &FileSystemDock::_file_option); - ClassDB::bind_method(D_METHOD("_folder_option"), &FileSystemDock::_folder_option); + ClassDB::bind_method(D_METHOD("_tree_multi_selected"), &FileSystemDock::_tree_multi_selected); ClassDB::bind_method(D_METHOD("_make_dir_confirm"), &FileSystemDock::_make_dir_confirm); ClassDB::bind_method(D_METHOD("_resource_created"), &FileSystemDock::_resource_created); ClassDB::bind_method(D_METHOD("_move_operation_confirm", "to_path", "overwrite"), &FileSystemDock::_move_operation_confirm, DEFVAL(false)); @@ -1901,13 +2321,10 @@ void FileSystemDock::_bind_methods() { ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &FileSystemDock::get_drag_data_fw); ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &FileSystemDock::can_drop_data_fw); ClassDB::bind_method(D_METHOD("drop_data_fw"), &FileSystemDock::drop_data_fw); - ClassDB::bind_method(D_METHOD("_files_list_rmb_select"), &FileSystemDock::_files_list_rmb_select); ClassDB::bind_method(D_METHOD("_preview_invalidated"), &FileSystemDock::_preview_invalidated); - ClassDB::bind_method(D_METHOD("_file_selected"), &FileSystemDock::_file_selected); ClassDB::bind_method(D_METHOD("_file_multi_selected"), &FileSystemDock::_file_multi_selected); ClassDB::bind_method(D_METHOD("_update_import_dock"), &FileSystemDock::_update_import_dock); - ClassDB::bind_method(D_METHOD("_rmb_pressed"), &FileSystemDock::_rmb_pressed); ADD_SIGNAL(MethodInfo("instance", PropertyInfo(Variant::POOL_STRING_ARRAY, "files"))); ADD_SIGNAL(MethodInfo("open")); @@ -1924,9 +2341,12 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { ED_SHORTCUT("filesystem_dock/delete", TTR("Delete"), KEY_DELETE); ED_SHORTCUT("filesystem_dock/rename", TTR("Rename")); + VBoxContainer *top_vbc = memnew(VBoxContainer); + add_child(top_vbc); + HBoxContainer *toolbar_hbc = memnew(HBoxContainer); toolbar_hbc->add_constant_override("separation", 0); - add_child(toolbar_hbc); + top_vbc->add_child(toolbar_hbc); button_hist_prev = memnew(ToolButton); button_hist_prev->set_disabled(true); @@ -1942,6 +2362,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { current_path = memnew(LineEdit); current_path->set_h_size_flags(SIZE_EXPAND_FILL); + _set_current_path_text(path); toolbar_hbc->add_child(current_path); button_reload = memnew(Button); @@ -1952,22 +2373,25 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { button_reload->hide(); toolbar_hbc->add_child(button_reload); - //toolbar_hbc->add_spacer(); + button_toggle_display_mode = memnew(Button); + button_toggle_display_mode->set_flat(true); + button_toggle_display_mode->set_toggle_mode(true); + button_toggle_display_mode->connect("toggled", this, "_toggle_split_mode"); + button_toggle_display_mode->set_focus_mode(FOCUS_NONE); + button_toggle_display_mode->set_tooltip(TTR("Toggle split mode")); + toolbar_hbc->add_child(button_toggle_display_mode); + + HBoxContainer *toolbar2_hbc = memnew(HBoxContainer); + toolbar2_hbc->add_constant_override("separation", 0); + top_vbc->add_child(toolbar2_hbc); + + tree_search_box = memnew(LineEdit); + tree_search_box->set_h_size_flags(SIZE_EXPAND_FILL); + tree_search_box->set_placeholder(TTR("Search files")); + tree_search_box->connect("text_changed", this, "_search_changed", varray(tree_search_box)); + toolbar2_hbc->add_child(tree_search_box); - button_favorite = memnew(Button); - button_favorite->set_flat(true); - button_favorite->set_toggle_mode(true); - button_favorite->connect("pressed", this, "_favorites_pressed"); - button_favorite->set_tooltip(TTR("Toggle folder status as Favorite.")); - button_favorite->set_focus_mode(FOCUS_NONE); - toolbar_hbc->add_child(button_favorite); - - button_show = memnew(Button); - button_show->set_flat(true); - button_show->connect("pressed", this, "_show_current_scene_file"); - toolbar_hbc->add_child(button_show); - button_show->set_focus_mode(FOCUS_NONE); - button_show->set_tooltip(TTR("Show current scene file.")); + //toolbar_hbc->add_spacer(); //Control *spacer = memnew( Control); @@ -1990,13 +2414,13 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { button_instance->set_tooltip(TTR("Instance the selected scene(s) as child of the selected node.")); */ - file_options = memnew(PopupMenu); - file_options->set_hide_on_window_lose_focus(true); - add_child(file_options); + file_list_popup = memnew(PopupMenu); + file_list_popup->set_hide_on_window_lose_focus(true); + add_child(file_list_popup); - folder_options = memnew(PopupMenu); - folder_options->set_hide_on_window_lose_focus(true); - add_child(folder_options); + tree_popup = memnew(PopupMenu); + tree_popup->set_hide_on_window_lose_focus(true); + add_child(tree_popup); split_box = memnew(VSplitContainer); split_box->set_v_size_flags(SIZE_EXPAND_FILL); @@ -2007,13 +2431,15 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { tree->set_hide_root(true); tree->set_drag_forwarding(this); tree->set_allow_rmb_select(true); - tree->set_custom_minimum_size(Size2(0, 200 * EDSCALE)); + tree->set_select_mode(Tree::SELECT_MULTI); + tree->set_custom_minimum_size(Size2(0, 15 * EDSCALE)); split_box->add_child(tree); tree->connect("item_edited", this, "_favorite_toggled"); - tree->connect("item_activated", this, "_go_to_file_list"); - tree->connect("cell_selected", this, "_dir_selected"); - tree->connect("item_rmb_selected", this, "_dir_rmb_pressed"); + tree->connect("item_activated", this, "_tree_activate_file"); + tree->connect("multi_selected", this, "_tree_multi_selected"); + tree->connect("item_rmb_selected", this, "_tree_rmb_select"); + tree->connect("gui_input", this, "_tree_gui_input"); file_list_vb = memnew(VBoxContainer); file_list_vb->set_v_size_flags(SIZE_EXPAND_FILL); @@ -2027,11 +2453,11 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { button_tree->hide(); path_hb->add_child(button_tree); - search_box = memnew(LineEdit); - search_box->set_h_size_flags(SIZE_EXPAND_FILL); - search_box->set_placeholder(TTR("Search files")); - search_box->connect("text_changed", this, "_search_changed"); - path_hb->add_child(search_box); + file_list_search_box = memnew(LineEdit); + file_list_search_box->set_h_size_flags(SIZE_EXPAND_FILL); + file_list_search_box->set_placeholder(TTR("Search files")); + file_list_search_box->connect("text_changed", this, "_search_changed", varray(file_list_search_box)); + path_hb->add_child(file_list_search_box); button_file_list_display_mode = memnew(ToolButton); button_file_list_display_mode->set_toggle_mode(true); @@ -2041,11 +2467,11 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { files->set_v_size_flags(SIZE_EXPAND_FILL); files->set_select_mode(ItemList::SELECT_MULTI); files->set_drag_forwarding(this); - files->connect("item_rmb_selected", this, "_files_list_rmb_select"); - files->connect("gui_input", this, "_files_gui_input"); - files->connect("item_selected", this, "_file_selected"); + files->connect("item_rmb_selected", this, "_file_list_rmb_select"); + files->connect("gui_input", this, "_file_list_gui_input"); files->connect("multi_selected", this, "_file_multi_selected"); - files->connect("rmb_clicked", this, "_rmb_pressed"); + files->connect("rmb_clicked", this, "_file_list_rmb_pressed"); + files->set_custom_minimum_size(Size2(0, 15 * EDSCALE)); files->set_allow_rmb_select(true); file_list_vb->add_child(files); @@ -2123,7 +2549,11 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { new_resource_dialog->set_base_type("Resource"); new_resource_dialog->connect("create", this, "_resource_created"); + searched_string = String(); + uncollapsed_paths_before_search = Vector<String>(); + updating_tree = false; + tree_update_id = 0; initialized = false; import_dock_needs_update = false; @@ -2131,8 +2561,12 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { history_max_size = 20; history.push_back("res://"); - display_mode = DISPLAY_SPLIT; + display_mode = DISPLAY_MODE_SPLIT; file_list_display_mode = FILE_LIST_DISPLAY_THUMBNAILS; + + display_mode_setting = DISPLAY_MODE_SETTING_TREE_ONLY; + old_display_mode_setting = DISPLAY_MODE_SETTING_TREE_ONLY; + always_show_folders = false; } FileSystemDock::~FileSystemDock() { diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 40be645bf7..d964515572 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -66,15 +66,22 @@ public: }; private: + enum DisplayModeSetting { + DISPLAY_MODE_SETTING_TREE_ONLY, + DISPLAY_MODE_SETTING_SPLIT, + }; + enum DisplayMode { - DISPLAY_TREE_ONLY, - DISPLAY_FILE_LIST_ONLY, - DISPLAY_SPLIT, + DISPLAY_MODE_TREE_ONLY, + DISPLAY_MODE_FILE_LIST_ONLY, + DISPLAY_MODE_SPLIT, }; enum FileMenu { FILE_OPEN, FILE_INSTANCE, + FILE_ADD_FAVORITE, + FILE_REMOVE_FAVORITE, FILE_DEPENDENCIES, FILE_OWNERS, FILE_MOVE, @@ -87,18 +94,9 @@ private: FILE_NEW_SCRIPT, FILE_SHOW_IN_EXPLORER, FILE_COPY_PATH, - FILE_NEW_RESOURCE - }; - - enum FolderMenu { + FILE_NEW_RESOURCE, FOLDER_EXPAND_ALL, FOLDER_COLLAPSE_ALL, - FOLDER_MOVE, - FOLDER_RENAME, - FOLDER_REMOVE, - FOLDER_NEW_FOLDER, - FOLDER_SHOW_IN_EXPLORER, - FOLDER_COPY_PATH }; VBoxContainer *scanning_vb; @@ -109,24 +107,30 @@ private: EditorNode *editor; Set<String> favorites; + Button *button_toggle_display_mode; Button *button_reload; - Button *button_favorite; Button *button_tree; Button *button_file_list_display_mode; Button *button_hist_next; Button *button_hist_prev; - Button *button_show; LineEdit *current_path; - LineEdit *search_box; + LineEdit *tree_search_box; + LineEdit *file_list_search_box; + + String searched_string; + Vector<String> uncollapsed_paths_before_search; + TextureRect *search_icon; HBoxContainer *path_hb; FileListDisplayMode file_list_display_mode; DisplayMode display_mode; + DisplayModeSetting display_mode_setting; + DisplayModeSetting old_display_mode_setting; bool file_list_view; - PopupMenu *file_options; - PopupMenu *folder_options; + PopupMenu *file_list_popup; + PopupMenu *tree_popup; DependencyEditor *deps_editor; DependencyEditorOwners *owners_editor; @@ -143,6 +147,8 @@ private: ScriptCreateDialog *make_script_dialog_text; CreateDialog *new_resource_dialog; + bool always_show_folders; + class FileOrFolder { public: String path; @@ -169,16 +175,20 @@ private: bool initialized; bool updating_tree; + int tree_update_id; Tree *tree; //directories ItemList *files; bool import_dock_needs_update; + Ref<Texture> _get_tree_item_icon(EditorFileSystemDirectory *p_dir, int p_idx); bool _create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths); - void _update_tree(bool keep_collapse_state, bool p_uncollapse_root = false); + Vector<String> _compute_uncollapsed_paths(); + void _update_tree(const Vector<String> p_uncollapsed_paths = Vector<String>(), bool p_uncollapse_root = false); - void _files_gui_input(Ref<InputEvent> p_event); + void _file_list_gui_input(Ref<InputEvent> p_event); + void _tree_gui_input(Ref<InputEvent> p_event); - void _update_files(bool p_keep_selection); + void _update_file_list(bool p_keep_selection); void _update_file_list_display_mode_button(); void _change_file_display(); void _fs_changed(); @@ -186,12 +196,13 @@ private: void _go_to_tree(); void _go_to_file_list(); - void _select_file(int p_idx); + void _select_file(const String p_path); + void _tree_activate_file(); + void _file_list_activate_file(int p_idx); void _file_multi_selected(int p_index, bool p_selected); - void _update_import_dock(); + void _tree_multi_selected(Object *p_item, int p_column, bool p_selected); - void _file_selected(); - void _dir_selected(); + void _update_import_dock(); void _get_all_items_in_dir(EditorFileSystemDirectory *efsd, Vector<String> &files, Vector<String> &folders) const; void _find_remaps(EditorFileSystemDirectory *efsd, const Map<String, String> &renames, Vector<String> &to_remaps) const; @@ -199,8 +210,8 @@ private: void _try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const; void _update_dependencies_after_move(const Map<String, String> &p_renames) const; void _update_resource_paths_after_move(const Map<String, String> &p_renames) const; - void _update_favorite_dirs_list_after_move(const Map<String, String> &p_renames) const; - void _update_project_settings_after_move(const Map<String, String> &p_renames) const; + void _update_favorites_list_after_move(const Map<String, String> &p_files_renames, const Map<String, String> &p_folders_renames) const; + void _update_project_settings_after_move(const Map<String, String> &p_folders_renames) const; void _resource_created() const; void _make_dir_confirm(); @@ -210,8 +221,9 @@ private: bool _check_existing(); void _move_operation_confirm(const String &p_to_path, bool overwrite = false); - void _file_option(int p_option); - void _folder_option(int p_option); + void _tree_rmb_option(int p_option); + void _file_list_rmb_option(int p_option); + void _file_option(int p_option, const Vector<String> p_selected); void _fw_history(); void _bw_history(); @@ -221,13 +233,14 @@ private: void _set_scanning_mode(); void _rescan(); - void _favorites_pressed(); - void _show_current_scene_file(); - void _search_changed(const String &p_text); + void _toggle_split_mode(bool p_active); - void _dir_rmb_pressed(const Vector2 &p_pos); - void _files_list_rmb_select(int p_item, const Vector2 &p_pos); - void _rmb_pressed(const Vector2 &p_pos); + void _search_changed(const String &p_text, const Control *p_from); + + void _file_and_folders_fill_popup(PopupMenu *p_popup, Vector<String> p_paths); + void _tree_rmb_select(const Vector2 &p_pos); + void _file_list_rmb_select(int p_item, const Vector2 &p_pos); + void _file_list_rmb_pressed(const Vector2 &p_pos); struct FileInfo { String name; @@ -238,22 +251,27 @@ private: bool import_broken; bool operator<(const FileInfo &fi) const { - return name < fi.name; + return NaturalNoCaseComparator()(name, fi.name); } }; void _search(EditorFileSystemDirectory *p_path, List<FileInfo> *matches, int p_max_items); + void _set_current_path_text(const String &p_path); + 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); - String _get_drag_target_folder(const Point2 &p_point, Control *p_from) const; + void _get_drag_target_folder(String &target, bool &target_favorites, const Point2 &p_point, Control *p_from) const; void _preview_invalidated(const String &p_path); - void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata); + void _file_list_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata); + void _tree_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata); void _update_display_mode(); + Vector<String> _tree_get_selected(bool remove_self_inclusion = true); + protected: void _notification(int p_what); static void _bind_methods(); diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index 11d0b67bd6..2af81b8ac7 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -302,7 +302,7 @@ FindInFilesDialog::FindInFilesDialog() { set_custom_minimum_size(Size2(400, 190)); set_resizable(true); - set_title(TTR("Find in files")); + set_title(TTR("Find in Files")); VBoxContainer *vbc = memnew(VBoxContainer); vbc->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 8 * EDSCALE); @@ -406,11 +406,8 @@ FindInFilesDialog::FindInFilesDialog() { HBoxContainer *hbc = memnew(HBoxContainer); hbc->set_alignment(HBoxContainer::ALIGN_CENTER); - _find_button = memnew(Button); - _find_button->set_text(TTR("Find...")); - _find_button->connect("pressed", this, "_on_find_button_pressed"); + _find_button = add_button(TTR("Find..."), false, "find"); _find_button->set_disabled(true); - hbc->add_child(_find_button); { Control *placeholder = memnew(Control); @@ -418,11 +415,8 @@ FindInFilesDialog::FindInFilesDialog() { hbc->add_child(placeholder); } - _replace_button = memnew(Button); - _replace_button->set_text(TTR("Replace...")); - _replace_button->connect("pressed", this, "_on_replace_button_pressed"); + _replace_button = add_button(TTR("Replace..."), false, "replace"); _replace_button->set_disabled(true); - hbc->add_child(_replace_button); { Control *placeholder = memnew(Control); @@ -430,10 +424,8 @@ FindInFilesDialog::FindInFilesDialog() { hbc->add_child(placeholder); } - Button *cancel_button = memnew(Button); + Button *cancel_button = get_ok(); cancel_button->set_text(TTR("Cancel")); - cancel_button->connect("pressed", this, "hide"); - hbc->add_child(cancel_button); vbc->add_child(hbc); } @@ -487,14 +479,14 @@ void FindInFilesDialog::_on_folder_button_pressed() { _folder_dialog->popup_centered_ratio(); } -void FindInFilesDialog::_on_find_button_pressed() { - emit_signal(SIGNAL_FIND_REQUESTED); - hide(); -} - -void FindInFilesDialog::_on_replace_button_pressed() { - emit_signal(SIGNAL_REPLACE_REQUESTED); - hide(); +void FindInFilesDialog::custom_action(const String &p_action) { + if (p_action == "find") { + emit_signal(SIGNAL_FIND_REQUESTED); + hide(); + } else if (p_action == "replace") { + emit_signal(SIGNAL_REPLACE_REQUESTED); + hide(); + } } void FindInFilesDialog::_on_search_text_modified(String text) { @@ -509,7 +501,7 @@ void FindInFilesDialog::_on_search_text_modified(String text) { void FindInFilesDialog::_on_search_text_entered(String text) { // This allows to trigger a global search without leaving the keyboard if (!_find_button->is_disabled()) - _on_find_button_pressed(); + custom_action("find"); } void FindInFilesDialog::_on_folder_selected(String path) { @@ -522,8 +514,6 @@ void FindInFilesDialog::_on_folder_selected(String path) { void FindInFilesDialog::_bind_methods() { ClassDB::bind_method("_on_folder_button_pressed", &FindInFilesDialog::_on_folder_button_pressed); - ClassDB::bind_method("_on_find_button_pressed", &FindInFilesDialog::_on_find_button_pressed); - ClassDB::bind_method("_on_replace_button_pressed", &FindInFilesDialog::_on_replace_button_pressed); ClassDB::bind_method("_on_folder_selected", &FindInFilesDialog::_on_folder_selected); ClassDB::bind_method("_on_search_text_modified", &FindInFilesDialog::_on_search_text_modified); ClassDB::bind_method("_on_search_text_entered", &FindInFilesDialog::_on_search_text_entered); diff --git a/editor/find_in_files.h b/editor/find_in_files.h index 75ea1c3161..7f37123430 100644 --- a/editor/find_in_files.h +++ b/editor/find_in_files.h @@ -91,8 +91,8 @@ class CheckBox; class FileDialog; // Prompts search parameters -class FindInFilesDialog : public WindowDialog { - GDCLASS(FindInFilesDialog, WindowDialog) +class FindInFilesDialog : public AcceptDialog { + GDCLASS(FindInFilesDialog, AcceptDialog) public: static const char *SIGNAL_FIND_REQUESTED; static const char *SIGNAL_REPLACE_REQUESTED; @@ -111,11 +111,10 @@ protected: static void _bind_methods(); void _notification(int p_what); + void custom_action(const String &p_action); private: void _on_folder_button_pressed(); - void _on_find_button_pressed(); - void _on_replace_button_pressed(); void _on_folder_selected(String path); void _on_search_text_modified(String text); void _on_search_text_entered(String text); diff --git a/editor/icons/SCsub b/editor/icons/SCsub index 31bf8f116a..109e1aa83b 100644 --- a/editor/icons/SCsub +++ b/editor/icons/SCsub @@ -1,15 +1,13 @@ #!/usr/bin/env python Import('env') + from platform_methods import run_in_subprocess import editor_icons_builders - make_editor_icons_builder = Builder(action=run_in_subprocess(editor_icons_builders.make_editor_icons_action), suffix='.h', src_suffix='.svg') env['BUILDERS']['MakeEditorIconsBuilder'] = make_editor_icons_builder env.Alias('editor_icons', [env.MakeEditorIconsBuilder('#editor/editor_icons.gen.h', Glob("*.svg"))]) - -Export('env') diff --git a/editor/icons/icon_GUI_viewport_hdiagsplitter.svg b/editor/icons/icon_GUI_viewport_hdiagsplitter.svg new file mode 100644 index 0000000000..36769768fd --- /dev/null +++ b/editor/icons/icon_GUI_viewport_hdiagsplitter.svg @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="64" + height="34" + version="1.1" + viewBox="0 0 64 34" + id="svg6" + sodipodi:docname="icon_GUI_vsplitter1.svg" + inkscape:version="0.92.2 2405546, 2018-03-11"> + <metadata + id="metadata12"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs10" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1366" + inkscape:window-height="714" + id="namedview8" + showgrid="false" + inkscape:zoom="5.6568543" + inkscape:cx="37.006499" + inkscape:cy="15.680715" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg6" /> + <g + transform="translate(0,-1018.4)" + id="g4" /> + <g + transform="rotate(90,541.2,539.2)" + id="g4-3"> + <path + id="path2-6" + style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-opacity:0.39216003" + d="M 4.0306826,1048.4 H 34 m -30,30 v -60" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + </g> +</svg> diff --git a/editor/icons/icon_GUI_viewport_vdiagsplitter.svg b/editor/icons/icon_GUI_viewport_vdiagsplitter.svg new file mode 100644 index 0000000000..f23b4a0a74 --- /dev/null +++ b/editor/icons/icon_GUI_viewport_vdiagsplitter.svg @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="34" + height="64" + version="1.1" + viewBox="0 0 34 64" + id="svg6" + sodipodi:docname="icon_GUI_vsplitter2.svg" + inkscape:version="0.92.2 2405546, 2018-03-11"> + <metadata + id="metadata12"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs10" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1366" + inkscape:window-height="714" + id="namedview8" + showgrid="false" + inkscape:zoom="4" + inkscape:cx="32.245723" + inkscape:cy="44.255214" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg6" /> + <g + transform="translate(0,-988.4)" + id="g4" /> + <g + id="g839" + transform="rotate(90,32.003536,32.003535)"> + <g + id="g4-3" + transform="rotate(90,526.2,554.2)"> + <path + sodipodi:nodetypes="cccc" + inkscape:connector-curvature="0" + d="M 4.0306826,1048.4 H 34 m -30,30 v -60" + style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-opacity:0.39216003" + id="path2-6" /> + </g> + </g> +</svg> diff --git a/editor/icons/icon_GUI_viewport_vhsplitter.svg b/editor/icons/icon_GUI_viewport_vhsplitter.svg new file mode 100644 index 0000000000..429cf909ae --- /dev/null +++ b/editor/icons/icon_GUI_viewport_vhsplitter.svg @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="64" + height="64" + version="1.1" + viewBox="0 0 64 64" + id="svg6" + sodipodi:docname="icon_GUI_vsplitter.svg" + inkscape:version="0.92.2 2405546, 2018-03-11"> + <metadata + id="metadata12"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs10" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1366" + inkscape:window-height="714" + id="namedview8" + showgrid="false" + inkscape:zoom="4.65625" + inkscape:cx="9.8488117" + inkscape:cy="20.04653" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg6" /> + <g + transform="translate(0,-988.4)" + id="g4" /> + <g + transform="rotate(90,526.2,554.2)" + id="g4-3"> + <path + id="path2-6" + style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-opacity:0.39216003" + d="m -26,1048.4 h 60 m -30,30 v -60" + inkscape:connector-curvature="0" /> + </g> +</svg> diff --git a/editor/icons/icon_text_file.svg b/editor/icons/icon_text_file.svg new file mode 100644 index 0000000000..342a407b79 --- /dev/null +++ b/editor/icons/icon_text_file.svg @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg8" + sodipodi:docname="icon_text_file.svg" + inkscape:version="0.92.2 2405546, 2018-03-11" + enable-background="new"> + <metadata + id="metadata14"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs12" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="2560" + inkscape:window-height="1440" + id="namedview10" + showgrid="false" + inkscape:zoom="64" + inkscape:cx="-0.11275433" + inkscape:cy="5.0633688" + inkscape:window-x="1920" + inkscape:window-y="0" + inkscape:window-maximized="0" + inkscape:current-layer="svg8" + inkscape:snap-grids="true" /> + <path + style="display:inline;fill:#e0e0e0" + d="m 13.370548,12.198712 c 0.359546,-0.0075 0.719092,-0.015 1.078638,-0.0225 -0.004,-0.738576 -0.008,-1.477152 -0.01198,-2.215728 -1.429703,0.011985 -2.859406,0.02397 -4.289109,0.035955 0.004,0.759672 0.008,1.519344 0.01198,2.279016 0.40349,-0.01135 0.806981,-0.02271 1.210471,-0.03406 0,1.251681 0,2.503363 0,3.755044 0.666667,0 1.333333,0 2,0 M 6.1005477,12.247152 c 0.332722,0.21587 0.665444,0.431741 0.998166,0.647611 -0.3328629,0.218648 -0.6657258,0.437297 -0.9985887,0.655945 -1e-7,0.818044 -2e-7,1.636088 -3e-7,2.454132 0.5662705,-0.533749 1.1325409,-1.067498 1.6988114,-1.601247 0.6353035,0.532396 1.2706071,1.064791 1.9059106,1.597187 -9.5e-4,-0.757409 -0.0019,-1.514817 -0.00285,-2.272226 -0.2987204,-0.278501 -0.5974407,-0.557002 -0.8961611,-0.835503 0.2983766,-0.205775 0.5967531,-0.41155 0.8951297,-0.617325 0.00283,-0.73844 0.00565,-1.476881 0.00848,-2.215321 -0.63732,0.474447 -1.27464,0.948893 -1.91196,1.42334 C 7.2318406,10.979446 6.6661958,10.475146 6.1005511,9.9708468 M 4.6399123,12.202271 c 0.3595459,-0.0075 0.7190917,-0.015 1.0786376,-0.0225 -0.00399,-0.738576 -0.00799,-1.477152 -0.011985,-2.2157276 -1.4297028,0.011985 -2.8594057,0.02397 -4.2891085,0.035955 0.00399,0.7596716 0.00799,1.5193436 0.011985,2.2790156 0.4034903,-0.01135 0.8069806,-0.02271 1.2104709,-0.03406 0,1.251681 0,2.503363 0,3.755044 0.6666667,0 1.3333333,0 2,0 M 7,1 C 6.81185,1.7526 6.6237,2.5052 6.43555,3.2578 6.0521572,3.3957205 5.6943609,3.6619566 5.3589944,3.3047548 4.8252629,2.9844032 4.2915315,2.6640516 3.7578,2.3437 3.2864333,2.8150667 2.8150667,3.2864333 2.3437,3.7578 2.7421333,4.4225 3.1405667,5.0872 3.539,5.7519 3.3683054,6.121632 3.3058712,6.5625877 2.8157946,6.5467719 2.2105097,6.6978312 1.6052249,6.8488906 0.99994,6.99995 c 0,0.6666667 0,1.3333333 0,2 1.7571667,0 3.5143333,0 5.2715,0 C 5.5845118,7.9199003 6.2580962,6.3373839 7.5001288,6.0629153 8.7083679,5.7047153 10.045643,6.7406952 9.99996,7.99995 c 0.104409,0.4657408 -0.6052318,1.1778026 0.181951,1 1.606006,0 3.212013,0 4.818019,0 0,-0.6666667 0,-1.3333333 0,-2 C 14.24733,6.8118 13.49473,6.62365 12.74213,6.4355 12.603459,6.0528244 12.33852,5.6958457 12.695012,5.3607965 13.015418,4.8264643 13.335824,4.2921322 13.65623,3.7578 13.184863,3.2864333 12.713497,2.8150667 12.24213,2.3437 11.57743,2.7421333 10.91273,3.1405667 10.24803,3.539 9.8782981,3.3683053 9.4373423,3.3058712 9.4531581,2.8157946 9.3020988,2.2105097 9.1510394,1.6052249 8.99998,0.99994 8.3333478,0.99998002 7.6664935,0.99985998 7,1 Z" + id="path4781-7" + inkscape:connector-curvature="0" /> +</svg> diff --git a/editor/import/SCsub b/editor/import/SCsub index f1fa50148f..2b1e889fb0 100644 --- a/editor/import/SCsub +++ b/editor/import/SCsub @@ -1,5 +1,5 @@ #!/usr/bin/env python Import('env') -Export('env') + env.add_source_files(env.editor_sources, "*.cpp") diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index 31c1886d32..60ca66e464 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -490,120 +490,6 @@ Error ColladaImport::_create_material(const String &p_target) { return OK; } -static void _generate_normals(const PoolVector<int> &p_indices, const PoolVector<Vector3> &p_vertices, PoolVector<Vector3> &r_normals) { - - r_normals.resize(p_vertices.size()); - PoolVector<Vector3>::Write narrayw = r_normals.write(); - - int iacount = p_indices.size() / 3; - PoolVector<int>::Read index_arrayr = p_indices.read(); - PoolVector<Vector3>::Read vertex_arrayr = p_vertices.read(); - - for (int idx = 0; idx < iacount; idx++) { - - Vector3 v[3] = { - vertex_arrayr[index_arrayr[idx * 3 + 0]], - vertex_arrayr[index_arrayr[idx * 3 + 1]], - vertex_arrayr[index_arrayr[idx * 3 + 2]] - }; - - Vector3 normal = Plane(v[0], v[1], v[2]).normal; - - narrayw[index_arrayr[idx * 3 + 0]] += normal; - narrayw[index_arrayr[idx * 3 + 1]] += normal; - narrayw[index_arrayr[idx * 3 + 2]] += normal; - } - - int vlen = p_vertices.size(); - - for (int idx = 0; idx < vlen; idx++) { - narrayw[idx].normalize(); - } -} - -static void _generate_tangents_and_binormals(const PoolVector<int> &p_indices, const PoolVector<Vector3> &p_vertices, const PoolVector<Vector3> &p_uvs, const PoolVector<Vector3> &p_normals, PoolVector<real_t> &r_tangents) { - - int vlen = p_vertices.size(); - - Vector<Vector3> tangents; - tangents.resize(vlen); - Vector<Vector3> binormals; - binormals.resize(vlen); - - int iacount = p_indices.size() / 3; - - PoolVector<int>::Read index_arrayr = p_indices.read(); - PoolVector<Vector3>::Read vertex_arrayr = p_vertices.read(); - PoolVector<Vector3>::Read narrayr = p_normals.read(); - PoolVector<Vector3>::Read uvarrayr = p_uvs.read(); - - for (int idx = 0; idx < iacount; idx++) { - - Vector3 v1 = vertex_arrayr[index_arrayr[idx * 3 + 0]]; - Vector3 v2 = vertex_arrayr[index_arrayr[idx * 3 + 1]]; - Vector3 v3 = vertex_arrayr[index_arrayr[idx * 3 + 2]]; - - Vector3 w1 = uvarrayr[index_arrayr[idx * 3 + 0]]; - Vector3 w2 = uvarrayr[index_arrayr[idx * 3 + 1]]; - Vector3 w3 = uvarrayr[index_arrayr[idx * 3 + 2]]; - - real_t x1 = v2.x - v1.x; - real_t x2 = v3.x - v1.x; - real_t y1 = v2.y - v1.y; - real_t y2 = v3.y - v1.y; - real_t z1 = v2.z - v1.z; - real_t z2 = v3.z - v1.z; - - real_t s1 = w2.x - w1.x; - real_t s2 = w3.x - w1.x; - real_t t1 = w2.y - w1.y; - real_t t2 = w3.y - w1.y; - - real_t r = (s1 * t2 - s2 * t1); - - Vector3 tangent; - Vector3 binormal; - - if (r == 0) { - - binormal = Vector3(); - tangent = Vector3(); - } else { - tangent = Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, - (t2 * z1 - t1 * z2) * r) - .normalized(); - binormal = Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, - (s1 * z2 - s2 * z1) * r) - .normalized(); - } - - tangents.write[index_arrayr[idx * 3 + 0]] += tangent; - binormals.write[index_arrayr[idx * 3 + 0]] += binormal; - tangents.write[index_arrayr[idx * 3 + 1]] += tangent; - binormals.write[index_arrayr[idx * 3 + 1]] += binormal; - tangents.write[index_arrayr[idx * 3 + 2]] += tangent; - binormals.write[index_arrayr[idx * 3 + 2]] += binormal; - } - - r_tangents.resize(vlen * 4); - PoolVector<real_t>::Write tarrayw = r_tangents.write(); - - for (int idx = 0; idx < vlen; idx++) { - Vector3 tangent = tangents[idx]; - Vector3 bingen = narrayr[idx].cross(tangent); - float dir; - if (bingen.dot(binormals[idx]) < 0) - dir = -1.0; - else - dir = +1.0; - - tarrayw[idx * 4 + 0] = tangent.x; - tarrayw[idx * 4 + 1] = tangent.y; - tarrayw[idx * 4 + 2] = tangent.z; - tarrayw[idx * 4 + 3] = dir; - } -} - Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<ArrayMesh> > p_morph_meshes, bool p_use_compression, bool p_use_mesh_material) { bool local_xform_mirror = p_local_xform.basis.determinant() < 0; diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp index 85383fd69d..a6b754de3b 100644 --- a/editor/import/editor_scene_importer_gltf.cpp +++ b/editor/import/editor_scene_importer_gltf.cpp @@ -1910,15 +1910,15 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye NodePath node_path; GLTFNode *node = state.nodes[E->key()]; - for (int i = 0; i < node->godot_nodes.size(); i++) { + for (int n = 0; n < node->godot_nodes.size(); n++) { if (node->joints.size()) { - Skeleton *sk = (Skeleton *)node->godot_nodes[i]; + Skeleton *sk = (Skeleton *)node->godot_nodes[n]; String path = ap->get_parent()->get_path_to(sk); - String bone = sk->get_bone_name(node->joints[i].godot_bone_index); + String bone = sk->get_bone_name(node->joints[n].godot_bone_index); node_path = path + ":" + bone; } else { - node_path = ap->get_parent()->get_path_to(node->godot_nodes[i]); + node_path = ap->get_parent()->get_path_to(node->godot_nodes[n]); } for (int i = 0; i < track.rotation_track.times.size(); i++) { @@ -1993,8 +1993,8 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye xform.basis.set_quat_scale(rot, scale); xform.origin = pos; - Skeleton *skeleton = skeletons[node->joints[i].skin]; - int bone = node->joints[i].godot_bone_index; + Skeleton *skeleton = skeletons[node->joints[n].skin]; + int bone = node->joints[n].godot_bone_index; xform = skeleton->get_bone_rest(bone).affine_inverse() * xform; rot = xform.basis.get_rotation_quat(); diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp index b18bbc8ce9..c237d2e854 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/resource_importer_obj.cpp @@ -126,7 +126,12 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Spati ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT); String p = l.replace("map_Kd", "").replace("\\", "/").strip_edges(); - String path = base_path.plus_file(p); + String path; + if (p.is_abs_path()) { + path = p; + } else { + path = base_path.plus_file(p); + } Ref<Texture> texture = ResourceLoader::load(path); @@ -141,7 +146,12 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Spati ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT); String p = l.replace("map_Ks", "").replace("\\", "/").strip_edges(); - String path = base_path.plus_file(p); + String path; + if (p.is_abs_path()) { + path = p; + } else { + path = base_path.plus_file(p); + } Ref<Texture> texture = ResourceLoader::load(path); @@ -156,7 +166,12 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Spati ERR_FAIL_COND_V(current.is_null(), ERR_FILE_CORRUPT); String p = l.replace("map_Ns", "").replace("\\", "/").strip_edges(); - String path = base_path.plus_file(p); + String path; + if (p.is_abs_path()) { + path = p; + } else { + path = base_path.plus_file(p); + } Ref<Texture> texture = ResourceLoader::load(path); diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index 81a798f0b6..4f4980d83c 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -259,6 +259,8 @@ void InspectorDock::_prepare_history() { } history_menu->get_popup()->add_icon_item(icon, text, i); } + + editor_path->update_path(); } void InspectorDock::_select_history(int p_idx) const { diff --git a/editor/multi_node_edit.cpp b/editor/multi_node_edit.cpp index 173be01586..be4e752d55 100644 --- a/editor/multi_node_edit.cpp +++ b/editor/multi_node_edit.cpp @@ -30,7 +30,7 @@ #include "multi_node_edit.h" -#include "core/helper/math_fieldwise.h" +#include "core/math/math_fieldwise.h" #include "editor_node.h" bool MultiNodeEdit::_set(const StringName &p_name, const Variant &p_value) { diff --git a/editor/plugins/SCsub b/editor/plugins/SCsub index f1fa50148f..2b1e889fb0 100644 --- a/editor/plugins/SCsub +++ b/editor/plugins/SCsub @@ -1,5 +1,5 @@ #!/usr/bin/env python Import('env') -Export('env') + env.add_source_files(env.editor_sources, "*.cpp") diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index b51ff8b320..f7e59e2beb 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -516,12 +516,10 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) return false; } -void AbstractPolygon2DEditor::forward_draw_over_viewport(Control *p_overlay) { +void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { if (!_get_node()) return; - Control *vpc = canvas_item_editor->get_viewport_control(); - Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform(); const Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons"); @@ -562,7 +560,7 @@ void AbstractPolygon2DEditor::forward_draw_over_viewport(Control *p_overlay) { Vector2 point = xform.xform(p); Vector2 next_point = xform.xform(p2); - vpc->draw_line(point, next_point, col, 2 * EDSCALE); + p_overlay->draw_line(point, next_point, col, 2 * EDSCALE); } } @@ -586,7 +584,7 @@ void AbstractPolygon2DEditor::forward_draw_over_viewport(Control *p_overlay) { p2 = points[(i + 1) % n_points] + offset; const Vector2 next_point = xform.xform(p2); - vpc->draw_line(point, next_point, col, 2 * EDSCALE); + p_overlay->draw_line(point, next_point, col, 2 * EDSCALE); } } @@ -598,14 +596,14 @@ void AbstractPolygon2DEditor::forward_draw_over_viewport(Control *p_overlay) { const Vector2 point = xform.xform(p); const Color modulate = vertex == active_point ? Color(0.5, 1, 2) : Color(1, 1, 1); - vpc->draw_texture(handle, point - handle->get_size() * 0.5, modulate); + p_overlay->draw_texture(handle, point - handle->get_size() * 0.5, modulate); } } if (edge_point.valid()) { Ref<Texture> add_handle = get_icon("EditorHandleAdd", "EditorIcons"); - vpc->draw_texture(add_handle, edge_point.pos - add_handle->get_size() * 0.5); + p_overlay->draw_texture(add_handle, edge_point.pos - add_handle->get_size() * 0.5); } } diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h index 9ba03bcdf6..00634ba5b8 100644 --- a/editor/plugins/abstract_polygon_2d_editor.h +++ b/editor/plugins/abstract_polygon_2d_editor.h @@ -137,7 +137,7 @@ protected: public: bool forward_gui_input(const Ref<InputEvent> &p_event); - void forward_draw_over_viewport(Control *p_overlay); + void forward_canvas_draw_over_viewport(Control *p_overlay); void edit(Node *p_polygon); AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wip_destructive = true); @@ -153,7 +153,7 @@ class AbstractPolygon2DEditorPlugin : public EditorPlugin { public: virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return polygon_editor->forward_gui_input(p_event); } - virtual void forward_draw_over_viewport(Control *p_overlay) { polygon_editor->forward_draw_over_viewport(p_overlay); } + virtual void forward_canvas_draw_over_viewport(Control *p_overlay) { polygon_editor->forward_canvas_draw_over_viewport(p_overlay); } bool has_main_screen() const { return false; } virtual String get_name() const { return klass; } diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index 19d5243776..205458fb1d 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -131,10 +131,6 @@ void AnimationNodeBlendTreeEditor::_update_graph() { Ref<AnimationNode> agnode = blend_tree->get_node(E->get()); - if (!agnode->is_connected("changed", this, "_node_changed")) { - agnode->connect("changed", this, "_node_changed", varray(agnode->get_instance_id()), CONNECT_DEFERRED); - } - node->set_offset(blend_tree->get_node_position(E->get()) * EDSCALE); node->set_title(agnode->get_caption()); @@ -721,14 +717,6 @@ void AnimationNodeBlendTreeEditor::_scroll_changed(const Vector2 &p_scroll) { updating = false; } -void AnimationNodeBlendTreeEditor::_node_changed(ObjectID p_node) { - - AnimationNode *an = Object::cast_to<AnimationNode>(ObjectDB::get_instance(p_node)); - //if (an && an->get_parent() == blend_tree) { - _update_graph(); - //} -} - void AnimationNodeBlendTreeEditor::_bind_methods() { ClassDB::bind_method("_update_graph", &AnimationNodeBlendTreeEditor::_update_graph); @@ -746,7 +734,6 @@ void AnimationNodeBlendTreeEditor::_bind_methods() { ClassDB::bind_method("_update_filters", &AnimationNodeBlendTreeEditor::_update_filters); ClassDB::bind_method("_filter_edited", &AnimationNodeBlendTreeEditor::_filter_edited); ClassDB::bind_method("_filter_toggled", &AnimationNodeBlendTreeEditor::_filter_toggled); - ClassDB::bind_method("_node_changed", &AnimationNodeBlendTreeEditor::_node_changed); ClassDB::bind_method("_removed_from_graph", &AnimationNodeBlendTreeEditor::_removed_from_graph); ClassDB::bind_method("_property_changed", &AnimationNodeBlendTreeEditor::_property_changed); ClassDB::bind_method("_file_opened", &AnimationNodeBlendTreeEditor::_file_opened); diff --git a/editor/plugins/animation_blend_tree_editor_plugin.h b/editor/plugins/animation_blend_tree_editor_plugin.h index 9616e8b5da..e2daefdec6 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.h +++ b/editor/plugins/animation_blend_tree_editor_plugin.h @@ -104,8 +104,6 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin { void _filter_toggled(); Ref<AnimationNode> _filter_edit; - void _node_changed(ObjectID p_node); - void _property_changed(const StringName &p_property, const Variant &p_value); void _removed_from_graph(); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index bf7603bd86..445664f8dd 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -908,7 +908,7 @@ void AnimationPlayerEditor::edit(AnimationPlayer *p_player) { } } -void AnimationPlayerEditor::forward_force_draw_over_viewport(Control *p_overlay) { +void AnimationPlayerEditor::forward_canvas_force_draw_over_viewport(Control *p_overlay) { if (!onion.can_overlay) return; diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h index 5ac7b99903..55f082aadb 100644 --- a/editor/plugins/animation_player_editor_plugin.h +++ b/editor/plugins/animation_player_editor_plugin.h @@ -246,7 +246,7 @@ public: void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; } void edit(AnimationPlayer *p_player); - void forward_force_draw_over_viewport(Control *p_overlay); + void forward_canvas_force_draw_over_viewport(Control *p_overlay); AnimationPlayerEditor(EditorNode *p_editor, AnimationPlayerEditorPlugin *p_plugin); }; @@ -271,7 +271,7 @@ public: virtual bool handles(Object *p_object) const; virtual void make_visible(bool p_visible); - virtual void forward_force_draw_over_viewport(Control *p_overlay) { anim_editor->forward_force_draw_over_viewport(p_overlay); } + virtual void forward_canvas_force_draw_over_viewport(Control *p_overlay) { anim_editor->forward_canvas_force_draw_over_viewport(p_overlay); } AnimationPlayerEditorPlugin(EditorNode *p_node); ~AnimationPlayerEditorPlugin(); diff --git a/editor/plugins/baked_lightmap_editor_plugin.cpp b/editor/plugins/baked_lightmap_editor_plugin.cpp index 59b79bd070..e65a697857 100644 --- a/editor/plugins/baked_lightmap_editor_plugin.cpp +++ b/editor/plugins/baked_lightmap_editor_plugin.cpp @@ -50,6 +50,7 @@ void BakedLightmapEditorPlugin::_bake() { case BakedLightmap::BAKE_ERROR_CANT_CREATE_IMAGE: EditorNode::get_singleton()->show_warning(TTR("Failed creating lightmap images, make sure path is writable.")); break; + default: {} } } } diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index eedb4be323..e8f00ce0ba 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -719,6 +719,46 @@ Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2 return (p_control->get_transform().xform(position) - parent_rect.position) / parent_rect.size; } +void CanvasItemEditor::_save_canvas_item_ik_chain(const CanvasItem *p_canvas_item, List<float> *p_bones_length, List<Dictionary> *p_bones_state) { + if (p_bones_length) + *p_bones_length = List<float>(); + if (p_bones_state) + *p_bones_state = List<Dictionary>(); + + const Node2D *bone = Object::cast_to<Node2D>(p_canvas_item); + if (bone && bone->has_meta("_edit_bone_")) { + // Check if we have an IK chain + List<const Node2D *> bone_ik_list; + bool ik_found = false; + bone = Object::cast_to<Node2D>(bone->get_parent()); + while (bone) { + bone_ik_list.push_back(bone); + if (bone->has_meta("_edit_ik_")) { + ik_found = true; + break; + } else if (!bone->has_meta("_edit_bone_")) { + break; + } + bone = Object::cast_to<Node2D>(bone->get_parent()); + } + + //Save the bone state and length if we have an IK chain + if (ik_found) { + bone = Object::cast_to<Node2D>(p_canvas_item); + Transform2D bone_xform = bone->get_global_transform(); + for (List<const Node2D *>::Element *bone_E = bone_ik_list.front(); bone_E; bone_E = bone_E->next()) { + bone_xform = bone_xform * bone->get_transform().affine_inverse(); + const Node2D *parent_bone = bone_E->get(); + if (p_bones_length) + p_bones_length->push_back(parent_bone->get_global_transform().get_origin().distance_to(bone->get_global_position())); + if (p_bones_state) + p_bones_state->push_back(parent_bone->_edit_get_state()); + bone = parent_bone; + } + } + } +} + void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones) { for (List<CanvasItem *>::Element *E = p_canvas_items.front(); E; E = E->next()) { CanvasItem *canvas_item = E->get(); @@ -731,54 +771,28 @@ void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items } else { se->pre_drag_rect = Rect2(); } - se->pre_drag_bones_length = List<float>(); - se->pre_drag_bones_undo_state = List<Dictionary>(); // If we have a bone, save the state of all nodes in the IK chain - Node2D *bone = Object::cast_to<Node2D>(canvas_item); - if (bone && bone->has_meta("_edit_bone_")) { - // Check if we have an IK chain - List<Node2D *> bone_ik_list; - bool ik_found = false; - bone = Object::cast_to<Node2D>(bone->get_parent()); - while (bone) { - bone_ik_list.push_back(bone); - if (bone->has_meta("_edit_ik_")) { - ik_found = true; - break; - } else if (!bone->has_meta("_edit_bone_")) { - break; - } - bone = Object::cast_to<Node2D>(bone->get_parent()); - } - - //Save the bone state and length if we have an IK chain - if (ik_found) { - bone = Object::cast_to<Node2D>(canvas_item); - Transform2D bone_xform = bone->get_global_transform(); - for (List<Node2D *>::Element *bone_E = bone_ik_list.front(); bone_E; bone_E = bone_E->next()) { - bone_xform = bone_xform * bone->get_transform().affine_inverse(); - Node2D *parent_bone = bone_E->get(); - se->pre_drag_bones_length.push_back(parent_bone->get_global_transform().get_origin().distance_to(bone->get_global_position())); - se->pre_drag_bones_undo_state.push_back(parent_bone->_edit_get_state()); - bone = parent_bone; - } - } - } + _save_canvas_item_ik_chain(canvas_item, &(se->pre_drag_bones_length), &(se->pre_drag_bones_undo_state)); } } } +void CanvasItemEditor::_restore_canvas_item_ik_chain(CanvasItem *p_canvas_item, const List<Dictionary> *p_bones_state) { + CanvasItem *canvas_item = p_canvas_item; + for (const List<Dictionary>::Element *E = p_bones_state->front(); E; E = E->next()) { + canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent()); + canvas_item->_edit_set_state(E->get()); + } +} + void CanvasItemEditor::_restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones) { for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { CanvasItem *canvas_item = E->get(); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); canvas_item->_edit_set_state(se->undo_state); if (restore_bones) { - for (List<Dictionary>::Element *E = se->pre_drag_bones_undo_state.front(); E; E = E->next()) { - canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent()); - canvas_item->_edit_set_state(E->get()); - } + _restore_canvas_item_ik_chain(canvas_item, &(se->pre_drag_bones_undo_state)); } } } @@ -1203,73 +1217,72 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) { void CanvasItemEditor::_solve_IK(Node2D *leaf_node, Point2 target_position) { CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(leaf_node); - if (se && !se->pre_drag_bones_undo_state.empty()) { - - // Build the node list - Point2 leaf_pos = target_position; - - List<Node2D *> joints_list; - List<Point2> joints_pos; - Node2D *joint = leaf_node; - Transform2D joint_transform = leaf_node->get_global_transform_with_canvas(); - for (int i = 0; i < se->pre_drag_bones_undo_state.size() + 1; i++) { - joints_list.push_back(joint); - joints_pos.push_back(joint_transform.get_origin()); - joint_transform = joint_transform * joint->get_transform().affine_inverse(); - joint = Object::cast_to<Node2D>(joint->get_parent()); - } - Point2 root_pos = joints_list.back()->get()->get_global_transform_with_canvas().get_origin(); - - // Restraints the node to a maximum distance is necessary - float total_len = 0; - for (List<float>::Element *E = se->pre_drag_bones_length.front(); E; E = E->next()) { - total_len += E->get(); - } - if ((root_pos.distance_to(leaf_pos)) > total_len) { - Vector2 rel = leaf_pos - root_pos; - rel = rel.normalized() * total_len; - leaf_pos = root_pos + rel; - } - joints_pos[0] = leaf_pos; - - // Run the solver - int solver_iterations = 64; - float solver_k = 0.3; - - // Build the position list - for (int i = 0; i < solver_iterations; i++) { - // Handle the leaf joint - int node_id = 0; + if (se) { + int nb_bones = se->pre_drag_bones_undo_state.size(); + if (nb_bones > 0) { + + // Build the node list + Point2 leaf_pos = target_position; + + List<Node2D *> joints_list; + List<Point2> joints_pos; + Node2D *joint = leaf_node; + Transform2D joint_transform = leaf_node->get_global_transform_with_canvas(); + for (int i = 0; i < nb_bones + 1; i++) { + joints_list.push_back(joint); + joints_pos.push_back(joint_transform.get_origin()); + joint_transform = joint_transform * joint->get_transform().affine_inverse(); + joint = Object::cast_to<Node2D>(joint->get_parent()); + } + Point2 root_pos = joints_list.back()->get()->get_global_transform_with_canvas().get_origin(); + + // Restraints the node to a maximum distance is necessary + float total_len = 0; for (List<float>::Element *E = se->pre_drag_bones_length.front(); E; E = E->next()) { - Vector2 direction = (joints_pos[node_id + 1] - joints_pos[node_id]).normalized(); - int len = E->get(); - if (E == se->pre_drag_bones_length.front()) { - joints_pos[1] = joints_pos[1].linear_interpolate(joints_pos[0] + len * direction, solver_k); - } else if (E == se->pre_drag_bones_length.back()) { - joints_pos[node_id] = joints_pos[node_id].linear_interpolate(joints_pos[node_id + 1] - len * direction, solver_k); - } else { - Vector2 center = (joints_pos[node_id + 1] + joints_pos[node_id]) / 2.0; - joints_pos[node_id] = joints_pos[node_id].linear_interpolate(center - (direction * len) / 2.0, solver_k); - joints_pos[node_id + 1] = joints_pos[node_id + 1].linear_interpolate(center + (direction * len) / 2.0, solver_k); + total_len += E->get(); + } + if ((root_pos.distance_to(leaf_pos)) > total_len) { + Vector2 rel = leaf_pos - root_pos; + rel = rel.normalized() * total_len; + leaf_pos = root_pos + rel; + } + joints_pos[0] = leaf_pos; + + // Run the solver + int solver_iterations = 64; + float solver_k = 0.3; + + // Build the position list + for (int i = 0; i < solver_iterations; i++) { + // Handle the leaf joint + int node_id = 0; + for (List<float>::Element *E = se->pre_drag_bones_length.front(); E; E = E->next()) { + Vector2 direction = (joints_pos[node_id + 1] - joints_pos[node_id]).normalized(); + int len = E->get(); + if (E == se->pre_drag_bones_length.front()) { + joints_pos[1] = joints_pos[1].linear_interpolate(joints_pos[0] + len * direction, solver_k); + } else if (E == se->pre_drag_bones_length.back()) { + joints_pos[node_id] = joints_pos[node_id].linear_interpolate(joints_pos[node_id + 1] - len * direction, solver_k); + } else { + Vector2 center = (joints_pos[node_id + 1] + joints_pos[node_id]) / 2.0; + joints_pos[node_id] = joints_pos[node_id].linear_interpolate(center - (direction * len) / 2.0, solver_k); + joints_pos[node_id + 1] = joints_pos[node_id + 1].linear_interpolate(center + (direction * len) / 2.0, solver_k); + } + node_id++; } - node_id++; } - } - // Set the position - float total_rot = 0.0f; - for (int node_id = joints_list.size() - 1; node_id > 0; node_id--) { - Point2 current = (joints_list[node_id - 1]->get_global_position() - joints_list[node_id]->get_global_position()).normalized(); - Point2 target = (joints_pos[node_id - 1] - joints_list[node_id]->get_global_position()).normalized(); - float rot = current.angle_to(target); - if (joints_list[node_id]->get_global_transform().basis_determinant() < 0) { - rot = -rot; + // Set the position + for (int node_id = joints_list.size() - 1; node_id > 0; node_id--) { + Point2 current = (joints_list[node_id - 1]->get_global_position() - joints_list[node_id]->get_global_position()).normalized(); + Point2 target = (joints_pos[node_id - 1] - joints_list[node_id]->get_global_position()).normalized(); + float rot = current.angle_to(target); + if (joints_list[node_id]->get_global_transform().basis_determinant() < 0) { + rot = -rot; + } + joints_list[node_id]->rotate(rot); } - joints_list[node_id]->rotate(rot); - total_rot += rot; } - - joints_list[0]->rotate(-total_rot); } } @@ -1645,6 +1658,8 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * Transform2D(canvas_item->_edit_get_rotation(), canvas_item->_edit_get_position())).orthonormalized(); Transform2D simple_xform = viewport->get_transform() * unscaled_transform; + drag_type = DRAG_SCALE_BOTH; + Size2 scale_factor = Size2(SCALE_HANDLE_DISTANCE, SCALE_HANDLE_DISTANCE); Rect2 x_handle_rect = Rect2(scale_factor.x * EDSCALE, -5 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); if (x_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) { @@ -1654,43 +1669,67 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { if (y_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) { drag_type = DRAG_SCALE_Y; } - if (drag_type == DRAG_SCALE_X || drag_type == DRAG_SCALE_Y) { - drag_from = transform.affine_inverse().xform(b->get_position()); - drag_selection = List<CanvasItem *>(); - drag_selection.push_back(canvas_item); - _save_canvas_item_state(drag_selection); - return true; - } + + drag_from = transform.affine_inverse().xform(b->get_position()); + drag_selection = List<CanvasItem *>(); + drag_selection.push_back(canvas_item); + _save_canvas_item_state(drag_selection); + return true; } } } - if (drag_type == DRAG_SCALE_X || drag_type == DRAG_SCALE_Y) { + if (drag_type == DRAG_SCALE_BOTH || drag_type == DRAG_SCALE_X || drag_type == DRAG_SCALE_Y) { // Resize the node if (m.is_valid()) { - _restore_canvas_item_state(drag_selection, true); + _restore_canvas_item_state(drag_selection); CanvasItem *canvas_item = drag_selection[0]; drag_to = transform.affine_inverse().xform(m->get_position()); + Transform2D parent_xform = canvas_item->get_global_transform_with_canvas() * canvas_item->get_transform().affine_inverse(); + Transform2D unscaled_transform = (transform * parent_xform * Transform2D(canvas_item->_edit_get_rotation(), canvas_item->_edit_get_position())).orthonormalized(); + Transform2D simple_xform = (viewport->get_transform() * unscaled_transform).affine_inverse() * transform; + bool uniform = m->get_shift(); - Point2 offset = drag_to - drag_from; + + Point2 drag_from_local = simple_xform.xform(drag_from); + Point2 drag_to_local = simple_xform.xform(drag_to); + Point2 offset = drag_to_local - drag_from_local; + Size2 scale = canvas_item->call("get_scale"); float ratio = scale.y / scale.x; - if (drag_type == DRAG_SCALE_X) { - scale.x += offset.x / SCALE_HANDLE_DISTANCE; + if (drag_type == DRAG_SCALE_BOTH) { + Size2 scale_factor = drag_to_local / drag_from_local; if (uniform) { - scale.y = scale.x * ratio; + if (ABS(offset.x) > ABS(offset.y)) { + scale.x *= scale_factor.x; + scale.y = scale.x * ratio; + } else { + scale.y *= scale_factor.y; + scale.x = scale.y / ratio; + } + } else { + scale *= scale_factor; } - canvas_item->call("set_scale", scale); - - } else if (drag_type == DRAG_SCALE_Y) { - scale.y -= offset.y / SCALE_HANDLE_DISTANCE; - if (uniform) { - scale.x = scale.y / ratio; + } else { + Size2 scale_factor = Vector2(offset.x, -offset.y) / SCALE_HANDLE_DISTANCE; + Size2 parent_scale = parent_xform.get_scale(); + scale_factor *= Vector2(1.0 / parent_scale.x, 1.0 / parent_scale.y); + if (drag_type == DRAG_SCALE_X) { + scale.x += scale_factor.x; + if (uniform) { + scale.y = scale.x * ratio; + } + } else if (drag_type == DRAG_SCALE_Y) { + scale.y += scale_factor.y; + if (uniform) { + scale.x = scale.y / ratio; + } } - canvas_item->call("set_scale", scale); } + canvas_item->call("set_scale", scale); + return true; } // Confirm resize @@ -1734,6 +1773,15 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { if (drag_type == DRAG_MOVE) { // Move the nodes if (m.is_valid()) { + + // Save the ik chain for reapplying before IK solve + Vector<List<Dictionary> > all_bones_ik_states; + for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { + List<Dictionary> bones_ik_states; + _save_canvas_item_ik_chain(E->get(), NULL, &bones_ik_states); + all_bones_ik_states.push_back(bones_ik_states); + } + _restore_canvas_item_state(drag_selection, true); drag_to = transform.affine_inverse().xform(m->get_position()); @@ -1755,6 +1803,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { } bool force_no_IK = m->get_alt(); + int index = 0; for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { CanvasItem *canvas_item = E->get(); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); @@ -1762,10 +1811,15 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { Node2D *node2d = Object::cast_to<Node2D>(canvas_item); if (node2d && se->pre_drag_bones_undo_state.size() > 0 && !force_no_IK) { + real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation(); + _restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index])); + real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation(); + node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation); _solve_IK(node2d, new_pos); } else { canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos)); } + index++; } return true; } @@ -1804,6 +1858,14 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { if (drag_selection.size() > 0) { + // Save the ik chain for reapplying before IK solve + Vector<List<Dictionary> > all_bones_ik_states; + for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { + List<Dictionary> bones_ik_states; + _save_canvas_item_ik_chain(E->get(), NULL, &bones_ik_states); + all_bones_ik_states.push_back(bones_ik_states); + } + _restore_canvas_item_state(drag_selection, true); bool move_local_base = k->get_alt(); @@ -1849,6 +1911,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { new_pos = previous_pos + (drag_to - drag_from); } + int index = 0; for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { CanvasItem *canvas_item = E->get(); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); @@ -1856,10 +1919,15 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { Node2D *node2d = Object::cast_to<Node2D>(canvas_item); if (node2d && se->pre_drag_bones_undo_state.size() > 0) { + real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation(); + _restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index])); + real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation(); + node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation); _solve_IK(node2d, new_pos); } else { canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos)); } + index++; } } return true; @@ -2314,7 +2382,7 @@ void CanvasItemEditor::_draw_rulers() { if (i % minor_subdivision == 0) { viewport->draw_line(Point2(position.x, RULER_WIDTH * 0.33), Point2(position.x, RULER_WIDTH), graduation_color); } else { - viewport->draw_line(Point2(position.x, RULER_WIDTH * 0.66), Point2(position.x, RULER_WIDTH), graduation_color); + viewport->draw_line(Point2(position.x, RULER_WIDTH * 0.75), Point2(position.x, RULER_WIDTH), graduation_color); } } } @@ -2326,12 +2394,17 @@ void CanvasItemEditor::_draw_rulers() { if (i % (major_subdivision * minor_subdivision) == 0) { viewport->draw_line(Point2(0, position.y), Point2(RULER_WIDTH, position.y), graduation_color); float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i)).y; - viewport->draw_string(font, Point2(2, position.y + 2 + font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color); + + Transform2D text_xform = Transform2D(-Math_PI / 2.0, Point2(font->get_height(), position.y - 2)); + viewport->draw_set_transform_matrix(viewport->get_transform() * text_xform); + viewport->draw_string(font, Point2(), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color); + viewport->draw_set_transform_matrix(viewport->get_transform()); + } else { if (i % minor_subdivision == 0) { viewport->draw_line(Point2(RULER_WIDTH * 0.33, position.y), Point2(RULER_WIDTH, position.y), graduation_color); } else { - viewport->draw_line(Point2(RULER_WIDTH * 0.66, position.y), Point2(RULER_WIDTH, position.y), graduation_color); + viewport->draw_line(Point2(RULER_WIDTH * 0.75, position.y), Point2(RULER_WIDTH, position.y), graduation_color); } } } @@ -2777,7 +2850,7 @@ void CanvasItemEditor::_draw_axis() { RID ci = viewport->get_canvas_item(); - Color area_axis_color(0.4, 0.4, 1.0, 0.4); + Color area_axis_color = EditorSettings::get_singleton()->get("editors/2d/viewport_border_color"); Size2 screen_size = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height")); @@ -3030,6 +3103,7 @@ bool CanvasItemEditor::_build_bones_list(Node *p_node) { } void CanvasItemEditor::_draw_viewport() { + // Update the transform transform = Transform2D(); transform.scale_basis(Size2(zoom, zoom)); @@ -3078,11 +3152,11 @@ void CanvasItemEditor::_draw_viewport() { EditorPluginList *over_plugin_list = editor->get_editor_plugins_over(); if (!over_plugin_list->empty()) { - over_plugin_list->forward_draw_over_viewport(viewport); + over_plugin_list->forward_canvas_draw_over_viewport(viewport); } EditorPluginList *force_over_plugin_list = editor->get_editor_plugins_force_over(); if (!force_over_plugin_list->empty()) { - force_over_plugin_list->forward_force_draw_over_viewport(viewport); + force_over_plugin_list->forward_canvas_force_draw_over_viewport(viewport); } _draw_bones(); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 6d176601ac..6a788692d7 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -195,6 +195,7 @@ private: DRAG_MOVE, DRAG_SCALE_X, DRAG_SCALE_Y, + DRAG_SCALE_BOTH, DRAG_ROTATE, DRAG_PIVOT, DRAG_V_GUIDE, @@ -378,7 +379,9 @@ private: void _add_canvas_item(CanvasItem *p_canvas_item); + void _save_canvas_item_ik_chain(const CanvasItem *p_canvas_item, List<float> *p_bones_length, List<Dictionary> *p_bones_state); void _save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones = false); + void _restore_canvas_item_ik_chain(CanvasItem *p_canvas_item, const List<Dictionary> *p_bones_state); void _restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones = false); void _commit_canvas_item_state(List<CanvasItem *> p_canvas_items, String action_name, bool commit_bones = false); diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index 9e052bb027..d1a94f5b49 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -323,7 +323,6 @@ bool CollisionShape2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_e if (mb.is_valid()) { Vector2 gpoint = mb->get_position(); - Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); if (mb->get_button_index() == BUTTON_LEFT) { if (mb->is_pressed()) { @@ -415,7 +414,7 @@ void CollisionShape2DEditor::_get_current_shape_type() { canvas_item_editor->get_viewport_control()->update(); } -void CollisionShape2DEditor::forward_draw_over_viewport(Control *p_overlay) { +void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { if (!node) { return; diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h index 10784f1129..fb7b2acb0f 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.h +++ b/editor/plugins/collision_shape_2d_editor_plugin.h @@ -75,7 +75,7 @@ protected: public: bool forward_canvas_gui_input(const Ref<InputEvent> &p_event); - void forward_draw_over_viewport(Control *p_overlay); + void forward_canvas_draw_over_viewport(Control *p_overlay); void edit(Node *p_node); CollisionShape2DEditor(EditorNode *p_editor); @@ -89,7 +89,7 @@ class CollisionShape2DEditorPlugin : public EditorPlugin { public: virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return collision_shape_2d_editor->forward_canvas_gui_input(p_event); } - virtual void forward_draw_over_viewport(Control *p_overlay) { return collision_shape_2d_editor->forward_draw_over_viewport(p_overlay); } + virtual void forward_canvas_draw_over_viewport(Control *p_overlay) { return collision_shape_2d_editor->forward_canvas_draw_over_viewport(p_overlay); } virtual String get_name() const { return "CollisionShape2D"; } bool has_main_screen() const { return false; } diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index 79169d3183..ace3012c10 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -205,13 +205,13 @@ void CurveEditor::on_gui_input(const Ref<InputEvent> &p_event) { curve.set_point_left_tangent(_selected_point, tangent); // Note: if a tangent is set to linear, it shouldn't be linked to the other - if (link && _selected_point != curve.get_point_count() - 1 && !curve.get_point_right_mode(_selected_point) != Curve::TANGENT_FREE) + if (link && _selected_point != (curve.get_point_count() - 1) && curve.get_point_right_mode(_selected_point) != Curve::TANGENT_LINEAR) curve.set_point_right_tangent(_selected_point, tangent); } else { curve.set_point_right_tangent(_selected_point, tangent); - if (link && _selected_point != 0 && !curve.get_point_left_mode(_selected_point) != Curve::TANGENT_FREE) + if (link && _selected_point != 0 && curve.get_point_left_mode(_selected_point) != Curve::TANGENT_LINEAR) curve.set_point_left_tangent(_selected_point, tangent); } } @@ -782,12 +782,13 @@ bool CurvePreviewGenerator::handles(const String &p_type) const { return p_type == "Curve"; } -Ref<Texture> CurvePreviewGenerator::generate(const Ref<Resource> &p_from) { +Ref<Texture> CurvePreviewGenerator::generate(const Ref<Resource> &p_from, const Size2 p_size) const { Ref<Curve> curve_ref = p_from; ERR_FAIL_COND_V(curve_ref.is_null(), Ref<Texture>()); Curve &curve = **curve_ref; + // FIXME: Should be ported to use p_size as done in b2633a97 int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); thumbnail_size *= EDSCALE; Ref<Image> img_ref; diff --git a/editor/plugins/curve_editor_plugin.h b/editor/plugins/curve_editor_plugin.h index 255f359ed2..fa0b92e353 100644 --- a/editor/plugins/curve_editor_plugin.h +++ b/editor/plugins/curve_editor_plugin.h @@ -131,14 +131,14 @@ class CurveEditorPlugin : public EditorPlugin { public: CurveEditorPlugin(EditorNode *p_node); - String get_name() const { return "Curve"; } + virtual String get_name() const { return "Curve"; } }; class CurvePreviewGenerator : public EditorResourcePreviewGenerator { GDCLASS(CurvePreviewGenerator, EditorResourcePreviewGenerator) public: - bool handles(const String &p_type) const; - Ref<Texture> generate(const Ref<Resource> &p_from); + virtual bool handles(const String &p_type) const; + virtual Ref<Texture> generate(const Ref<Resource> &p_from, const Size2 p_size) const; }; #endif // CURVE_EDITOR_PLUGIN_H diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 72a746e95b..7f83865777 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -78,7 +78,11 @@ bool EditorTexturePreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "Texture"); } -Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from) const { +bool EditorTexturePreviewPlugin::should_generate_small_preview() const { + return true; +} + +Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { Ref<Image> img; Ref<AtlasTexture> atex = p_from; @@ -100,8 +104,6 @@ Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from) const { img = img->duplicate(); img->clear_mipmaps(); - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; if (img->is_compressed()) { if (img->decompress() != OK) return Ref<Texture>(); @@ -109,22 +111,15 @@ Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from) const { img->convert(Image::FORMAT_RGBA8); } - int width, height; - if (img->get_width() > thumbnail_size && img->get_width() >= img->get_height()) { - - width = thumbnail_size; - height = img->get_height() * thumbnail_size / img->get_width(); - } else if (img->get_height() > thumbnail_size && img->get_height() >= img->get_width()) { - - height = thumbnail_size; - width = img->get_width() * thumbnail_size / img->get_height(); - } else { - - width = img->get_width(); - height = img->get_height(); + Vector2 new_size = img->get_size(); + if (new_size.x > p_size.x) { + new_size = Vector2(p_size.x, new_size.y * p_size.x / new_size.x); } + if (new_size.y > p_size.y) { + new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y); + } + img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC); - img->resize(width, height); post_process_preview(img); Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture)); @@ -143,7 +138,7 @@ bool EditorImagePreviewPlugin::handles(const String &p_type) const { return p_type == "Image"; } -Ref<Texture> EditorImagePreviewPlugin::generate(const RES &p_from) const { +Ref<Texture> EditorImagePreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { Ref<Image> img = p_from; @@ -153,8 +148,6 @@ Ref<Texture> EditorImagePreviewPlugin::generate(const RES &p_from) const { img = img->duplicate(); img->clear_mipmaps(); - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; if (img->is_compressed()) { if (img->decompress() != OK) return Ref<Image>(); @@ -162,22 +155,15 @@ Ref<Texture> EditorImagePreviewPlugin::generate(const RES &p_from) const { img->convert(Image::FORMAT_RGBA8); } - int width, height; - if (img->get_width() > thumbnail_size && img->get_width() >= img->get_height()) { - - width = thumbnail_size; - height = img->get_height() * thumbnail_size / img->get_width(); - } else if (img->get_height() > thumbnail_size && img->get_height() >= img->get_width()) { - - height = thumbnail_size; - width = img->get_width() * thumbnail_size / img->get_height(); - } else { - - width = img->get_width(); - height = img->get_height(); + Vector2 new_size = img->get_size(); + if (new_size.x > p_size.x) { + new_size = Vector2(p_size.x, new_size.y * p_size.x / new_size.x); + } + if (new_size.y > p_size.y) { + new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y); } + img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC); - img->resize(width, height); post_process_preview(img); Ref<ImageTexture> ptex; @@ -190,6 +176,9 @@ Ref<Texture> EditorImagePreviewPlugin::generate(const RES &p_from) const { EditorImagePreviewPlugin::EditorImagePreviewPlugin() { } +bool EditorImagePreviewPlugin::should_generate_small_preview() const { + return true; +} //////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////// bool EditorBitmapPreviewPlugin::handles(const String &p_type) const { @@ -197,7 +186,7 @@ bool EditorBitmapPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "BitMap"); } -Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) const { +Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { Ref<BitMap> bm = p_from; @@ -227,8 +216,6 @@ Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) const { img.instance(); img->create(bm->get_size().width, bm->get_size().height, 0, Image::FORMAT_L8, data); - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; if (img->is_compressed()) { if (img->decompress() != OK) return Ref<Texture>(); @@ -236,22 +223,15 @@ Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) const { img->convert(Image::FORMAT_RGBA8); } - int width, height; - if (img->get_width() > thumbnail_size && img->get_width() >= img->get_height()) { - - width = thumbnail_size; - height = img->get_height() * thumbnail_size / img->get_width(); - } else if (img->get_height() > thumbnail_size && img->get_height() >= img->get_width()) { - - height = thumbnail_size; - width = img->get_width() * thumbnail_size / img->get_height(); - } else { - - width = img->get_width(); - height = img->get_height(); + Vector2 new_size = img->get_size(); + if (new_size.x > p_size.x) { + new_size = Vector2(p_size.x, new_size.y * p_size.x / new_size.x); + } + if (new_size.y > p_size.y) { + new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y); } + img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC); - img->resize(width, height); post_process_preview(img); Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture)); @@ -260,6 +240,10 @@ Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) const { return ptex; } +bool EditorBitmapPreviewPlugin::should_generate_small_preview() const { + return true; +} + EditorBitmapPreviewPlugin::EditorBitmapPreviewPlugin() { } @@ -269,12 +253,12 @@ bool EditorPackedScenePreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "PackedScene"); } -Ref<Texture> EditorPackedScenePreviewPlugin::generate(const RES &p_from) const { +Ref<Texture> EditorPackedScenePreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { - return generate_from_path(p_from->get_path()); + return generate_from_path(p_from->get_path(), p_size); } -Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String &p_path) const { +Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String &p_path, const Size2 p_size) const { String temp_path = EditorSettings::get_singleton()->get_cache_dir(); String cache_base = ProjectSettings::get_singleton()->globalize_path(p_path).md5_text(); @@ -323,7 +307,11 @@ bool EditorMaterialPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "Material"); //any material } -Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES &p_from) const { +bool EditorMaterialPreviewPlugin::should_generate_small_preview() const { + return true; +} + +Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { Ref<Material> material = p_from; ERR_FAIL_COND_V(material.is_null(), Ref<Texture>()); @@ -346,10 +334,9 @@ Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES &p_from) const { ERR_FAIL_COND_V(!img.is_valid(), Ref<ImageTexture>()); - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; img->convert(Image::FORMAT_RGBA8); - img->resize(thumbnail_size, thumbnail_size); + int thumbnail_size = MAX(p_size.x, p_size.y); + img->resize(thumbnail_size, thumbnail_size, Image::INTERPOLATE_CUBIC); post_process_preview(img); Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture)); ptex->create_from_image(img, 0); @@ -490,7 +477,7 @@ bool EditorScriptPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "Script"); } -Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) const { +Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { Ref<Script> scr = p_from; if (scr.is_null()) @@ -512,10 +499,9 @@ Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) const { int line = 0; int col = 0; - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; Ref<Image> img; img.instance(); + int thumbnail_size = MAX(p_size.x, p_size.y); img->create(thumbnail_size, thumbnail_size, 0, Image::FORMAT_RGBA8); Color bg_color = EditorSettings::get_singleton()->get("text_editor/highlighting/background_color"); @@ -613,16 +599,15 @@ bool EditorAudioStreamPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "AudioStream"); } -Ref<Texture> EditorAudioStreamPreviewPlugin::generate(const RES &p_from) const { +Ref<Texture> EditorAudioStreamPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { Ref<AudioStream> stream = p_from; ERR_FAIL_COND_V(stream.is_null(), Ref<Texture>()); - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; PoolVector<uint8_t> img; - int w = thumbnail_size; - int h = thumbnail_size; + + int w = p_size.x; + int h = p_size.y; img.resize(w * h * 3); PoolVector<uint8_t>::Write imgdata = img.write(); @@ -711,7 +696,7 @@ bool EditorMeshPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "Mesh"); //any Mesh } -Ref<Texture> EditorMeshPreviewPlugin::generate(const RES &p_from) const { +Ref<Texture> EditorMeshPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { Ref<Mesh> mesh = p_from; ERR_FAIL_COND_V(mesh.is_null(), Ref<Texture>()); @@ -749,10 +734,17 @@ Ref<Texture> EditorMeshPreviewPlugin::generate(const RES &p_from) const { VS::get_singleton()->instance_set_base(mesh_instance, RID()); - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; img->convert(Image::FORMAT_RGBA8); - img->resize(thumbnail_size, thumbnail_size); + + Vector2 new_size = img->get_size(); + if (new_size.x > p_size.x) { + new_size = Vector2(p_size.x, new_size.y * p_size.x / new_size.x); + } + if (new_size.y > p_size.y) { + new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y); + } + img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC); + post_process_preview(img); Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture)); @@ -825,15 +817,12 @@ bool EditorFontPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "DynamicFontData"); } -Ref<Texture> EditorFontPreviewPlugin::generate_from_path(const String &p_path) const { +Ref<Texture> EditorFontPreviewPlugin::generate_from_path(const String &p_path, const Size2 p_size) const { Ref<DynamicFontData> SampledFont; SampledFont.instance(); SampledFont->set_font_path(p_path); - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; - Ref<DynamicFont> sampled_font; sampled_font.instance(); sampled_font->set_size(50); @@ -864,7 +853,15 @@ Ref<Texture> EditorFontPreviewPlugin::generate_from_path(const String &p_path) c ERR_FAIL_COND_V(img.is_null(), Ref<ImageTexture>()); img->convert(Image::FORMAT_RGBA8); - img->resize(thumbnail_size, thumbnail_size); + + Vector2 new_size = img->get_size(); + if (new_size.x > p_size.x) { + new_size = Vector2(p_size.x, new_size.y * p_size.x / new_size.x); + } + if (new_size.y > p_size.y) { + new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y); + } + img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC); post_process_preview(img); @@ -874,9 +871,9 @@ Ref<Texture> EditorFontPreviewPlugin::generate_from_path(const String &p_path) c return ptex; } -Ref<Texture> EditorFontPreviewPlugin::generate(const RES &p_from) const { +Ref<Texture> EditorFontPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { - return generate_from_path(p_from->get_path()); + return generate_from_path(p_from->get_path(), p_size); } EditorFontPreviewPlugin::EditorFontPreviewPlugin() { diff --git a/editor/plugins/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h index 8bd7943383..ed5d2a3ecd 100644 --- a/editor/plugins/editor_preview_plugins.h +++ b/editor/plugins/editor_preview_plugins.h @@ -39,7 +39,8 @@ class EditorTexturePreviewPlugin : public EditorResourcePreviewGenerator { GDCLASS(EditorTexturePreviewPlugin, EditorResourcePreviewGenerator) public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; + virtual bool should_generate_small_preview() const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; EditorTexturePreviewPlugin(); }; @@ -48,7 +49,8 @@ class EditorImagePreviewPlugin : public EditorResourcePreviewGenerator { GDCLASS(EditorImagePreviewPlugin, EditorResourcePreviewGenerator) public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; + virtual bool should_generate_small_preview() const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; EditorImagePreviewPlugin(); }; @@ -57,7 +59,8 @@ class EditorBitmapPreviewPlugin : public EditorResourcePreviewGenerator { GDCLASS(EditorBitmapPreviewPlugin, EditorResourcePreviewGenerator) public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; + virtual bool should_generate_small_preview() const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; EditorBitmapPreviewPlugin(); }; @@ -66,8 +69,8 @@ class EditorPackedScenePreviewPlugin : public EditorResourcePreviewGenerator { public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; - virtual Ref<Texture> generate_from_path(const String &p_path) const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; + virtual Ref<Texture> generate_from_path(const String &p_path, const Size2 p_size) const; EditorPackedScenePreviewPlugin(); }; @@ -95,7 +98,8 @@ protected: public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; + virtual bool should_generate_small_preview() const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; EditorMaterialPreviewPlugin(); ~EditorMaterialPreviewPlugin(); @@ -104,7 +108,7 @@ public: class EditorScriptPreviewPlugin : public EditorResourcePreviewGenerator { public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; EditorScriptPreviewPlugin(); }; @@ -112,7 +116,7 @@ public: class EditorAudioStreamPreviewPlugin : public EditorResourcePreviewGenerator { public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; EditorAudioStreamPreviewPlugin(); }; @@ -139,7 +143,7 @@ protected: public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; EditorMeshPreviewPlugin(); ~EditorMeshPreviewPlugin(); @@ -162,8 +166,8 @@ protected: public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; - virtual Ref<Texture> generate_from_path(const String &p_path) const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; + virtual Ref<Texture> generate_from_path(const String &p_path, const Size2 p_size) const; EditorFontPreviewPlugin(); ~EditorFontPreviewPlugin(); diff --git a/editor/plugins/light_occluder_2d_editor_plugin.cpp b/editor/plugins/light_occluder_2d_editor_plugin.cpp index 4f8a307cc1..2f2e1dae81 100644 --- a/editor/plugins/light_occluder_2d_editor_plugin.cpp +++ b/editor/plugins/light_occluder_2d_editor_plugin.cpp @@ -319,13 +319,11 @@ bool LightOccluder2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return false; } -void LightOccluder2DEditor::forward_draw_over_viewport(Control *p_overlay) { +void LightOccluder2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { if (!node || !node->get_occluder_polygon().is_valid()) return; - Control *vpc = canvas_item_editor->get_viewport_control(); - Vector<Vector2> poly; if (wip_active) @@ -353,9 +351,9 @@ void LightOccluder2DEditor::forward_draw_over_viewport(Control *p_overlay) { if (i == poly.size() - 1 && (!node->get_occluder_polygon()->is_closed() || wip_active)) { } else { - vpc->draw_line(point, next_point, col, 2); + p_overlay->draw_line(point, next_point, col, 2); } - vpc->draw_texture(handle, point - handle->get_size() * 0.5); + p_overlay->draw_texture(handle, point - handle->get_size() * 0.5); } } diff --git a/editor/plugins/light_occluder_2d_editor_plugin.h b/editor/plugins/light_occluder_2d_editor_plugin.h index 39de8b1020..a1962892ee 100644 --- a/editor/plugins/light_occluder_2d_editor_plugin.h +++ b/editor/plugins/light_occluder_2d_editor_plugin.h @@ -83,7 +83,7 @@ protected: public: Vector2 snap_point(const Vector2 &p_point) const; - void forward_draw_over_viewport(Control *p_overlay); + void forward_canvas_draw_over_viewport(Control *p_overlay); bool forward_gui_input(const Ref<InputEvent> &p_event); void edit(Node *p_collision_polygon); LightOccluder2DEditor(EditorNode *p_editor); @@ -98,7 +98,7 @@ class LightOccluder2DEditorPlugin : public EditorPlugin { public: virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return light_occluder_editor->forward_gui_input(p_event); } - virtual void forward_draw_over_viewport(Control *p_overlay) { return light_occluder_editor->forward_draw_over_viewport(p_overlay); } + virtual void forward_canvas_draw_over_viewport(Control *p_overlay) { return light_occluder_editor->forward_canvas_draw_over_viewport(p_overlay); } virtual String get_name() const { return "LightOccluder2D"; } bool has_main_screen() const { return false; } diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp index 7b7e23531a..73a216e96f 100644 --- a/editor/plugins/mesh_editor_plugin.cpp +++ b/editor/plugins/mesh_editor_plugin.cpp @@ -65,14 +65,6 @@ void MeshEditor::_notification(int p_what) { first_enter = false; } } - - if (p_what == NOTIFICATION_DRAW) { - - Ref<Texture> checkerboard = get_icon("Checkerboard", "EditorIcons"); - Size2 size = get_size(); - - //draw_texture_rect(checkerboard, Rect2(Point2(), size), true); - } } void MeshEditor::_update_rotation() { diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index 96c1ad2f2b..88b3194490 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -288,7 +288,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return false; } -void Path2DEditor::forward_draw_over_viewport(Control *p_overlay) { +void Path2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { if (!node) return; diff --git a/editor/plugins/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h index 1e3955f84f..3a78657746 100644 --- a/editor/plugins/path_2d_editor_plugin.h +++ b/editor/plugins/path_2d_editor_plugin.h @@ -107,7 +107,7 @@ protected: public: bool forward_gui_input(const Ref<InputEvent> &p_event); - void forward_draw_over_viewport(Control *p_overlay); + void forward_canvas_draw_over_viewport(Control *p_overlay); void edit(Node *p_path2d); Path2DEditor(EditorNode *p_editor); }; @@ -121,7 +121,7 @@ class Path2DEditorPlugin : public EditorPlugin { public: virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return path2d_editor->forward_gui_input(p_event); } - virtual void forward_draw_over_viewport(Control *p_overlay) { return path2d_editor->forward_draw_over_viewport(p_overlay); } + virtual void forward_canvas_draw_over_viewport(Control *p_overlay) { return path2d_editor->forward_canvas_draw_over_viewport(p_overlay); } virtual String get_name() const { return "Path2D"; } bool has_main_screen() const { return false; } diff --git a/editor/plugins/physical_bone_plugin.cpp b/editor/plugins/physical_bone_plugin.cpp index 1c3c000808..6341d7f2ef 100644 --- a/editor/plugins/physical_bone_plugin.cpp +++ b/editor/plugins/physical_bone_plugin.cpp @@ -69,15 +69,7 @@ PhysicalBoneEditor::PhysicalBoneEditor(EditorNode *p_editor) : hide(); } -PhysicalBoneEditor::~PhysicalBoneEditor() { - // TODO the spatial_editor_hb should be removed from SpatialEditor, but in this moment it's not possible - for (int i = spatial_editor_hb->get_child_count() - 1; 0 <= i; --i) { - Node *n = spatial_editor_hb->get_child(i); - spatial_editor_hb->remove_child(n); - memdelete(n); - } - memdelete(spatial_editor_hb); -} +PhysicalBoneEditor::~PhysicalBoneEditor() {} void PhysicalBoneEditor::set_selected(PhysicalBone *p_pb) { @@ -98,19 +90,17 @@ void PhysicalBoneEditor::show() { PhysicalBonePlugin::PhysicalBonePlugin(EditorNode *p_editor) : editor(p_editor), - selected(NULL) { - - physical_bone_editor = memnew(PhysicalBoneEditor(editor)); -} + selected(NULL), + physical_bone_editor(editor) {} void PhysicalBonePlugin::make_visible(bool p_visible) { if (p_visible) { - physical_bone_editor->show(); + physical_bone_editor.show(); } else { - physical_bone_editor->hide(); - physical_bone_editor->set_selected(NULL); + physical_bone_editor.hide(); + physical_bone_editor.set_selected(NULL); selected = NULL; } } @@ -119,5 +109,5 @@ void PhysicalBonePlugin::edit(Object *p_node) { selected = static_cast<PhysicalBone *>(p_node); // Trust it ERR_FAIL_COND(!selected); - physical_bone_editor->set_selected(selected); + physical_bone_editor.set_selected(selected); } diff --git a/editor/plugins/physical_bone_plugin.h b/editor/plugins/physical_bone_plugin.h index e03d342709..e1f8c9ec47 100644 --- a/editor/plugins/physical_bone_plugin.h +++ b/editor/plugins/physical_bone_plugin.h @@ -64,7 +64,7 @@ class PhysicalBonePlugin : public EditorPlugin { EditorNode *editor; PhysicalBone *selected; - PhysicalBoneEditor *physical_bone_editor; + PhysicalBoneEditor physical_bone_editor; public: virtual String get_name() const { return "PhysicalBone"; } diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index e0c8cf41ff..f937744d45 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -767,6 +767,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { node->set_polygon(uv_new); } } break; + default: {} } if (bone_painting) { diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index c8e7bfb74b..7cda15bdc6 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -96,7 +96,7 @@ public: } } - RES get_cached_resource(const String &p_path) { + virtual RES get_cached_resource(const String &p_path) { Map<String, Cache>::Element *E = cached.find(p_path); if (!E) { @@ -134,9 +134,11 @@ public: max_cache_size = 128; max_time_cache = 5 * 60 * 1000; //minutes, five } + + virtual ~EditorScriptCodeCompletionCache() {} }; -void ScriptEditorQuickOpen::popup(const Vector<String> &p_functions, bool p_dontclear) { +void ScriptEditorQuickOpen::popup_dialog(const Vector<String> &p_functions, bool p_dontclear) { popup_centered_ratio(0.6); if (p_dontclear) @@ -968,11 +970,11 @@ void ScriptEditor::_menu_option(int p_option) { } break; case SEARCH_HELP: { - help_search_dialog->popup(); + help_search_dialog->popup_dialog(); } break; case SEARCH_CLASSES: { - help_index->popup(); + help_index->popup_dialog(); } break; case SEARCH_WEBSITE: { @@ -1204,7 +1206,7 @@ void ScriptEditor::_menu_option(int p_option) { case SEARCH_CLASSES: { - help_index->popup(); + help_index->popup_dialog(); help_index->call_deferred("select_class", help->get_class()); } break; case HELP_SEARCH_FIND: { @@ -1414,21 +1416,6 @@ void ScriptEditor::notify_script_changed(const Ref<Script> &p_script) { emit_signal("editor_script_changed", p_script); } -static const Node *_find_node_with_script(const Node *p_node, const RefPtr &p_script) { - - if (p_node->get_script() == p_script) - return p_node; - - for (int i = 0; i < p_node->get_child_count(); i++) { - - const Node *result = _find_node_with_script(p_node->get_child(i), p_script); - if (result) - return result; - } - - return NULL; -} - void ScriptEditor::get_breakpoints(List<String> *p_breakpoints) { for (int i = 0; i < tab_container->get_child_count(); i++) { @@ -2742,11 +2729,11 @@ void ScriptEditor::set_live_auto_reload_running_scripts(bool p_enabled) { } void ScriptEditor::_help_index(String p_text) { - help_index->popup(); + help_index->popup_dialog(); } void ScriptEditor::_help_search(String p_text) { - help_search_dialog->popup(p_text); + help_search_dialog->popup_dialog(p_text); } void ScriptEditor::_open_script_request(const String &p_path) { @@ -3013,7 +3000,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/show_in_file_system", TTR("Show In File System")), SHOW_IN_FILE_SYSTEM); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_previous", TTR("History Prev"), KEY_MASK_ALT | KEY_LEFT), WINDOW_PREV); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_previous", TTR("History Previous"), KEY_MASK_ALT | KEY_LEFT), WINDOW_PREV); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_next", TTR("History Next"), KEY_MASK_ALT | KEY_RIGHT), WINDOW_NEXT); file_menu->get_popup()->add_separator(); @@ -3060,7 +3047,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { debug_menu->get_popup()->add_separator(); //debug_menu->get_popup()->add_check_item("Show Debugger",DEBUG_SHOW); debug_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("debugger/keep_debugger_open", TTR("Keep Debugger Open")), DEBUG_SHOW_KEEP_OPEN); - debug_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("debugger/debug_with_exteral_editor", TTR("Debug with external editor")), DEBUG_WITH_EXTERNAL_EDITOR); + debug_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("debugger/debug_with_external_editor", TTR("Debug with External Editor")), DEBUG_WITH_EXTERNAL_EDITOR); debug_menu->get_popup()->connect("id_pressed", this, "_menu_option"); debug_menu->get_popup()->set_item_disabled(debug_menu->get_popup()->get_item_index(DEBUG_NEXT), true); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 120755b5af..28c07393f7 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -67,7 +67,7 @@ protected: static void _bind_methods(); public: - void popup(const Vector<String> &p_functions, bool p_dontclear = false); + void popup_dialog(const Vector<String> &p_functions, bool p_dontclear = false); ScriptEditorQuickOpen(); }; diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index d4ddaf274f..9b968c3523 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -940,7 +940,8 @@ void ScriptTextEditor::_edit_option(int p_op) { } break; case SEARCH_LOCATE_FUNCTION: { - quick_open->popup(get_functions()); + quick_open->popup_dialog(get_functions()); + quick_open->set_title(TTR("Go to Function")); } break; case SEARCH_GOTO_LINE: { @@ -1275,7 +1276,6 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { word_at_mouse = tx->get_selection_text(); bool has_color = (word_at_mouse == "Color"); - int fold_state = 0; bool foldable = tx->can_fold(row) || tx->is_folded(row); bool open_docs = false; bool goto_definition = false; @@ -1567,8 +1567,8 @@ void ScriptTextEditor::register_editor() { ED_SHORTCUT("script_text_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), KEY_F9); #endif ED_SHORTCUT("script_text_editor/remove_all_breakpoints", TTR("Remove All Breakpoints"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F9); - ED_SHORTCUT("script_text_editor/goto_next_breakpoint", TTR("Goto Next Breakpoint"), KEY_MASK_CMD | KEY_PERIOD); - ED_SHORTCUT("script_text_editor/goto_previous_breakpoint", TTR("Goto Previous Breakpoint"), KEY_MASK_CMD | KEY_COMMA); + ED_SHORTCUT("script_text_editor/goto_next_breakpoint", TTR("Go to Next Breakpoint"), KEY_MASK_CMD | KEY_PERIOD); + ED_SHORTCUT("script_text_editor/goto_previous_breakpoint", TTR("Go to Previous Breakpoint"), KEY_MASK_CMD | KEY_COMMA); ED_SHORTCUT("script_text_editor/find", TTR("Find..."), KEY_MASK_CMD | KEY_F); #ifdef OSX_ENABLED @@ -1581,14 +1581,14 @@ void ScriptTextEditor::register_editor() { ED_SHORTCUT("script_text_editor/replace", TTR("Replace..."), KEY_MASK_CMD | KEY_R); #endif - ED_SHORTCUT("script_text_editor/find_in_files", TTR("Find in files..."), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F); + ED_SHORTCUT("script_text_editor/find_in_files", TTR("Find in Files..."), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F); #ifdef OSX_ENABLED - ED_SHORTCUT("script_text_editor/goto_function", TTR("Goto Function..."), KEY_MASK_CTRL | KEY_MASK_CMD | KEY_J); + ED_SHORTCUT("script_text_editor/goto_function", TTR("Go to Function..."), KEY_MASK_CTRL | KEY_MASK_CMD | KEY_J); #else - ED_SHORTCUT("script_text_editor/goto_function", TTR("Goto Function..."), KEY_MASK_ALT | KEY_MASK_CMD | KEY_F); + ED_SHORTCUT("script_text_editor/goto_function", TTR("Go to Function..."), KEY_MASK_ALT | KEY_MASK_CMD | KEY_F); #endif - ED_SHORTCUT("script_text_editor/goto_line", TTR("Goto Line..."), KEY_MASK_CMD | KEY_L); + ED_SHORTCUT("script_text_editor/goto_line", TTR("Go to Line..."), KEY_MASK_CMD | KEY_L); #ifdef OSX_ENABLED ED_SHORTCUT("script_text_editor/contextual_help", TTR("Contextual Help"), KEY_MASK_ALT | KEY_MASK_SHIFT | KEY_SPACE); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 51e58b712e..17f93b55a1 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -86,10 +86,7 @@ void ShaderTextEditor::_load_theme_settings() { Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color"); Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color"); Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color"); - Color basetype_color = EDITOR_GET("text_editor/highlighting/base_type_color"); - Color type_color = EDITOR_GET("text_editor/highlighting/engine_type_color"); Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color"); - Color string_color = EDITOR_GET("text_editor/highlighting/string_color"); get_text_edit()->add_color_override("background_color", background_color); get_text_edit()->add_color_override("completion_background_color", completion_background_color); @@ -140,26 +137,9 @@ void ShaderTextEditor::_load_theme_settings() { get_text_edit()->add_keyword_color(E->get(), keyword_color); } - //colorize core types - //Color basetype_color= EDITOR_DEF("text_editor/base_type_color",Color(0.3,0.3,0.0)); - //colorize comments get_text_edit()->add_color_region("/*", "*/", comment_color, false); get_text_edit()->add_color_region("//", "", comment_color, false); - - /*//colorize strings - Color string_color = EDITOR_DEF("text_editor/string_color",Color::hex(0x6b6f00ff)); - - List<String> strings; - shader->get_shader_mode()->get_string_delimiters(&strings); - - for (List<String>::Element *E=strings.front();E;E=E->next()) { - - String string = E->get(); - String beg = string.get_slice(" ",0); - String end = string.get_slice_count(" ")>1?string.get_slice(" ",1):String(); - get_text_edit()->add_color_region(beg,end,string_color,end==""); - }*/ } void ShaderTextEditor::_check_shader_mode() { @@ -426,7 +406,7 @@ void ShaderEditor::ensure_select_current() { void ShaderEditor::edit(const Ref<Shader> &p_shader) { - if (p_shader.is_null()) + if (p_shader.is_null() || !p_shader->is_text_shader()) return; shader = p_shader; @@ -468,7 +448,6 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { int col, row; TextEdit *tx = shader_editor->get_text_edit(); tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col); - Vector2 mpos = mb->get_global_position() - tx->get_global_position(); tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret")); if (tx->is_right_click_moving_caret()) { @@ -606,7 +585,7 @@ void ShaderEditorPlugin::edit(Object *p_object) { bool ShaderEditorPlugin::handles(Object *p_object) const { Shader *shader = Object::cast_to<Shader>(p_object); - return shader != NULL; + return shader != NULL && shader->is_text_shader(); } void ShaderEditorPlugin::make_visible(bool p_visible) { diff --git a/editor/plugins/skeleton_editor_plugin.cpp b/editor/plugins/skeleton_editor_plugin.cpp index 50deb80668..e7d9f1b702 100644 --- a/editor/plugins/skeleton_editor_plugin.cpp +++ b/editor/plugins/skeleton_editor_plugin.cpp @@ -29,9 +29,10 @@ /*************************************************************************/ #include "skeleton_editor_plugin.h" + #include "scene/3d/collision_shape.h" #include "scene/3d/physics_body.h" -#include "scene/3d/physics_joint.h"; +#include "scene/3d/physics_joint.h" #include "scene/resources/capsule_shape.h" #include "scene/resources/sphere_shape.h" #include "spatial_editor_plugin.h" diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index fed4362405..114610c562 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -531,12 +531,12 @@ void SpatialEditorViewport::_select_region() { void SpatialEditorViewport::_update_name() { - String ortho = orthogonal ? TTR("Orthogonal") : TTR("Perspective"); + String view_mode = orthogonal ? TTR("Orthogonal") : TTR("Perspective"); if (name != "") - view_menu->set_text("[ " + name + " " + ortho + " ]"); + view_menu->set_text("[ " + name + " " + view_mode + " ]"); else - view_menu->set_text("[ " + ortho + " ]"); + view_menu->set_text("[ " + view_mode + " ]"); view_menu->set_size(Vector2(0, 0)); // resets the button size } @@ -997,6 +997,10 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { set_message(TTR("View Plane Transform."), 2); } break; + case TRANSFORM_YZ: + case TRANSFORM_XZ: + case TRANSFORM_XY: { + } break; } } } break; @@ -1545,6 +1549,10 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(2)); axis = Vector3(0, 0, 1); break; + case TRANSFORM_YZ: + case TRANSFORM_XZ: + case TRANSFORM_XY: + break; } Vector3 intersection; @@ -1904,7 +1912,7 @@ void SpatialEditorViewport::_nav_orbit(Ref<InputEventWithModifiers> p_event, con void SpatialEditorViewport::_nav_look(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative) { // Freelook only works properly in perspective. - // It technically works too in ortho, but it's awful for a user due to fov being near zero + // It could technically work in ortho, but it's terrible for a user due to FOV being a fixed width. if (!orthogonal) { real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity"); real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel); @@ -2075,7 +2083,7 @@ void SpatialEditorViewport::set_message(String p_message, float p_time) { } void SpatialEditorPlugin::edited_scene_changed() { - for (int i = 0; i < SpatialEditor::VIEWPORTS_COUNT; i++) { + for (uint32_t i = 0; i < SpatialEditor::VIEWPORTS_COUNT; i++) { SpatialEditorViewport *viewport = SpatialEditor::get_singleton()->get_editor_viewport(i); if (viewport->is_visible()) { viewport->notification(Control::NOTIFICATION_VISIBILITY_CHANGED); @@ -2199,7 +2207,7 @@ void SpatialEditorViewport::_notification(int p_what) { bool shrink = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_HALF_RESOLUTION)); - if (shrink != viewport_container->get_stretch_shrink() > 1) { + if (shrink != (viewport_container->get_stretch_shrink() > 1)) { viewport_container->set_stretch_shrink(shrink ? 2 : 1); } @@ -2312,12 +2320,12 @@ void SpatialEditorViewport::_draw() { EditorPluginList *over_plugin_list = EditorNode::get_singleton()->get_editor_plugins_over(); if (!over_plugin_list->empty()) { - over_plugin_list->forward_draw_over_viewport(surface); + over_plugin_list->forward_spatial_draw_over_viewport(surface); } EditorPluginList *force_over_plugin_list = editor->get_editor_plugins_force_over(); if (!force_over_plugin_list->empty()) { - force_over_plugin_list->forward_force_draw_over_viewport(surface); + force_over_plugin_list->forward_spatial_force_draw_over_viewport(surface); } if (surface->has_focus()) { @@ -2346,7 +2354,6 @@ void SpatialEditorViewport::_draw() { Point2 center = _point_to_screen(_edit.center); VisualServer::get_singleton()->canvas_item_add_line(ci, _edit.mouse_pos, center, Color(0.4, 0.7, 1.0, 0.8)); } - if (previewing) { Size2 ss = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height")); @@ -3536,69 +3543,77 @@ void SpatialEditorViewportContainer::_gui_input(const Ref<InputEvent> &p_event) Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - - Vector2 size = get_size(); - - int h_sep = get_constant("separation", "HSplitContainer"); - int v_sep = get_constant("separation", "VSplitContainer"); + if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) { - int mid_w = size.width * ratio_h; - int mid_h = size.height * ratio_v; + if (mb->is_pressed()) { + Vector2 size = get_size(); - dragging_h = mb->get_position().x > (mid_w - h_sep / 2) && mb->get_position().x < (mid_w + h_sep / 2); - dragging_v = mb->get_position().y > (mid_h - v_sep / 2) && mb->get_position().y < (mid_h + v_sep / 2); + int h_sep = get_constant("separation", "HSplitContainer"); + int v_sep = get_constant("separation", "VSplitContainer"); - drag_begin_pos = mb->get_position(); - drag_begin_ratio.x = ratio_h; - drag_begin_ratio.y = ratio_v; + int mid_w = size.width * ratio_h; + int mid_h = size.height * ratio_v; - switch (view) { - case VIEW_USE_1_VIEWPORT: { + dragging_h = mb->get_position().x > (mid_w - h_sep / 2) && mb->get_position().x < (mid_w + h_sep / 2); + dragging_v = mb->get_position().y > (mid_h - v_sep / 2) && mb->get_position().y < (mid_h + v_sep / 2); - dragging_h = false; - dragging_v = false; + drag_begin_pos = mb->get_position(); + drag_begin_ratio.x = ratio_h; + drag_begin_ratio.y = ratio_v; - } break; - case VIEW_USE_2_VIEWPORTS: { + switch (view) { + case VIEW_USE_1_VIEWPORT: { - dragging_h = false; + dragging_h = false; + dragging_v = false; - } break; - case VIEW_USE_2_VIEWPORTS_ALT: { + } break; + case VIEW_USE_2_VIEWPORTS: { - dragging_v = false; + dragging_h = false; - } break; - case VIEW_USE_3_VIEWPORTS: { + } break; + case VIEW_USE_2_VIEWPORTS_ALT: { - if (dragging_v) - dragging_h = false; - else dragging_v = false; - } break; - case VIEW_USE_3_VIEWPORTS_ALT: { + } break; + case VIEW_USE_3_VIEWPORTS: + case VIEW_USE_3_VIEWPORTS_ALT: + case VIEW_USE_4_VIEWPORTS: { - if (dragging_h) - dragging_v = false; - else - dragging_h = false; - } break; - case VIEW_USE_4_VIEWPORTS: { + // Do nothing. - } break; + } break; + } + } else { + dragging_h = false; + dragging_v = false; } } - if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - dragging_h = false; - dragging_v = false; - } - Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && (dragging_h || dragging_v)) { + if (mm.is_valid()) { + + if (view == VIEW_USE_3_VIEWPORTS || view == VIEW_USE_3_VIEWPORTS_ALT || view == VIEW_USE_4_VIEWPORTS) { + Vector2 size = get_size(); + + int h_sep = get_constant("separation", "HSplitContainer"); + int v_sep = get_constant("separation", "VSplitContainer"); + + int mid_w = size.width * ratio_h; + int mid_h = size.height * ratio_v; + + bool was_hovering_h = hovering_h; + bool was_hovering_v = hovering_v; + hovering_h = mm->get_position().x > (mid_w - h_sep / 2) && mm->get_position().x < (mid_w + h_sep / 2); + hovering_v = mm->get_position().y > (mid_h - v_sep / 2) && mm->get_position().y < (mid_h + v_sep / 2); + + if (was_hovering_h != hovering_h || was_hovering_v != hovering_v) { + update(); + } + } if (dragging_h) { float new_ratio = drag_begin_ratio.x + (mm->get_position().x - drag_begin_pos.x) / get_size().width; @@ -3628,9 +3643,12 @@ void SpatialEditorViewportContainer::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW && mouseover) { Ref<Texture> h_grabber = get_icon("grabber", "HSplitContainer"); - Ref<Texture> v_grabber = get_icon("grabber", "VSplitContainer"); + Ref<Texture> hdiag_grabber = get_icon("GuiViewportHdiagsplitter", "EditorIcons"); + Ref<Texture> vdiag_grabber = get_icon("GuiViewportVdiagsplitter", "EditorIcons"); + Ref<Texture> vh_grabber = get_icon("GuiViewportVhsplitter", "EditorIcons"); + Vector2 size = get_size(); int h_sep = get_constant("separation", "HSplitContainer"); @@ -3647,35 +3665,62 @@ void SpatialEditorViewportContainer::_notification(int p_what) { case VIEW_USE_1_VIEWPORT: { - //nothing to show + // Nothing to show. } break; case VIEW_USE_2_VIEWPORTS: { draw_texture(v_grabber, Vector2((size.width - v_grabber->get_width()) / 2, mid_h - v_grabber->get_height() / 2)); + set_default_cursor_shape(CURSOR_VSPLIT); } break; case VIEW_USE_2_VIEWPORTS_ALT: { draw_texture(h_grabber, Vector2(mid_w - h_grabber->get_width() / 2, (size.height - h_grabber->get_height()) / 2)); + set_default_cursor_shape(CURSOR_HSPLIT); } break; case VIEW_USE_3_VIEWPORTS: { - draw_texture(v_grabber, Vector2((size.width - v_grabber->get_width()) / 2, mid_h - v_grabber->get_height() / 2)); - draw_texture(h_grabber, Vector2(mid_w - h_grabber->get_width() / 2, mid_h + v_grabber->get_height() / 2 + (size_bottom - h_grabber->get_height()) / 2)); + if ((hovering_v && hovering_h && !dragging_v && !dragging_h) || (dragging_v && dragging_h)) { + draw_texture(hdiag_grabber, Vector2(mid_w - hdiag_grabber->get_width() / 2, mid_h - v_grabber->get_height() / 4)); + set_default_cursor_shape(CURSOR_DRAG); + } else if ((hovering_v && !dragging_h) || dragging_v) { + draw_texture(v_grabber, Vector2((size.width - v_grabber->get_width()) / 2, mid_h - v_grabber->get_height() / 2)); + set_default_cursor_shape(CURSOR_VSPLIT); + } else if (hovering_h || dragging_h) { + draw_texture(h_grabber, Vector2(mid_w - h_grabber->get_width() / 2, mid_h + v_grabber->get_height() / 2 + (size_bottom - h_grabber->get_height()) / 2)); + set_default_cursor_shape(CURSOR_HSPLIT); + } } break; case VIEW_USE_3_VIEWPORTS_ALT: { - draw_texture(v_grabber, Vector2((size_left - v_grabber->get_width()) / 2, mid_h - v_grabber->get_height() / 2)); - draw_texture(h_grabber, Vector2(mid_w - h_grabber->get_width() / 2, (size.height - h_grabber->get_height()) / 2)); + if ((hovering_v && hovering_h && !dragging_v && !dragging_h) || (dragging_v && dragging_h)) { + draw_texture(vdiag_grabber, Vector2(mid_w - vdiag_grabber->get_width() + v_grabber->get_height() / 4, mid_h - vdiag_grabber->get_height() / 2)); + set_default_cursor_shape(CURSOR_DRAG); + } else if ((hovering_v && !dragging_h) || dragging_v) { + draw_texture(v_grabber, Vector2((size_left - v_grabber->get_width()) / 2, mid_h - v_grabber->get_height() / 2)); + set_default_cursor_shape(CURSOR_VSPLIT); + } else if (hovering_h || dragging_h) { + draw_texture(h_grabber, Vector2(mid_w - h_grabber->get_width() / 2, (size.height - h_grabber->get_height()) / 2)); + set_default_cursor_shape(CURSOR_HSPLIT); + } + } break; case VIEW_USE_4_VIEWPORTS: { Vector2 half(mid_w, mid_h); - draw_texture(v_grabber, half - v_grabber->get_size() / 2.0); - draw_texture(h_grabber, half - h_grabber->get_size() / 2.0); + if ((hovering_v && hovering_h && !dragging_v && !dragging_h) || (dragging_v && dragging_h)) { + draw_texture(vh_grabber, half - vh_grabber->get_size() / 2.0); + set_default_cursor_shape(CURSOR_DRAG); + } else if ((hovering_v && !dragging_h) || dragging_v) { + draw_texture(v_grabber, half - v_grabber->get_size() / 2.0); + set_default_cursor_shape(CURSOR_VSPLIT); + } else if (hovering_h || dragging_h) { + draw_texture(h_grabber, half - h_grabber->get_size() / 2.0); + set_default_cursor_shape(CURSOR_HSPLIT); + } } break; } @@ -3719,6 +3764,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { case VIEW_USE_1_VIEWPORT: { + viewports[0]->show(); for (int i = 1; i < 4; i++) { viewports[i]->hide(); @@ -3729,7 +3775,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { } break; case VIEW_USE_2_VIEWPORTS: { - for (int i = 1; i < 4; i++) { + for (int i = 0; i < 4; i++) { if (i == 1 || i == 3) viewports[i]->hide(); @@ -3743,7 +3789,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { } break; case VIEW_USE_2_VIEWPORTS_ALT: { - for (int i = 1; i < 4; i++) { + for (int i = 0; i < 4; i++) { if (i == 1 || i == 3) viewports[i]->hide(); @@ -3756,7 +3802,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { } break; case VIEW_USE_3_VIEWPORTS: { - for (int i = 1; i < 4; i++) { + for (int i = 0; i < 4; i++) { if (i == 1) viewports[i]->hide(); @@ -3771,7 +3817,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { } break; case VIEW_USE_3_VIEWPORTS_ALT: { - for (int i = 1; i < 4; i++) { + for (int i = 0; i < 4; i++) { if (i == 1) viewports[i]->hide(); @@ -3786,7 +3832,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { } break; case VIEW_USE_4_VIEWPORTS: { - for (int i = 1; i < 4; i++) { + for (int i = 0; i < 4; i++) { viewports[i]->show(); } @@ -3819,10 +3865,13 @@ void SpatialEditorViewportContainer::_bind_methods() { SpatialEditorViewportContainer::SpatialEditorViewportContainer() { + set_clip_contents(true); view = VIEW_USE_1_VIEWPORT; mouseover = false; ratio_h = 0.5; ratio_v = 0.5; + hovering_v = false; + hovering_h = false; dragging_v = false; dragging_h = false; } @@ -4094,7 +4143,7 @@ void SpatialEditor::set_state(const Dictionary &p_state) { for (int j = 0; j < gizmo_plugins.size(); ++j) { if (!gizmo_plugins[j]->can_be_hidden()) continue; int state = EditorSpatialGizmoPlugin::ON_TOP; - for (uint32_t i = 0; i < keys.size(); i++) { + for (int i = 0; i < keys.size(); i++) { if (gizmo_plugins.write[j]->get_name() == keys[i]) { state = gizmos_status[keys[i]]; } @@ -4980,32 +5029,29 @@ void SpatialEditor::_unhandled_key_input(Ref<InputEvent> p_event) { if (!k->is_pressed()) return; - if (ED_IS_SHORTCUT("spatial_editor/tool_select", p_event)) + if (ED_IS_SHORTCUT("spatial_editor/tool_select", p_event)) { _menu_item_pressed(MENU_TOOL_SELECT); - - else if (ED_IS_SHORTCUT("spatial_editor/tool_move", p_event)) + } else if (ED_IS_SHORTCUT("spatial_editor/tool_move", p_event)) { _menu_item_pressed(MENU_TOOL_MOVE); - - else if (ED_IS_SHORTCUT("spatial_editor/tool_rotate", p_event)) + } else if (ED_IS_SHORTCUT("spatial_editor/tool_rotate", p_event)) { _menu_item_pressed(MENU_TOOL_ROTATE); - - else if (ED_IS_SHORTCUT("spatial_editor/tool_scale", p_event)) + } else if (ED_IS_SHORTCUT("spatial_editor/tool_scale", p_event)) { _menu_item_pressed(MENU_TOOL_SCALE); - else if (ED_IS_SHORTCUT("spatial_editor/snap_to_floor", p_event)) + } else if (ED_IS_SHORTCUT("spatial_editor/snap_to_floor", p_event)) { snap_selected_nodes_to_floor(); - - else if (ED_IS_SHORTCUT("spatial_editor/local_coords", p_event)) + } else if (ED_IS_SHORTCUT("spatial_editor/local_coords", p_event)) { if (are_local_coords_enabled()) { _menu_item_toggled(false, MENU_TOOL_LOCAL_COORDS); } else { _menu_item_toggled(true, MENU_TOOL_LOCAL_COORDS); } - else if (ED_IS_SHORTCUT("spatial_editor/snap", p_event)) + } else if (ED_IS_SHORTCUT("spatial_editor/snap", p_event)) { if (is_snap_enabled()) { _menu_item_toggled(false, MENU_TOOL_USE_SNAP); } else { _menu_item_toggled(true, MENU_TOOL_USE_SNAP); } + } } } } @@ -5584,7 +5630,6 @@ void SpatialEditorPlugin::make_visible(bool p_visible) { spatial_editor->show(); spatial_editor->set_process(true); - spatial_editor->grab_focus(); } else { diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index b7317cd593..c552f21e39 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -86,7 +86,7 @@ public: Vector<Vector3> handles; Vector<Vector3> secondary_handles; - float selectable_icon_size = -1.0f; + float selectable_icon_size; bool billboard_handle; bool valid; @@ -404,6 +404,7 @@ public: AcceptDialog *p_accept); Viewport *get_viewport_node() { return viewport; } + Camera *get_camera() { return camera; } // return the default camera object. SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index); }; @@ -443,6 +444,9 @@ private: float ratio_h; float ratio_v; + bool hovering_v; + bool hovering_h; + bool dragging_v; bool dragging_h; Vector2 drag_begin_pos; @@ -707,7 +711,6 @@ public: void register_gizmo_plugin(Ref<EditorSpatialGizmoPlugin> ref); - Camera *get_camera() { return NULL; } void edit(Spatial *p_spatial); void clear(); diff --git a/editor/plugins/sprite_editor_plugin.cpp b/editor/plugins/sprite_editor_plugin.cpp index 58a1835e68..c574b5e8ba 100644 --- a/editor/plugins/sprite_editor_plugin.cpp +++ b/editor/plugins/sprite_editor_plugin.cpp @@ -97,7 +97,7 @@ Vector<Vector2> expand(const Vector<Vector2> &points, const Rect2i &rect, float int lasti = p2->Contour.size() - 1; Vector2 prev = Vector2(p2->Contour[lasti].X / PRECISION, p2->Contour[lasti].Y / PRECISION); - for (int i = 0; i < p2->Contour.size(); i++) { + for (unsigned int i = 0; i < p2->Contour.size(); i++) { Vector2 cur = Vector2(p2->Contour[i].X / PRECISION, p2->Contour[i].Y / PRECISION); if (cur.distance_to(prev) > 0.5) { diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index a0adbfccff..aa4338d775 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -686,7 +686,7 @@ void TileMapEditor::_erase_selection() { } } -void TileMapEditor::_draw_cell(int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform) { +void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform) { Ref<Texture> t = node->get_tileset()->tile_get_texture(p_cell); @@ -783,19 +783,19 @@ void TileMapEditor::_draw_cell(int p_cell, const Point2i &p_point, bool p_flip_h modulate.a = 0.5; if (r.has_no_area()) - canvas_item_editor->draw_texture_rect(t, rect, false, modulate, p_transpose); + p_viewport->draw_texture_rect(t, rect, false, modulate, p_transpose); else - canvas_item_editor->draw_texture_rect_region(t, rect, r, modulate, p_transpose); + p_viewport->draw_texture_rect_region(t, rect, r, modulate, p_transpose); } -void TileMapEditor::_draw_fill_preview(int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform) { +void TileMapEditor::_draw_fill_preview(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform) { PoolVector<Vector2> points = _bucket_fill(p_point, false, true); PoolVector<Vector2>::Read pr = points.read(); int len = points.size(); for (int i = 0; i < len; ++i) { - _draw_cell(p_cell, pr[i], p_flip_h, p_flip_v, p_transpose, p_xform); + _draw_cell(p_viewport, p_cell, pr[i], p_flip_h, p_flip_v, p_transpose, p_xform); } } @@ -1390,17 +1390,17 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return false; } -void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { +void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { if (!node) return; Transform2D cell_xf = node->get_cell_transform(); - Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform(); + Transform2D xform = p_overlay->get_canvas_transform() * node->get_global_transform(); Transform2D xform_inv = xform.affine_inverse(); - Size2 screen_size = canvas_item_editor->get_size(); + Size2 screen_size = p_overlay->get_size(); { Rect2 aabb; aabb.position = node->world_to_map(xform_inv.xform(Vector2())); @@ -1419,7 +1419,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { Vector2 to = xform.xform(node->map_to_world(Vector2(i, si.position.y + si.size.y + 1))); Color col = i == 0 ? Color(1, 0.8, 0.2, 0.5) : Color(1, 0.3, 0.1, 0.2); - canvas_item_editor->draw_line(from, to, col, 1); + p_overlay->draw_line(from, to, col, 1); if (max_lines-- == 0) break; } @@ -1439,7 +1439,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { Vector2 from = xform.xform(node->map_to_world(Vector2(i, j), true) + ofs); Vector2 to = xform.xform(node->map_to_world(Vector2(i, j + 1), true) + ofs); Color col = i == 0 ? Color(1, 0.8, 0.2, 0.5) : Color(1, 0.3, 0.1, 0.2); - canvas_item_editor->draw_line(from, to, col, 1); + p_overlay->draw_line(from, to, col, 1); if (max_lines-- == 0) break; @@ -1457,7 +1457,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { Vector2 to = xform.xform(node->map_to_world(Vector2(si.position.x + si.size.x + 1, i))); Color col = i == 0 ? Color(1, 0.8, 0.2, 0.5) : Color(1, 0.3, 0.1, 0.2); - canvas_item_editor->draw_line(from, to, col, 1); + p_overlay->draw_line(from, to, col, 1); if (max_lines-- == 0) break; @@ -1476,7 +1476,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { Vector2 from = xform.xform(node->map_to_world(Vector2(j, i), true) + ofs); Vector2 to = xform.xform(node->map_to_world(Vector2(j + 1, i), true) + ofs); Color col = i == 0 ? Color(1, 0.8, 0.2, 0.5) : Color(1, 0.3, 0.1, 0.2); - canvas_item_editor->draw_line(from, to, col, 1); + p_overlay->draw_line(from, to, col, 1); if (max_lines-- == 0) break; @@ -1493,7 +1493,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { points.push_back(xform.xform(node->map_to_world((rectangle.position + Point2(rectangle.size.x + 1, rectangle.size.y + 1))))); points.push_back(xform.xform(node->map_to_world((rectangle.position + Point2(0, rectangle.size.y + 1))))); - canvas_item_editor->draw_colored_polygon(points, Color(0.2, 0.8, 1, 0.4)); + p_overlay->draw_colored_polygon(points, Color(0.2, 0.8, 1, 0.4)); } if (mouse_over) { @@ -1519,7 +1519,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { col = Color(1.0, 0.4, 0.2, 0.8); for (int i = 0; i < 4; i++) - canvas_item_editor->draw_line(endpoints[i], endpoints[(i + 1) % 4], col, 2); + p_overlay->draw_line(endpoints[i], endpoints[(i + 1) % 4], col, 2); bool bucket_preview = EditorSettings::get_singleton()->get("editors/tile_map/bucket_fill_preview"); if (tool == TOOL_SELECTING || tool == TOOL_PICKING || !bucket_preview) { @@ -1538,7 +1538,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) { - _draw_cell(ids[0], E->key(), flip_h, flip_v, transpose, xform); + _draw_cell(p_overlay, ids[0], E->key(), flip_h, flip_v, transpose, xform); } } else if (tool == TOOL_RECTANGLE_PAINT) { @@ -1551,7 +1551,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) { for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) { - _draw_cell(ids[0], Point2i(j, i), flip_h, flip_v, transpose, xform); + _draw_cell(p_overlay, ids[0], Point2i(j, i), flip_h, flip_v, transpose, xform); } } } else if (tool == TOOL_PASTING) { @@ -1573,7 +1573,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { TileData tcd = E->get(); - _draw_cell(tcd.cell, tcd.pos + ofs, tcd.flip_h, tcd.flip_v, tcd.transpose, xform); + _draw_cell(p_overlay, tcd.cell, tcd.pos + ofs, tcd.flip_h, tcd.flip_v, tcd.transpose, xform); } Rect2i duplicate = rectangle; @@ -1585,12 +1585,12 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { points.push_back(xform.xform(node->map_to_world((duplicate.position + Point2(duplicate.size.x + 1, duplicate.size.y + 1))))); points.push_back(xform.xform(node->map_to_world((duplicate.position + Point2(0, duplicate.size.y + 1))))); - canvas_item_editor->draw_colored_polygon(points, Color(0.2, 1.0, 0.8, 0.2)); + p_overlay->draw_colored_polygon(points, Color(0.2, 1.0, 0.8, 0.2)); } else if (tool == TOOL_BUCKET) { Vector<int> tiles = get_selected_tiles(); - _draw_fill_preview(tiles[0], over_tile, flip_h, flip_v, transpose, xform); + _draw_fill_preview(p_overlay, tiles[0], over_tile, flip_h, flip_v, transpose, xform); } else { @@ -1599,7 +1599,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { if (st.size() == 1 && st[0] == TileMap::INVALID_CELL) return; - _draw_cell(st[0], over_tile, flip_h, flip_v, transpose, xform); + _draw_cell(p_overlay, st[0], over_tile, flip_h, flip_v, transpose, xform); } } } diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h index c824824d56..74aece6f47 100644 --- a/editor/plugins/tile_map_editor_plugin.h +++ b/editor/plugins/tile_map_editor_plugin.h @@ -168,8 +168,8 @@ class TileMapEditor : public VBoxContainer { void _select(const Point2i &p_from, const Point2i &p_to); void _erase_selection(); - void _draw_cell(int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform); - void _draw_fill_preview(int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform); + void _draw_cell(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform); + void _draw_fill_preview(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform); void _clear_bucket_cache(); void _update_copydata(); @@ -206,7 +206,7 @@ public: HBoxContainer *get_toolbar() const { return toolbar; } bool forward_gui_input(const Ref<InputEvent> &p_event); - void forward_draw_over_viewport(Control *p_overlay); + void forward_canvas_draw_over_viewport(Control *p_overlay); void edit(Node *p_tile_map); @@ -225,7 +225,7 @@ protected: public: virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return tile_map_editor->forward_gui_input(p_event); } - virtual void forward_draw_over_viewport(Control *p_overlay) { tile_map_editor->forward_draw_over_viewport(p_overlay); } + virtual void forward_canvas_draw_over_viewport(Control *p_overlay) { tile_map_editor->forward_canvas_draw_over_viewport(p_overlay); } virtual String get_name() const { return "TileMap"; } bool has_main_screen() const { return false; } diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index a6a256f0d6..3de2284cea 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -795,6 +795,7 @@ void TileSetEditor::_on_workspace_draw() { spin_priority->set_suffix(" / " + String::num(total, 0)); draw_highlight_subtile(edited_shape_coord, queue_others); } break; + default: {} } draw_tile_subdivision(get_current_tile(), Color(0.347214, 0.722656, 0.617063)); @@ -1365,6 +1366,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } } } break; + default: {} } } } @@ -1434,6 +1436,7 @@ void TileSetEditor::_on_tool_clicked(int p_tool) { workspace->update(); } } break; + default: {} } } } else if (p_tool == ZOOM_OUT) { @@ -1862,6 +1865,7 @@ void TileSetEditor::draw_polygon_shapes() { } } } break; + default: {} } if (creating_shape) { for (int j = 0; j < current_shape.size() - 1; j++) { diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 207078d90f..39e50ec7f8 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -510,6 +510,17 @@ void VisualShaderEditor::_connection_request(const String &p_from, int p_from_in } undo_redo->create_action("Nodes Connected"); + + List<VisualShader::Connection> conns; + visual_shader->get_node_connections(type, &conns); + + for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) { + if (E->get().to_node == to && E->get().to_port == p_to_index) { + undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + } + } + undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->add_do_method(this, "_update_graph"); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 91ab5b4dff..83de5a646a 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -999,6 +999,10 @@ void ProjectManager::_unhandled_input(const Ref<InputEvent> &p_ev) { _open_project(); } break; + case KEY_DELETE: { + + _erase_project(); + } break; case KEY_HOME: { for (int i = 0; i < scroll_children->get_child_count(); i++) { diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 508db2e03f..c611327a31 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -1991,60 +1991,3 @@ CustomPropertyEditor::CustomPropertyEditor() { create_dialog = NULL; property_select = NULL; } - -///////////////////////////// - -double PropertyValueEvaluator::eval(const String &p_text) { - - // If range value contains a comma replace it with dot (issue #6028) - const String &p_new_text = p_text.replace(",", "."); - - if (!obj || !script_language) - return _default_eval(p_new_text); - - Ref<Script> script = Ref<Script>(script_language->create_script()); - script->set_source_code(_build_script(p_new_text)); - Error err = script->reload(); - if (err) { - ERR_PRINTS("PropertyValueEvaluator: Error loading script for expression: " + p_new_text); - return _default_eval(p_new_text); - } - - Object dummy; - ScriptInstance *script_instance = script->instance_create(&dummy); - if (!script_instance) - return _default_eval(p_new_text); - - Variant::CallError call_err; - Variant arg = obj; - const Variant *args[] = { &arg }; - double result = script_instance->call("eval", args, 1, call_err); - if (call_err.error == Variant::CallError::CALL_OK) { - return result; - } - ERR_PRINTS("PropertyValueEvaluator: Eval failed, error code: " + itos(call_err.error)); - - return _default_eval(p_new_text); -} - -void PropertyValueEvaluator::edit(Object *p_obj) { - obj = p_obj; -} - -String PropertyValueEvaluator::_build_script(const String &p_text) { - String script_text = "tool\nextends Object\nfunc eval(s):\n\tself = s\n\treturn " + p_text.strip_edges() + "\n"; - return script_text; -} - -PropertyValueEvaluator::PropertyValueEvaluator() { - script_language = NULL; - - for (int i = 0; i < ScriptServer::get_language_count(); i++) { - if (ScriptServer::get_language(i)->get_name() == "GDScript") { - script_language = ScriptServer::get_language(i); - } - } -} - -PropertyValueEvaluator::~PropertyValueEvaluator() { -} diff --git a/editor/property_editor.h b/editor/property_editor.h index ee3a56d857..c74103df3d 100644 --- a/editor/property_editor.h +++ b/editor/property_editor.h @@ -171,30 +171,9 @@ public: void set_read_only(bool p_read_only) { read_only = p_read_only; } - void set_value_evaluator(PropertyValueEvaluator *p_evaluator) { evaluator = p_evaluator; } - bool edit(Object *p_owner, const String &p_name, Variant::Type p_type, const Variant &p_variant, int p_hint, String p_hint_text); CustomPropertyEditor(); }; -class PropertyValueEvaluator : public ValueEvaluator { - GDCLASS(PropertyValueEvaluator, ValueEvaluator); - - Object *obj; - ScriptLanguage *script_language; - String _build_script(const String &p_text); - - _FORCE_INLINE_ double _default_eval(const String &p_text) { - return p_text.to_double(); - } - -public: - void edit(Object *p_obj); - double eval(const String &p_text); - - PropertyValueEvaluator(); - ~PropertyValueEvaluator(); -}; - #endif diff --git a/editor/pvrtc_compress.cpp b/editor/pvrtc_compress.cpp index b1c847570c..30e78aa32b 100644 --- a/editor/pvrtc_compress.cpp +++ b/editor/pvrtc_compress.cpp @@ -115,11 +115,6 @@ static void _compress_pvrtc4(Image *p_image) { _compress_image(Image::COMPRESS_PVRTC4, p_image); } -static void _compress_etc(Image *p_image) { - - _compress_image(Image::COMPRESS_ETC, p_image); -} - void _pvrtc_register_compressors() { _base_image_compress_pvrtc2_func = Image::_image_compress_pvrtc2_func; @@ -127,5 +122,4 @@ void _pvrtc_register_compressors() { Image::_image_compress_pvrtc2_func = _compress_pvrtc2; Image::_image_compress_pvrtc4_func = _compress_pvrtc4; - //Image::_image_compress_etc_func=_compress_etc; //use the built in one for ETC } diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp index 497596a508..e48a0022e8 100644 --- a/editor/quick_open.cpp +++ b/editor/quick_open.cpp @@ -32,7 +32,7 @@ #include "core/os/keyboard.h" -void EditorQuickOpen::popup(const StringName &p_base, bool p_enable_multi, bool p_add_dirs, bool p_dontclear) { +void EditorQuickOpen::popup_dialog(const StringName &p_base, bool p_enable_multi, bool p_add_dirs, bool p_dontclear) { add_directories = p_add_dirs; popup_centered_ratio(0.6); diff --git a/editor/quick_open.h b/editor/quick_open.h index ffea6b52bd..5451d5a08c 100644 --- a/editor/quick_open.h +++ b/editor/quick_open.h @@ -66,7 +66,7 @@ public: String get_selected() const; Vector<String> get_selected_files() const; - void popup(const StringName &p_base, bool p_enable_multi = false, bool p_add_dirs = false, bool p_dontclear = false); + void popup_dialog(const StringName &p_base, bool p_enable_multi = false, bool p_add_dirs = false, bool p_dontclear = false); EditorQuickOpen(); }; diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index ff6832177e..11a0a42b9e 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -568,15 +568,21 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { return; editor_data->get_undo_redo().create_action("Make node as Root"); - _node_replace_owner(root, node, node, MODE_DO); editor_data->get_undo_redo().add_do_method(node->get_parent(), "remove_child", node); + editor_data->get_undo_redo().add_do_method(root->get_parent(), "remove_child", root); + editor_data->get_undo_redo().add_do_method(node, "add_child", root); editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", node); editor_data->get_undo_redo().add_do_method(node, "set_filename", root->get_filename()); + editor_data->get_undo_redo().add_do_method(root, "set_filename", String()); + _node_replace_owner(root, root, node, MODE_DO); + editor_data->get_undo_redo().add_undo_method(root, "set_filename", root->get_filename()); editor_data->get_undo_redo().add_undo_method(node, "set_filename", String()); + editor_data->get_undo_redo().add_undo_method(node, "remove_child", root); editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", root); editor_data->get_undo_redo().add_undo_method(node->get_parent(), "add_child", node); - _node_replace_owner(root, node, root, MODE_UNDO); + _node_replace_owner(root, root, root, MODE_UNDO); + editor_data->get_undo_redo().add_do_method(scene_tree, "update_tree"); editor_data->get_undo_redo().add_undo_method(scene_tree, "update_tree"); editor_data->get_undo_redo().add_undo_reference(root); @@ -690,21 +696,13 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { Node *node = e->get(); if (node) { bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(node); - int editable_item_idx = menu->get_item_idx_from_text(TTR("Editable Children")); - int placeholder_item_idx = menu->get_item_idx_from_text(TTR("Load As Placeholder")); - editable = !editable; - EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(node, editable); - - menu->set_item_checked(editable_item_idx, editable); if (editable) { - node->set_scene_instance_load_placeholder(false); - menu->set_item_checked(placeholder_item_idx, false); + editable_instance_remove_dialog->set_text(TTR("Disabling \"editable_instance\" will cause all properties of the node to be reverted to their default.")); + editable_instance_remove_dialog->popup_centered_minsize(); + break; } - - SpatialEditor::get_singleton()->update_all_gizmos(node); - - scene_tree->update_tree(); + _toggle_editable_children(); } } } break; @@ -975,24 +973,22 @@ void SceneTreeDock::_notification(int p_what) { void SceneTreeDock::_node_replace_owner(Node *p_base, Node *p_node, Node *p_root, ReplaceOwnerMode p_mode) { - if (p_base != p_node) { - if (p_node->get_owner() == p_base) { - UndoRedo *undo_redo = &editor_data->get_undo_redo(); - switch (p_mode) { - case MODE_BIDI: { - undo_redo->add_do_method(p_node, "set_owner", p_root); - undo_redo->add_undo_method(p_node, "set_owner", p_base); + if (p_node->get_owner() == p_base || !p_node->get_owner()) { + UndoRedo *undo_redo = &editor_data->get_undo_redo(); + switch (p_mode) { + case MODE_BIDI: { + undo_redo->add_do_method(p_node, "set_owner", p_root); + undo_redo->add_undo_method(p_node, "set_owner", p_base); - } break; - case MODE_DO: { - undo_redo->add_do_method(p_node, "set_owner", p_root); + } break; + case MODE_DO: { + undo_redo->add_do_method(p_node, "set_owner", p_root); - } break; - case MODE_UNDO: { - undo_redo->add_undo_method(p_node, "set_owner", p_root); + } break; + case MODE_UNDO: { + undo_redo->add_undo_method(p_node, "set_owner", p_root); - } break; - } + } break; } } @@ -1489,6 +1485,33 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) { editor->push_item(p_script.operator->()); } +void SceneTreeDock::_toggle_editable_children() { + List<Node *> selection = editor_selection->get_selected_node_list(); + List<Node *>::Element *e = selection.front(); + if (e) { + Node *node = e->get(); + if (node) { + bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(node); + + int editable_item_idx = menu->get_item_idx_from_text(TTR("Editable Children")); + int placeholder_item_idx = menu->get_item_idx_from_text(TTR("Load As Placeholder")); + editable = !editable; + + EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(node, editable); + + menu->set_item_checked(editable_item_idx, editable); + if (editable) { + node->set_scene_instance_load_placeholder(false); + menu->set_item_checked(placeholder_item_idx, false); + } + + SpatialEditor::get_singleton()->update_all_gizmos(node); + + scene_tree->update_tree(); + } + } +} + void SceneTreeDock::_delete_confirm() { List<Node *> remove_list = editor_selection->get_selected_node_list(); @@ -1570,7 +1593,7 @@ void SceneTreeDock::_delete_confirm() { // Fixes the EditorHistory from still offering deleted notes EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history(); editor_history->cleanup_history(); - EditorNode::get_singleton()->call("_prepare_history"); + EditorNode::get_singleton()->get_inspector_dock()->call("_prepare_history"); } void SceneTreeDock::_update_script_button() { @@ -1587,6 +1610,10 @@ void SceneTreeDock::_selection_changed() { if (selection_size > 1) { //automatically turn on multi-edit _tool_selected(TOOL_MULTI_EDIT); + } else if (selection_size == 1) { + editor->push_item(EditorNode::get_singleton()->get_editor_selection()->get_selected_node_list()[0]); + } else { + editor->push_item(NULL); } _update_script_button(); } @@ -1852,32 +1879,6 @@ static bool _has_visible_children(Node *p_node) { return false; } -static Node *_find_last_visible(Node *p_node) { - - Node *last = NULL; - - bool collapsed = p_node->is_displayed_folded(); - - if (!collapsed) { - for (int i = 0; i < p_node->get_child_count(); i++) { - if (_is_node_visible(p_node->get_child(i))) { - last = p_node->get_child(i); - } - } - } - - if (last) { - Node *lastc = _find_last_visible(last); - if (lastc) - last = lastc; - - } else { - last = p_node; - } - - return last; -} - void SceneTreeDock::_normalize_drop(Node *&to_node, int &to_pos, int p_type) { to_pos = -1; @@ -2262,6 +2263,7 @@ void SceneTreeDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_input"), &SceneTreeDock::_input); ClassDB::bind_method(D_METHOD("_nodes_drag_begin"), &SceneTreeDock::_nodes_drag_begin); ClassDB::bind_method(D_METHOD("_delete_confirm"), &SceneTreeDock::_delete_confirm); + ClassDB::bind_method(D_METHOD("_toggle_editable_children"), &SceneTreeDock::_toggle_editable_children); ClassDB::bind_method(D_METHOD("_node_prerenamed"), &SceneTreeDock::_node_prerenamed); ClassDB::bind_method(D_METHOD("_import_subscene"), &SceneTreeDock::_import_subscene); ClassDB::bind_method(D_METHOD("_selection_changed"), &SceneTreeDock::_selection_changed); @@ -2427,6 +2429,10 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel add_child(delete_dialog); delete_dialog->connect("confirmed", this, "_delete_confirm"); + editable_instance_remove_dialog = memnew(ConfirmationDialog); + add_child(editable_instance_remove_dialog); + editable_instance_remove_dialog->connect("confirmed", this, "_toggle_editable_children"); + import_subscene_dialog = memnew(EditorSubScene); add_child(import_subscene_dialog); import_subscene_dialog->connect("subscene_selected", this, "_import_subscene"); diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 34a7c98d11..269b0b69db 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -121,6 +121,7 @@ class SceneTreeDock : public VBoxContainer { ScriptCreateDialog *script_create_dialog; AcceptDialog *accept; ConfirmationDialog *delete_dialog; + ConfirmationDialog *editable_instance_remove_dialog; ReparentDialog *reparent_dialog; EditorFileDialog *file; @@ -169,6 +170,8 @@ class SceneTreeDock : public VBoxContainer { void _delete_confirm(); + void _toggle_editable_children(); + void _node_prerenamed(Node *p_node, const String &p_new_name); void _nodes_drag_begin(); diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index d8de775d36..df704706af 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -50,7 +50,11 @@ void ScriptCreateDialog::_notification(int p_what) { } } -void ScriptCreateDialog::config(const String &p_base_name, const String &p_base_path) { +bool ScriptCreateDialog::_can_be_built_in() { + return (supports_built_in && built_in_enabled); +} + +void ScriptCreateDialog::config(const String &p_base_name, const String &p_base_path, bool p_built_in_enabled) { class_name->set_text(""); class_name->deselect(); @@ -66,6 +70,8 @@ void ScriptCreateDialog::config(const String &p_base_name, const String &p_base_ } file_path->deselect(); + built_in_enabled = p_built_in_enabled; + _lang_changed(current_language); _class_name_changed(""); _path_changed(file_path->get_text()); @@ -544,7 +550,7 @@ void ScriptCreateDialog::_update_dialog() { } } - if (!supports_built_in) + if (!_can_be_built_in()) internal->set_pressed(false); /* Is Script created or loaded from existing file */ @@ -553,14 +559,14 @@ void ScriptCreateDialog::_update_dialog() { get_ok()->set_text(TTR("Create")); parent_name->set_editable(true); parent_browse_button->set_disabled(false); - internal->set_disabled(!supports_built_in); + internal->set_disabled(!_can_be_built_in()); _msg_path_valid(true, TTR("Built-in script (into scene file)")); } else if (is_new_script_created) { // New Script Created get_ok()->set_text(TTR("Create")); parent_name->set_editable(true); parent_browse_button->set_disabled(false); - internal->set_disabled(!supports_built_in); + internal->set_disabled(!_can_be_built_in()); if (is_path_valid) { _msg_path_valid(true, TTR("Create new script file")); } @@ -569,7 +575,7 @@ void ScriptCreateDialog::_update_dialog() { get_ok()->set_text(TTR("Load")); parent_name->set_editable(false); parent_browse_button->set_disabled(true); - internal->set_disabled(!supports_built_in); + internal->set_disabled(!_can_be_built_in()); if (is_path_valid) { _msg_path_valid(true, TTR("Load existing script file")); } @@ -588,7 +594,7 @@ void ScriptCreateDialog::_bind_methods() { ClassDB::bind_method("_path_entered", &ScriptCreateDialog::_path_entered); ClassDB::bind_method("_template_changed", &ScriptCreateDialog::_template_changed); - ClassDB::bind_method(D_METHOD("config", "inherits", "path"), &ScriptCreateDialog::config); + ClassDB::bind_method(D_METHOD("config", "inherits", "path", "built_in_enabled"), &ScriptCreateDialog::config, DEFVAL(true)); ADD_SIGNAL(MethodInfo("script_created", PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script"))); } @@ -793,6 +799,7 @@ ScriptCreateDialog::ScriptCreateDialog() { has_named_classes = false; supports_built_in = false; can_inherit_from_file = false; + built_in_enabled = true; is_built_in = false; is_new_script_created = true; diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h index 1ad4a1b7a1..e0bf336b56 100644 --- a/editor/script_create_dialog.h +++ b/editor/script_create_dialog.h @@ -69,11 +69,13 @@ class ScriptCreateDialog : public ConfirmationDialog { bool is_parent_name_valid; bool is_class_name_valid; bool is_built_in; + bool built_in_enabled; int current_language; bool re_check_path; String script_template; Vector<String> template_list; + bool _can_be_built_in(); void _path_changed(const String &p_path = String()); void _path_entered(const String &p_path = String()); void _lang_changed(int l = 0); @@ -96,8 +98,7 @@ protected: static void _bind_methods(); public: - void config(const String &p_base_name, const String &p_base_path); - + void config(const String &p_base_name, const String &p_base_path, bool p_built_in_enabled = true); ScriptCreateDialog(); }; diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index cc477314e9..eb72d0aa6e 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -30,6 +30,7 @@ #include "script_editor_debugger.h" +#include "core/io/marshalls.h" #include "core/project_settings.h" #include "core/ustring.h" #include "editor_node.h" @@ -501,8 +502,12 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da String str = var; var = str.substr(4, str.length()); - if (str.begins_with("PATH")) - var = ResourceLoader::load(var); + if (str.begins_with("PATH")) { + if (String(var).empty()) + var = RES(); + else + var = ResourceLoader::load(var); + } } debugObj->prop_values[pinfo.name] = var; @@ -576,11 +581,9 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da String hs = String(); if (v.get_type() == Variant::OBJECT) { + v = Object::cast_to<EncodedObjectAsID>(v)->get_object_id(); h = PROPERTY_HINT_OBJECT_ID; - String s = v; - s = s.replace("[", ""); - hs = s.get_slice(":", 0); - v = s.get_slice(":", 1).to_int(); + hs = "Object"; } variables->add_property("Locals/" + n, v, h, hs); @@ -597,11 +600,9 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da String hs = String(); if (v.get_type() == Variant::OBJECT) { + v = Object::cast_to<EncodedObjectAsID>(v)->get_object_id(); h = PROPERTY_HINT_OBJECT_ID; - String s = v; - s = s.replace("[", ""); - hs = s.get_slice(":", 0); - v = s.get_slice(":", 1).to_int(); + hs = "Object"; } variables->add_property("Members/" + n, v, h, hs); @@ -618,11 +619,9 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da String hs = String(); if (v.get_type() == Variant::OBJECT) { + v = Object::cast_to<EncodedObjectAsID>(v)->get_object_id(); h = PROPERTY_HINT_OBJECT_ID; - String s = v; - s = s.replace("[", ""); - hs = s.get_slice(":", 0); - v = s.get_slice(":", 1).to_int(); + hs = "Object"; } variables->add_property("Globals/" + n, v, h, hs); @@ -727,9 +726,10 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da String source(err[5]); bool source_is_project_file = source.begins_with("res://"); if (source_is_project_file) - source = source.get_file(); + txt = source.get_file() + ":" + String(err[6]); + else + txt = source + ":" + String(err[6]); - txt = source + ":" + String(err[6]); String method = err[4]; if (method.length() > 0) txt += " @ " + method + "()"; @@ -1294,9 +1294,6 @@ void ScriptEditorDebugger::stop() { EditorNode::get_singleton()->get_scene_tree_dock()->hide_remote_tree(); EditorNode::get_singleton()->get_scene_tree_dock()->hide_tab_buttons(); - Node *node = editor->get_scene_tree_dock()->get_tree_editor()->get_selected(); - editor->push_item(node); - if (hide_on_stop) { if (is_visible_in_tree()) EditorNode::get_singleton()->hide_bottom_panel(); diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp index fe384da75b..537c9ac6b8 100644 --- a/editor/settings_config_dialog.cpp +++ b/editor/settings_config_dialog.cpp @@ -361,7 +361,7 @@ void EditorSettingsDialog::_tabs_tab_changed(int p_tab) { void EditorSettingsDialog::_focus_current_search_box() { Control *tab = tabs->get_current_tab_control(); - LineEdit *current_search_box; + LineEdit *current_search_box = NULL; if (tab == tab_general) current_search_box = search_box; else if (tab == tab_shortcuts) diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index 3097f0d0b9..96bca86f83 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -715,6 +715,7 @@ EditorSpatialGizmo::EditorSpatialGizmo() { instanced = false; spatial_node = NULL; gizmo_plugin = NULL; + selectable_icon_size = -1.0f; } EditorSpatialGizmo::~EditorSpatialGizmo() { |