diff options
Diffstat (limited to 'tools/editor')
38 files changed, 1996 insertions, 243 deletions
diff --git a/tools/editor/dependency_editor.cpp b/tools/editor/dependency_editor.cpp new file mode 100644 index 0000000000..c04e82a08a --- /dev/null +++ b/tools/editor/dependency_editor.cpp @@ -0,0 +1,512 @@ +#include "dependency_editor.h" +#include "os/file_access.h" +#include "scene/gui/margin_container.h" +#include "io/resource_loader.h" +#include "editor_node.h" + +void DependencyEditor::_notification(int p_what){ + + +} + +void DependencyEditor::_searched(const String& p_path) { + + Map<String,String> dep_rename; + dep_rename[replacing]=p_path; + + + ResourceLoader::rename_dependencies(editing,dep_rename); + + _update_list(); + _update_file(); +} + +void DependencyEditor::_load_pressed(Object* p_item,int p_cell,int p_button){ + + TreeItem *ti=p_item->cast_to<TreeItem>(); + String fname = ti->get_text(0); + replacing = ti->get_text(1); + + search->set_title("Search Replacement For: "+replacing.get_file()); + + search->clear_filters(); + List<String> ext; + ResourceLoader::get_recognized_extensions_for_type(ti->get_metadata(0),&ext); + for (List<String>::Element *E=ext.front();E;E=E->next()) { + search->add_filter("*"+E->get()); + } + search->popup_centered_ratio(); + +} + +void DependencyEditor::_fix_and_find(EditorFileSystemDirectory *efsd, Map<String,Map<String,String> >& candidates){ + + for(int i=0;i<efsd->get_subdir_count();i++) { + _fix_and_find(efsd->get_subdir(i),candidates); + } + + for(int i=0;i<efsd->get_file_count();i++) { + + String file = efsd->get_file(i); + if (!candidates.has(file)) + continue; + + String path = efsd->get_file_path(i); + Map<String,String> &ss = candidates[file]; + + + for(Map<String,String>::Element *E=candidates[file].front();E;E=E->next()) { + + if (E->get()==String()) { + E->get()=path; + continue; + } + + //must match the best, using subdirs + String existing=E->get().replace_first("res://",""); + String current=path.replace_first("res://",""); + String lost=E->key().replace_first("res://",""); + + Vector<String> existingv=existing.split("/"); + existingv.invert(); + Vector<String> currentv=current.split("/"); + currentv.invert(); + Vector<String> lostv=lost.split("/"); + lostv.invert(); + + int existing_score=0; + int current_score=0; + + for(int j=0;j<lostv.size();j++) { + + if (j<existingv.size() && lostv[j]==existingv[j]) { + existing_score++; + } + if (j<currentv.size() && lostv[j]==currentv[j]) { + current_score++; + } + } + + if (current_score > existing_score) { + + //if it was the same, could track distance to new path but.. + + E->get()=path; //replace by more accurate + } + + } + + } + +} + + +void DependencyEditor::_fix_all(){ + + if (!EditorFileSystem::get_singleton()->get_filesystem()) + return; + + Map<String,Map<String,String> > candidates; + + for (List<String>::Element *E=missing.front();E;E=E->next()) { + + String base = E->get().get_file(); + if (!candidates.has(base)) { + candidates[base]=Map<String,String>(); + } + + candidates[base][E->get()]=""; + } + + _fix_and_find(EditorFileSystem::get_singleton()->get_filesystem(),candidates); + + Map<String,String> remaps; + + for (Map<String,Map<String,String> >::Element *E=candidates.front();E;E=E->next()) { + + for (Map<String,String>::Element *F=E->get().front();F;F=F->next()) { + + if (F->get()!=String()) { + remaps[F->key()]=F->get(); + } + } + + } + + if (remaps.size()) { + + ResourceLoader::rename_dependencies(editing,remaps); + + _update_list(); + _update_file(); + } +} + +void DependencyEditor::_update_file() { + + EditorFileSystem::get_singleton()->update_file(editing); + +} + +void DependencyEditor::_update_list() { + + List<String> deps; + ResourceLoader::get_dependencies(editing,&deps,true); + + tree->clear(); + missing.clear(); + + TreeItem *root = tree->create_item(); + + Ref<Texture> folder = get_icon("folder","FileDialog"); + + bool broken=false; + + for(List<String>::Element *E=deps.front();E;E=E->next()) { + + TreeItem *item = tree->create_item(root); + + String n = E->get(); + String path; + String type; + + if (n.find("::")!=-1) { + path = n.get_slice("::",0); + type = n.get_slice("::",1); + } else { + path=n; + type="Resource"; + } + String name = path.get_file(); + + Ref<Texture> icon; + if (has_icon(type,"EditorIcons")) { + icon=get_icon(type,"EditorIcons"); + } else { + icon=get_icon("Object","EditorIcons"); + } + item->set_text(0,name); + item->set_icon(0,icon); + item->set_metadata(0,type); + item->set_text(1,path); + + if (!FileAccess::exists(path)) { + item->set_custom_color(1,Color(1,0.4,0.3)); + missing.push_back(path); + broken=true; + } + + item->add_button(1,folder,0); + } + + fixdeps->set_disabled(!broken); + +} + + + +void DependencyEditor::edit(const String& p_path) { + + + editing=p_path; + set_title("Dependencies For: "+p_path.get_file()); + + _update_list(); + popup_centered_ratio(); + + if (EditorNode::get_singleton()->is_scene_open(p_path)) { + EditorNode::get_singleton()->show_warning("Scene '"+p_path.get_file()+"' is currently being edited.\nChanges will not take effect unless reloaded."); + } else if (ResourceCache::has(p_path)) { + EditorNode::get_singleton()->show_warning("Resource '"+p_path.get_file()+"' is in use.\nChanges will take effect when reloaded."); + } +} + + +void DependencyEditor::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("_searched"),&DependencyEditor::_searched); + ObjectTypeDB::bind_method(_MD("_load_pressed"),&DependencyEditor::_load_pressed); + ObjectTypeDB::bind_method(_MD("_fix_all"),&DependencyEditor::_fix_all); + +} + +DependencyEditor::DependencyEditor() { + + VBoxContainer *vb = memnew( VBoxContainer ); + vb->set_name("Dependencies"); + add_child(vb); + set_child_rect(vb); + + tree = memnew( Tree ); + tree->set_columns(2); + tree->set_column_titles_visible(true); + tree->set_column_title(0,"Resource"); + tree->set_column_title(1,"Path"); + tree->set_hide_root(true); + tree->connect("button_pressed",this,"_load_pressed"); + + HBoxContainer *hbc = memnew( HBoxContainer ); + Label *label = memnew( Label("Dependencies:")); + hbc->add_child(label); + hbc->add_spacer(); + fixdeps = memnew( Button("Fix Broken")); + hbc->add_child(fixdeps); + fixdeps->connect("pressed",this,"_fix_all"); + + vb->add_child(hbc); + + MarginContainer *mc = memnew( MarginContainer ); + mc->set_v_size_flags(SIZE_EXPAND_FILL); + + mc->add_child(tree); + vb->add_child(mc); + + set_title("Dependency Editor"); + search = memnew( EditorFileDialog ); + search->connect("file_selected",this,"_searched"); + search->set_mode(EditorFileDialog::MODE_OPEN_FILE); + search->set_title("Search Replacement Resource:"); + add_child(search); + +} + +///////////////////////////////////// + + + +void DependencyEditorOwners::_fill_owners(EditorFileSystemDirectory *efsd) { + + if (!efsd) + return; + + for(int i=0;i<efsd->get_subdir_count();i++) { + _fill_owners(efsd->get_subdir(i)); + } + + for(int i=0;i<efsd->get_file_count();i++) { + + Vector<String> deps = efsd->get_file_deps(i); + //print_line(":::"+efsd->get_file_path(i)); + bool found=false; + for(int j=0;j<deps.size();j++) { + //print_line("\t"+deps[j]+" vs "+editing); + if (deps[j]==editing) { + //print_line("found"); + found=true; + break; + } + } + if (!found) + continue; + + Ref<Texture> icon; + String type=efsd->get_file_type(i); + if (!has_icon(type,"EditorIcons")) { + icon=get_icon("Object","EditorIcons"); + } else { + icon=get_icon(type,"EditorIcons"); + } + + owners->add_item(efsd->get_file_path(i),icon); + } + +} + +void DependencyEditorOwners::show(const String& p_path) { + + editing=p_path; + owners->clear(); + _fill_owners(EditorFileSystem::get_singleton()->get_filesystem()); + popup_centered_ratio(); + + set_title("Owners Of: "+p_path.get_file()); + +} + +DependencyEditorOwners::DependencyEditorOwners() { + + + owners = memnew( ItemList ); + add_child(owners); + set_child_rect(owners); + + +} + +/////////////////////// + + +void DependencyRemoveDialog::_fill_owners(EditorFileSystemDirectory *efsd) { + + if (!efsd) + return; + + for(int i=0;i<efsd->get_subdir_count();i++) { + _fill_owners(efsd->get_subdir(i)); + } + + for(int i=0;i<efsd->get_file_count();i++) { + + Vector<String> deps = efsd->get_file_deps(i); + //print_line(":::"+efsd->get_file_path(i)); + Set<String> met; + for(int j=0;j<deps.size();j++) { + if (files.has(deps[j])) { + met.insert(deps[j]); + } + } + if (!met.size()) + continue; + + exist=true; + + Ref<Texture> icon; + String type=efsd->get_file_type(i); + if (!has_icon(type,"EditorIcons")) { + icon=get_icon("Object","EditorIcons"); + } else { + icon=get_icon(type,"EditorIcons"); + } + + + for(Set<String>::Element *E=met.front();E;E=E->next()) { + + String which = E->get(); + if (!files[which]) { + TreeItem *ti=owners->create_item(owners->get_root()); + ti->set_text(0,which.get_file()); + files[which]=ti; + + } + TreeItem *ti=owners->create_item(files[which]); + ti->set_text(0,efsd->get_file_path(i)); + ti->set_icon(0,icon); + } + + } + +} + +void DependencyRemoveDialog::show(const Vector<String> &to_erase) { + + exist=false; + owners->clear(); + files.clear(); + TreeItem *root=owners->create_item(); + for(int i=0;i<to_erase.size();i++) { + files[to_erase[i]]=NULL; + } + + _fill_owners(EditorFileSystem::get_singleton()->get_filesystem()); + + if (exist) { + owners->show(); + text->set_text("The files being removed are required by other resources in order for them to work.\nRemove them anyway? (no undo)"); + popup_centered_minsize(Size2(500,220)); + } else { + owners->hide(); + text->set_text("Remove selected files from the project? (no undo)"); + popup_centered_minsize(Size2(400,100)); + } + +} + +void DependencyRemoveDialog::ok_pressed() { + + + DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + for (Map<String,TreeItem*>::Element *E=files.front();E;E=E->next()) { + + da->remove(E->key()); + EditorFileSystem::get_singleton()->update_file(E->key()); + } + memdelete(da); + +} + +DependencyRemoveDialog::DependencyRemoveDialog() { + + VBoxContainer *vb = memnew( VBoxContainer ); + add_child(vb); + set_child_rect(vb); + + text = memnew( Label ); + vb->add_child(text); + + owners = memnew( Tree ); + owners->set_hide_root(true); + vb->add_child(owners); + owners->set_v_size_flags(SIZE_EXPAND_FILL); + get_ok()->set_text("Remove"); +} + + +////////////// + + +void DependencyErrorDialog::show(const String& p_for_file,const Vector<String> &report) { + + + for_file=p_for_file; + set_title("Error loading: "+p_for_file.get_file()); + files->clear(); + + TreeItem *root = files->create_item(NULL); + for(int i=0;i<report.size();i++) { + + String dep; + String type="Object"; + dep=report[i].get_slice("::",0); + if (report[i].get_slice_count("::")>0) + type=report[i].get_slice("::",1); + + Ref<Texture> icon; + if (!has_icon(type,"EditorIcons")) { + icon=get_icon("Object","EditorIcons"); + } else { + icon=get_icon(type,"EditorIcons"); + } + + TreeItem *ti=files->create_item(root); + ti->set_text(0,dep); + ti->set_icon(0,icon); + + } + + popup_centered_minsize(Size2(500,220)); + +} + +void DependencyErrorDialog::ok_pressed() { + + EditorNode::get_singleton()->load_scene(for_file,true); +} + +void DependencyErrorDialog::custom_action(const String&) { + + EditorNode::get_singleton()->fix_dependencies(for_file); +} + +DependencyErrorDialog::DependencyErrorDialog() { + + VBoxContainer *vb = memnew( VBoxContainer ); + add_child(vb); + set_child_rect(vb); + + + files = memnew( Tree ); + files->set_hide_root(true); + vb->add_margin_child("Scene failed to load due to missing dependencies:",files,true); + files->set_v_size_flags(SIZE_EXPAND_FILL); + get_ok()->set_text("Open Anyway"); + + text = memnew( Label ); + vb->add_child(text); + text->set_text("Which action should be taken?"); + + + fdep=add_button("Fix Dependencies",true,"fixdeps"); + + set_title("Errors loading!"); + +} diff --git a/tools/editor/dependency_editor.h b/tools/editor/dependency_editor.h new file mode 100644 index 0000000000..1c328e7a93 --- /dev/null +++ b/tools/editor/dependency_editor.h @@ -0,0 +1,94 @@ +#ifndef DEPENDENCY_EDITOR_H +#define DEPENDENCY_EDITOR_H + +#include "scene/gui/dialogs.h" +#include "scene/gui/tree.h" +#include "scene/gui/tab_container.h" +#include "editor_file_dialog.h" + +class EditorFileSystemDirectory; + +class DependencyEditor : public AcceptDialog { + OBJ_TYPE(DependencyEditor,AcceptDialog); + + + Tree *tree; + Button *fixdeps; + + EditorFileDialog *search; + + String replacing; + String editing; + List<String> missing; + + + void _fix_and_find(EditorFileSystemDirectory *efsd, Map<String,Map<String,String> >& candidates); + + void _searched(const String& p_path); + void _load_pressed(Object* p_item,int p_cell,int p_button); + void _fix_all(); + void _update_list(); + + void _update_file(); + +protected: + + static void _bind_methods(); + void _notification(int p_what); +public: + + + void edit(const String& p_path); + DependencyEditor(); +}; + +class DependencyEditorOwners : public AcceptDialog { + OBJ_TYPE(DependencyEditorOwners,AcceptDialog); + + ItemList *owners; + String editing; + void _fill_owners(EditorFileSystemDirectory *efsd); + +public: + + void show(const String& p_path); + DependencyEditorOwners(); +}; + +class DependencyRemoveDialog : public ConfirmationDialog { + OBJ_TYPE(DependencyRemoveDialog,ConfirmationDialog); + + + Label *text; + Tree *owners; + bool exist; + Map<String,TreeItem*> files; + void _fill_owners(EditorFileSystemDirectory *efsd); + + void ok_pressed(); + +public: + + void show(const Vector<String> &to_erase); + DependencyRemoveDialog(); +}; + + +class DependencyErrorDialog : public ConfirmationDialog { + OBJ_TYPE(DependencyErrorDialog,ConfirmationDialog); + + + String for_file; + Button *fdep; + Label *text; + Tree *files; + void ok_pressed(); + void custom_action(const String&); + +public: + + void show(const String& p_for,const Vector<String> &report); + DependencyErrorDialog(); +}; + +#endif // DEPENDENCY_EDITOR_H diff --git a/tools/editor/editor_file_dialog.cpp b/tools/editor/editor_file_dialog.cpp index b1bbd71f7b..c62347d129 100644 --- a/tools/editor/editor_file_dialog.cpp +++ b/tools/editor/editor_file_dialog.cpp @@ -190,7 +190,7 @@ void EditorFileDialog::_thumbnail_done(const String& p_path,const Ref<Texture>& void EditorFileDialog::_request_single_thumbnail(const String& p_path) { EditorResourcePreview::get_singleton()->queue_resource_preview(p_path,this,"_thumbnail_done",p_path); - print_line("want file "+p_path); + //print_line("want file "+p_path); set_process(true); preview_waiting=true; preview_wheel_timeout=0; @@ -359,7 +359,7 @@ void EditorFileDialog::_item_dc_selected(int p_item) { if (d["dir"]) { - print_line("change dir: "+String(d["name"])); + //print_line("change dir: "+String(d["name"])); dir_access->change_dir(d["name"]); if (mode==MODE_OPEN_FILE || mode==MODE_OPEN_FILES || mode==MODE_OPEN_DIR) file->set_text(""); @@ -536,6 +536,7 @@ void EditorFileDialog::update_file_list() { if (get_icon_func) { + Ref<Texture> icon = get_icon_func(base_dir.plus_file(files.front()->get())); //ti->set_icon(0,icon); if (display_mode==DISPLAY_THUMBNAILS) { diff --git a/tools/editor/editor_file_system.cpp b/tools/editor/editor_file_system.cpp index d741087a9f..33e4a15c85 100644 --- a/tools/editor/editor_file_system.cpp +++ b/tools/editor/editor_file_system.cpp @@ -94,6 +94,12 @@ bool EditorFileSystemDirectory::get_file_meta(int p_idx) const { return files[p_idx].meta.enabled; } +Vector<String> EditorFileSystemDirectory::get_file_deps(int p_idx) const { + + ERR_FAIL_INDEX_V(p_idx,files.size(),Vector<String>()); + return files[p_idx].meta.deps; + +} Vector<String> EditorFileSystemDirectory::get_missing_sources(int p_idx) const { ERR_FAIL_INDEX_V(p_idx,files.size(),Vector<String>()); @@ -118,7 +124,7 @@ bool EditorFileSystemDirectory::is_missing_sources(int p_idx) const { return false; } -String EditorFileSystemDirectory::get_file_type(int p_idx) const { +StringName EditorFileSystemDirectory::get_file_type(int p_idx) const { ERR_FAIL_INDEX_V(p_idx,files.size(),""); return files[p_idx].type; @@ -198,6 +204,13 @@ EditorFileSystemDirectory::ImportMeta EditorFileSystem::_get_meta(const String& } m.import_editor=imd->get_editor(); } + + List<String> deps; + ResourceLoader::get_dependencies(p_path,&deps); + for(List<String>::Element *E=deps.front();E;E=E->next()) { + m.deps.push_back(E->get()); + } + return m; } @@ -358,7 +371,7 @@ void EditorFileSystem::_scan_scenes() { String project=Globals::get_singleton()->get_resource_path(); - String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("file_cache"); + String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache"); FileAccess *f =FileAccess::open(fscache,FileAccess::READ); if (f) { @@ -397,7 +410,7 @@ void EditorFileSystem::_scan_scenes() { } else { Vector<String> split = l.split("::"); - ERR_CONTINUE( split.size() != 4); + ERR_CONTINUE( split.size() != 5); String name = split[0]; String file; @@ -429,6 +442,15 @@ void EditorFileSystem::_scan_scenes() { } } + String deps = split[4].strip_edges(); + if (deps.length()) { + Vector<String> dp = deps.split("<>"); + for(int i=0;i<dp.size();i++) { + String path=dp[i]; + fc.meta.deps.push_back(path); + } + } + file_cache[name]=fc; ERR_CONTINUE(!dc); @@ -530,6 +552,7 @@ void EditorFileSystem::scan() { thread = Thread::create(_thread_func,this,s); //tree->hide(); //progress->show(); + } @@ -798,6 +821,14 @@ void EditorFileSystem::_save_type_cache_fs(DirItem *p_dir,FileAccess *p_file) { } } + s+="::"; + for(int j=0;j<p_dir->files[i]->meta.deps.size();j++) { + + if (j>0) + s+="<>"; + s+=p_dir->files[i]->meta.deps[j]; + } + p_file->store_line(s); } @@ -1037,6 +1068,13 @@ void EditorFileSystem::update_file(const String& p_file) { return; } + if (!FileAccess::exists(p_file)) { + //was removed + fs->files.remove(cpos); + call_deferred("emit_signal","filesystem_changed"); //update later + return; + + } String type = ResourceLoader::get_resource_type(p_file); diff --git a/tools/editor/editor_file_system.h b/tools/editor/editor_file_system.h index 3f413292fe..f79dd209ef 100644 --- a/tools/editor/editor_file_system.h +++ b/tools/editor/editor_file_system.h @@ -59,13 +59,14 @@ class EditorFileSystemDirectory : public Object { Vector<Source> sources; String import_editor; + Vector<String> deps; bool enabled; }; struct FileInfo { String file; - String type; + StringName type; uint64_t modified_time; ImportMeta meta; @@ -87,10 +88,11 @@ public: int get_file_count() const; String get_file(int p_idx) const; String get_file_path(int p_idx) const; - String get_file_type(int p_idx) const; + StringName get_file_type(int p_idx) const; bool get_file_meta(int p_idx) const; bool is_missing_sources(int p_idx) const; Vector<String> get_missing_sources(int p_idx) const; + Vector<String> get_file_deps(int p_idx) const; EditorFileSystemDirectory *get_parent(); @@ -120,7 +122,7 @@ class EditorFileSystem : public Node { String path; String name; Vector<DirItem*> dirs; - Vector<SceneItem*> files; + Vector<SceneItem*> files; ~DirItem(); }; @@ -149,6 +151,7 @@ class EditorFileSystem : public Node { String type; uint64_t modification_time; EditorFileSystemDirectory::ImportMeta meta; + Vector<String> deps; }; struct DirCache { diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index b0a2c568de..597fb236f5 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -1804,6 +1804,13 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { quick_open->set_title("Quick Open Script.."); } break; + case FILE_QUICK_OPEN_FILE: { + + + quick_open->popup("Resource",false,true); + quick_open->set_title("Quick Search File.."); + + } break; case FILE_RUN_SCRIPT: { file_script->popup_centered_ratio(); @@ -3050,7 +3057,21 @@ void EditorNode::set_current_scene(int p_idx) { } -Error EditorNode::load_scene(const String& p_scene) { +bool EditorNode::is_scene_open(const String& p_path) { + + for(int i=0;i<editor_data.get_edited_scene_count();i++) { + if (editor_data.get_scene_path(i)==p_path) + return true; + } + + return false; +} + +void EditorNode::fix_dependencies(const String& p_for_file) { + dependency_fixer->edit(p_for_file); +} + +Error EditorNode::load_scene(const String& p_scene, bool p_ignore_broken_deps) { if (!is_inside_tree()) { defer_load_scene = p_scene; @@ -3096,6 +3117,8 @@ Error EditorNode::load_scene(const String& p_scene) { //_cleanup_scene(); // i'm sorry but this MUST happen to avoid modified resources to not be reloaded. + dependency_errors.clear(); + Ref<PackedScene> sdata = ResourceLoader::load(lpath,"",true); if (!sdata.is_valid()) { @@ -3113,6 +3136,35 @@ Error EditorNode::load_scene(const String& p_scene) { return ERR_FILE_NOT_FOUND; } + if (!p_ignore_broken_deps && dependency_errors.has(lpath)) { + + current_option=-1; + Vector<String> errors; + for(Set<String>::Element *E=dependency_errors[lpath].front();E;E=E->next()) { + + errors.push_back(E->get()); + } + dependency_error->show(lpath,errors); + opening_prev=false; + + if (prev!=-1) { + set_current_scene(prev); + editor_data.remove_scene(idx); + } + return ERR_FILE_MISSING_DEPENDENCIES; + } + + dependency_errors.erase(lpath); //at least not self path + + for (Map<String,Set<String> >::Element *E=dependency_errors.front();E;E=E->next()) { + + String txt="Scene '"+E->key()+"' has broken dependencies:\n"; + for(Set<String>::Element *F=E->get().front();F;F=F->next()) { + txt+="\t"+F->get()+"\n"; + } + add_io_error(txt); + } + sdata->set_path(lpath,true); //take over path Node*new_scene=sdata->instance(true); @@ -3408,9 +3460,12 @@ void EditorNode::hide_animation_player_editors() { void EditorNode::_quick_opened(const String& p_resource) { - print_line("quick_opened"); - if (quick_open->get_base_type()=="PackedScene") { + if (current_option==FILE_QUICK_OPEN_FILE) { + scenes_dock->open(p_resource); + return; + } + if (quick_open->get_base_type()=="PackedScene") { open_request(p_resource); } else { load_resource(p_resource); @@ -4120,6 +4175,7 @@ EditorNode::EditorNode() { ResourceLoader::set_abort_on_missing_resources(false); FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("file_dialog/show_hidden_files")); ResourceLoader::set_error_notify_func(this,_load_error_notify); + ResourceLoader::set_dependency_error_notify_func(this,_dependency_error_report); ResourceLoader::set_timestamp_on_load(true); ResourceSaver::set_timestamp_on_save(true); @@ -4493,6 +4549,7 @@ EditorNode::EditorNode() { p->add_separator(); p->add_item("Quick Open Scene..",FILE_QUICK_OPEN_SCENE,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_O); p->add_item("Quick Open Script..",FILE_QUICK_OPEN_SCRIPT,KEY_MASK_ALT+KEY_MASK_CMD+KEY_O); + p->add_item("Quick Search File..",FILE_QUICK_OPEN_FILE,KEY_MASK_ALT+KEY_MASK_CMD+KEY_P); p->add_separator(); PopupMenu *pm_export = memnew(PopupMenu ); @@ -4929,7 +4986,11 @@ EditorNode::EditorNode() { + dependency_error = memnew( DependencyErrorDialog ); + gui_base->add_child(dependency_error); + dependency_fixer = memnew( DependencyEditor ); + gui_base->add_child( dependency_fixer ); settings_config_dialog = memnew( EditorSettingsDialog ); gui_base->add_child(settings_config_dialog); diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index d40658a056..ee45a49e4e 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -123,6 +123,7 @@ class EditorNode : public Node { FILE_OPEN_OLD_SCENE, FILE_QUICK_OPEN_SCENE, FILE_QUICK_OPEN_SCRIPT, + FILE_QUICK_OPEN_FILE, FILE_RUN_SCRIPT, FILE_OPEN_PREV, FILE_CLOSE, @@ -312,6 +313,9 @@ class EditorNode : public Node { ProgressDialog *progress_dialog; BackgroundProgress *progress_hb; + DependencyErrorDialog *dependency_error; + DependencyEditor *dependency_fixer; + TabContainer *dock_slot[DOCK_SLOT_MAX]; Rect2 dock_select_rect[DOCK_SLOT_MAX]; int dock_select_rect_over; @@ -451,6 +455,16 @@ class EditorNode : public Node { void _save_scene_with_preview(String p_file); + Map<String,Set<String> > dependency_errors; + + static void _dependency_error_report(void *ud,const String& p_path,const String& p_dep,const String& p_type) { + EditorNode*en=(EditorNode*)ud; + if (!en->dependency_errors.has(p_path)) + en->dependency_errors[p_path]=Set<String>(); + en->dependency_errors[p_path].insert(p_dep+"::"+p_type); + + } + struct ExportDefer { String platform; String path; @@ -534,10 +548,13 @@ public: Viewport *get_scene_root() { return scene_root; } //root of the scene being edited Error save_optimized_copy(const String& p_scene,const String& p_preset); + void fix_dependencies(const String& p_for_file); void clear_scene() { _cleanup_scene(); } - Error load_scene(const String& p_scene); + Error load_scene(const String& p_scene,bool p_ignore_broken_deps=false); Error load_resource(const String& p_scene); + bool is_scene_open(const String& p_path); + void set_current_version(uint64_t p_version); void set_current_scene(int p_idx); diff --git a/tools/editor/icons/icon_anchor.png b/tools/editor/icons/icon_anchor.png Binary files differnew file mode 100644 index 0000000000..1f9f9fa139 --- /dev/null +++ b/tools/editor/icons/icon_anchor.png diff --git a/tools/editor/icons/icon_control_align_bottom_center.png b/tools/editor/icons/icon_control_align_bottom_center.png Binary files differnew file mode 100644 index 0000000000..5ce9fe5c1c --- /dev/null +++ b/tools/editor/icons/icon_control_align_bottom_center.png diff --git a/tools/editor/icons/icon_control_align_bottom_left.png b/tools/editor/icons/icon_control_align_bottom_left.png Binary files differnew file mode 100644 index 0000000000..6c5129bf95 --- /dev/null +++ b/tools/editor/icons/icon_control_align_bottom_left.png diff --git a/tools/editor/icons/icon_control_align_bottom_right.png b/tools/editor/icons/icon_control_align_bottom_right.png Binary files differnew file mode 100644 index 0000000000..8857f4e940 --- /dev/null +++ b/tools/editor/icons/icon_control_align_bottom_right.png diff --git a/tools/editor/icons/icon_control_align_bottom_wide.png b/tools/editor/icons/icon_control_align_bottom_wide.png Binary files differnew file mode 100644 index 0000000000..56f009b8e4 --- /dev/null +++ b/tools/editor/icons/icon_control_align_bottom_wide.png diff --git a/tools/editor/icons/icon_control_align_center.png b/tools/editor/icons/icon_control_align_center.png Binary files differnew file mode 100644 index 0000000000..acd42525fa --- /dev/null +++ b/tools/editor/icons/icon_control_align_center.png diff --git a/tools/editor/icons/icon_control_align_center_left.png b/tools/editor/icons/icon_control_align_center_left.png Binary files differnew file mode 100644 index 0000000000..997074b097 --- /dev/null +++ b/tools/editor/icons/icon_control_align_center_left.png diff --git a/tools/editor/icons/icon_control_align_center_right.png b/tools/editor/icons/icon_control_align_center_right.png Binary files differnew file mode 100644 index 0000000000..b5cae63f7a --- /dev/null +++ b/tools/editor/icons/icon_control_align_center_right.png diff --git a/tools/editor/icons/icon_control_align_left_center.png b/tools/editor/icons/icon_control_align_left_center.png Binary files differnew file mode 100644 index 0000000000..7bb4dfb567 --- /dev/null +++ b/tools/editor/icons/icon_control_align_left_center.png diff --git a/tools/editor/icons/icon_control_align_left_wide.png b/tools/editor/icons/icon_control_align_left_wide.png Binary files differnew file mode 100644 index 0000000000..1b0a6cff95 --- /dev/null +++ b/tools/editor/icons/icon_control_align_left_wide.png diff --git a/tools/editor/icons/icon_control_align_right_center.png b/tools/editor/icons/icon_control_align_right_center.png Binary files differnew file mode 100644 index 0000000000..cf12d44c6a --- /dev/null +++ b/tools/editor/icons/icon_control_align_right_center.png diff --git a/tools/editor/icons/icon_control_align_right_wide.png b/tools/editor/icons/icon_control_align_right_wide.png Binary files differnew file mode 100644 index 0000000000..406ed25aed --- /dev/null +++ b/tools/editor/icons/icon_control_align_right_wide.png diff --git a/tools/editor/icons/icon_control_align_top_center.png b/tools/editor/icons/icon_control_align_top_center.png Binary files differnew file mode 100644 index 0000000000..da7ede984a --- /dev/null +++ b/tools/editor/icons/icon_control_align_top_center.png diff --git a/tools/editor/icons/icon_control_align_top_left.png b/tools/editor/icons/icon_control_align_top_left.png Binary files differnew file mode 100644 index 0000000000..84a224fbbe --- /dev/null +++ b/tools/editor/icons/icon_control_align_top_left.png diff --git a/tools/editor/icons/icon_control_align_top_right.png b/tools/editor/icons/icon_control_align_top_right.png Binary files differnew file mode 100644 index 0000000000..3b58eead9c --- /dev/null +++ b/tools/editor/icons/icon_control_align_top_right.png diff --git a/tools/editor/icons/icon_control_align_top_wide.png b/tools/editor/icons/icon_control_align_top_wide.png Binary files differnew file mode 100644 index 0000000000..869ae26134 --- /dev/null +++ b/tools/editor/icons/icon_control_align_top_wide.png diff --git a/tools/editor/icons/icon_control_align_wide.png b/tools/editor/icons/icon_control_align_wide.png Binary files differnew file mode 100644 index 0000000000..57a2933b25 --- /dev/null +++ b/tools/editor/icons/icon_control_align_wide.png diff --git a/tools/editor/icons/icon_control_hcenter_wide.png b/tools/editor/icons/icon_control_hcenter_wide.png Binary files differnew file mode 100644 index 0000000000..739ea5baeb --- /dev/null +++ b/tools/editor/icons/icon_control_hcenter_wide.png diff --git a/tools/editor/icons/icon_control_vcenter_wide.png b/tools/editor/icons/icon_control_vcenter_wide.png Binary files differnew file mode 100644 index 0000000000..44cbb8f344 --- /dev/null +++ b/tools/editor/icons/icon_control_vcenter_wide.png diff --git a/tools/editor/icons/icon_file_list.png b/tools/editor/icons/icon_file_list.png Binary files differindex e5e9213e61..ab790a85a5 100644 --- a/tools/editor/icons/icon_file_list.png +++ b/tools/editor/icons/icon_file_list.png diff --git a/tools/editor/icons/icon_filesystem.png b/tools/editor/icons/icon_filesystem.png Binary files differnew file mode 100644 index 0000000000..6841f9a792 --- /dev/null +++ b/tools/editor/icons/icon_filesystem.png diff --git a/tools/editor/icons/icon_non_favorite.png b/tools/editor/icons/icon_non_favorite.png Binary files differnew file mode 100644 index 0000000000..edd806fbe8 --- /dev/null +++ b/tools/editor/icons/icon_non_favorite.png diff --git a/tools/editor/icons/icon_patch_9_frame.png b/tools/editor/icons/icon_patch_9_frame.png Binary files differnew file mode 100644 index 0000000000..c8f38fa61a --- /dev/null +++ b/tools/editor/icons/icon_patch_9_frame.png diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp index f2738f0a62..8fc2945450 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.cpp +++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp @@ -1910,12 +1910,20 @@ void CanvasItemEditor::_notification(int p_what) { List<Node*> &selection = editor_selection->get_selected_node_list(); + bool all_control=true; + bool has_control=false; + for(List<Node*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->cast_to<Control>()) + has_control=true; + else + all_control=false; + CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); if (!se) continue; @@ -1932,6 +1940,13 @@ void CanvasItemEditor::_notification(int p_what) { } + bool show_anchor = all_control && has_control; + if (show_anchor != !anchor_menu->is_hidden()) { + if (show_anchor) + anchor_menu->show(); + else + anchor_menu->hide(); + } for(Map<ObjectID,BoneList>::Element *E=bone_list.front();E;E=E->next()) { @@ -1974,6 +1989,32 @@ void CanvasItemEditor::_notification(int p_what) { ungroup_button->set_icon(get_icon("Ungroup","EditorIcons")); key_insert_button->set_icon(get_icon("Key","EditorIcons")); + + //anchor_menu->add_icon_override("Align Top Left"); + anchor_menu->set_icon(get_icon("Anchor","EditorIcons")); + PopupMenu *p=anchor_menu->get_popup(); + + p->add_icon_item(get_icon("ControlAlignTopLeft","EditorIcons"),"Top Left",ANCHOR_ALIGN_TOP_LEFT); + p->add_icon_item(get_icon("ControlAlignTopRight","EditorIcons"),"Top Right",ANCHOR_ALIGN_TOP_RIGHT); + p->add_icon_item(get_icon("ControlAlignBottomRight","EditorIcons"),"Bottom Right",ANCHOR_ALIGN_BOTTOM_RIGHT); + p->add_icon_item(get_icon("ControlAlignBottomLeft","EditorIcons"),"Bottom Left",ANCHOR_ALIGN_BOTTOM_LEFT); + p->add_separator(); + p->add_icon_item(get_icon("ControlAlignLeftCenter","EditorIcons"),"Center Left",ANCHOR_ALIGN_CENTER_LEFT); + p->add_icon_item(get_icon("ControlAlignTopCenter","EditorIcons"),"Center Top",ANCHOR_ALIGN_CENTER_TOP); + p->add_icon_item(get_icon("ControlAlignRightCenter","EditorIcons"),"Center Right",ANCHOR_ALIGN_CENTER_RIGHT); + p->add_icon_item(get_icon("ControlAlignBottomCenter","EditorIcons"),"Center Bottom",ANCHOR_ALIGN_CENTER_BOTTOM); + p->add_icon_item(get_icon("ControlAlignCenter","EditorIcons"),"Center",ANCHOR_ALIGN_CENTER); + p->add_separator(); + p->add_icon_item(get_icon("ControlAlignLeftWide","EditorIcons"),"Left Wide",ANCHOR_ALIGN_LEFT_WIDE); + p->add_icon_item(get_icon("ControlAlignTopWide","EditorIcons"),"Top Wide",ANCHOR_ALIGN_TOP_WIDE); + p->add_icon_item(get_icon("ControlAlignRightWide","EditorIcons"),"Right Wide",ANCHOR_ALIGN_RIGHT_WIDE); + p->add_icon_item(get_icon("ControlAlignBottomWide","EditorIcons"),"Bottom Wide",ANCHOR_ALIGN_BOTTOM_WIDE); + p->add_icon_item(get_icon("ControlVcenterWide","EditorIcons"),"VCenter Wide ",ANCHOR_ALIGN_VCENTER_WIDE); + p->add_icon_item(get_icon("ControlHcenterWide","EditorIcons"),"HCenter Wide ",ANCHOR_ALIGN_HCENTER_WIDE); + p->add_separator(); + p->add_icon_item(get_icon("ControlAlignWide","EditorIcons"),"Full Rect",ANCHOR_ALIGN_WIDE); + + } if (p_what==NOTIFICATION_READY) { @@ -2179,6 +2220,27 @@ void CanvasItemEditor::_update_scroll(float) { } +void CanvasItemEditor::_set_anchor(Control::AnchorType p_left,Control::AnchorType p_top,Control::AnchorType p_right,Control::AnchorType p_bottom) { + List<Node*> &selection = editor_selection->get_selected_node_list(); + + undo_redo->create_action("Change Anchors"); + for(List<Node*>::Element *E=selection.front();E;E=E->next()) { + + Control *c = E->get()->cast_to<Control>(); + + undo_redo->add_do_method(c,"set_anchor",MARGIN_LEFT,p_left); + undo_redo->add_do_method(c,"set_anchor",MARGIN_TOP,p_top); + undo_redo->add_do_method(c,"set_anchor",MARGIN_RIGHT,p_right); + undo_redo->add_do_method(c,"set_anchor",MARGIN_BOTTOM,p_bottom); + undo_redo->add_undo_method(c,"set_anchor",MARGIN_LEFT,c->get_anchor(MARGIN_LEFT)); + undo_redo->add_undo_method(c,"set_anchor",MARGIN_TOP,c->get_anchor(MARGIN_TOP)); + undo_redo->add_undo_method(c,"set_anchor",MARGIN_RIGHT,c->get_anchor(MARGIN_RIGHT)); + undo_redo->add_undo_method(c,"set_anchor",MARGIN_BOTTOM,c->get_anchor(MARGIN_BOTTOM)); + } + + undo_redo->commit_action(); + +} void CanvasItemEditor::_popup_callback(int p_op) { @@ -2381,6 +2443,56 @@ void CanvasItemEditor::_popup_callback(int p_op) { case SPACE_VERTICAL: { //space_selected_items< proj_vector2_y, compare_items_y >(); } break; + case ANCHOR_ALIGN_TOP_LEFT: { + _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN); + } break; + case ANCHOR_ALIGN_TOP_RIGHT: { + _set_anchor(ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN); + } break; + case ANCHOR_ALIGN_BOTTOM_LEFT: { + _set_anchor(ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END); + } break; + case ANCHOR_ALIGN_BOTTOM_RIGHT: { + _set_anchor(ANCHOR_END,ANCHOR_END,ANCHOR_END,ANCHOR_END); + } break; + case ANCHOR_ALIGN_CENTER_LEFT: { + _set_anchor(ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER); + } break; + case ANCHOR_ALIGN_CENTER_RIGHT: { + + _set_anchor(ANCHOR_END,ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER); + } break; + case ANCHOR_ALIGN_CENTER_TOP: { + _set_anchor(ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_BEGIN); + } break; + case ANCHOR_ALIGN_CENTER_BOTTOM: { + _set_anchor(ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER,ANCHOR_END); + } break; + case ANCHOR_ALIGN_CENTER: { + _set_anchor(ANCHOR_CENTER,ANCHOR_CENTER,ANCHOR_CENTER,ANCHOR_CENTER); + } break; + case ANCHOR_ALIGN_TOP_WIDE: { + _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN); + } break; + case ANCHOR_ALIGN_LEFT_WIDE: { + _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END); + } break; + case ANCHOR_ALIGN_RIGHT_WIDE: { + _set_anchor(ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END); + } break; + case ANCHOR_ALIGN_BOTTOM_WIDE: { + _set_anchor(ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END,ANCHOR_END); + } break; + case ANCHOR_ALIGN_VCENTER_WIDE: { + _set_anchor(ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_END); + } break; + case ANCHOR_ALIGN_HCENTER_WIDE: { + _set_anchor(ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER); + } break; + case ANCHOR_ALIGN_WIDE: { + _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END); + } break; + case ANIM_INSERT_KEY: case ANIM_INSERT_KEY_EXISTING: { @@ -2999,6 +3111,14 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p->add_item("Center Selection", VIEW_CENTER_TO_SELECTION, KEY_F); p->add_item("Frame Selection", VIEW_FRAME_TO_SELECTION, KEY_MASK_CMD|KEY_F); + anchor_menu = memnew( MenuButton ); + anchor_menu->set_text("Anchor"); + hb->add_child(anchor_menu); + anchor_menu->get_popup()->connect("item_pressed", this,"_popup_callback"); + anchor_menu->hide(); + + //p = anchor_menu->get_popup(); + animation_hb = memnew( HBoxContainer ); diff --git a/tools/editor/plugins/canvas_item_editor_plugin.h b/tools/editor/plugins/canvas_item_editor_plugin.h index 48a34e2d07..485422028e 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.h +++ b/tools/editor/plugins/canvas_item_editor_plugin.h @@ -90,6 +90,23 @@ class CanvasItemEditor : public VBoxContainer { UNGROUP_SELECTED, ALIGN_HORIZONTAL, ALIGN_VERTICAL, + ANCHOR_ALIGN_TOP_LEFT, + ANCHOR_ALIGN_TOP_RIGHT, + ANCHOR_ALIGN_BOTTOM_LEFT, + ANCHOR_ALIGN_BOTTOM_RIGHT, + ANCHOR_ALIGN_CENTER_LEFT, + ANCHOR_ALIGN_CENTER_RIGHT, + ANCHOR_ALIGN_CENTER_TOP, + ANCHOR_ALIGN_CENTER_BOTTOM, + ANCHOR_ALIGN_CENTER, + ANCHOR_ALIGN_TOP_WIDE, + ANCHOR_ALIGN_LEFT_WIDE, + ANCHOR_ALIGN_RIGHT_WIDE, + ANCHOR_ALIGN_BOTTOM_WIDE, + ANCHOR_ALIGN_VCENTER_WIDE, + ANCHOR_ALIGN_HCENTER_WIDE, + ANCHOR_ALIGN_WIDE, + SPACE_HORIZONTAL, SPACE_VERTICAL, EXPAND_TO_PARENT, @@ -225,6 +242,7 @@ class CanvasItemEditor : public VBoxContainer { MenuButton *view_menu; HBoxContainer *animation_hb; MenuButton *animation_menu; + MenuButton *anchor_menu; Button *key_loc_button; Button *key_rot_button; @@ -305,6 +323,8 @@ class CanvasItemEditor : public VBoxContainer { void _viewport_input_event(const InputEvent& p_event); void _viewport_draw(); + void _set_anchor(Control::AnchorType p_left,Control::AnchorType p_top,Control::AnchorType p_right,Control::AnchorType p_bottom); + HSplitContainer *palette_split; VSplitContainer *bottom_split; diff --git a/tools/editor/project_export.cpp b/tools/editor/project_export.cpp index a087f23c25..626fc6e6df 100644 --- a/tools/editor/project_export.cpp +++ b/tools/editor/project_export.cpp @@ -80,7 +80,7 @@ bool ProjectExportDialog::_create_tree(TreeItem *p_parent,EditorFileSystemDirect String path = p_dir->get_file_path(i); fitem->set_tooltip(0,path); fitem->set_metadata(0,path); - Ref<Texture> icon = get_icon( (has_icon(p_dir->get_file_type(i),"EditorIcons")?p_dir->get_file_type(i):String("Object")),"EditorIcons"); + Ref<Texture> icon = get_icon( (has_icon(p_dir->get_file_type(i),ei)?p_dir->get_file_type(i):ot),ei); fitem->set_icon(0,icon); fitem->set_cell_mode(1,TreeItem::CELL_MODE_RANGE); @@ -1372,6 +1372,8 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) { button_export = add_button("Export..",!OS::get_singleton()->get_swap_ok_cancel(),"export_pck"); updating_script=false; + ei="EditorIcons"; + ot="Object"; } diff --git a/tools/editor/project_export.h b/tools/editor/project_export.h index c88233ae01..d85e688e58 100644 --- a/tools/editor/project_export.h +++ b/tools/editor/project_export.h @@ -78,6 +78,9 @@ private: HBoxContainer *plat_errors; Label *platform_error_string; + StringName ei; + StringName ot; + Tree * tree; EditorFileDialog *pck_export; diff --git a/tools/editor/quick_open.cpp b/tools/editor/quick_open.cpp index 749318386c..6135a4ab64 100644 --- a/tools/editor/quick_open.cpp +++ b/tools/editor/quick_open.cpp @@ -30,8 +30,9 @@ #include "os/keyboard.h" -void EditorQuickOpen::popup(const String& p_base, bool p_dontclear) { +void EditorQuickOpen::popup(const StringName &p_base, bool p_dontclear, bool p_add_dirs) { + add_directories=p_add_dirs; popup_centered_ratio(0.6); if (p_dontclear) search_box->select_all(); @@ -66,27 +67,53 @@ void EditorQuickOpen::_sbox_input(const InputEvent& p_ie) { void EditorQuickOpen::_parse_fs(EditorFileSystemDirectory *efsd) { - for(int i=0;i<efsd->get_subdir_count();i++) { + if (!add_directories) { + for(int i=0;i<efsd->get_subdir_count();i++) { - _parse_fs(efsd->get_subdir(i)); + _parse_fs(efsd->get_subdir(i)); + } } + TreeItem *root = search_options->get_root(); + + if (add_directories) { + String path = efsd->get_path(); + if (!path.ends_with("/")) + path+="/"; + if (path!="res://") { + path=path.substr(6,path.length()); + if (path.findn(search_box->get_text())!=-1) { + TreeItem *ti = search_options->create_item(root); + ti->set_text(0,path); + Ref<Texture> icon = get_icon("folder","FileDialog"); + ti->set_icon(0,icon); + } + } + } for(int i=0;i<efsd->get_file_count();i++) { String file = efsd->get_file_path(i); file=file.substr(6,file.length()); if (ObjectTypeDB::is_type(efsd->get_file_type(i),base_type) && (search_box->get_text()=="" || file.findn(search_box->get_text())!=-1)) { - TreeItem *root = search_options->get_root(); TreeItem *ti = search_options->create_item(root); ti->set_text(0,file); - Ref<Texture> icon = get_icon( (has_icon(efsd->get_file_type(i),"EditorIcons")?efsd->get_file_type(i):String("Object")),"EditorIcons"); + Ref<Texture> icon = get_icon( (has_icon(efsd->get_file_type(i),ei)?efsd->get_file_type(i):ot),ei); ti->set_icon(0,icon); if (root->get_children()==ti) ti->select(0); } } + + + if (add_directories) { + for(int i=0;i<efsd->get_subdir_count();i++) { + + _parse_fs(efsd->get_subdir(i)); + } + } + } void EditorQuickOpen::_update_search() { @@ -118,7 +145,7 @@ void EditorQuickOpen::_notification(int p_what) { } -String EditorQuickOpen::get_base_type() const { +StringName EditorQuickOpen::get_base_type() const { return base_type; } @@ -152,4 +179,7 @@ EditorQuickOpen::EditorQuickOpen() { set_hide_on_ok(false); search_options->connect("item_activated",this,"_confirmed"); search_options->set_hide_root(true); + ei="EditorIcons"; + ot="Object"; + add_directories=false; } diff --git a/tools/editor/quick_open.h b/tools/editor/quick_open.h index 63652a442a..8b38256d39 100644 --- a/tools/editor/quick_open.h +++ b/tools/editor/quick_open.h @@ -38,7 +38,11 @@ class EditorQuickOpen : public ConfirmationDialog { LineEdit *search_box; Tree *search_options; - String base_type; + StringName base_type; + StringName ei; + StringName ot; + bool add_directories; + void _update_search(); @@ -55,9 +59,9 @@ protected: static void _bind_methods(); public: - String get_base_type() const; + StringName get_base_type() const; - void popup(const String& p_base,bool p_dontclear=false); + void popup(const StringName& p_base,bool p_dontclear=false,bool p_add_dirs=false); EditorQuickOpen(); }; diff --git a/tools/editor/scenes_dock.cpp b/tools/editor/scenes_dock.cpp index 9153616775..7d9c5b24b2 100644 --- a/tools/editor/scenes_dock.cpp +++ b/tools/editor/scenes_dock.cpp @@ -35,15 +35,30 @@ #include "os/os.h" #include "editor_node.h" +#include "editor_settings.h" + bool ScenesDock::_create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_dir) { - String search_term = tree_filter->get_search_term(); - ScenesDockFilter::FilterOption file_filter = tree_filter->get_file_filter(); TreeItem *item = tree->create_item(p_parent); - item->set_text(0,p_dir->get_name()+"/"); + 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_custom_bg_color(0,get_color("prop_subsection","Editor")); + 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); + } + + + //item->set_custom_bg_color(0,get_color("prop_subsection","Editor")); bool has_items=false; @@ -52,7 +67,7 @@ bool ScenesDock::_create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_di if (_create_tree(item,p_dir->get_subdir(i))) has_items=true; } - +#if 0 for (int i=0;i<p_dir->get_file_count();i++) { String file_name = p_dir->get_file(i); @@ -89,13 +104,13 @@ bool ScenesDock::_create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_di has_items=true; } - - if (!has_items) { +#endif + /*if (!has_items) { memdelete(item); return false; - } + }*/ return true; } @@ -105,7 +120,28 @@ void ScenesDock::_update_tree() { tree->clear(); updating_tree=true; - _create_tree(NULL,EditorFileSystem::get_singleton()->get_filesystem()); + TreeItem *root = tree->create_item(); + TreeItem *favorites = tree->create_item(root); + favorites->set_icon(0, get_icon("Favorites","EditorIcons") ); + favorites->set_text(0,"Favorites:"); + favorites->set_selectable(0,false); + Vector<String> faves = EditorSettings::get_singleton()->get_favorite_dirs(); + for(int i=0;i<faves.size();i++) { + if (!faves[i].begins_with("res://")) + continue; + + TreeItem *ti = tree->create_item(favorites); + String fv = faves[i]; + if (fv=="res://") + ti->set_text(0,"/"); + else + ti->set_text(0,faves[i].get_file()); + ti->set_icon(0,get_icon("Folder","EditorIcons")); + ti->set_selectable(0,true); + ti->set_metadata(0,faves[i]); + } + + _create_tree(root,EditorFileSystem::get_singleton()->get_filesystem()); updating_tree=false; } @@ -117,68 +153,192 @@ void ScenesDock::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { + if (initialized) + return; + initialized=false; - EditorFileSystem::get_singleton()->connect("filesystem_changed",this,"_update_tree"); + EditorFileSystem::get_singleton()->connect("filesystem_changed",this,"_fs_changed"); button_reload->set_icon( get_icon("Reload","EditorIcons")); button_favorite->set_icon( get_icon("Favorites","EditorIcons")); + button_fav_up->set_icon( get_icon("MoveUp","EditorIcons")); + button_fav_down->set_icon( get_icon("MoveDown","EditorIcons")); button_instance->set_icon( get_icon("Add","EditorIcons")); button_open->set_icon( get_icon("Folder","EditorIcons")); + button_back->set_icon( get_icon("Filesystem","EditorIcons")); + display_mode->set_icon( get_icon("FileList","EditorIcons")); + display_mode->connect("pressed",this,"_change_file_display"); + file_options->set_icon( get_icon("Tools","EditorIcons")); + files->connect("item_activated",this,"_select_file"); + button_hist_next->connect("pressed",this,"_fw_history"); + button_hist_prev->connect("pressed",this,"_bw_history"); - String path = Globals::get_singleton()->get_resource_path()+"/favorites.cfg"; - FileAccess *f=FileAccess::open(path,FileAccess::READ); - if (f) { + button_hist_next->set_icon( get_icon("Forward","EditorIcons")); + button_hist_prev->set_icon( get_icon("Back","EditorIcons")); + file_options->get_popup()->connect("item_pressed",this,"_file_option"); - String l = f->get_line(); - while(l!="") { - favorites.insert(l); - l = f->get_line(); - - } + button_back->connect("pressed",this,"_go_to_tree",varray(),CONNECT_DEFERRED); + current_path->connect("text_entered",this,"_go_to_dir"); + _update_tree(); //maybe it finished already - f->close(); - memdelete(f); + if (EditorFileSystem::get_singleton()->is_scanning()) { + _set_scannig_mode(); } - - - _update_tree(); //maybe it finished already + } break; + case NOTIFICATION_PROCESS: { + if (EditorFileSystem::get_singleton()->is_scanning()) { + scanning_progress->set_val(EditorFileSystem::get_singleton()->get_scanning_progress()*100); + } } break; case NOTIFICATION_EXIT_TREE: { } break; - case NOTIFICATION_PROCESS: { - } break; } } -void ScenesDock::_favorite_toggled() { - if (updating_tree) + + +void ScenesDock::_dir_selected() { + + TreeItem *ti = tree->get_selected(); + if (!ti) return; + String dir = ti->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]==dir) { + found=true; + break; + } + } + + + button_favorite->set_pressed(found); + if (ti->get_parent() && ti->get_parent()->get_parent()==tree->get_root() && !ti->get_parent()->get_prev()) { + + //a favorite!!! + button_fav_up->set_disabled(!ti->get_prev()); + button_fav_down->set_disabled(!ti->get_next()); + } else { + button_fav_up->set_disabled(true); + button_fav_down->set_disabled(true); + + } +} + +void ScenesDock::_fav_up_pressed() { TreeItem *sel = tree->get_selected(); if (!sel) - return; //? + return ; - bool faved = sel->is_checked(0); - String path = sel->get_metadata(0); - if (faved) - favorites.insert(path); - else - favorites.erase(path); + if (!sel->get_prev()) + return; + + String sw = sel->get_prev()->get_metadata(0); + String txt = sel->get_metadata(0); + + Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs(); + + int a_idx=favorited.find(sw); + int b_idx=favorited.find(txt); + + if (a_idx==-1 || b_idx==-1) + return; + SWAP(favorited[a_idx],favorited[b_idx]); + + EditorSettings::get_singleton()->set_favorite_dirs(favorited); + + _update_tree(); - timer->start(); + if (!tree->get_root() || !tree->get_root()->get_children() || !tree->get_root()->get_children()->get_children()) + return; + sel = tree->get_root()->get_children()->get_children(); + while(sel) { + String t = sel->get_metadata(0); + if (t==txt) { + sel->select(0); + return; + } + sel=sel->get_next(); + } } -void ScenesDock::_favorites_toggled(bool p_toggled) { +void ScenesDock::_fav_down_pressed() { + + TreeItem *sel = tree->get_selected(); + if (!sel) + return ; + + if (!sel->get_next()) + return; + + String sw = sel->get_next()->get_metadata(0); + String txt = sel->get_metadata(0); + + Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs(); + + int a_idx=favorited.find(sw); + int b_idx=favorited.find(txt); + + if (a_idx==-1 || b_idx==-1) + return; + SWAP(favorited[a_idx],favorited[b_idx]); + + EditorSettings::get_singleton()->set_favorite_dirs(favorited); _update_tree(); + + if (!tree->get_root() || !tree->get_root()->get_children() || !tree->get_root()->get_children()->get_children()) + return; + sel = tree->get_root()->get_children()->get_children(); + while(sel) { + + String t = sel->get_metadata(0); + if (t==txt) { + sel->select(0); + return; + } + sel=sel->get_next(); + } +} + +void ScenesDock::_favorites_pressed() { + + TreeItem *sel = tree->get_selected(); + if (!sel) + return ; + String dir = 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]==dir) { + idx=i; + break; + } + } + + if (button_favorite->is_pressed() && idx==-1) { + favorites.push_back(dir); + EditorSettings::get_singleton()->set_favorite_dirs(favorites); + _update_tree(); + } else if (!button_favorite->is_pressed() && idx!=-1) { + favorites.remove(idx); + EditorSettings::get_singleton()->set_favorite_dirs(favorites); + _update_tree(); + } + } String ScenesDock::get_selected_path() const { @@ -199,65 +359,712 @@ void ScenesDock::_instance_pressed() { emit_signal("instance",path); } -void ScenesDock::_open_pressed(){ +void ScenesDock::_thumbnail_done(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata) { - TreeItem *sel = tree->get_selected(); - if (!sel) { + if (p_preview.is_valid() && path==p_path.get_base_dir()) { + + int idx=p_udata; + if (idx>=files->get_item_count()) + return; + String fpath = files->get_item_metadata(idx); + if (fpath!=p_path) + return; + files->set_item_icon(idx,p_preview); + + } + +} + +void ScenesDock::_change_file_display() { + + if (display_mode->is_pressed()) { + display_mode->set_icon( get_icon("FileThumbnail","EditorIcons")); + + } else { + display_mode->set_icon( get_icon("FileList","EditorIcons")); + } + + _update_files(true); +} + +void ScenesDock::_update_files(bool p_keep_selection) { + + 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)); + } + } + + files->clear(); + + EditorFileSystemDirectory *efd = EditorFileSystem::get_singleton()->get_path(path); + if (!efd) return; + + int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size"); + Ref<Texture> folder_thumbnail; + Ref<Texture> file_thumbnail; + + bool use_thumbnails=!display_mode->is_pressed(); + + if (use_thumbnails) { //thumbnails + + files->set_max_columns(0); + files->set_icon_mode(ItemList::ICON_MODE_TOP); + files->set_fixed_column_width(thumbnail_size*3/2); + files->set_max_text_lines(2); + files->set_min_icon_size(Size2(thumbnail_size,thumbnail_size)); + + if (!has_icon("ResizedFolder","EditorIcons")) { + Ref<ImageTexture> folder = get_icon("FolderBig","EditorIcons"); + Image img = folder->get_data(); + img.resize(thumbnail_size,thumbnail_size); + Ref<ImageTexture> resized_folder = Ref<ImageTexture>( memnew( ImageTexture)); + resized_folder->create_from_image(img,0); + Theme::get_default()->set_icon("ResizedFolder","EditorIcons",resized_folder); + } + + folder_thumbnail = get_icon("ResizedFolder","EditorIcons"); + + if (!has_icon("ResizedFile","EditorIcons")) { + Ref<ImageTexture> file = get_icon("FileBig","EditorIcons"); + Image img = file->get_data(); + img.resize(thumbnail_size,thumbnail_size); + Ref<ImageTexture> resized_file = Ref<ImageTexture>( memnew( ImageTexture)); + resized_file->create_from_image(img,0); + Theme::get_default()->set_icon("ResizedFile","EditorIcons",resized_file); + } + + file_thumbnail = get_icon("ResizedFile","EditorIcons"); + + } else { + + files->set_icon_mode(ItemList::ICON_MODE_LEFT); + files->set_max_columns(1); + files->set_max_text_lines(1); + files->set_fixed_column_width(0); + files->set_min_icon_size(Size2()); + } - String path = sel->get_metadata(0); - if (ResourceLoader::get_resource_type(path)=="PackedScene") { - editor->open_request(path); + if (path!="res://") { + + if (use_thumbnails) { + files->add_item("..",folder_thumbnail,true); + } else { + files->add_item("..",get_icon("folder","FileDialog"),true); + } + + String bd = path.get_base_dir(); + if (bd!="res://" && !bd.ends_with("/")) + bd+="/"; + + files->set_item_metadata(files->get_item_count()-1,bd); + } + + for(int i=0;i<efd->get_subdir_count();i++) { + + String dname=efd->get_subdir(i)->get_name(); + + + if (use_thumbnails) { + files->add_item(dname,folder_thumbnail,true); + } else { + files->add_item(dname,get_icon("folder","FileDialog"),true); + } + + files->set_item_metadata(files->get_item_count()-1,path.plus_file(dname)+"/"); + + if (cselection.has(dname)) + files->select(files->get_item_count()-1,false); + } + + for(int i=0;i<efd->get_file_count();i++) { + + String fname=efd->get_file(i); + String fp = path.plus_file(fname); + + + String type = efd->get_file_type(i); + Ref<Texture> type_icon; + + if (has_icon(type,"EditorIcons")) { + type_icon=get_icon(type,"EditorIcons"); + } else { + type_icon=get_icon("Object","EditorIcons"); + } + + if (use_thumbnails) { + files->add_item(fname,file_thumbnail,true); + files->set_item_metadata(files->get_item_count()-1,fp); + files->set_item_tag_icon(files->get_item_count()-1,type_icon); + EditorResourcePreview::get_singleton()->queue_resource_preview(fp,this,"_thumbnail_done",files->get_item_count()-1); + } else { + files->add_item(fname,type_icon,true); + files->set_item_metadata(files->get_item_count()-1,fp); + + } + + if (cselection.has(fname)) + files->select(files->get_item_count()-1,false); + + } + + +} + +void ScenesDock::_select_file(int p_idx) { + + files->select(p_idx,true); + _open_pressed(); +} + +void ScenesDock::_go_to_tree() { + + tree->show(); + files->hide(); + path_hb->hide(); + _update_tree(); + tree->grab_focus(); + tree->ensure_cursor_is_visible(); + button_favorite->show(); + button_fav_up->show(); + button_fav_down->show(); + button_open->hide(); + button_instance->hide(); + button_open->hide(); + file_options->hide(); + tree_mode=true; +} + +void ScenesDock::_go_to_dir(const String& p_dir){ + + DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + if (da->change_dir(p_dir)==OK) { + path=da->get_current_dir(); + _update_files(false); + } + current_path->set_text(path); + memdelete(da); + + +} +void ScenesDock::_fs_changed() { + + button_hist_prev->set_disabled(history_pos==0); + button_hist_next->set_disabled(history_pos+1==history.size()); + scanning_vb->hide(); + + if (tree_mode) { + + tree->show(); + button_favorite->show(); + button_fav_up->show(); + button_fav_down->show(); + _update_tree(); + } else { + files->show(); + path_hb->show(); + button_instance->show(); + button_open->show(); + file_options->show(); + _update_files(true); + } + + set_process(false); +} + +void ScenesDock::_set_scannig_mode() { + + tree->hide(); + button_favorite->hide(); + button_fav_up->hide(); + button_fav_down->hide(); + button_instance->hide(); + button_open->hide(); + file_options->hide(); + button_hist_prev->set_disabled(true); + button_hist_next->set_disabled(true); + scanning_vb->show(); + path_hb->hide(); + files->hide(); + set_process(true); + if (EditorFileSystem::get_singleton()->is_scanning()) { + scanning_progress->set_val(EditorFileSystem::get_singleton()->get_scanning_progress()*100); + } else { + scanning_progress->set_val(0); + } + +} + +void ScenesDock::_fw_history() { + + if (history_pos<history.size()-1) + history_pos++; + + path=history[history_pos]; + + if (tree_mode) { + _update_tree(); + tree->grab_focus(); + tree->ensure_cursor_is_visible(); + } else { + _update_files(false); + current_path->set_text(path); + } + + button_hist_prev->set_disabled(history_pos==0); + button_hist_next->set_disabled(history_pos+1==history.size()); + +} + +void ScenesDock::_bw_history() { + + if (history_pos>0) + history_pos--; + + path=history[history_pos]; + + if (tree_mode) { + _update_tree(); + tree->grab_focus(); + tree->ensure_cursor_is_visible(); } else { + _update_files(false); + current_path->set_text(path); + } + + button_hist_prev->set_disabled(history_pos==0); + button_hist_next->set_disabled(history_pos+1==history.size()); + +} + +void ScenesDock::_push_to_history() { - /* + history.resize(history_pos+1); + if (history[history_pos]!=path) { + history.push_back(path); + history_pos++; + } + + button_hist_prev->set_disabled(history_pos==0); + button_hist_next->set_disabled(history_pos+1==history.size()); + +} + + +void ScenesDock::_find_inside_move_files(EditorFileSystemDirectory *efsd,Vector<String>& files) { - RES res = ResourceLoader::load(path); - if (res.is_null()) { + for(int i=0;i<efsd->get_subdir_count();i++) { + _find_inside_move_files(efsd->get_subdir(i),files); + } + for(int i=0;i<efsd->get_file_count();i++) { + files.push_back(efsd->get_file_path(i)); + } + +} +void ScenesDock::_find_remaps(EditorFileSystemDirectory *efsd,Map<String,String> &renames,List<String>& to_remaps) { + for(int i=0;i<efsd->get_subdir_count();i++) { + _find_remaps(efsd->get_subdir(i),renames,to_remaps); + } + for(int i=0;i<efsd->get_file_count();i++) { + Vector<String> deps=efsd->get_file_deps(i); + for(int j=0;j<deps.size();j++) { + if (renames.has(deps[j])) { + to_remaps.push_back(efsd->get_file_path(i)); + break; + } + } + } +} + + +void ScenesDock::_rename_operation(const String& p_to_path) { + + if (move_files[0]==p_to_path) { + EditorNode::get_singleton()->show_warning("Same source and destination files, doing nothing."); + return; + } + if (FileAccess::exists(p_to_path)) { + EditorNode::get_singleton()->show_warning("Target file exists, can't overwrite. Delete first."); + return; + } + + Map<String,String> renames; + renames[move_files[0]]=p_to_path; + + List<String> remap; + + _find_remaps(EditorFileSystem::get_singleton()->get_filesystem(),renames,remap); + print_line("found files to remap: "+itos(remap.size())); + + //perform remaps + for(List<String>::Element *E=remap.front();E;E=E->next()) { + + Error err = ResourceLoader::rename_dependencies(E->get(),renames); + print_line("remapping: "+E->get()); + + if (err!=OK) { + EditorNode::get_singleton()->add_io_error("Can't rename deps for:\n"+E->get()+"\n"); + } + } + + //finally, perform moves + + DirAccess *da=DirAccess::create(DirAccess::ACCESS_RESOURCES); + + Error err = da->rename(move_files[0],p_to_path); + print_line("moving file "+move_files[0]+" to "+p_to_path); + if (err!=OK) { + EditorNode::get_singleton()->add_io_error("Error moving file:\n"+move_files[0]+"\n"); + } + + //rescan everything + memdelete(da); + print_line("call rescan!"); + _rescan(); +} + + +void ScenesDock::_move_operation(const String& p_to_path) { + + if (p_to_path==path) { + EditorNode::get_singleton()->show_warning("Same source and destination paths, doing nothing."); + return; + } + + //find files inside dirs to be moved + + Vector<String> inside_files; + + for(int i=0;i<move_dirs.size();i++) { + if (p_to_path.begins_with(move_dirs[i])) { + EditorNode::get_singleton()->show_warning("Can't move directories to within themselves"); return; - }*/ + } - editor->load_resource(path); + EditorFileSystemDirectory *efsd=EditorFileSystem::get_singleton()->get_path(move_dirs[i]); + if (!efsd) + continue; + _find_inside_move_files(efsd,inside_files); } -// emit_signal("open",path); + //make list of remaps + Map<String,String> renames; + String repfrom=path=="res://"?path:String(path+"/"); + String repto=p_to_path=="res://"?p_to_path:String(p_to_path+"/"); + + for(int i=0;i<move_files.size();i++) { + renames[move_files[i]]=move_files[i].replace_first(repfrom,repto); + print_line("move file "+move_files[i]+" -> "+renames[move_files[i]]); + } + for(int i=0;i<inside_files.size();i++) { + renames[inside_files[i]]=inside_files[i].replace_first(repfrom,repto); + print_line("inside file "+inside_files[i]+" -> "+renames[inside_files[i]]); + } + + //make list of files that will be run the remapping + List<String> remap; + _find_remaps(EditorFileSystem::get_singleton()->get_filesystem(),renames,remap); + print_line("found files to remap: "+itos(remap.size())); + + //perform remaps + for(List<String>::Element *E=remap.front();E;E=E->next()) { + + Error err = ResourceLoader::rename_dependencies(E->get(),renames); + print_line("remapping: "+E->get()); + + if (err!=OK) { + EditorNode::get_singleton()->add_io_error("Can't rename deps for:\n"+E->get()+"\n"); + } + } + + //finally, perform moves + + DirAccess *da=DirAccess::create(DirAccess::ACCESS_RESOURCES); + + for(int i=0;i<move_files.size();i++) { + + String to = move_files[i].replace_first(repfrom,repto); + Error err = da->rename(move_files[i],to); + print_line("moving file "+move_files[i]+" to "+to); + if (err!=OK) { + EditorNode::get_singleton()->add_io_error("Error moving file:\n"+move_files[i]+"\n"); + } + } + + for(int i=0;i<move_dirs.size();i++) { + + String to = p_to_path.plus_file(move_dirs[i].get_file()); + Error err = da->rename(move_dirs[i],to); + print_line("moving dir "+move_dirs[i]+" to "+to); + if (err!=OK) { + EditorNode::get_singleton()->add_io_error("Error moving dir:\n"+move_dirs[i]+"\n"); + } + } + + memdelete(da); + //rescan everything + print_line("call rescan!"); + _rescan(); + +} + +void ScenesDock::_file_option(int p_option) { + + switch(p_option) { + + case FILE_DEPENDENCIES: { + + int idx = files->get_current(); + if (idx<0 || idx>=files->get_item_count()) + break; + String path = files->get_item_metadata(idx); + deps_editor->edit(path); + } break; + case FILE_OWNERS: { + + int idx = files->get_current(); + if (idx<0 || idx>=files->get_item_count()) + break; + String path = files->get_item_metadata(idx); + owners_editor->show(path); + } break; + case FILE_MOVE: { + + move_dirs.clear();; + move_files.clear(); + + for(int i=0;i<files->get_item_count();i++) { + + String path = files->get_item_metadata(i); + if (!files->is_selected(i)) + continue; + + if (files->get_item_text(i)=="..") { + EditorNode::get_singleton()->show_warning("Can't operate on '..'"); + return; + } + + if (path.ends_with("/")) { + move_dirs.push_back(path.substr(0,path.length()-1)); + } else { + move_files.push_back(path); + } + } + + + if (move_dirs.empty() && move_files.size()==1) { + + rename_dialog->clear_filters(); + rename_dialog->add_filter("*."+move_files[0].extension()); + rename_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE); + rename_dialog->set_current_path(move_files[0]); + rename_dialog->popup_centered_ratio(); + rename_dialog->set_title("Pick New Name and Location For: "+move_files[0].get_file()); + + + } else { + //just move + move_dialog->popup_centered_ratio(); + } + + + } break; + case FILE_REMOVE: { + + Vector<String> torem; + + for(int i=0;i<files->get_item_count();i++) { + + String path = files->get_item_metadata(i); + if (path.ends_with("/") || !files->is_selected(i)) + continue; + torem.push_back(path); + } + + if (torem.empty()) { + EditorNode::get_singleton()->show_warning("No files selected!"); + break; + } + + remove_dialog->show(torem); + //1) find if used + //2) warn + + } break; + case FILE_INFO: { + + } break; + + } } -void ScenesDock::_save_favorites() { +void ScenesDock::_open_pressed(){ + + + if (tree_mode) { + + TreeItem *sel = tree->get_selected(); + if (!sel) { + return; + } + path = sel->get_metadata(0); + /*if (path!="res://" && path.ends_with("/")) { + path=path.substr(0,path.length()-1); + }*/ + + tree_mode=false; + + tree->hide(); + files->show(); + path_hb->show(); + button_favorite->hide(); + button_fav_up->hide(); + button_fav_down->hide(); + button_instance->show(); + button_open->show(); + file_options->show(); + + _update_files(false); - String path = Globals::get_singleton()->get_resource_path()+"/favorites.cfg"; - FileAccess *f=FileAccess::open(path,FileAccess::WRITE); - ERR_FAIL_COND(!f); - for(Set<String>::Element *E=favorites.front();E;E=E->next() ) { + current_path->set_text(path); - CharString utf8f = E->get().utf8(); - f->store_buffer((const uint8_t*)utf8f.get_data(),utf8f.length()); - f->store_8('\n'); + _push_to_history(); + + + } else { + + int idx=-1; + for(int i=0;i<files->get_item_count();i++) { + if (files->is_selected(i)) { + idx=i; + break; + } + } + + if (idx<0) + return; + + + + String path = files->get_item_metadata(idx); + + if (path.ends_with("/")) { + if (path!="res://") { + path=path.substr(0,path.length()-1); + } + this->path=path; + _update_files(false); + current_path->set_text(path); + _push_to_history(); + } else { + + if (ResourceLoader::get_resource_type(path)=="PackedScene") { + + editor->open_request(path); + } else { + + editor->load_resource(path); + } + } } - f->close(); - memdelete(f); +// emit_signal("open",path); + } + void ScenesDock::_rescan() { + _set_scannig_mode(); EditorFileSystem::get_singleton()->scan(); + +} + +void ScenesDock::fix_dependencies(const String& p_for_file) { + deps_editor->edit(p_for_file); +} + +void ScenesDock::open(const String& p_path) { + + + String npath; + String nfile; + + if (p_path.ends_with("/")) { + + if (p_path!="res://") + npath=p_path.substr(0,p_path.length()-1); + else + npath="res://"; + } else { + nfile=p_path.get_file(); + npath=p_path.get_base_dir(); + } + + path=npath; + + if (tree_mode && nfile=="") { + _update_tree(); + tree->grab_focus(); + tree->call_deferred("ensure_cursor_is_visible"); + _push_to_history(); + return; + } else if (tree_mode){ + _update_tree(); + tree->grab_focus(); + tree->ensure_cursor_is_visible(); + _open_pressed(); + current_path->set_text(path); + } else { + _update_files(false); + _push_to_history(); + } + + for(int i=0;i<files->get_item_count();i++) { + + String md = files->get_item_metadata(i); + if (md==p_path) { + files->select(i,true); + files->ensure_current_is_visible(); + break; + } + } + } void ScenesDock::_bind_methods() { ObjectTypeDB::bind_method(_MD("_update_tree"),&ScenesDock::_update_tree); ObjectTypeDB::bind_method(_MD("_rescan"),&ScenesDock::_rescan); - ObjectTypeDB::bind_method(_MD("_favorites_toggled"),&ScenesDock::_favorites_toggled); - ObjectTypeDB::bind_method(_MD("_favorite_toggled"),&ScenesDock::_favorite_toggled); + ObjectTypeDB::bind_method(_MD("_favorites_pressed"),&ScenesDock::_favorites_pressed); ObjectTypeDB::bind_method(_MD("_instance_pressed"),&ScenesDock::_instance_pressed); ObjectTypeDB::bind_method(_MD("_open_pressed"),&ScenesDock::_open_pressed); - ObjectTypeDB::bind_method(_MD("_save_favorites"),&ScenesDock::_save_favorites); + + ObjectTypeDB::bind_method(_MD("_thumbnail_done"),&ScenesDock::_thumbnail_done); + ObjectTypeDB::bind_method(_MD("_select_file"), &ScenesDock::_select_file); + ObjectTypeDB::bind_method(_MD("_go_to_tree"), &ScenesDock::_go_to_tree); + ObjectTypeDB::bind_method(_MD("_go_to_dir"), &ScenesDock::_go_to_dir); + ObjectTypeDB::bind_method(_MD("_change_file_display"), &ScenesDock::_change_file_display); + ObjectTypeDB::bind_method(_MD("_fw_history"), &ScenesDock::_fw_history); + ObjectTypeDB::bind_method(_MD("_bw_history"), &ScenesDock::_bw_history); + ObjectTypeDB::bind_method(_MD("_fs_changed"), &ScenesDock::_fs_changed); + ObjectTypeDB::bind_method(_MD("_dir_selected"), &ScenesDock::_dir_selected); + ObjectTypeDB::bind_method(_MD("_fav_up_pressed"), &ScenesDock::_fav_up_pressed); + ObjectTypeDB::bind_method(_MD("_fav_down_pressed"), &ScenesDock::_fav_down_pressed); + ObjectTypeDB::bind_method(_MD("_file_option"), &ScenesDock::_file_option); + ObjectTypeDB::bind_method(_MD("_move_operation"), &ScenesDock::_move_operation); + ObjectTypeDB::bind_method(_MD("_rename_operation"), &ScenesDock::_rename_operation); ADD_SIGNAL(MethodInfo("instance")); ADD_SIGNAL(MethodInfo("open")); @@ -271,153 +1078,156 @@ ScenesDock::ScenesDock(EditorNode *p_editor) { HBoxContainer *toolbar_hbc = memnew( HBoxContainer ); add_child(toolbar_hbc); + button_hist_prev = memnew( ToolButton ); + toolbar_hbc->add_child(button_hist_prev); + button_hist_prev->set_disabled(true); + button_hist_prev->set_tooltip("Previous Directory"); + + button_hist_next = memnew( ToolButton ); + toolbar_hbc->add_child(button_hist_next); + button_hist_next->set_disabled(true); + button_hist_prev->set_focus_mode(FOCUS_NONE); + button_hist_next->set_focus_mode(FOCUS_NONE); + button_hist_next->set_tooltip("Next Directory"); + button_reload = memnew( Button ); button_reload->set_flat(true); button_reload->connect("pressed",this,"_rescan"); toolbar_hbc->add_child(button_reload); + button_reload->set_focus_mode(FOCUS_NONE); + button_reload->set_tooltip("Re-Scan Filesystem"); + + toolbar_hbc->add_spacer(); + + button_fav_up = memnew( ToolButton ); + button_fav_up->set_flat(true); + toolbar_hbc->add_child(button_fav_up); + button_fav_up->set_disabled(true); + button_fav_up->connect("pressed",this,"_fav_up_pressed"); + button_fav_up->set_tooltip("Move Favorite Up"); + + button_fav_down = memnew( ToolButton ); + button_fav_down->set_flat(true); + toolbar_hbc->add_child(button_fav_down); + button_fav_down->set_disabled(true); + button_fav_down->connect("pressed",this,"_fav_down_pressed"); + button_fav_down->set_tooltip("Move Favorite Down"); button_favorite = memnew( Button ); button_favorite->set_flat(true); button_favorite->set_toggle_mode(true); - button_favorite->connect("toggled",this,"_favorites_toggled"); + button_favorite->connect("pressed",this,"_favorites_pressed"); toolbar_hbc->add_child(button_favorite); + button_favorite->set_tooltip("Toggle folder status as Favorite"); + + button_favorite->set_focus_mode(FOCUS_NONE); + button_fav_up->set_focus_mode(FOCUS_NONE); + button_fav_down->set_focus_mode(FOCUS_NONE); - toolbar_hbc->add_spacer(); button_open = memnew( Button ); button_open->set_flat(true); button_open->connect("pressed",this,"_open_pressed"); toolbar_hbc->add_child(button_open); + button_open->hide(); + button_open->set_focus_mode(FOCUS_NONE); + button_open->set_tooltip("Open the selected file.\nOpen as scene if a scene, or as resource otherwise."); + button_instance = memnew( Button ); button_instance->set_flat(true); button_instance->connect("pressed",this,"_instance_pressed"); toolbar_hbc->add_child(button_instance); + button_instance->hide(); + button_instance->set_focus_mode(FOCUS_NONE); + button_instance->set_tooltip("Instance the selected scene(s) as child of the selected node."); + + + file_options = memnew( MenuButton ); + toolbar_hbc->add_child(file_options); + file_options->get_popup()->add_item("Rename or Move",FILE_MOVE); + file_options->get_popup()->add_item("Delete",FILE_REMOVE); + file_options->get_popup()->add_separator(); + file_options->get_popup()->add_item("Edit Dependencies",FILE_DEPENDENCIES); + file_options->get_popup()->add_item("View Owners",FILE_OWNERS); + //file_options->get_popup()->add_item("Info",FILE_INFO); + file_options->hide(); + file_options->set_focus_mode(FOCUS_NONE); + file_options->set_tooltip("Miscenaneous options related to resources on disk."); tree = memnew( Tree ); - tree_filter=memnew( ScenesDockFilter() ); - tree_filter->connect("filter_changed", this, "_update_tree"); - add_child(tree_filter); + + tree->set_hide_root(true); add_child(tree); + tree->set_v_size_flags(SIZE_EXPAND_FILL); tree->connect("item_edited",this,"_favorite_toggled"); tree->connect("item_activated",this,"_open_pressed"); - - timer = memnew( Timer ); - timer->set_one_shot(true); - timer->set_wait_time(2); - timer->connect("timeout",this,"_save_favorites"); - add_child(timer); - + tree->connect("cell_selected",this,"_dir_selected"); + + files = memnew( ItemList ); + files->set_v_size_flags(SIZE_EXPAND_FILL); + files->set_select_mode(ItemList::SELECT_MULTI); + + path_hb = memnew( HBoxContainer ); + button_back = memnew( ToolButton ); + path_hb->add_child(button_back); + current_path=memnew( LineEdit ); + current_path->set_h_size_flags(SIZE_EXPAND_FILL); + path_hb->add_child(current_path); + display_mode = memnew( ToolButton ); + path_hb->add_child(display_mode); + display_mode->set_toggle_mode(true); + add_child(path_hb); + path_hb->hide(); + + + add_child(files); + files->hide(); + + scanning_vb = memnew( VBoxContainer ); + Label *slabel = memnew( Label ); + slabel->set_text("Scanning Files,\nPlease Wait.."); + slabel->set_align(Label::ALIGN_CENTER); + scanning_vb->add_child(slabel); + scanning_progress = memnew( ProgressBar ); + scanning_vb->add_child(scanning_progress); + add_child(scanning_vb); + scanning_vb->hide(); + + + + deps_editor = memnew( DependencyEditor ); + add_child(deps_editor); + + owners_editor = memnew( DependencyEditorOwners); + add_child(owners_editor); + + remove_dialog = memnew( DependencyRemoveDialog); + add_child(remove_dialog); + + move_dialog = memnew( EditorDirDialog ); + add_child(move_dialog); + move_dialog->connect("dir_selected",this,"_move_operation"); + move_dialog->get_ok()->set_text("Move"); + + rename_dialog = memnew( EditorFileDialog ); + rename_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE); + rename_dialog->connect("file_selected",this,"_rename_operation"); + add_child(rename_dialog); updating_tree=false; + initialized=false; -} - -ScenesDock::~ScenesDock() { - -} - -void ScenesDockFilter::_setup_filters() { - - filter_option->clear(); - filter_option->add_item("Path"); - filter_option->add_item("Name"); - filter_option->add_item("Folder"); -#if 0 - List<String> extensions; - ResourceLoader::get_recognized_extensions_for_type("",&extensions); - - file_filter->add_item("All Files (*)"); - filters.push_back("*"); - - List<String> filter_texts; - for(int i=0;i<extensions.size();i++) { - filter_texts.push_back("*."+extensions[i]+" ; "+extensions[i].to_upper()); - filters.push_back(extensions[i]); - } - for(int i=0;i<filter_texts.size();i++) { - - String flt=filter_texts[i].get_slice(";",0).strip_edges(); - String desc=filter_texts[i].get_slice(";",1).strip_edges(); - if (desc.length()) - file_filter->add_item(desc+" ( "+flt+" )"); - else - file_filter->add_item("( "+flt+" )"); - } -#endif -} - -void ScenesDockFilter::_command(int p_command) { - switch (p_command) { - - case CMD_CLEAR_FILTER: { - if (search_box->get_text()!="") { - search_box->clear(); - emit_signal("filter_changed"); - } - }break; - } -} - -void ScenesDockFilter::_search_text_changed(const String &p_newtext) { - emit_signal("filter_changed"); -} - -String ScenesDockFilter::get_search_term() { - return search_box->get_text().strip_edges(); -} - -ScenesDockFilter::FilterOption ScenesDockFilter::get_file_filter() { - return _current_filter; -} - -void ScenesDockFilter::_file_filter_selected(int p_idx) { - FilterOption selected = (FilterOption)(filter_option->get_selected()); - if (_current_filter != selected ) { - _current_filter = selected; - emit_signal("filter_changed"); - } -} - -void ScenesDockFilter::_notification(int p_what) { - switch(p_what) { - case NOTIFICATION_ENTER_TREE: { - clear_search_button->set_icon(get_icon("CloseHover","EditorIcons")); - } break; - } -} - -void ScenesDockFilter::_bind_methods() { + history.push_back("res://"); + history_pos=0; + tree_mode=true; - ObjectTypeDB::bind_method(_MD("_command"),&ScenesDockFilter::_command); - ObjectTypeDB::bind_method(_MD("_search_text_changed"), &ScenesDockFilter::_search_text_changed); - ObjectTypeDB::bind_method(_MD("_file_filter_selected"), &ScenesDockFilter::_file_filter_selected); - ADD_SIGNAL( MethodInfo("filter_changed") ); } -ScenesDockFilter::ScenesDockFilter() { - - _current_filter = FILTER_PATH; - - filter_option = memnew( OptionButton ); - filter_option->set_custom_minimum_size(Size2(60,10)); - filter_option->set_clip_text(true); - filter_option->connect("item_selected", this, "_file_filter_selected"); - add_child(filter_option); - - _setup_filters(); - - search_box = memnew( LineEdit ); - search_box->connect("text_changed",this,"_search_text_changed"); - search_box->set_h_size_flags(SIZE_EXPAND_FILL); - add_child(search_box); - - clear_search_button = memnew( ToolButton ); - clear_search_button->connect("pressed",this,"_command",make_binds(CMD_CLEAR_FILTER)); - add_child(clear_search_button); +ScenesDock::~ScenesDock() { } diff --git a/tools/editor/scenes_dock.h b/tools/editor/scenes_dock.h index de7ab51edc..d045124bf7 100644 --- a/tools/editor/scenes_dock.h +++ b/tools/editor/scenes_dock.h @@ -36,40 +36,112 @@ #include "scene/gui/tool_button.h" #include "scene/gui/option_button.h" #include "scene/gui/box_container.h" +#include "scene/gui/menu_button.h" +#include "scene/gui/item_list.h" +#include "scene/gui/progress_bar.h" + #include "os/dir_access.h" #include "os/thread.h" #include "editor_file_system.h" - +#include "editor_dir_dialog.h" +#include "dependency_editor.h" class EditorNode; -class ScenesDockFilter; + class ScenesDock : public VBoxContainer { OBJ_TYPE( ScenesDock, VBoxContainer ); + enum FileMenu { + FILE_DEPENDENCIES, + FILE_OWNERS, + FILE_MOVE, + FILE_REMOVE, + FILE_REIMPORT, + FILE_INFO + }; + + + VBoxContainer *scanning_vb; + ProgressBar *scanning_progress; + EditorNode *editor; Set<String> favorites; Button *button_reload; Button *button_instance; Button *button_favorite; + Button *button_fav_up; + Button *button_fav_down; Button *button_open; - Timer *timer; + Button *button_back; + Button *display_mode; + Button *button_hist_next; + Button *button_hist_prev; + LineEdit *current_path; + HBoxContainer *path_hb; + + MenuButton *file_options; + + + DependencyEditor *deps_editor; + DependencyEditorOwners *owners_editor; + DependencyRemoveDialog *remove_dialog; + + EditorDirDialog *move_dialog; + EditorFileDialog *rename_dialog; - ScenesDockFilter *tree_filter; + Vector<String> move_dirs; + Vector<String> move_files; + + + Vector<String> history; + int history_pos; + + String path; + + bool initialized; bool updating_tree; - Tree * tree; + Tree * tree; //directories + ItemList *files; + + bool tree_mode; + + void _go_to_tree(); + void _go_to_dir(const String& p_dir); + void _select_file(int p_idx); + bool _create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_dir); + void _thumbnail_done(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata); + void _find_inside_move_files(EditorFileSystemDirectory *efsd,Vector<String>& files); + void _find_remaps(EditorFileSystemDirectory *efsd,Map<String,String> &renames,List<String>& to_remaps); + + void _rename_operation(const String& p_to_path); + void _move_operation(const String& p_to_path); + + + void _file_option(int p_option); + void _update_files(bool p_keep_selection); + void _change_file_display(); + void _fs_changed(); + void _fw_history(); + void _bw_history(); + void _push_to_history(); + + void _fav_up_pressed(); + void _fav_down_pressed(); + void _dir_selected(); void _update_tree(); void _rescan(); - void _favorites_toggled(bool); - void _favorite_toggled(); + void _set_scannig_mode(); + + void _favorites_pressed(); void _instance_pressed(); void _open_pressed(); - void _save_favorites(); + protected: void _notification(int p_what); @@ -77,48 +149,14 @@ protected: public: String get_selected_path() const; + void open(const String& p_path); + + void fix_dependencies(const String& p_for_file); + ScenesDock(EditorNode *p_editor); ~ScenesDock(); }; -class ScenesDockFilter : public HBoxContainer { - - OBJ_TYPE( ScenesDockFilter, HBoxContainer ); - -private: - friend class ScenesDock; - - enum Command { - CMD_CLEAR_FILTER, - }; - - Tree *tree; - OptionButton *filter_option; - LineEdit *search_box; - ToolButton *clear_search_button; - - enum FilterOption { - FILTER_PATH, // NAME or Folder - FILTER_NAME, - FILTER_FOLDER, - }; - FilterOption _current_filter; - //Vector<String> filters; - - void _command(int p_command); - void _search_text_changed(const String& p_newtext); - void _setup_filters(); - void _file_filter_selected(int p_idx); - -protected: - void _notification(int p_what); - static void _bind_methods(); - -public: - String get_search_term(); - FilterOption get_file_filter(); - ScenesDockFilter(); -}; #endif // SCENES_DOCK_H |