From e9bbb97acccc08ae03fde41e4cc6d2dc6722021a Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Mon, 22 Jun 2015 00:03:19 -0300 Subject: Multiple scene editing *POTENTIALLY UNSTABLE* -ability to edit multiple scenes at the same time -resource internal IDs are now persistent, this makes multiple scene editing possible but maaaaay result in file corruption bugs (tested and could not find anything but possibility exists because core code changed, report immediately if you find this). -properly save settings, layout, etc when edited -script editing is independent from scene editing now -show a yellow box when a script belongs to the scene --- tools/editor/editor_data.cpp | 173 ++++++++ tools/editor/editor_data.h | 44 ++ tools/editor/editor_node.cpp | 487 +++++++++++++++++---- tools/editor/editor_node.h | 33 +- tools/editor/editor_plugin.cpp | 7 + tools/editor/editor_plugin.h | 4 +- tools/editor/editor_run_script.cpp | 2 +- tools/editor/editor_settings.cpp | 2 + tools/editor/icons/icon_panel_top.png | Bin 0 -> 195 bytes .../io_plugins/editor_mesh_import_plugin.cpp | 2 +- tools/editor/plugins/multimesh_editor_plugin.cpp | 2 +- tools/editor/plugins/script_editor_plugin.cpp | 381 ++++++++++------ tools/editor/plugins/script_editor_plugin.h | 52 ++- tools/editor/property_editor.cpp | 2 +- tools/editor/scene_tree_dock.h | 1 + tools/editor/scene_tree_editor.h | 5 +- 16 files changed, 949 insertions(+), 248 deletions(-) create mode 100644 tools/editor/icons/icon_panel_top.png (limited to 'tools') diff --git a/tools/editor/editor_data.cpp b/tools/editor/editor_data.cpp index a635034aca..c4808d0cad 100644 --- a/tools/editor/editor_data.cpp +++ b/tools/editor/editor_data.cpp @@ -424,9 +424,182 @@ void EditorData::remove_custom_type(const String& p_type){ } +int EditorData::add_edited_scene(int p_at_pos) { + + if (p_at_pos<0) + p_at_pos=edited_scene.size(); + EditedScene es; + es.root=NULL; + es.history_current=-1; + es.version=0; + + if (p_at_pos==edited_scene.size()) + edited_scene.push_back(es); + else + edited_scene.insert(p_at_pos,es); + + if (current_edited_scene<0) + current_edited_scene=0; + return p_at_pos; +} + +void EditorData::move_edited_scene_index(int p_idx,int p_to_idx){ + + ERR_FAIL_INDEX(p_idx,edited_scene.size()); + ERR_FAIL_INDEX(p_to_idx,edited_scene.size()); + SWAP(edited_scene[p_idx],edited_scene[p_to_idx]); +} +void EditorData::remove_scene(int p_idx){ + ERR_FAIL_INDEX(p_idx,edited_scene.size()); + if (edited_scene[p_idx].root) + memdelete(edited_scene[p_idx].root); + + if (current_edited_scene>p_idx) + current_edited_scene--; + else if (current_edited_scene==p_idx && current_edited_scene>0) { + current_edited_scene--; + } + + edited_scene.remove(p_idx); + +} +int EditorData::get_edited_scene() const { + + return current_edited_scene; +} +void EditorData::set_edited_scene(int p_idx){ + + ERR_FAIL_INDEX(p_idx,edited_scene.size()); + current_edited_scene=p_idx; + //swap +} +Node* EditorData::get_edited_scene_root(){ + + ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),NULL); + + return edited_scene[current_edited_scene].root; +} +void EditorData::set_edited_scene_root(Node* p_root) { + + ERR_FAIL_INDEX(current_edited_scene,edited_scene.size()); + edited_scene[current_edited_scene].root=p_root; +} + +int EditorData::get_edited_scene_count() const { + + return edited_scene.size(); +} + +void EditorData::set_edited_scene_version(uint64_t version) { + ERR_FAIL_INDEX(current_edited_scene,edited_scene.size()); + edited_scene[current_edited_scene].version=version; + +} + +uint64_t EditorData::get_edited_scene_version() const{ + + ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),0); + return edited_scene[current_edited_scene].version; + +} +uint64_t EditorData::get_scene_version(int p_idx) const{ + ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),false); + return edited_scene[p_idx].version; +} + +String EditorData::get_scene_title(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),String()); + if (!edited_scene[p_idx].root) + return "[empty]"; + if (edited_scene[p_idx].root->get_filename()=="") + return "[unsaved]"; + return edited_scene[p_idx].root->get_filename().get_file(); +} + + +String EditorData::get_scene_path(int p_idx) const { + + ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),String()); + + if (!edited_scene[p_idx].root) + return ""; + return edited_scene[p_idx].root->get_filename(); + +} + +void EditorData::save_edited_scene_state(EditorSelection *p_selection, EditorHistory *p_history, const Dictionary& p_custom) { + + ERR_FAIL_INDEX(current_edited_scene,edited_scene.size()); + + EditedScene &es=edited_scene[current_edited_scene]; + es.selection = p_selection->get_selected_node_list(); + es.history_current=p_history->current; + es.history_stored=p_history->history; + es.editor_states=get_editor_states(); + es.custom_state=p_custom; + +} + +Dictionary EditorData::restore_edited_scene_state(EditorSelection *p_selection, EditorHistory *p_history) { + ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),Dictionary()); + + EditedScene &es=edited_scene[current_edited_scene]; + + p_history->current=es.history_current; + p_history->history=es.history_stored; + + + p_selection->clear(); + for(List::Element *E=es.selection.front();E;E=E->next()) { + p_selection->add_node(E->get()); + } + set_editor_states(es.editor_states); + + return es.custom_state; +} + + +void EditorData::set_edited_scene_import_metadata(Ref p_mdata) { + + ERR_FAIL_INDEX(current_edited_scene,edited_scene.size()); + edited_scene[current_edited_scene].medatata=p_mdata; + +} + +Ref EditorData::get_edited_scene_import_metadata() const{ + + ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),Ref()); + return edited_scene[current_edited_scene].medatata; +} + +void EditorData::clear_edited_scenes() { + + for(int i=0;i p_layout) { + for(int i=0;iset_window_layout(p_layout); + } +} + +void EditorData::get_plugin_window_layout(Ref p_layout) { + for(int i=0;iget_window_layout(p_layout); + } +} EditorData::EditorData() { + current_edited_scene=-1; + // load_imported_scenes_from_globals(); } diff --git a/tools/editor/editor_data.h b/tools/editor/editor_data.h index 42abb317d1..e3fdd52d01 100644 --- a/tools/editor/editor_data.h +++ b/tools/editor/editor_data.h @@ -55,6 +55,7 @@ class EditorHistory { Vector path; int level; }; +friend class EditorData; Vector history; int current; @@ -91,6 +92,8 @@ public: EditorHistory(); }; +class EditorSelection; + class EditorData { public: @@ -117,6 +120,21 @@ private: void _cleanup_history(); + struct EditedScene { + Node* root; + Dictionary editor_states; + Ref medatata; + List selection; + Vector history_stored; + int history_current; + Dictionary custom_state; + uint64_t version; + + + }; + + Vector edited_scene; + int current_edited_scene; public: @@ -146,6 +164,32 @@ public: void remove_custom_type(const String& p_type); const Map >& get_custom_types() const { return custom_types; } + + int add_edited_scene(int p_at_pos); + void move_edited_scene_index(int p_idx,int p_to_idx); + void remove_scene(int p_idx); + void set_edited_scene(int p_idx); + void set_edited_scene_root(Node* p_root); + void set_edited_scene_import_metadata(Ref p_mdata); + Ref get_edited_scene_import_metadata() const; + int get_edited_scene() const; + Node* get_edited_scene_root(); + int get_edited_scene_count() const; + String get_scene_title(int p_idx) const; + String get_scene_path(int p_idx) const; + void set_edited_scene_version(uint64_t version); + uint64_t get_edited_scene_version() const; + uint64_t get_scene_version(int p_idx) const; + void clear_edited_scenes(); + + + void set_plugin_window_layout(Ref p_layout); + void get_plugin_window_layout(Ref p_layout); + + void save_edited_scene_state(EditorSelection *p_selection,EditorHistory *p_history,const Dictionary& p_custom); + Dictionary restore_edited_scene_state(EditorSelection *p_selection, EditorHistory *p_history); + + EditorData(); }; diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 373c8aba73..d080ac3597 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -105,11 +105,24 @@ EditorNode *EditorNode::singleton=NULL; +void EditorNode::_update_scene_tabs() { + + scene_tabs->clear_tabs(); + for(int i=0;iadd_tab(editor_data.get_scene_title(i)+(unsaved?"(*)":"")); + } + + scene_tabs->set_current_tab(editor_data.get_edited_scene()); + +} + void EditorNode::_update_title() { String appname = Globals::get_singleton()->get("application/name"); String title = appname.empty()?String(VERSION_FULL_NAME):String(_MKSTR(VERSION_NAME) + String(" - ") + appname); - String edited = edited_scene?edited_scene->get_filename():String(); + String edited = editor_data.get_edited_scene_root()?editor_data.get_edited_scene_root()->get_filename():String(); if (!edited.empty()) title+=" - " + String(edited.get_file()); if (unsaved_cache) @@ -174,6 +187,11 @@ void EditorNode::_notification(int p_what) { _update_title(); } + if (last_checked_version!=editor_data.get_undo_redo().get_version()) { + _update_scene_tabs(); + last_checked_version=editor_data.get_undo_redo().get_version(); + } + //get_root_node()->set_rect(viewport->get_global_rect()); //update the circle @@ -231,6 +249,13 @@ void EditorNode::_notification(int p_what) { //import_monitor->scan_changes(); } + + if (p_what==NOTIFICATION_EXIT_TREE) { + + + editor_data.clear_edited_scenes(); + + } if (p_what==NOTIFICATION_READY) { VisualServer::get_singleton()->viewport_set_hide_scenario(get_scene_root()->get_viewport(),true); @@ -468,7 +493,7 @@ void EditorNode::_dialog_display_file_error(String p_file,Error p_error) { void EditorNode::_get_scene_metadata() { - Node *scene = edited_scene; + Node *scene = editor_data.get_edited_scene_root(); if (!scene) return; @@ -495,7 +520,7 @@ void EditorNode::_get_scene_metadata() { void EditorNode::_set_scene_metadata() { - Node *scene = edited_scene; + Node *scene = editor_data.get_edited_scene_root(); if (!scene) return; @@ -718,7 +743,7 @@ void EditorNode::_save_edited_subresources(Node* scene,Map& processed, for(int i=0;iget_child_count();i++) { Node *n = scene->get_child(i); - if (n->get_owner()!=edited_scene) + if (n->get_owner()!=editor_data.get_edited_scene_root()) continue; _save_edited_subresources(n,processed,flags); } @@ -727,7 +752,7 @@ void EditorNode::_save_edited_subresources(Node* scene,Map& processed, void EditorNode::_find_node_types(Node* p_node, int&count_2d, int&count_3d) { - if (p_node->is_type("Viewport") || (p_node!=get_edited_scene() && p_node->get_owner()!=get_edited_scene())) + if (p_node->is_type("Viewport") || (p_node!=editor_data.get_edited_scene_root() && p_node->get_owner()!=editor_data.get_edited_scene_root())) return; if (p_node->is_type("CanvasItem")) @@ -748,7 +773,7 @@ void EditorNode::_save_scene_with_preview(String p_file) { EditorProgress save("save","Saving Scene",4); save.step("Analyzing",0); - _find_node_types(get_edited_scene(),c2d,c3d); + _find_node_types(editor_data.get_edited_scene_root(),c2d,c3d); RID viewport; bool is2d; @@ -799,11 +824,11 @@ void EditorNode::_save_scene_with_preview(String p_file) { img.save_png(pfile); Vector imgdata = FileAccess::get_file_as_array(pfile); - print_line("img data is "+itos(imgdata.size())); + //print_line("img data is "+itos(imgdata.size())); - if (scene_import_metadata.is_null()) - scene_import_metadata = Ref( memnew( ResourceImportMetadata ) ); - scene_import_metadata->set_option("thumbnail",imgdata); + if (editor_data.get_edited_scene_import_metadata().is_null()) + editor_data.set_edited_scene_import_metadata(Ref( memnew( ResourceImportMetadata ) ) ); + editor_data.get_edited_scene_import_metadata()->set_option("thumbnail",imgdata); //tamanio tel thumbnail if (screen!=-1) { @@ -817,7 +842,7 @@ void EditorNode::_save_scene_with_preview(String p_file) { void EditorNode::_save_scene(String p_file) { - Node *scene = edited_scene; + Node *scene = editor_data.get_edited_scene_root(); if (!scene) { @@ -851,7 +876,7 @@ void EditorNode::_save_scene(String p_file) { return; } - sdata->set_import_metadata(scene_import_metadata); + sdata->set_import_metadata(editor_data.get_edited_scene_import_metadata()); int flg=0; if (EditorSettings::get_singleton()->get("on_save/compress_binary_resources")) flg|=ResourceSaver::FLAG_COMPRESS; @@ -867,7 +892,7 @@ void EditorNode::_save_scene(String p_file) { if (err==OK) { scene->set_filename( Globals::get_singleton()->localize_path(p_file) ); //EditorFileSystem::get_singleton()->update_file(p_file,sdata->get_type()); - saved_version=editor_data.get_undo_redo().get_version(); + set_current_version(editor_data.get_undo_redo().get_version()); _update_title(); } else { @@ -1055,7 +1080,7 @@ void EditorNode::_dialog_action(String p_file) { Node *base = selection.front()->get(); Map reown; - reown[get_edited_scene()]=base; + reown[editor_data.get_edited_scene_root()]=base; Node *copy = base->duplicate_and_reown(reown); if (copy) { @@ -1150,7 +1175,7 @@ void EditorNode::_dialog_action(String p_file) { ml = Ref( memnew( MeshLibrary )); } - MeshLibraryEditor::update_library_file(edited_scene,ml,true); + MeshLibraryEditor::update_library_file(editor_data.get_edited_scene_root(),ml,true); Error err = ResourceSaver::save(p_file,ml); if (err) { @@ -1184,7 +1209,7 @@ void EditorNode::_dialog_action(String p_file) { ml = Ref( memnew( TileSet )); } - TileSetEditor::update_library_file(edited_scene,ml,true); + TileSetEditor::update_library_file(editor_data.get_edited_scene_root(),ml,true); Error err = ResourceSaver::save(p_file,ml); if (err) { @@ -1325,15 +1350,15 @@ void EditorNode::_property_editor_back() { void EditorNode::_imported(Node *p_node) { - Node *scene = edited_scene; - set_edited_scene(p_node); - + Node *scene = editor_data.get_edited_scene_root(); +// add_edited_scene(p_node); +/* if (scene) { String path = scene->get_filename(); p_node->set_filename(path); memdelete(scene); } - +*/ } @@ -1408,17 +1433,22 @@ void EditorNode::_edit_current() { if (main_plugin!=editor_plugin_screen) { // update screen main_plugin - if (editor_plugin_screen) - editor_plugin_screen->make_visible(false); - editor_plugin_screen=main_plugin; - editor_plugin_screen->edit(current_obj); - editor_plugin_screen->make_visible(true); + if (!changing_scene) { - for(int i=0;iset_current_tab(i); - break; + if (editor_plugin_screen) + editor_plugin_screen->make_visible(false); + editor_plugin_screen=main_plugin; + editor_plugin_screen->edit(current_obj); + + editor_plugin_screen->make_visible(true); + + + for(int i=0;iset_current_tab(i); + break; + } } } @@ -1527,10 +1557,10 @@ void EditorNode::_run(bool p_current,const String& p_custom) { - if (p_current || (edited_scene && p_custom==edited_scene->get_filename())) { + if (p_current || (editor_data.get_edited_scene_root() && p_custom==editor_data.get_edited_scene_root()->get_filename())) { - Node *scene = edited_scene; + Node *scene = editor_data.get_edited_scene_root(); if (!scene) { @@ -1592,7 +1622,7 @@ void EditorNode::_run(bool p_current,const String& p_custom) { if (unsaved_cache) { - Node *scene = edited_scene; + Node *scene = editor_data.get_edited_scene_root(); if (scene) { //only autosave if there is a scene obviously @@ -1644,8 +1674,8 @@ void EditorNode::_run(bool p_current,const String& p_custom) { void EditorNode::_cleanup_scene() { - - Node *scene = edited_scene; +#if 0 + Node *scene = editor_data.get_edited_scene_root(); editor_selection->clear(); editor_data.clear_editor_states(); editor_history.clear(); @@ -1654,7 +1684,7 @@ void EditorNode::_cleanup_scene() { property_editor->edit(NULL); resources_dock->cleanup(); scene_import_metadata.unref(); - set_edited_scene(NULL); + //set_edited_scene(NULL); if (scene) { if (scene->get_filename()!="") { previous_scenes.push_back(scene->get_filename()); @@ -1680,7 +1710,7 @@ void EditorNode::_cleanup_scene() { } _update_title(); - +#endif } void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { @@ -1693,16 +1723,20 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { switch( p_option ) { case FILE_NEW_SCENE: { + /* if (!p_confirmed) { confirmation->get_ok()->set_text("Yes"); //confirmation->get_cancel()->show(); confirmation->set_text("Start a New Scene? (Current will be lost)"); confirmation->popup_centered_minsize(); break; - } + }*/ + + int idx = editor_data.add_edited_scene(-1); + _scene_tab_changed(idx); - _cleanup_scene(); + //_cleanup_scene(); } break; @@ -1722,7 +1756,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { //file->set_current_path(current_path); - Node *scene = edited_scene; + Node *scene = editor_data.get_edited_scene_root(); if (scene) { file->set_current_path(scene->get_filename()); }; @@ -1754,11 +1788,26 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { opening_prev=true; open_request(previous_scenes.back()->get()); + } break; + case FILE_CLOSE: { + + if (!p_confirmed) { + confirmation->get_ok()->set_text("Yes"); + //confirmation->get_cancel()->show(); + confirmation->set_text("Close scene? (Unsaved changes will be lost)"); + confirmation->popup_centered_minsize(); + break; + } + + _remove_edited_scene(); + + + } break; case FILE_SAVE_SCENE: { - Node *scene = edited_scene; + Node *scene = editor_data.get_edited_scene_root(); if (scene && scene->get_filename()!="") { //_save_scene(scene->get_filename()); @@ -1769,7 +1818,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { }; case FILE_SAVE_AS_SCENE: { - Node *scene = edited_scene; + Node *scene = editor_data.get_edited_scene_root(); if (!scene) { @@ -1831,7 +1880,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { case FILE_DUMP_STRINGS: { - Node *scene = edited_scene; + Node *scene = editor_data.get_edited_scene_root(); if (!scene) { @@ -1875,7 +1924,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { case FILE_SAVE_SUBSCENE: { - Node *scene = edited_scene; + Node *scene = editor_data.get_edited_scene_root(); if (!scene) { @@ -1902,7 +1951,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { Node *tocopy = selection.front()->get(); - if (tocopy!=edited_scene && tocopy->get_filename()!="") { + if (tocopy!=editor_data.get_edited_scene_root() && tocopy->get_filename()!="") { current_option=-1; @@ -1936,7 +1985,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { file->set_title("Save Sub-Scene As.."); } break; case FILE_SAVE_OPTIMIZED: { - Node *scene = edited_scene; + Node *scene = editor_data.get_edited_scene_root(); #if 0 if (!scene) { @@ -1998,7 +2047,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { case FILE_EXPORT_MESH_LIBRARY: { - if (!edited_scene) { + if (!editor_data.get_edited_scene_root()) { current_option=-1; //confirmation->get_cancel()->hide(); @@ -2043,7 +2092,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { //import_subscene->popup_centered_ratio(); - if (!edited_scene) { + if (!editor_data.get_edited_scene_root()) { current_option=-1; //accept->get_cancel()->hide(); @@ -2569,30 +2618,54 @@ void EditorNode::remove_editor_import_plugin(const Ref& p_ed _rebuild_import_menu(); } +void EditorNode::_remove_edited_scene() { + int new_index = editor_data.get_edited_scene(); + int old_index=new_index; + + if (new_index>0) { + new_index=new_index-1; + } else if (editor_data.get_edited_scene_count()>1) { + new_index=1; + } else { + editor_data.add_edited_scene(-1); + new_index=1; + } + + _scene_tab_changed(new_index); + editor_data.remove_scene(old_index); + editor_data.get_undo_redo().clear_history(); + _update_title(); + _update_scene_tabs(); + if (editor_data.get_edited_scene_count()==1) { + //make new scene appear saved + set_current_version(editor_data.get_undo_redo().get_version()); + unsaved_cache=false; + } +} void EditorNode::set_edited_scene(Node *p_scene) { - if (edited_scene) { - if (edited_scene->get_parent()==scene_root) - scene_root->remove_child(edited_scene); + if (get_editor_data().get_edited_scene_root()) { + if (get_editor_data().get_edited_scene_root()->get_parent()==scene_root) + scene_root->remove_child(get_editor_data().get_edited_scene_root()); animation_editor->set_root(NULL); } - edited_scene=p_scene; - if (edited_scene && edited_scene->cast_to()) - edited_scene->cast_to()->show(); //show popups - scene_tree_dock->set_edited_scene(edited_scene); + get_editor_data().set_edited_scene_root(p_scene); + + if (p_scene && p_scene->cast_to()) + p_scene->cast_to()->show(); //show popups + scene_tree_dock->set_edited_scene(p_scene); if (get_tree()) - get_tree()->set_edited_scene_root(edited_scene); + get_tree()->set_edited_scene_root(p_scene); - if (edited_scene) { + if (p_scene) { if (p_scene->get_parent()!=scene_root) scene_root->add_child(p_scene); animation_editor->set_root(p_scene); } - - } + void EditorNode::_fetch_translatable_strings(const Object *p_object,Set& strings) { @@ -2818,6 +2891,115 @@ Error EditorNode::save_optimized_copy(const String& p_scene,const String& p_pres return OK; } + +Dictionary EditorNode::_get_main_scene_state() { + + Dictionary state; + state["main_tab"]=main_editor_tabs->get_current_tab(); + state["scene_tree_offset"]=scene_tree_dock->get_tree_editor()->get_scene_tree()->get_vscroll_bar()->get_val(); + state["property_edit_offset"]=get_property_editor()->get_scene_tree()->get_vscroll_bar()->get_val(); + state["saved_version"]=saved_version; + //print_line(" getting main tab: "+itos(state["main_tab"])); + return state; +} + +void EditorNode::_set_main_scene_state(Dictionary p_state) { + + //print_line("set current 7 "); + + if (p_state.has("main_tab")) { + int idx = p_state["main_tab"]; + int current=-1; + for(int i=0;iget_tree_editor()->get_scene_tree()->get_vscroll_bar()->set_val(p_state["scene_tree_offset"]); + if (p_state.has("property_edit_offset")) + get_property_editor()->get_scene_tree()->get_vscroll_bar()->set_val(p_state["property_edit_offset"]); + + //print_line("set current 8 "); + + +} + +void EditorNode::set_current_version(uint64_t p_version) { + + saved_version=p_version; + editor_data.set_edited_scene_version(p_version); +} + +bool EditorNode::is_changing_scene() const { + return changing_scene; +} +void EditorNode::set_current_scene(int p_idx) { + + changing_scene=true; + editor_data.save_edited_scene_state(editor_selection,&editor_history,_get_main_scene_state()); + + if (get_editor_data().get_edited_scene_root()) { + if (get_editor_data().get_edited_scene_root()->get_parent()==scene_root) + scene_root->remove_child(get_editor_data().get_edited_scene_root()); + animation_editor->set_root(NULL); + } + + //print_line("set current 2 "); + + editor_selection->clear(); + editor_data.set_edited_scene(p_idx); + + Node* new_scene = editor_data.get_edited_scene_root(); + + if (new_scene && new_scene->cast_to()) + new_scene->cast_to()->show(); //show popups + + //print_line("set current 3 "); + + scene_tree_dock->set_edited_scene(new_scene); + if (get_tree()) + get_tree()->set_edited_scene_root(new_scene); + + if (new_scene) { + if (new_scene->get_parent()!=scene_root) + scene_root->add_child(new_scene); + animation_editor->set_root(new_scene); + } + //print_line("set current 4 "); + + + Dictionary state = editor_data.restore_edited_scene_state(editor_selection,&editor_history); + _edit_current(); + + /*if (!unsaved) { + saved_version=editor_data.get_undo_redo().get_version(); + if (p_backwards) + saved_version--; + else + saved_version++; + print_line("was saved, updating version"); + } else { + saved_version=state["saved_version"]; + }*/ + //_set_main_scene_state(state); + + call_deferred("_set_main_scene_state",state); //do after everything else is done setting up + //print_line("set current 6 "); + changing_scene=false; + + +} + Error EditorNode::load_scene(const String& p_scene) { if (!is_inside_tree()) { @@ -2826,6 +3008,14 @@ Error EditorNode::load_scene(const String& p_scene) { } + for(int i=0;iclear(); String lpath = Globals::get_singleton()->localize_path(p_scene); @@ -2841,7 +3031,20 @@ Error EditorNode::load_scene(const String& p_scene) { return ERR_FILE_NOT_FOUND; } - _cleanup_scene(); // i'm sorry but this MUST happen to avoid modified resources to not be reloaded. + int prev = editor_data.get_edited_scene(); + int idx = editor_data.add_edited_scene(-1); + //print_line("load scene callback"); + //set_current_scene(idx); + + if (!editor_data.get_edited_scene_root() && editor_data.get_edited_scene_count()==2) { + _remove_edited_scene(); + } else { + _scene_tab_changed(idx); + } + + + + //_cleanup_scene(); // i'm sorry but this MUST happen to avoid modified resources to not be reloaded. Ref sdata = ResourceLoader::load(lpath); if (!sdata.is_valid()) { @@ -2852,6 +3055,11 @@ Error EditorNode::load_scene(const String& p_scene) { accept->set_text("Error loading scene."); accept->popup_centered_minsize(); opening_prev=false; + + if (prev!=-1) { + set_current_scene(prev); + editor_data.remove_scene(idx); + } return ERR_FILE_NOT_FOUND; } @@ -2859,15 +3067,23 @@ Error EditorNode::load_scene(const String& p_scene) { if (!new_scene) { + sdata.unref(); current_option=-1; //accept->get_cancel()->hide(); accept->get_ok()->set_text("Ugh"); accept->set_text("Error loading scene."); accept->popup_centered_minsize(); opening_prev=false; + if (prev!=-1) { + set_current_scene(prev); + editor_data.remove_scene(idx); + } return ERR_FILE_NOT_FOUND; } + //guess not needed in the end? + //new_scene->clear_internal_tree_resource_paths(); //make sure no internal tree paths to internal resources exist + /* Node *old_scene = edited_scene; _hide_top_editors(); @@ -2880,16 +3096,23 @@ Error EditorNode::load_scene(const String& p_scene) { memdelete(old_scene); } */ + set_edited_scene(new_scene); _get_scene_metadata(); + /* + editor_data.set_edited_scene_root(new_scene); + scene_tree_dock->set_selected(new_scene, true); property_editor->edit(new_scene); - scene_import_metadata = sdata->get_import_metadata(); + editor_data.set_edited_scene_root(new_scene); +*/ + editor_data.set_edited_scene_import_metadata( sdata->get_import_metadata() ); - editor_data.get_undo_redo().clear_history(); + +// editor_data.get_undo_redo().clear_history(); saved_version=editor_data.get_undo_redo().get_version(); _update_title(); - + _update_scene_tabs(); _add_to_recent_scenes(lpath); if (new_scene->has_meta("__editor_plugin_screen__")) { @@ -2919,8 +3142,9 @@ Error EditorNode::load_scene(const String& p_scene) { void EditorNode::open_request(const String& p_path) { - external_file=p_path; - _menu_option_confirm(FILE_EXTERNAL_OPEN_SCENE,false); + load_scene(p_path); // as it will be opened in separate tab + //external_file=p_path; + //_menu_option_confirm(FILE_EXTERNAL_OPEN_SCENE,false); } @@ -3058,15 +3282,16 @@ void EditorNode::_open_recent_scene(int p_idx) { String path = "res://"+rc[p_idx]; - if (unsaved_cache) { + + /*if (unsaved_cache) { _recent_scene=rc[p_idx]; open_recent_confirmation->set_text("Discard current scene and open:\n'"+rc[p_idx]+"'"); open_recent_confirmation->get_label()->set_align(Label::ALIGN_CENTER); open_recent_confirmation->popup_centered(Size2(400,100)); return; - } + }*/ - load_scene(rc[p_idx]); + load_scene(path); } @@ -3110,12 +3335,6 @@ void EditorNode::_save_optimized() { #endif } -void EditorNode::_open_recent_scene_confirm() { - - load_scene(_recent_scene); - -} - void EditorNode::_update_recent_scenes() { String base="_"+Globals::get_singleton()->get_resource_path().replace("\\","::").replace("/","::"); @@ -3325,7 +3544,7 @@ void EditorNode::_bind_methods() { //ObjectTypeDB::bind_method("_import",&EditorNode::_import); // ObjectTypeDB::bind_method("_import_conflicts_solved",&EditorNode::_import_conflicts_solved); ObjectTypeDB::bind_method("_open_recent_scene",&EditorNode::_open_recent_scene); - ObjectTypeDB::bind_method("_open_recent_scene_confirm",&EditorNode::_open_recent_scene_confirm); +// ObjectTypeDB::bind_method("_open_recent_scene_confirm",&EditorNode::_open_recent_scene_confirm); ObjectTypeDB::bind_method("_save_optimized",&EditorNode::_save_optimized); ObjectTypeDB::bind_method(_MD("animation_panel_make_visible","enable"),&EditorNode::animation_panel_make_visible); @@ -3343,6 +3562,11 @@ void EditorNode::_bind_methods() { ObjectTypeDB::bind_method("_dock_move_left",&EditorNode::_dock_move_left); ObjectTypeDB::bind_method("_dock_move_right",&EditorNode::_dock_move_right); + ObjectTypeDB::bind_method("set_current_scene",&EditorNode::set_current_scene); + ObjectTypeDB::bind_method("set_current_version",&EditorNode::set_current_version); + ObjectTypeDB::bind_method("_scene_tab_changed",&EditorNode::_scene_tab_changed); + ObjectTypeDB::bind_method("_set_main_scene_state",&EditorNode::_set_main_scene_state); + ObjectTypeDB::bind_method("_update_scene_tabs",&EditorNode::_update_scene_tabs); @@ -3655,10 +3879,29 @@ void EditorNode::_save_docks() { } + HSplitContainer *h_splits[4]={ + left_l_hsplit, + left_r_hsplit, + main_hsplit, + right_hsplit, + }; + + for(int i=0;i<4;i++) { + + config->set_value("docks","dock_hsplit_"+itos(i+1),h_splits[i]->get_split_offset()); + } + + editor_data.get_plugin_window_layout(config); + config->save(EditorSettings::get_singleton()->get_project_settings_path().plus_file("editor_layout.cfg")); } +void EditorNode::save_layout() { + + dock_drag_timer->start(); +} + void EditorNode::_dock_split_dragged(int ofs) { dock_drag_timer->start(); @@ -3732,6 +3975,20 @@ void EditorNode::_load_docks() { splits[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++) { + if (!config->has_section_key("docks","dock_hsplit_"+itos(i+1))) + continue; + int ofs = config->get_value("docks","dock_hsplit_"+itos(i+1)); + h_splits[i]->set_split_offset(ofs); + } + for(int i=0;iget_tab_count() || dock_slot[i*2+1]->get_tab_count(); if (in_use) @@ -3747,6 +4004,38 @@ void EditorNode::_load_docks() { } } + editor_data.set_plugin_window_layout(config); + +} + + +void EditorNode::_scene_tab_changed(int p_tab) { + + + //print_line("set current 1 "); + bool unsaved = (saved_version!=editor_data.get_undo_redo().get_version()); + //print_line("version: "+itos(editor_data.get_undo_redo().get_version())+", saved "+itos(saved_version)); + + if (p_tab==editor_data.get_edited_scene()) + return; //pointless + + uint64_t next_scene_version = editor_data.get_scene_version(p_tab); + + + + //print_line("scene tab changed???"); + editor_data.get_undo_redo().create_action("Switch Scene Tab"); + editor_data.get_undo_redo().add_do_method(this,"set_current_version",unsaved?saved_version:0); + editor_data.get_undo_redo().add_do_method(this,"set_current_scene",p_tab); + editor_data.get_undo_redo().add_do_method(scene_tabs,"set_current_tab",p_tab); + editor_data.get_undo_redo().add_do_method(this,"set_current_version",next_scene_version==0?editor_data.get_undo_redo().get_version()+1:next_scene_version); + + editor_data.get_undo_redo().add_undo_method(this,"set_current_version",next_scene_version); + editor_data.get_undo_redo().add_undo_method(this,"set_current_scene",editor_data.get_edited_scene()); + editor_data.get_undo_redo().add_undo_method(scene_tabs,"set_current_tab",editor_data.get_edited_scene()); + editor_data.get_undo_redo().add_undo_method(this,"set_current_version",saved_version); + editor_data.get_undo_redo().commit_action(); + } EditorNode::EditorNode() { @@ -3754,6 +4043,8 @@ EditorNode::EditorNode() { EditorHelp::generate_doc(); //before any editor classes are crated singleton=this; + last_checked_version=0; + changing_scene=false; FileAccess::set_backup_save(true); @@ -3841,14 +4132,38 @@ EditorNode::EditorNode() { gui_base->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END ); gui_base->set_anchor( MARGIN_BOTTOM, Control::ANCHOR_END ); gui_base->set_end( Point2(0,0) ); - + main_vbox = memnew( VBoxContainer ); gui_base->add_child(main_vbox); main_vbox->set_area_as_parent_rect(8); + PanelContainer *top_dark_panel = memnew( PanelContainer ); + Ref top_dark_sb; + top_dark_sb.instance();; + top_dark_sb->set_texture(theme->get_icon("PanelTop","EditorIcons")); + for(int i=0;i<4;i++) { + top_dark_sb->set_margin_size(Margin(i),3); + top_dark_sb->set_default_margin(Margin(i),0); + } + top_dark_sb->set_expand_margin_size(MARGIN_LEFT,20); + top_dark_sb->set_expand_margin_size(MARGIN_RIGHT,20); + + top_dark_panel->add_style_override("panel",top_dark_sb); + VBoxContainer *top_dark_vb = memnew( VBoxContainer ); + main_vbox->add_child(top_dark_panel); + top_dark_panel->add_child(top_dark_vb); + + + + menu_hb = memnew( HBoxContainer ); - main_vbox->add_child(menu_hb); + top_dark_vb->add_child(menu_hb); + scene_tabs=memnew( Tabs ); + scene_tabs->add_tab("unsaved"); + scene_tabs->set_tab_align(Tabs::ALIGN_CENTER); + scene_tabs->connect("tab_changed",this,"_scene_tab_changed"); + top_dark_vb->add_child(scene_tabs); //left left_l_hsplit = memnew( HSplitContainer ); main_vbox->add_child(left_l_hsplit); @@ -3912,6 +4227,12 @@ EditorNode::EditorNode() { right_l_vsplit->connect("dragged",this,"_dock_split_dragged"); right_r_vsplit->connect("dragged",this,"_dock_split_dragged"); + 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"); + + dock_select_popoup = memnew( PopupPanel ); gui_base->add_child(dock_select_popoup); @@ -4101,7 +4422,9 @@ EditorNode::EditorNode() { p->add_item("Save Scene",FILE_SAVE_SCENE,KEY_MASK_CMD+KEY_S); p->add_item("Save Scene As..",FILE_SAVE_AS_SCENE,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_S); p->add_separator(); - p->add_item("Goto Prev. Scene",FILE_OPEN_PREV,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_P); + p->add_item("Close Scene",FILE_CLOSE,KEY_MASK_SHIFT+KEY_MASK_CTRL+KEY_W); + p->add_separator(); + p->add_item("Close Goto Prev. Scene",FILE_OPEN_PREV,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_P); p->add_submenu_item("Open Recent","RecentScenes",FILE_OPEN_RECENT); p->add_separator(); p->add_item("Quick Open Scene..",FILE_QUICK_OPEN_SCENE,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_O); @@ -4791,8 +5114,8 @@ EditorNode::EditorNode() { } - edited_scene=NULL; - saved_version=0; + //edited_scene=NULL; + saved_version=1; unsaved_cache=true; _last_instanced_scene=NULL; @@ -4854,7 +5177,13 @@ EditorNode::EditorNode() { for(int i=0;i<_init_callbacks.size();i++) _init_callbacks[i](); + editor_data.add_edited_scene(-1); + editor_data.set_edited_scene(0); + _update_scene_tabs(); + _load_docks(); + + } diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index 2ef9332c84..293da2031d 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -125,6 +125,7 @@ class EditorNode : public Node { FILE_QUICK_OPEN_SCRIPT, FILE_RUN_SCRIPT, FILE_OPEN_PREV, + FILE_CLOSE, FILE_QUIT, FILE_EXTERNAL_OPEN_SCENE, EDIT_UNDO, @@ -183,16 +184,16 @@ class EditorNode : public Node { }; - Node *edited_scene; //scene being edited + //Node *edited_scene; //scene being edited Viewport *scene_root; //root of the scene being edited - Ref scene_import_metadata; + //Ref scene_import_metadata; Control* scene_root_parent; Control *gui_base; VBoxContainer *main_vbox; - + //split HSplitContainer *left_l_hsplit; VSplitContainer *left_l_vsplit; @@ -205,6 +206,9 @@ class EditorNode : public Node { VSplitContainer *center_split; + //main tabs + + Tabs *scene_tabs; int old_split_ofs; @@ -324,8 +328,10 @@ class EditorNode : public Node { bool reference_resource_mem; bool save_external_resources_mem; uint64_t saved_version; + uint64_t last_checked_version; bool unsaved_cache; String open_navigate; + bool changing_scene; uint32_t circle_step_msec; uint64_t circle_step_frame; @@ -375,6 +381,7 @@ class EditorNode : public Node { void _set_scene_metadata(); void _get_scene_metadata(); void _update_title(); + void _update_scene_tabs(); void _close_messages(); void _show_messages(); void _vp_resized(); @@ -402,7 +409,7 @@ class EditorNode : public Node { void _add_to_recent_scenes(const String& p_scene); void _update_recent_scenes(); void _open_recent_scene(int p_idx); - void _open_recent_scene_confirm(); + //void _open_recent_scene_confirm(); String _recent_scene; bool convert_old; @@ -431,7 +438,7 @@ class EditorNode : public Node { void _cleanup_scene(); - + void _remove_edited_scene(); bool _find_and_save_resource(RES p_res,Map& processed,int32_t flags); bool _find_and_save_edited_subresources(Object *obj,Map& processed,int32_t flags); void _save_edited_subresources(Node* scene,Map& processed,int32_t flags); @@ -461,6 +468,10 @@ class EditorNode : public Node { void _dock_pre_popup(int p_which); void _dock_split_dragged(int ofs); void _dock_popup_exit(); + void _scene_tab_changed(int p_tab); + + Dictionary _get_main_scene_state(); + void _set_main_scene_state(Dictionary p_state); void _save_docks(); void _load_docks(); @@ -498,7 +509,7 @@ public: void open_request(const String& p_path); - void set_edited_scene(Node *p_scene); + bool is_changing_scene() const; static EditorLog *get_log() { return singleton->log; } @@ -511,7 +522,9 @@ public: void hide_animation_player_editors(); void animation_panel_make_visible(bool p_visible); - Node *get_edited_scene() { return edited_scene; } + void set_edited_scene(Node *p_scene); + + Node *get_edited_scene() { return editor_data.get_edited_scene_root(); } 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); @@ -520,6 +533,9 @@ public: Error load_scene(const String& p_scene); Error load_resource(const String& p_scene); + void set_current_version(uint64_t p_version); + void set_current_scene(int p_idx); + static EditorData& get_editor_data() { return singleton->editor_data; } static VSplitContainer *get_top_split() { return singleton->top_split; } @@ -566,6 +582,9 @@ public: bool is_scene_in_use(const String& p_path); void scan_import_changes(); + + void save_layout(); + EditorNode(); ~EditorNode(); void get_singleton(const char* arg1, bool arg2); diff --git a/tools/editor/editor_plugin.cpp b/tools/editor/editor_plugin.cpp index e6b8ee0993..04c34d9a88 100644 --- a/tools/editor/editor_plugin.cpp +++ b/tools/editor/editor_plugin.cpp @@ -197,6 +197,13 @@ bool EditorPlugin::get_remove_list(List *p_list) { void EditorPlugin::restore_global_state() {} void EditorPlugin::save_global_state() {} +void EditorPlugin::set_window_layout(Ref p_layout) { + +} + +void EditorPlugin::get_window_layout(Ref p_layout){ + +} void EditorPlugin::_bind_methods() { diff --git a/tools/editor/editor_plugin.h b/tools/editor/editor_plugin.h index a9e6b1be49..0f3a1e2e3c 100644 --- a/tools/editor/editor_plugin.h +++ b/tools/editor/editor_plugin.h @@ -32,7 +32,7 @@ #include "scene/main/node.h" #include "scene/resources/texture.h" #include "undo_redo.h" - +#include "io/config_file.h" /** @author Juan Linietsky */ @@ -90,6 +90,8 @@ public: virtual void apply_changes() ; // if changes are pending in editor, apply them virtual void get_breakpoints(List *p_breakpoints); virtual bool get_remove_list(List *p_list); + virtual void set_window_layout(Ref p_layout); + virtual void get_window_layout(Ref p_layout); virtual void restore_global_state(); virtual void save_global_state(); diff --git a/tools/editor/editor_run_script.cpp b/tools/editor/editor_run_script.cpp index 5f8598d052..90581374f6 100644 --- a/tools/editor/editor_run_script.cpp +++ b/tools/editor/editor_run_script.cpp @@ -18,7 +18,7 @@ void EditorScript::add_root_node(Node *p_node) { return; } - editor->set_edited_scene(p_node); +// editor->set_edited_scene(p_node); } Node *EditorScript::get_scene() { diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp index 361a86b88e..0df9fcadef 100644 --- a/tools/editor/editor_settings.cpp +++ b/tools/editor/editor_settings.cpp @@ -433,9 +433,11 @@ void EditorSettings::_load_defaults() { set("text_editor/idle_parse_delay",2); set("text_editor/create_signal_callbacks",true); set("text_editor/autosave_interval_secs",0); + set("text_editor/font",""); hints["text_editor/font"]=PropertyInfo(Variant::STRING,"text_editor/font",PROPERTY_HINT_GLOBAL_FILE,"*.fnt"); set("text_editor/auto_brace_complete", false); + set("text_editor/restore_scripts_on_load",true); set("scenetree_editor/duplicate_node_name_num_separator",0); diff --git a/tools/editor/icons/icon_panel_top.png b/tools/editor/icons/icon_panel_top.png new file mode 100644 index 0000000000..20e67fad1a Binary files /dev/null and b/tools/editor/icons/icon_panel_top.png differ diff --git a/tools/editor/io_plugins/editor_mesh_import_plugin.cpp b/tools/editor/io_plugins/editor_mesh_import_plugin.cpp index 2e5a6f8a81..2139513025 100644 --- a/tools/editor/io_plugins/editor_mesh_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_mesh_import_plugin.cpp @@ -105,7 +105,7 @@ public: _EditorMeshImportOptions() { generate_tangents=true; - generate_normals=true; + generate_normals=false; flip_faces=false; smooth_shading=false; weld_vertices=true; diff --git a/tools/editor/plugins/multimesh_editor_plugin.cpp b/tools/editor/plugins/multimesh_editor_plugin.cpp index d858f3b896..0df906117e 100644 --- a/tools/editor/plugins/multimesh_editor_plugin.cpp +++ b/tools/editor/plugins/multimesh_editor_plugin.cpp @@ -305,7 +305,7 @@ void MultiMeshEditor::edit(MultiMeshInstance *p_multimesh) { void MultiMeshEditor::_browse(bool p_source) { browsing_source=p_source; - std->get_tree()->set_marked(node,false); + std->get_scene_tree()->set_marked(node,false); std->popup_centered_ratio(); if (p_source) std->set_title("Select a Source Mesh:"); diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp index f5ba6a08e6..cf934b988d 100644 --- a/tools/editor/plugins/script_editor_plugin.cpp +++ b/tools/editor/plugins/script_editor_plugin.cpp @@ -38,10 +38,12 @@ #include "os/file_access.h" #include "scene/main/viewport.h" #include "os/keyboard.h" -/*** SCRIPT EDITOR ****/ +#include "os/input.h" +/*** SCRIPT EDITOR ****/ +#define SORT_SCRIPT_LIST void ScriptEditorQuickOpen::popup(const Vector& p_functions, bool p_dontclear) { @@ -118,6 +120,8 @@ void ScriptEditorQuickOpen::_notification(int p_what) { if (p_what==NOTIFICATION_ENTER_TREE) { connect("confirmed",this,"_confirmed"); + + } } @@ -296,12 +300,11 @@ void ScriptTextEditor::_notification(int p_what) { if (p_what==NOTIFICATION_READY) { - _update_name(); + //emit_signal("name_changed"); } } -void ScriptTextEditor::_update_name() { - +String ScriptTextEditor::get_name() { String name; if (script->get_path().find("local://")==-1 && script->get_path().find("::")==-1) { @@ -314,21 +317,20 @@ void ScriptTextEditor::_update_name() { else name=script->get_type()+"("+itos(script->get_instance_ID())+")"; + return name; - if (name!=String(get_name())) { +} - set_name(name); +Ref ScriptTextEditor::get_icon() { + if (get_parent_control() && get_parent_control()->has_icon(script->get_type(),"EditorIcons")) { + return get_parent_control()->get_icon(script->get_type(),"EditorIcons"); } - if (!has_meta("_tab_icon")) { - if (get_parent_control() && get_parent_control()->has_icon(script->get_type(),"EditorIcons")) { - set_meta("_tab_icon",get_parent_control()->get_icon(script->get_type(),"EditorIcons")); - } - } + return Ref(); +} -} void ScriptTextEditor::set_edited_script(const Ref