diff options
Diffstat (limited to 'tools')
25 files changed, 1868 insertions, 336 deletions
diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp index bb6f7e9a6f..d431af6c8d 100644 --- a/tools/editor/animation_editor.cpp +++ b/tools/editor/animation_editor.cpp @@ -3319,7 +3319,8 @@ void AnimationKeyEditor::_insert_delay() { void AnimationKeyEditor::_step_changed(float p_len) { updating=true; - animation->set_step(p_len); + if (!animation.is_null()) + animation->set_step(p_len); updating=false; } diff --git a/tools/editor/connections_dialog.cpp b/tools/editor/connections_dialog.cpp index e927a6e441..b0bacdae61 100644 --- a/tools/editor/connections_dialog.cpp +++ b/tools/editor/connections_dialog.cpp @@ -530,7 +530,7 @@ void ConnectionsDialog::ok_pressed() { get_ok()->set_disabled(true); return; } - if (item->get_parent()==tree->get_root()) { + if (item->get_parent()==tree->get_root() || item->get_parent()->get_parent()==tree->get_root()) { //a signal - connect String signal=item->get_metadata(0).operator Dictionary()["name"]; String signalname=signal; @@ -632,74 +632,130 @@ void ConnectionsDialog::update_tree() { node->get_signal_list(&node_signals); //node_signals.sort_custom<_ConnectionsDialogMethodInfoSort>(); + bool did_script=false; + StringName base = node->get_type(); - for(List<MethodInfo>::Element *E=node_signals.front();E;E=E->next()) { - + while(base) { + + List<MethodInfo> node_signals; + Ref<Texture> icon; + String name; - MethodInfo &mi =E->get(); + if (!did_script) { - String signaldesc; - signaldesc=mi.name+"("; - StringArray argnames; - if (mi.arguments.size()) { - signaldesc+=" "; - for(int i=0;i<mi.arguments.size();i++) { + Ref<Script> scr = node->get_script(); + if (scr.is_valid()) { + scr->get_script_signal_list(&node_signals); + if (scr->get_path().is_resource_file()) + name=scr->get_path().get_file(); + else + name=scr->get_type(); - PropertyInfo &pi = mi.arguments[i]; + if (has_icon(scr->get_type(),"EditorIcons")) { + icon=get_icon(scr->get_type(),"EditorIcons"); + } + } - if (i>0) - signaldesc+=", "; - signaldesc+=Variant::get_type_name(pi.type)+" "+(pi.name==""?String("arg "+itos(i)):pi.name); - argnames.push_back(pi.name); + } else { + ObjectTypeDB::get_signal_list(base,&node_signals,true); + if (has_icon(base,"EditorIcons")) { + icon=get_icon(base,"EditorIcons"); } - signaldesc+=" "; + name=base; } - signaldesc+=")"; - - TreeItem *item=tree->create_item(root); - item->set_text(0,signaldesc); - Dictionary sinfo; - sinfo["name"]=mi.name; - sinfo["args"]=argnames; - item->set_metadata(0,sinfo); - item->set_icon(0,get_icon("Signal","EditorIcons")); - List<Object::Connection> connections; - node->get_signal_connection_list(mi.name,&connections); + TreeItem *pitem = NULL; + + if (node_signals.size()) { + pitem=tree->create_item(root); + pitem->set_text(0,name); + pitem->set_icon(0,icon); + pitem->set_selectable(0,false); + pitem->set_editable(0,false); + pitem->set_custom_bg_color(0,get_color("prop_subsection","Editor")); + node_signals.sort(); + } - for(List<Object::Connection>::Element *F=connections.front();F;F=F->next()) { + for(List<MethodInfo>::Element *E=node_signals.front();E;E=E->next()) { - Object::Connection&c = F->get(); - if (!(c.flags&CONNECT_PERSIST)) - continue; - Node *target = c.target->cast_to<Node>(); - if (!target) - continue; + MethodInfo &mi =E->get(); - String path = String(node->get_path_to(target))+" :: "+c.method+"()"; - if (c.flags&CONNECT_DEFERRED) - path+=" (deferred)"; - if (c.binds.size()) { + String signaldesc; + signaldesc=mi.name+"("; + StringArray argnames; + if (mi.arguments.size()) { + signaldesc+=" "; + for(int i=0;i<mi.arguments.size();i++) { - path+=" binds( "; - for(int i=0;i<c.binds.size();i++) { + PropertyInfo &pi = mi.arguments[i]; if (i>0) - path+=", "; - path+=c.binds[i].operator String(); + signaldesc+=", "; + String tname="var"; + if (pi.type!=Variant::NIL) { + tname=Variant::get_type_name(pi.type); + } + signaldesc+=tname+" "+(pi.name==""?String("arg "+itos(i)):pi.name); + argnames.push_back(pi.name); + } - path+=" )"; + signaldesc+=" "; } - TreeItem *item2=tree->create_item(item); - item2->set_text(0,path); - item2->set_metadata(0,c); - item2->set_icon(0,get_icon("Slot","EditorIcons")); + signaldesc+=")"; + + TreeItem *item=tree->create_item(pitem); + item->set_text(0,signaldesc); + Dictionary sinfo; + sinfo["name"]=mi.name; + sinfo["args"]=argnames; + item->set_metadata(0,sinfo); + item->set_icon(0,get_icon("Signal","EditorIcons")); + + List<Object::Connection> connections; + node->get_signal_connection_list(mi.name,&connections); + for(List<Object::Connection>::Element *F=connections.front();F;F=F->next()) { + + Object::Connection&c = F->get(); + if (!(c.flags&CONNECT_PERSIST)) + continue; + + Node *target = c.target->cast_to<Node>(); + if (!target) + continue; + + String path = String(node->get_path_to(target))+" :: "+c.method+"()"; + if (c.flags&CONNECT_DEFERRED) + path+=" (deferred)"; + if (c.binds.size()) { + + path+=" binds( "; + for(int i=0;i<c.binds.size();i++) { + + if (i>0) + path+=", "; + path+=c.binds[i].operator String(); + } + path+=" )"; + } + + TreeItem *item2=tree->create_item(item); + item2->set_text(0,path); + item2->set_metadata(0,c); + item2->set_icon(0,get_icon("Slot","EditorIcons")); + + + } + } + if (!did_script) { + did_script=true; + } else { + base=ObjectTypeDB::type_inherits_from(base); } } @@ -722,7 +778,7 @@ void ConnectionsDialog::_something_selected() { get_ok()->set_text("Connect.."); get_ok()->set_disabled(true); - } else if (item->get_parent()==tree->get_root()) { + } else if (item->get_parent()==tree->get_root() || item->get_parent()->get_parent()==tree->get_root()) { //a signal - connect get_ok()->set_text("Connect.."); get_ok()->set_disabled(false); 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<Node*>::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<ResourceImportMetadata> p_mdata) { + + ERR_FAIL_INDEX(current_edited_scene,edited_scene.size()); + edited_scene[current_edited_scene].medatata=p_mdata; + +} + +Ref<ResourceImportMetadata> EditorData::get_edited_scene_import_metadata() const{ + + ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),Ref<ResourceImportMetadata>()); + return edited_scene[current_edited_scene].medatata; +} + +void EditorData::clear_edited_scenes() { + + for(int i=0;i<edited_scene.size();i++) { + if (edited_scene[i].root) { + memdelete( edited_scene[i].root ); + } + } + edited_scene.clear(); +} + + + +void EditorData::set_plugin_window_layout(Ref<ConfigFile> p_layout) { + for(int i=0;i<editor_plugins.size();i++) { + editor_plugins[i]->set_window_layout(p_layout); + } +} + +void EditorData::get_plugin_window_layout(Ref<ConfigFile> p_layout) { + for(int i=0;i<editor_plugins.size();i++) { + editor_plugins[i]->get_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<Obj> path; int level; }; +friend class EditorData; Vector<History> 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<ResourceImportMetadata> medatata; + List<Node*> selection; + Vector<EditorHistory::History> history_stored; + int history_current; + Dictionary custom_state; + uint64_t version; + + + }; + + Vector<EditedScene> edited_scene; + int current_edited_scene; public: @@ -146,6 +164,32 @@ public: void remove_custom_type(const String& p_type); const Map<String,Vector<CustomType> >& 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<ResourceImportMetadata> p_mdata); + Ref<ResourceImportMetadata> 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<ConfigFile> p_layout); + void get_plugin_window_layout(Ref<ConfigFile> 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..7b44f2cad9 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -92,6 +92,7 @@ #include "plugins/navigation_polygon_editor_plugin.h" #include "plugins/light_occluder_2d_editor_plugin.h" #include "plugins/color_ramp_editor_plugin.h" +#include "plugins/collision_shape_2d_editor_plugin.h" // end #include "tools/editor/io_plugins/editor_texture_import_plugin.h" #include "tools/editor/io_plugins/editor_scene_import_plugin.h" @@ -105,11 +106,24 @@ EditorNode *EditorNode::singleton=NULL; +void EditorNode::_update_scene_tabs() { + + scene_tabs->clear_tabs(); + for(int i=0;i<editor_data.get_edited_scene_count();i++) { + int current = editor_data.get_edited_scene(); + bool unsaved = (i==current)?saved_version!=editor_data.get_undo_redo().get_version():editor_data.get_scene_version(i)!=0; + scene_tabs->add_tab(editor_data.get_scene_title(i)+(unsaved?"(*)":"")); + } + + 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 +188,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 +250,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 +494,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 +521,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 +744,7 @@ void EditorNode::_save_edited_subresources(Node* scene,Map<RES,bool>& processed, for(int i=0;i<scene->get_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 +753,7 @@ void EditorNode::_save_edited_subresources(Node* scene,Map<RES,bool>& 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 +774,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 +825,11 @@ void EditorNode::_save_scene_with_preview(String p_file) { img.save_png(pfile); Vector<uint8_t> 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<ResourceImportMetadata>( 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<ResourceImportMetadata>( memnew( ResourceImportMetadata ) ) ); + editor_data.get_edited_scene_import_metadata()->set_option("thumbnail",imgdata); //tamanio tel thumbnail if (screen!=-1) { @@ -817,7 +843,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 +877,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 +893,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 +1081,7 @@ void EditorNode::_dialog_action(String p_file) { Node *base = selection.front()->get(); Map<Node*,Node*> 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 +1176,7 @@ void EditorNode::_dialog_action(String p_file) { ml = Ref<MeshLibrary>( 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 +1210,7 @@ void EditorNode::_dialog_action(String p_file) { ml = Ref<TileSet>( 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 +1351,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 +1434,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;i<editor_table.size();i++) { - if (editor_table[i]==main_plugin) { - main_editor_tabs->set_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;i<editor_table.size();i++) { + if (editor_table[i]==main_plugin) { + main_editor_tabs->set_current_tab(i); + break; + } } } @@ -1527,10 +1558,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 +1623,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 +1675,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 +1685,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 +1711,7 @@ void EditorNode::_cleanup_scene() { } _update_title(); - +#endif } void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { @@ -1693,16 +1724,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 +1757,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()); }; @@ -1755,10 +1790,25 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { 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 +1819,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 +1881,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 +1925,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 +1952,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 +1986,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 +2048,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 +2093,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 +2619,54 @@ void EditorNode::remove_editor_import_plugin(const Ref<EditorImportPlugin>& 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<Popup>()) - edited_scene->cast_to<Popup>()->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<Popup>()) + p_scene->cast_to<Popup>()->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<StringName>& strings) { @@ -2818,6 +2892,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;i<editor_table.size();i++) { + if (editor_plugin_screen==editor_table[i]) { + current=i; + break; + } + } + + if (idx<2 && current<2) { + //only set tab for 2D and 3D + _editor_select(p_state["main_tab"]); + //print_line(" setting main tab: "+itos(p_state["main_tab"])); + } + } + + if (p_state.has("scene_tree_offset")) + scene_tree_dock->get_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<Popup>()) + new_scene->cast_to<Popup>()->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 +3009,14 @@ Error EditorNode::load_scene(const String& p_scene) { } + for(int i=0;i<editor_data.get_edited_scene_count();i++) { + + if (editor_data.get_scene_path(i)==p_scene) { + _scene_tab_changed(i); + return OK; + } + } + load_errors->clear(); String lpath = Globals::get_singleton()->localize_path(p_scene); @@ -2841,9 +3032,22 @@ 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); + } + - Ref<PackedScene> sdata = ResourceLoader::load(lpath); + + //_cleanup_scene(); // i'm sorry but this MUST happen to avoid modified resources to not be reloaded. + + Ref<PackedScene> sdata = ResourceLoader::load(lpath,"",true); if (!sdata.is_valid()) { current_option=-1; @@ -2852,22 +3056,37 @@ 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; } + sdata->set_path(lpath,true); //take over path + Node*new_scene=sdata->instance(true); 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 +3099,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 +3145,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 +3285,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 +3338,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("/","::"); @@ -3236,6 +3458,7 @@ void EditorNode::register_editor_types() { ObjectTypeDB::register_type<EditorScenePostImport>(); ObjectTypeDB::register_type<EditorScript>(); ObjectTypeDB::register_type<EditorFileDialog>(); + ObjectTypeDB::register_type<UndoRedo>(); //ObjectTypeDB::register_type<EditorImporter>(); @@ -3325,7 +3548,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 +3566,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 +3883,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 +3979,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;i<DOCK_SLOT_MAX/2;i++) { bool in_use = dock_slot[i*2+0]->get_tab_count() || dock_slot[i*2+1]->get_tab_count(); if (in_use) @@ -3747,6 +4008,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 +4047,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 +4136,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<StyleBoxTexture> 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 +4231,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); @@ -3951,7 +4276,7 @@ EditorNode::EditorNode() { //dock_select_popoup->set_(Size2(20,20)); for(int i=0;i<DOCK_SLOT_MAX;i++) { - dock_slot[i]->set_custom_minimum_size(Size2(250,250)); + dock_slot[i]->set_custom_minimum_size(Size2(230,220)); dock_slot[i]->set_v_size_flags(Control::SIZE_EXPAND_FILL); dock_slot[i]->set_popup(dock_select_popoup); dock_slot[i]->connect("pre_popup_pressed",this,"_dock_pre_popup",varray(i)); @@ -4101,7 +4426,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); @@ -4727,6 +5054,7 @@ EditorNode::EditorNode() { add_editor_plugin( memnew( LightOccluder2DEditorPlugin(this) ) ); add_editor_plugin( memnew( NavigationPolygonEditorPlugin(this) ) ); add_editor_plugin( memnew( ColorRampEditorPlugin(this) ) ); + add_editor_plugin( memnew( CollisionShape2DEditorPlugin(this) ) ); for(int i=0;i<EditorPlugins::get_plugin_count();i++) add_editor_plugin( EditorPlugins::create(i,this) ); @@ -4791,8 +5119,8 @@ EditorNode::EditorNode() { } - edited_scene=NULL; - saved_version=0; + //edited_scene=NULL; + saved_version=1; unsaved_cache=true; _last_instanced_scene=NULL; @@ -4854,7 +5182,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<ResourceImportMetadata> scene_import_metadata; + //Ref<ResourceImportMetadata> 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<RES,bool>& processed,int32_t flags); bool _find_and_save_edited_subresources(Object *obj,Map<RES,bool>& processed,int32_t flags); void _save_edited_subresources(Node* scene,Map<RES,bool>& 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<Node*> *p_list) { void EditorPlugin::restore_global_state() {} void EditorPlugin::save_global_state() {} +void EditorPlugin::set_window_layout(Ref<ConfigFile> p_layout) { + +} + +void EditorPlugin::get_window_layout(Ref<ConfigFile> 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 <reduzio@gmail.com> */ @@ -90,6 +90,8 @@ public: virtual void apply_changes() ; // if changes are pending in editor, apply them virtual void get_breakpoints(List<String> *p_breakpoints); virtual bool get_remove_list(List<Node*> *p_list); + virtual void set_window_layout(Ref<ConfigFile> p_layout); + virtual void get_window_layout(Ref<ConfigFile> 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 Binary files differnew file mode 100644 index 0000000000..20e67fad1a --- /dev/null +++ b/tools/editor/icons/icon_panel_top.png diff --git a/tools/editor/icons/icon_script_list.png b/tools/editor/icons/icon_script_list.png Binary files differnew file mode 100644 index 0000000000..cdea1e161e --- /dev/null +++ b/tools/editor/icons/icon_script_list.png 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/collision_shape_2d_editor_plugin.cpp b/tools/editor/plugins/collision_shape_2d_editor_plugin.cpp new file mode 100644 index 0000000000..62cf1b4acb --- /dev/null +++ b/tools/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -0,0 +1,533 @@ +#include "collision_shape_2d_editor_plugin.h" + +#include "canvas_item_editor_plugin.h" + +#include "scene/resources/segment_shape_2d.h" +#include "scene/resources/shape_line_2d.h" +#include "scene/resources/circle_shape_2d.h" +#include "scene/resources/rectangle_shape_2d.h" +#include "scene/resources/capsule_shape_2d.h" +#include "scene/resources/convex_polygon_shape_2d.h" +#include "scene/resources/concave_polygon_shape_2d.h" + +Variant CollisionShape2DEditor::get_handle_value(int idx) const { + + switch ( shape_type ) { + case CAPSULE_SHAPE: { + Ref<CapsuleShape2D> capsule = node->get_shape(); + + if (idx==0) { + return capsule->get_radius(); + } else if (idx==1) { + return capsule->get_height(); + } + + } break; + + case CIRCLE_SHAPE: { + Ref<CircleShape2D> circle = node->get_shape(); + + if (idx==0) { + return circle->get_radius(); + } + + } break; + + case CONCAVE_POLYGON_SHAPE: { + + } break; + + case CONVEX_POLYGON_SHAPE: { + + } break; + + case LINE_SHAPE: { + + } break; + + case RAY_SHAPE: { + Ref<RayShape2D> ray = node->get_shape(); + + if (idx==0) { + return ray->get_length(); + } + + } break; + + case RECTANGLE_SHAPE: { + Ref<RectangleShape2D> rect = node->get_shape(); + + if (idx<2) { + return rect->get_extents().abs(); + } + + } break; + + case SEGMENT_SHAPE: { + Ref<SegmentShape2D> seg = node->get_shape(); + + if (idx==0) { + return seg->get_a(); + } else if (idx==1) { + return seg->get_b(); + } + + } break; + } + + return Variant(); +} + +void CollisionShape2DEditor::set_handle(int idx, Point2& p_point) { + + switch ( shape_type ) { + case CAPSULE_SHAPE: { + if (idx < 2) { + Ref<CapsuleShape2D> capsule = node->get_shape(); + + real_t parameter = Math::abs(p_point[idx]); + + if (idx==0) { + capsule->set_radius(parameter); + } else if (idx==1){ + capsule->set_height(parameter*2 - capsule->get_radius()*2); + } + + canvas_item_editor->get_viewport_control()->update(); + } + + } break; + + case CIRCLE_SHAPE: { + Ref<CircleShape2D> circle = node->get_shape(); + circle->set_radius(p_point.length()); + + canvas_item_editor->get_viewport_control()->update(); + + } break; + + case CONCAVE_POLYGON_SHAPE: { + + } break; + + case CONVEX_POLYGON_SHAPE: { + + } break; + + case LINE_SHAPE: { + + } break; + + case RAY_SHAPE: { + Ref<RayShape2D> ray = node->get_shape(); + + ray->set_length(Math::abs(p_point.y)); + + canvas_item_editor->get_viewport_control()->update(); + + } break; + + case RECTANGLE_SHAPE: { + if (idx<2) { + Ref<RectangleShape2D> rect = node->get_shape(); + + Vector2 extents = rect->get_extents(); + extents[idx] = p_point[idx]; + + rect->set_extents(extents.abs()); + + canvas_item_editor->get_viewport_control()->update(); + } + + } break; + + case SEGMENT_SHAPE: { + if (edit_handle < 2) { + Ref<SegmentShape2D> seg = node->get_shape(); + + if (idx==0) { + seg->set_a(p_point); + } else if (idx==1) { + seg->set_b(p_point); + } + + canvas_item_editor->get_viewport_control()->update(); + } + + } break; + } +} + +void CollisionShape2DEditor::commit_handle(int idx, Variant& p_org) { + + Control* c = canvas_item_editor->get_viewport_control(); + undo_redo->create_action("Set Handle"); + + switch ( shape_type ) { + case CAPSULE_SHAPE: { + Ref<CapsuleShape2D> capsule = node->get_shape(); + + if (idx==0) { + undo_redo->add_do_method(capsule.ptr(),"set_radius",capsule->get_radius()); + undo_redo->add_do_method(c,"update"); + undo_redo->add_undo_method(capsule.ptr(),"set_radius",p_org); + undo_redo->add_do_method(c,"update"); + } else if (idx==1) { + undo_redo->add_do_method(capsule.ptr(),"set_height",capsule->get_height()); + undo_redo->add_do_method(c,"update"); + undo_redo->add_undo_method(capsule.ptr(),"set_height",p_org); + undo_redo->add_undo_method(c,"update"); + } + + } break; + + case CIRCLE_SHAPE: { + Ref<CircleShape2D> circle = node->get_shape(); + + undo_redo->add_do_method(circle.ptr(),"set_radius",circle->get_radius()); + undo_redo->add_do_method(c,"update"); + undo_redo->add_undo_method(circle.ptr(),"set_radius",p_org); + undo_redo->add_undo_method(c,"update"); + + } break; + + case CONCAVE_POLYGON_SHAPE: { + + } break; + + case CONVEX_POLYGON_SHAPE: { + + } break; + + case LINE_SHAPE: { + + } break; + + case RAY_SHAPE: { + Ref<RayShape2D> ray = node->get_shape(); + + undo_redo->add_do_method(ray.ptr(),"set_length",ray->get_length()); + undo_redo->add_do_method(c,"update"); + undo_redo->add_undo_method(ray.ptr(),"set_length",p_org); + undo_redo->add_undo_method(c,"update"); + + } break; + + case RECTANGLE_SHAPE: { + Ref<RectangleShape2D> rect = node->get_shape(); + + undo_redo->add_do_method(rect.ptr(),"set_extents",rect->get_extents()); + undo_redo->add_do_method(c,"update"); + undo_redo->add_undo_method(rect.ptr(),"set_extents",p_org); + undo_redo->add_undo_method(c,"update"); + + } break; + + case SEGMENT_SHAPE: { + Ref<SegmentShape2D> seg = node->get_shape(); + if (idx==0) { + undo_redo->add_do_method(seg.ptr(),"set_a",seg->get_a()); + undo_redo->add_do_method(c,"update"); + undo_redo->add_undo_method(seg.ptr(),"set_a",p_org); + undo_redo->add_undo_method(c,"update"); + } else if (idx==1) { + undo_redo->add_do_method(seg.ptr(),"set_b",seg->get_b()); + undo_redo->add_do_method(c,"update"); + undo_redo->add_undo_method(seg.ptr(),"set_b",p_org); + undo_redo->add_undo_method(c,"update"); + } + + } break; + } + + undo_redo->commit_action(); +} + +bool CollisionShape2DEditor::forward_input_event(const InputEvent& p_event) { + + if (!node) { + return false; + } + + if (!node->get_shape().is_valid()) { + return false; + } + + if (shape_type == -1) { + return false; + } + + switch( p_event.type ) { + case InputEvent::MOUSE_BUTTON: { + const InputEventMouseButton& mb = p_event.mouse_button; + + Matrix32 gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); + + Point2 gpoint(mb.x,mb.y); + + if (mb.button_index == BUTTON_LEFT) { + if (mb.pressed) { + for (int i = 0; i < handles.size(); i++) { + if (gt.xform(handles[i]).distance_to(gpoint) < 8) { + edit_handle = i; + + break; + } + } + + if (edit_handle==-1) { + pressed = false; + + return false; + } + + original = get_handle_value(edit_handle); + pressed = true; + + return true; + + } else { + if (pressed) { + commit_handle(edit_handle, original); + + edit_handle = -1; + pressed = false; + + return true; + } + } + } + + return false; + + } break; + + case InputEvent::MOUSE_MOTION: { + const InputEventMouseMotion& mm = p_event.mouse_motion; + + if (edit_handle == -1 || !pressed) { + return false; + } + + Point2 gpoint = Point2(mm.x,mm.y); + Point2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); + cpoint = canvas_item_editor->snap_point(cpoint); + cpoint = node->get_global_transform().affine_inverse().xform(cpoint); + + set_handle(edit_handle, cpoint); + + return true; + + } break; + } + + return false; +} + +void CollisionShape2DEditor::_get_current_shape_type() { + + if (!node) { + return; + } + + Ref<Shape2D> s = node->get_shape(); + + if (!s.is_valid()) { + return; + } + + if (s->cast_to<CapsuleShape2D>()) { + shape_type = CAPSULE_SHAPE; + } else if (s->cast_to<CircleShape2D>()) { + shape_type = CIRCLE_SHAPE; + } else if (s->cast_to<ConcavePolygonShape2D>()) { + shape_type = CONCAVE_POLYGON_SHAPE; + } else if (s->cast_to<ConvexPolygonShape2D>()) { + shape_type = CONVEX_POLYGON_SHAPE; + } else if (s->cast_to<LineShape2D>()) { + shape_type = LINE_SHAPE; + } else if (s->cast_to<RayShape2D>()) { + shape_type = RAY_SHAPE; + } else if (s->cast_to<RectangleShape2D>()) { + shape_type = RECTANGLE_SHAPE; + } else if (s->cast_to<SegmentShape2D>()) { + shape_type = SEGMENT_SHAPE; + } else { + shape_type = -1; + } + + canvas_item_editor->get_viewport_control()->update(); +} + +void CollisionShape2DEditor::_canvas_draw() { + + if (!node) { + return; + } + + if (!node->get_shape().is_valid()) { + return; + } + + _get_current_shape_type(); + + if (shape_type == -1) { + return; + } + + Control *c = canvas_item_editor->get_viewport_control(); + Matrix32 gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); + + Ref<Texture> h = get_icon("EditorHandle","EditorIcons"); + Vector2 size = h->get_size()*0.5; + + handles.clear(); + + switch (shape_type) { + case CAPSULE_SHAPE: { + Ref<CapsuleShape2D> shape = node->get_shape(); + + handles.resize(2); + float radius = shape->get_radius(); + float height = shape->get_height()/2; + + handles[0] = Point2(radius, -height); + handles[1] = Point2(0,-(height + radius)); + + c->draw_texture(h, gt.xform(handles[0])-size); + c->draw_texture(h, gt.xform(handles[1])-size); + + } break; + + case CIRCLE_SHAPE: { + Ref<CircleShape2D> shape = node->get_shape(); + + handles.resize(1); + handles[0] = Point2(shape->get_radius(),0); + + c->draw_texture(h, gt.xform(handles[0])-size); + + } break; + + case CONCAVE_POLYGON_SHAPE: { + + } break; + + case CONVEX_POLYGON_SHAPE: { + + } break; + + case LINE_SHAPE: { + + } break; + + case RAY_SHAPE: { + Ref<RayShape2D> shape = node->get_shape(); + + handles.resize(1); + handles[0] = Point2(0,shape->get_length()); + + c->draw_texture(h,gt.xform(handles[0])-size); + + } break; + + case RECTANGLE_SHAPE: { + Ref<RectangleShape2D> shape = node->get_shape(); + + handles.resize(2); + Vector2 ext = shape->get_extents(); + handles[0] = Point2(ext.x,0); + handles[1] = Point2(0,-ext.y); + + c->draw_texture(h,gt.xform(handles[0])-size); + c->draw_texture(h,gt.xform(handles[1])-size); + + } break; + + case SEGMENT_SHAPE: { + Ref<SegmentShape2D> shape = node->get_shape(); + + handles.resize(2); + handles[0] = shape->get_a(); + handles[1] = shape->get_b(); + + c->draw_texture(h, gt.xform(handles[0])-size); + c->draw_texture(h, gt.xform(handles[1])-size); + + } break; + } +} + +void CollisionShape2DEditor::edit(Node* p_node) { + + if (!canvas_item_editor) { + canvas_item_editor=CanvasItemEditor::get_singleton(); + } + + if (p_node) { + node=p_node->cast_to<CollisionShape2D>(); + + if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw")) + canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw"); + + _get_current_shape_type(); + + } else { + edit_handle = -1; + shape_type = -1; + + if (canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw")) + canvas_item_editor->get_viewport_control()->disconnect("draw",this,"_canvas_draw"); + + node=NULL; + } + + canvas_item_editor->get_viewport_control()->update(); +} + +void CollisionShape2DEditor::_bind_methods() { + + ObjectTypeDB::bind_method("_canvas_draw",&CollisionShape2DEditor::_canvas_draw); + ObjectTypeDB::bind_method("_get_current_shape_type",&CollisionShape2DEditor::_get_current_shape_type); +} + +CollisionShape2DEditor::CollisionShape2DEditor(EditorNode* p_editor) { + + node = NULL; + canvas_item_editor = NULL; + editor = p_editor; + + undo_redo = p_editor->get_undo_redo(); + + edit_handle = -1; + pressed = false; +} + +void CollisionShape2DEditorPlugin::edit(Object* p_obj) { + + collision_shape_2d_editor->edit(p_obj->cast_to<Node>()); +} + +bool CollisionShape2DEditorPlugin::handles(Object* p_obj) const { + + return p_obj->is_type("CollisionShape2D"); +} + +void CollisionShape2DEditorPlugin::make_visible(bool visible) { + + if (!visible) { + edit(NULL); + } +} + +CollisionShape2DEditorPlugin::CollisionShape2DEditorPlugin(EditorNode* p_node) { + + editor=p_node; + + collision_shape_2d_editor = memnew( CollisionShape2DEditor(p_node) ); + p_node->get_gui_base()->add_child(collision_shape_2d_editor); +} + +CollisionShape2DEditorPlugin::~CollisionShape2DEditorPlugin() { + +} diff --git a/tools/editor/plugins/collision_shape_2d_editor_plugin.h b/tools/editor/plugins/collision_shape_2d_editor_plugin.h new file mode 100644 index 0000000000..75e9b68ea7 --- /dev/null +++ b/tools/editor/plugins/collision_shape_2d_editor_plugin.h @@ -0,0 +1,73 @@ +#ifndef COLLISION_SHAPE_2D_EDITOR_PLUGIN_H +#define COLLISION_SHAPE_2D_EDITOR_PLUGIN_H + +#include "tools/editor/editor_plugin.h" +#include "tools/editor/editor_node.h" + +#include "scene/2d/collision_shape_2d.h" + +class CanvasItemEditor; + +class CollisionShape2DEditor : public Control { + OBJ_TYPE(CollisionShape2DEditor, Control); + + enum ShapeType { + CAPSULE_SHAPE, + CIRCLE_SHAPE, + CONCAVE_POLYGON_SHAPE, + CONVEX_POLYGON_SHAPE, + LINE_SHAPE, + RAY_SHAPE, + RECTANGLE_SHAPE, + SEGMENT_SHAPE + }; + + EditorNode* editor; + UndoRedo* undo_redo; + CanvasItemEditor* canvas_item_editor; + CollisionShape2D* node; + + Vector<Point2> handles; + + int shape_type; + int edit_handle; + bool pressed; + Variant original; + + Variant get_handle_value(int idx) const; + void set_handle(int idx, Point2& p_point); + void commit_handle(int idx, Variant& p_org); + + void _get_current_shape_type(); + void _canvas_draw(); + +protected: + static void _bind_methods(); + +public: + bool forward_input_event(const InputEvent& p_event); + void edit(Node* p_node); + + CollisionShape2DEditor(EditorNode* p_editor); +}; + +class CollisionShape2DEditorPlugin : public EditorPlugin { + OBJ_TYPE(CollisionShape2DEditorPlugin, EditorPlugin); + + CollisionShape2DEditor* collision_shape_2d_editor; + EditorNode* editor; + +public: + virtual bool forward_input_event(const InputEvent& p_event) { return collision_shape_2d_editor->forward_input_event(p_event); } + + virtual String get_name() const { return "CollisionShape2D"; } + bool has_main_screen() const { return false; } + virtual void edit(Object* p_obj); + virtual bool handles(Object* p_obj) const; + virtual void make_visible(bool visible); + + CollisionShape2DEditorPlugin(EditorNode* p_editor); + ~CollisionShape2DEditorPlugin(); +}; + +#endif //COLLISION_SHAPE_2D_EDITOR_PLUGIN_H 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..b15abf8096 100644 --- a/tools/editor/plugins/script_editor_plugin.cpp +++ b/tools/editor/plugins/script_editor_plugin.cpp @@ -38,10 +38,89 @@ #include "os/file_access.h" #include "scene/main/viewport.h" #include "os/keyboard.h" +#include "os/input.h" + /*** SCRIPT EDITOR ****/ +class EditorScriptCodeCompletionCache : public ScriptCodeCompletionCache { + + + struct Cache { + uint64_t time_loaded; + RES cache; + }; + + Map<String,Cache> cached; + + +public: + + uint64_t max_time_cache; + int max_cache_size; + + void cleanup() { + + List< Map<String,Cache>::Element * > to_clean; + + + Map<String,Cache>::Element *I=cached.front(); + while(I) { + if ((OS::get_singleton()->get_ticks_msec()-I->get().time_loaded)>max_time_cache) { + to_clean.push_back(I); + } + I=I->next(); + } + + while(to_clean.front()) { + cached.erase(to_clean.front()->get()); + to_clean.pop_front(); + } + } + + RES get_cached_resource(const String& p_path) { + + Map<String,Cache>::Element *E=cached.find(p_path); + if (!E) { + + Cache c; + c.cache=ResourceLoader::load(p_path); + E=cached.insert(p_path,c); + } + + E->get().time_loaded=OS::get_singleton()->get_ticks_msec(); + + if (cached.size()>max_cache_size) { + uint64_t older; + Map<String,Cache>::Element *O=cached.front(); + older=O->get().time_loaded; + Map<String,Cache>::Element *I=O; + while(I) { + if (I->get().time_loaded<older) { + older = I->get().time_loaded; + O=I; + } + I=I->next(); + } + + if (O!=E) {//should never heppane.. + cached.erase(O); + } + } + + return E->get().cache; + } + + + EditorScriptCodeCompletionCache() { + + max_cache_size=128; + max_time_cache=5*60*1000; //minutes, five + } + +}; +#define SORT_SCRIPT_LIST void ScriptEditorQuickOpen::popup(const Vector<String>& p_functions, bool p_dontclear) { @@ -118,6 +197,8 @@ void ScriptEditorQuickOpen::_notification(int p_what) { if (p_what==NOTIFICATION_ENTER_TREE) { connect("confirmed",this,"_confirmed"); + + } } @@ -286,8 +367,19 @@ void ScriptTextEditor::reload_text() { ERR_FAIL_COND(script.is_null()) ; - get_text_edit()->set_text(script->get_source_code()); - get_text_edit()->clear_undo_history(); + TextEdit *te = get_text_edit(); + int column = te->cursor_get_column(); + int row = te->cursor_get_line(); + int h = te->get_h_scroll(); + int v = te->get_v_scroll(); + + te->set_text(script->get_source_code()); + te->clear_undo_history(); + te->cursor_set_line(row); + te->cursor_set_column(column); + te->set_h_scroll(h); + te->set_v_scroll(v); + _line_col_changed(); } @@ -296,12 +388,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 +405,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<Texture> 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<Texture>(); +} -} void ScriptTextEditor::set_edited_script(const Ref<Script>& p_script) { @@ -344,8 +434,7 @@ void ScriptTextEditor::set_edited_script(const Ref<Script>& p_script) { get_text_edit()->tag_saved_version(); - _update_name(); - + emit_signal("name_changed"); _line_col_changed(); } @@ -384,7 +473,7 @@ void ScriptTextEditor::_validate_script() { te->set_line_as_marked(i,line==i); } - _update_name(); + emit_signal("name_changed"); } @@ -418,6 +507,10 @@ void ScriptTextEditor::_code_complete_script(const String& p_code, List<String>* } } +void ScriptTextEditor::_bind_methods() { + + ADD_SIGNAL(MethodInfo("name_changed")); +} ScriptTextEditor::ScriptTextEditor() { @@ -492,11 +585,15 @@ void ScriptEditor::_close_current_tab() { memdelete(current); if (idx>=tab_container->get_child_count()) idx=tab_container->get_child_count()-1; - if (idx>=0) + if (idx>=0) { tab_container->set_current_tab(idx); + //script_list->select(idx); + } + - _update_window_menu(); - _save_files_state(); + + _update_script_names(); + EditorNode::get_singleton()->save_layout(); } @@ -587,10 +684,10 @@ void ScriptEditor::_res_saved_callback(const Ref<Resource>& p_res) { ste->get_text_edit()->tag_saved_version(); } - ste->_update_name(); - } + _update_script_names(); + } bool ScriptEditor::_test_script_times_on_disk() { @@ -1045,7 +1142,7 @@ void ScriptEditor::_menu_option(int p_option) { if (text != "") editor->emit_signal("request_help", text); } break; - case WINDOW_CLOSE: { + case FILE_CLOSE: { if (current->get_text_edit()->get_version()!=current->get_text_edit()->get_saved_version()) { erase_tab_confirm->set_text("Close and save changes?\n\""+current->get_name()+"\""); erase_tab_confirm->popup_centered_minsize(); @@ -1057,16 +1154,18 @@ void ScriptEditor::_menu_option(int p_option) { if (tab_container->get_current_tab()>0) { tab_container->call_deferred("set_current_tab",tab_container->get_current_tab()-1); + script_list->call_deferred("select",tab_container->get_current_tab()-1); tab_container->move_child(current,tab_container->get_current_tab()-1); - _update_window_menu(); + _update_script_names(); } } break; case WINDOW_MOVE_RIGHT: { if (tab_container->get_current_tab()<tab_container->get_child_count()-1) { tab_container->call_deferred("set_current_tab",tab_container->get_current_tab()+1); + script_list->call_deferred("select",tab_container->get_current_tab()+1); tab_container->move_child(current,tab_container->get_current_tab()+1); - _update_window_menu(); + _update_script_names(); } @@ -1076,6 +1175,8 @@ void ScriptEditor::_menu_option(int p_option) { if (p_option>=WINDOW_SELECT_BASE) { tab_container->set_current_tab(p_option-WINDOW_SELECT_BASE); + script_list->select(p_option-WINDOW_SELECT_BASE); + } } } @@ -1096,6 +1197,8 @@ void ScriptEditor::_notification(int p_what) { editor->connect("stop_pressed",this,"_editor_stop"); editor->connect("script_add_function_request",this,"_add_callback"); editor->connect("resource_saved",this,"_res_saved_callback"); + script_list->connect("item_selected",this,"_script_selected"); + script_split->connect("dragged",this,"_script_split_dragged"); autosave_timer->connect("timeout",this,"_autosave_scripts"); { float autosave_time = EditorSettings::get_singleton()->get("text_editor/autosave_interval_secs"); @@ -1113,7 +1216,8 @@ void ScriptEditor::_notification(int p_what) { } if (p_what==NOTIFICATION_READY) { - _update_window_menu(); + + get_tree()->connect("tree_changed",this,"_tree_changed"); } if (p_what==NOTIFICATION_EXIT_TREE) { @@ -1153,10 +1257,11 @@ static const Node * _find_node_with_script(const Node* p_node, const RefPtr & p_ Dictionary ScriptEditor::get_state() const { - apply_scripts(); - Dictionary state; +// apply_scripts(); + Dictionary state; +#if 0 Array paths; int open=-1; @@ -1189,12 +1294,12 @@ Dictionary ScriptEditor::get_state() const { if (open!=-1) state["current"]=open; - +#endif return state; } void ScriptEditor::set_state(const Dictionary& p_state) { - +#if 0 print_line("attempt set state: "+String(Variant(p_state))); if (!p_state.has("sources")) @@ -1231,6 +1336,7 @@ void ScriptEditor::set_state(const Dictionary& p_state) { if (p_state.has("current")) { tab_container->set_current_tab(p_state["current"]); } +#endif } void ScriptEditor::clear() { @@ -1254,68 +1360,17 @@ void ScriptEditor::clear() { int idx = tab_container->get_current_tab(); if (idx>=tab_container->get_child_count()) idx=tab_container->get_child_count()-1; - if (idx>=0) + if (idx>=0) { tab_container->set_current_tab(idx); - - _update_window_menu(); - - -} - -void ScriptEditor::_save_files_state() { - - return; //no thank you - - String rpath="_open_scripts_"+Globals::get_singleton()->get_resource_path(); - rpath=rpath.replace("\\","_-_"); - rpath=rpath.replace("/","_-_"); - rpath=rpath.replace(":","_"); - - Vector<String> scripts; - - for(int i=0;i<tab_container->get_child_count();i++) { - - ScriptTextEditor *ste = tab_container->get_child(i)->cast_to<ScriptTextEditor>(); - if (!ste) - continue; - - - Ref<Script> script = ste->get_edited_script(); - if (script->get_path()!="" && script->get_path().find("local://")==-1 && script->get_path().find("::")==-1) { - - - scripts.push_back(script->get_path()); - } + script_list->select( script_list->find_metadata(idx) ); } - EditorSettings::get_singleton()->set(rpath,scripts); - EditorSettings::get_singleton()->save(); - -} -void ScriptEditor::_load_files_state() { - return; - - String rpath="_open_scripts_"+Globals::get_singleton()->get_resource_path(); - rpath=rpath.replace("\\","_-_"); - rpath=rpath.replace("/","_-_"); - rpath=rpath.replace(":","_"); - - if (EditorSettings::get_singleton()->has(rpath)) { - - Vector<String> open_files=EditorSettings::get_singleton()->get("rpath"); - for(int i=0;i<open_files.size();i++) { - Ref<Script> scr = ResourceLoader::load(open_files[i]); - if (!scr.is_valid()) - continue; - - editor->edit_resource(scr); - } - } } + void ScriptEditor::get_breakpoints(List<String> *p_breakpoints) { for(int i=0;i<tab_container->get_child_count();i++) { @@ -1360,11 +1415,18 @@ void ScriptEditor::_bind_methods() { ObjectTypeDB::bind_method("_get_debug_tooltip",&ScriptEditor::_get_debug_tooltip); ObjectTypeDB::bind_method("_autosave_scripts",&ScriptEditor::_autosave_scripts); ObjectTypeDB::bind_method("_editor_settings_changed",&ScriptEditor::_editor_settings_changed); + ObjectTypeDB::bind_method("_update_script_names",&ScriptEditor::_update_script_names); + ObjectTypeDB::bind_method("_tree_changed",&ScriptEditor::_tree_changed); + ObjectTypeDB::bind_method("_script_selected",&ScriptEditor::_script_selected); + ObjectTypeDB::bind_method("_script_split_dragged",&ScriptEditor::_script_split_dragged); } void ScriptEditor::ensure_focus_current() { + if (!is_inside_tree()) + return; + int cidx = tab_container->get_current_tab(); if (cidx<0 || cidx>=tab_container->get_tab_count()); Control *c = tab_container->get_child(cidx)->cast_to<Control>(); @@ -1376,6 +1438,13 @@ void ScriptEditor::ensure_focus_current() { ste->get_text_edit()->grab_focus(); } +void ScriptEditor::_script_selected(int p_idx) { + + grab_focus_block = !Input::get_singleton()->is_mouse_button_pressed(1); //amazing hack, simply amazing + tab_container->set_current_tab(script_list->get_item_metadata(p_idx)); + grab_focus_block=false; +} + void ScriptEditor::ensure_select_current() { @@ -1386,8 +1455,66 @@ void ScriptEditor::ensure_select_current() { return; Ref<Script> script = ste->get_edited_script(); - ste->get_text_edit()->grab_focus(); + if (!grab_focus_block && is_inside_tree()) + ste->get_text_edit()->grab_focus(); } + + +} + +void ScriptEditor::_find_scripts(Node* p_base, Node* p_current, Set<Ref<Script> > &used) { + if (p_current!=p_base && p_current->get_owner()!=p_base) + return; + + if (p_current->get_script_instance()) { + Ref<Script> scr = p_current->get_script(); + if (scr.is_valid()) + used.insert(scr); + } + + for(int i=0;i<p_current->get_child_count();i++) { + _find_scripts(p_base,p_current->get_child(i),used); + } + +} + + +void ScriptEditor::_update_script_names() { + + waiting_update_names=false; + Set<Ref<Script> > used; + Node* edited = EditorNode::get_singleton()->get_edited_scene(); + if (edited) { + _find_scripts(edited,edited,used); + } + + script_list->clear(); + for(int i=0;i<tab_container->get_child_count();i++) { + + ScriptTextEditor *ste = tab_container->get_child(i)->cast_to<ScriptTextEditor>(); + if (!ste) + continue; + + String script = ste->get_name(); + Ref<Texture> icon = ste->get_icon(); + String path = ste->get_edited_script()->get_path(); + script_list->add_item(script,icon); + + int index = script_list->get_item_count()-1; + + script_list->set_item_tooltip(index,path); + script_list->set_item_metadata(index,i); + if (used.has(ste->get_edited_script())) { + + script_list->set_item_custom_bg_color(index,Color(88/255.0,88/255.0,60/255.0)); + } + if (tab_container->get_current_tab()==index) { + script_list->select(index); + } + } + + script_list->sort_items_by_text(); + } void ScriptEditor::edit(const Ref<Script>& p_script) { @@ -1425,9 +1552,13 @@ void ScriptEditor::edit(const Ref<Script>& p_script) { if (ste->get_edited_script()==p_script) { - if (tab_container->get_current_tab()!=i) - tab_container->set_current_tab(i); - ste->get_text_edit()->grab_focus(); + if (!EditorNode::get_singleton()->is_changing_scene()) { + if (tab_container->get_current_tab()!=i) { + tab_container->set_current_tab(i); + script_list->select( script_list->find_metadata(i) ); + } + ste->get_text_edit()->grab_focus(); + } return; } } @@ -1440,9 +1571,13 @@ void ScriptEditor::edit(const Ref<Script>& p_script) { tab_container->add_child(ste); tab_container->set_current_tab(tab_container->get_tab_count()-1); - _update_window_menu(); - _save_files_state(); + + _update_script_names(); + ste->connect("name_changed",this,"_update_script_names"); + if (!restoring_layout) { + EditorNode::get_singleton()->save_layout(); + } } void ScriptEditor::save_external_data() { @@ -1502,51 +1637,6 @@ void ScriptEditor::_editor_stop() { debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_CONTINUE), true ); } -void ScriptEditor::_update_window_menu() { - - int idx=0; - for(int i=0;i<tab_container->get_child_count();i++) { - - ScriptTextEditor *ste = tab_container->get_child(i)->cast_to<ScriptTextEditor>(); - if (!ste) - continue; - idx++; - } - - if (idx==0) { - window_menu->set_disabled(true); - edit_menu->set_disabled(true); - search_menu->set_disabled(true); - return; - } else { - - window_menu->set_disabled(false); - edit_menu->set_disabled(false); - search_menu->set_disabled(false); - } - - window_menu->get_popup()->clear(); - window_menu->get_popup()->add_item("Close",WINDOW_CLOSE,KEY_MASK_CMD|KEY_W); - window_menu->get_popup()->add_separator(); - window_menu->get_popup()->add_item("Move Left",WINDOW_MOVE_LEFT,KEY_MASK_CMD|KEY_MASK_ALT|KEY_LEFT); - window_menu->get_popup()->add_item("Move Right",WINDOW_MOVE_RIGHT,KEY_MASK_CMD|KEY_MASK_ALT|KEY_RIGHT); - window_menu->get_popup()->add_separator(); - - idx=0; - for(int i=0;i<tab_container->get_child_count();i++) { - - ScriptTextEditor *ste = tab_container->get_child(i)->cast_to<ScriptTextEditor>(); - if (!ste) - continue; - String n = ste->get_name(); - uint32_t accel=0; - if (idx<9) { - accel=KEY_MASK_ALT|KEY_MASK_CMD|(KEY_1+idx); - } - window_menu->get_popup()->add_item(n,WINDOW_SELECT_BASE+idx,accel); - idx++; - } -} void ScriptEditor::_add_callback(Object *p_obj, const String& p_function, const StringArray& p_args) { @@ -1582,6 +1672,8 @@ void ScriptEditor::_add_callback(Object *p_obj, const String& p_function, const ste->get_text_edit()->cursor_set_line(pos); ste->get_text_edit()->cursor_set_column(1); + script_list->select( script_list->find_metadata(i) ); + break; } @@ -1607,8 +1699,81 @@ void ScriptEditor::_autosave_scripts() { save_external_data(); } +void ScriptEditor::_tree_changed() { + + if (waiting_update_names) + return; + + waiting_update_names=true; + call_deferred("_update_script_names"); +} + +void ScriptEditor::_script_split_dragged(float) { + + EditorNode::get_singleton()->save_layout(); +} + +void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) { + + if (!bool(EDITOR_DEF("text_editor/restore_scripts_on_load",true))) { + return; + } + + if (!p_layout->has_section_key("ScriptEditor","open_scripts")) + return; + + Array scripts = p_layout->get_value("ScriptEditor","open_scripts"); + + restoring_layout=true; + + for(int i=0;i<scripts.size();i++) { + + String path = scripts[i]; + Ref<Script> scr = ResourceLoader::load(path); + if (scr.is_valid()) { + edit(scr); + } + } + + if (p_layout->has_section_key("ScriptEditor","split_offset")) { + script_split->set_split_offset(p_layout->get_value("ScriptEditor","split_offset")); + } + + + restoring_layout=false; + +} + +void ScriptEditor::get_window_layout(Ref<ConfigFile> p_layout) { + + Array scripts; + + for(int i=0;i<tab_container->get_child_count();i++) { + + ScriptTextEditor *ste = tab_container->get_child(i)->cast_to<ScriptTextEditor>(); + if (!ste) + continue; + + String path = ste->get_edited_script()->get_path(); + if (!path.is_resource_file()) + continue; + + scripts.push_back(path); + + } + + p_layout->set_value("ScriptEditor","open_scripts",scripts); + p_layout->set_value("ScriptEditor","split_offset",script_split->get_split_offset()); + +} + + + ScriptEditor::ScriptEditor(EditorNode *p_editor) { + completion_cache = memnew( EditorScriptCodeCompletionCache ); + restoring_layout=false; + waiting_update_names=false; editor=p_editor; menu_hb = memnew( HBoxContainer ); @@ -1618,17 +1783,32 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { add_child(v_split); v_split->set_v_size_flags(SIZE_EXPAND_FILL); + script_split = memnew( HSplitContainer ); + v_split->add_child(script_split); + script_split->set_v_size_flags(SIZE_EXPAND_FILL); + + script_list = memnew( ItemList ); + script_split->add_child(script_list); + script_list->set_custom_minimum_size(Size2(70,0)); + script_split->set_split_offset(70); + tab_container = memnew( TabContainer ); - v_split->add_child(tab_container); - tab_container->set_v_size_flags(SIZE_EXPAND_FILL); + tab_container->set_tabs_visible(false); + script_split->add_child(tab_container); + + + tab_container->set_h_size_flags(SIZE_EXPAND_FILL); file_menu = memnew( MenuButton ); menu_hb->add_child(file_menu); file_menu->set_text("File"); file_menu->get_popup()->add_item("Open",FILE_OPEN); + file_menu->get_popup()->add_separator(); file_menu->get_popup()->add_item("Save",FILE_SAVE,KEY_MASK_ALT|KEY_MASK_CMD|KEY_S); file_menu->get_popup()->add_item("Save As..",FILE_SAVE_AS); file_menu->get_popup()->add_item("Save All",FILE_SAVE_ALL,KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_S); + file_menu->get_popup()->add_separator(); + file_menu->get_popup()->add_item("Close",FILE_CLOSE,KEY_MASK_CMD|KEY_W); file_menu->get_popup()->connect("item_pressed", this,"_menu_option"); edit_menu = memnew( MenuButton ); @@ -1690,6 +1870,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_CONTINUE), true ); +#if 0 window_menu = memnew( MenuButton ); menu_hb->add_child(window_menu); window_menu->set_text("Window"); @@ -1700,6 +1881,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { window_menu->get_popup()->add_separator(); window_menu->get_popup()->connect("item_pressed", this,"_menu_option"); +#endif + help_menu = memnew( MenuButton ); menu_hb->add_child(help_menu); help_menu->set_text("Help"); @@ -1762,11 +1945,18 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { autosave_timer->set_one_shot(false); add_child(autosave_timer); + grab_focus_block=false; + // debugger_gui->hide(); } +ScriptEditor::~ScriptEditor() { + + memdelete(completion_cache); +} + void ScriptEditorPlugin::edit(Object *p_object) { if (!p_object->cast_to<Script>()) @@ -1826,20 +2016,24 @@ void ScriptEditorPlugin::apply_changes() { void ScriptEditorPlugin::restore_global_state() { - if (bool(EDITOR_DEF("text_editor/restore_scripts_on_load",true))) { - script_editor->_load_files_state(); - } } void ScriptEditorPlugin::save_global_state() { - if (bool(EDITOR_DEF("text_editor/restore_scripts_on_load",true))) { - script_editor->_save_files_state(); - } +} + +void ScriptEditorPlugin::set_window_layout(Ref<ConfigFile> p_layout) { + + script_editor->set_window_layout(p_layout); +} + +void ScriptEditorPlugin::get_window_layout(Ref<ConfigFile> p_layout){ + script_editor->get_window_layout(p_layout); } + void ScriptEditorPlugin::get_breakpoints(List<String> *p_breakpoints) { diff --git a/tools/editor/plugins/script_editor_plugin.h b/tools/editor/plugins/script_editor_plugin.h index acfdd1e966..0dd152cb25 100644 --- a/tools/editor/plugins/script_editor_plugin.h +++ b/tools/editor/plugins/script_editor_plugin.h @@ -33,12 +33,13 @@ #include "scene/gui/tab_container.h" #include "scene/gui/text_edit.h" #include "scene/gui/menu_button.h" +#include "scene/gui/tool_button.h" #include "scene/gui/tree.h" #include "scene/main/timer.h" #include "script_language.h" #include "tools/editor/code_editor.h" #include "scene/gui/split_container.h" - +#include "scene/gui/item_list.h" class ScriptEditorQuickOpen : public ConfirmationDialog { @@ -88,6 +89,7 @@ protected: virtual void _code_complete_script(const String& p_code, List<String>* r_options); virtual void _load_theme_settings(); void _notification(int p_what); + static void _bind_methods(); public: @@ -97,12 +99,15 @@ public: Vector<String> get_functions() ; void set_edited_script(const Ref<Script>& p_script); void reload_text(); - void _update_name(); + String get_name() ; + Ref<Texture> get_icon() ; ScriptTextEditor(); }; +class EditorScriptCodeCompletionCache; + class ScriptEditor : public VBoxContainer { OBJ_TYPE(ScriptEditor, VBoxContainer ); @@ -115,6 +120,7 @@ class ScriptEditor : public VBoxContainer { FILE_SAVE, FILE_SAVE_AS, FILE_SAVE_ALL, + FILE_CLOSE, EDIT_UNDO, EDIT_REDO, EDIT_CUT, @@ -123,12 +129,12 @@ class ScriptEditor : public VBoxContainer { EDIT_SELECT_ALL, EDIT_COMPLETE, EDIT_AUTO_INDENT, - EDIT_TOGGLE_COMMENT, - EDIT_MOVE_LINE_UP, - EDIT_MOVE_LINE_DOWN, - EDIT_INDENT_RIGHT, - EDIT_INDENT_LEFT, - EDIT_CLONE_DOWN, + EDIT_TOGGLE_COMMENT, + EDIT_MOVE_LINE_UP, + EDIT_MOVE_LINE_DOWN, + EDIT_INDENT_RIGHT, + EDIT_INDENT_LEFT, + EDIT_CLONE_DOWN, SEARCH_FIND, SEARCH_FIND_NEXT, SEARCH_REPLACE, @@ -140,8 +146,7 @@ class ScriptEditor : public VBoxContainer { DEBUG_BREAK, DEBUG_CONTINUE, DEBUG_SHOW, - HELP_CONTEXTUAL, - WINDOW_CLOSE, + HELP_CONTEXTUAL, WINDOW_MOVE_LEFT, WINDOW_MOVE_RIGHT, WINDOW_SELECT_BASE=100 @@ -151,17 +156,19 @@ class ScriptEditor : public VBoxContainer { MenuButton *file_menu; MenuButton *edit_menu; MenuButton *search_menu; - MenuButton *window_menu; MenuButton *debug_menu; MenuButton *help_menu; Timer *autosave_timer; uint64_t idle; + ItemList *script_list; + HSplitContainer *script_split; TabContainer *tab_container; FindReplaceDialog *find_replace_dialog; GotoLineDialog *goto_line_dialog; ConfirmationDialog *erase_tab_confirm; ScriptEditorDebugger* debugger; + ToolButton *scripts_visible; void _tab_changed(int p_which); void _menu_option(int p_optin); @@ -171,6 +178,8 @@ class ScriptEditor : public VBoxContainer { VSplitContainer *v_split; + bool restoring_layout; + String _get_debug_tooltip(const String&p_text,Node *_ste); void _resave_scripts(const String& p_str); @@ -180,8 +189,11 @@ class ScriptEditor : public VBoxContainer { void _close_current_tab(); + bool grab_focus_block; + ScriptEditorQuickOpen *quick_open; + EditorScriptCodeCompletionCache *completion_cache; void _editor_play(); void _editor_pause(); @@ -199,6 +211,18 @@ class ScriptEditor : public VBoxContainer { void _editor_settings_changed(); void _autosave_scripts(); + void _update_script_names(); + + void _script_selected(int p_idx); + + void _find_scripts(Node* p_base, Node* p_current,Set<Ref<Script> >& used); + + void _tree_changed(); + + void _script_split_dragged(float); + + bool waiting_update_names; + static ScriptEditor *script_editor; protected: void _notification(int p_what); @@ -206,9 +230,6 @@ protected: public: static ScriptEditor *get_singleton() { return script_editor; } - void _save_files_state(); - void _load_files_state(); - void ensure_focus_current(); void apply_scripts() const; @@ -222,11 +243,15 @@ public: void get_breakpoints(List<String> *p_breakpoints); - void swap_lines(TextEdit *tx, int line1, int line2); + void swap_lines(TextEdit *tx, int line1, int line2); void save_external_data(); + void set_window_layout(Ref<ConfigFile> p_layout); + void get_window_layout(Ref<ConfigFile> p_layout); + ScriptEditor(EditorNode *p_editor); + ~ScriptEditor(); }; class ScriptEditorPlugin : public EditorPlugin { @@ -254,6 +279,9 @@ public: virtual void restore_global_state(); virtual void save_global_state(); + virtual void set_window_layout(Ref<ConfigFile> p_layout); + virtual void get_window_layout(Ref<ConfigFile> p_layout); + virtual void get_breakpoints(List<String> *p_breakpoints); diff --git a/tools/editor/plugins/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp index 5c82973da4..017a26441d 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.cpp +++ b/tools/editor/plugins/tile_map_editor_plugin.cpp @@ -71,22 +71,19 @@ void TileMapEditor::_canvas_mouse_exit() { } int TileMapEditor::get_selected_tile() const { - - TreeItem *item = palette->get_selected(); - if (!item) + int item = palette->get_current(); + if (item==-1) return TileMap::INVALID_CELL; - return item->get_metadata(0); + return palette->get_item_metadata(item); } void TileMapEditor::set_selected_tile(int p_tile) { - TreeItem *item = palette->get_root()->get_children(); - while (item) { - if ((int)item->get_metadata(0) == p_tile) { - item->select(0); - palette->ensure_cursor_is_visible(); + for (int i = 0; i < palette->get_item_count(); i++) { + if (palette->get_item_metadata(i).operator int() == p_tile) { + palette->select(i,true); + palette->ensure_current_is_visible(); break; } - item = item->get_next(); } } @@ -95,7 +92,7 @@ void TileMapEditor::_set_cell_shortened(const Point2& p_pos,int p_value,bool p_f ERR_FAIL_COND(!node); node->set_cell(floor(p_pos.x), floor(p_pos.y), p_value, p_flip_h, p_flip_v, p_transpose); } - + void TileMapEditor::_set_cell(const Point2i& p_pos,int p_value,bool p_flip_h, bool p_flip_v, bool p_transpose,bool p_with_undo) { ERR_FAIL_COND(!node); @@ -120,42 +117,78 @@ void TileMapEditor::_set_cell(const Point2i& p_pos,int p_value,bool p_flip_h, bo } +void TileMapEditor::_set_display_mode(int p_mode) { + if (display_mode == p_mode) { + return; + } + + switch (p_mode) { + case DISPLAY_THUMBNAIL: { + button_thumbnail->set_pressed(true); + button_list->set_pressed(false); + } break; + case DISPLAY_LIST: { + button_thumbnail->set_pressed(false); + button_list->set_pressed(true); + } break; + } + + display_mode = p_mode; + + _update_palette(); +} + void TileMapEditor::_update_palette() { if (!node) return; - palette->clear();; + palette->clear(); Ref<TileSet> tileset=node->get_tileset(); if (!tileset.is_valid()) return; - - TreeItem *root = palette->create_item(); - palette->set_hide_root(true); List<int> tiles; tileset->get_tile_list(&tiles); - for(List<int>::Element *E=tiles.front();E;E=E->next()) { + if (display_mode == DISPLAY_THUMBNAIL) { + palette->set_max_columns(0); + palette->set_icon_mode(ItemList::ICON_MODE_TOP); + } else if (display_mode == DISPLAY_LIST) { + palette->set_max_columns(1); + palette->set_icon_mode(ItemList::ICON_MODE_LEFT); + } - TreeItem *tile = palette->create_item(root); + palette->set_max_text_lines(2); + + for(List<int>::Element *E=tiles.front();E;E=E->next()) { + palette->add_item(""); - tile->set_icon_max_width(0,64); Ref<Texture> tex = tileset->tile_get_texture(E->get()); + if (tex.is_valid()) { - tile->set_icon(0,tex); Rect2 region = tileset->tile_get_region(E->get()); - if (region!=Rect2()) - tile->set_icon_region(0,region); - } else if (tileset->tile_get_name(E->get())!="") - tile->set_text(0,tileset->tile_get_name(E->get())); - else - tile->set_text(0,"#"+itos(E->get())); + if (!region.has_no_area()) { + Image data = VS::get_singleton()->texture_get_data(tex->get_rid()); + + Ref<ImageTexture> img = memnew( ImageTexture ); + img->create_from_image(data.get_rect(region)); + + palette->set_item_icon(palette->get_item_count()-1, img); + } else { + palette->set_item_icon(palette->get_item_count()-1,tex); + } + } - tile->set_metadata(0,E->get()); + if (tileset->tile_get_name(E->get())!="") { + palette->set_item_text(palette->get_item_count()-1, tileset->tile_get_name(E->get())); + } else { + palette->set_item_text(palette->get_item_count()-1, "#"+itos(E->get())); + } + palette->set_item_metadata(palette->get_item_count()-1, E->get()); } } @@ -387,7 +420,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { } if (tool==TOOL_ERASING) { - Point2i local =over_tile; + Point2i local =over_tile; if (!paint_undo.has(over_tile)) { paint_undo[over_tile]=_get_op_from_cell(over_tile); } @@ -641,7 +674,7 @@ void TileMapEditor::_canvas_draw() { Ref<Texture> t = ts->tile_get_texture(st); if (t.is_valid()) { Vector2 from = node->map_to_world(over_tile)+node->get_cell_draw_offset(); - Rect2 r = ts->tile_get_region(st); + Rect2 r = ts->tile_get_region(st); Size2 sc = xform.get_scale(); if (mirror_x->is_pressed()) sc.x*=-1.0; @@ -755,7 +788,7 @@ void TileMapEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_tileset_settings_changed"),&TileMapEditor::_tileset_settings_changed); ObjectTypeDB::bind_method(_MD("_update_transform_buttons"),&TileMapEditor::_update_transform_buttons); ObjectTypeDB::bind_method(_MD("_set_cell_shortened","pos","tile","flip_x","flip_y","transpose"),&TileMapEditor::_set_cell_shortened,DEFVAL(false),DEFVAL(false),DEFVAL(false)); - + ObjectTypeDB::bind_method(_MD("_set_display_mode","mode"),&TileMapEditor::_set_display_mode); } TileMapEditor::CellOp TileMapEditor::_get_op_from_cell(const Point2i& p_pos) @@ -777,7 +810,7 @@ void TileMapEditor::_update_transform_buttons(Object *p_button) { //ERR_FAIL_NULL(p_button); ToolButton *b=p_button->cast_to<ToolButton>(); //ERR_FAIL_COND(!b); - + mirror_x->set_block_signals(true); mirror_y->set_block_signals(true); transpose->set_block_signals(true); @@ -785,7 +818,7 @@ void TileMapEditor::_update_transform_buttons(Object *p_button) { rotate_90->set_block_signals(true); rotate_180->set_block_signals(true); rotate_270->set_block_signals(true); - + if (b == rotate_0) { mirror_x->set_pressed(false); mirror_y->set_pressed(false); @@ -806,7 +839,7 @@ void TileMapEditor::_update_transform_buttons(Object *p_button) { mirror_y->set_pressed(true); transpose->set_pressed(true); } - + rotate_0->set_pressed(!mirror_x->is_pressed() && !mirror_y->is_pressed() && !transpose->is_pressed()); rotate_90->set_pressed(mirror_x->is_pressed() && !mirror_y->is_pressed() && transpose->is_pressed()); rotate_180->set_pressed(mirror_x->is_pressed() && mirror_y->is_pressed() && !transpose->is_pressed()); @@ -833,8 +866,27 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { ec->set_custom_minimum_size(Size2(mw,0)); add_child(ec); + HBoxContainer *hb = memnew( HBoxContainer ); + add_child(hb); + hb->set_h_size_flags(SIZE_EXPAND_FILL); + hb->add_spacer(true); + + button_thumbnail = memnew( ToolButton ); + button_thumbnail->set_toggle_mode(true); + button_thumbnail->set_pressed(true); + button_thumbnail->set_icon(p_editor->get_gui_base()->get_icon("FileThumbnail","EditorIcons")); + hb->add_child(button_thumbnail); + button_thumbnail->connect("pressed", this, "_set_display_mode", varray(DISPLAY_THUMBNAIL)); + + button_list = memnew( ToolButton ); + button_list->set_toggle_mode(true); + button_list->set_pressed(false); + button_list->set_icon(p_editor->get_gui_base()->get_icon("FileList","EditorIcons")); + hb->add_child(button_list); + button_list->connect("pressed", this, "_set_display_mode", varray(DISPLAY_LIST)); + // Add tile palette - palette = memnew( Tree ); + palette = memnew( ItemList ); palette->set_v_size_flags(SIZE_EXPAND_FILL); add_child(palette); @@ -886,7 +938,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { rotate_270->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_270)); canvas_item_editor_hb->add_child(rotate_270); canvas_item_editor_hb->hide(); - + rotate_0->set_pressed(true); tool=TOOL_NONE; selection_active=false; diff --git a/tools/editor/plugins/tile_map_editor_plugin.h b/tools/editor/plugins/tile_map_editor_plugin.h index eaa5c256d7..74d1573d0f 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.h +++ b/tools/editor/plugins/tile_map_editor_plugin.h @@ -55,10 +55,18 @@ class TileMapEditor : public VBoxContainer { TOOL_PICKING }; + enum DisplayMode { + DISPLAY_THUMBNAIL, + DISPLAY_LIST + }; + Tool tool; Control *canvas_item_editor; - Tree *palette; + int display_mode; + ItemList *palette; + ToolButton *button_thumbnail; + ToolButton *button_list; EditorNode *editor; Panel *panel; TileMap *node; @@ -95,6 +103,7 @@ class TileMapEditor : public VBoxContainer { int get_selected_tile() const; void set_selected_tile(int p_tile); + void _set_display_mode(int p_mode); void _update_palette(); void _canvas_draw(); void _menu_option(int p_option); diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp index 00956919b7..f1eecd53b0 100644 --- a/tools/editor/project_manager.cpp +++ b/tools/editor/project_manager.cpp @@ -819,6 +819,7 @@ ProjectManager::ProjectManager() { if (!EditorSettings::get_singleton()) EditorSettings::create(); + FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("file_dialog/show_hidden_files")); set_area_as_parent_rect(); Panel *panel = memnew( Panel ); diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index a7636f517f..2fa8b98ff1 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -1633,7 +1633,7 @@ CustomPropertyEditor::CustomPropertyEditor() { scene_tree = memnew( SceneTreeDialog ); add_child(scene_tree); scene_tree->connect("selected", this,"_node_path_selected"); - scene_tree->get_tree()->set_show_enabled_subscene(true); + scene_tree->get_scene_tree()->set_show_enabled_subscene(true); texture_preview = memnew( TextureFrame ); add_child( texture_preview); diff --git a/tools/editor/scene_tree_dock.h b/tools/editor/scene_tree_dock.h index 4baa4ef37b..f0bbbad6be 100644 --- a/tools/editor/scene_tree_dock.h +++ b/tools/editor/scene_tree_dock.h @@ -134,6 +134,7 @@ public: void set_selected(Node *p_node, bool p_emit_selected=false); void fill_path_renames(Node* p_node, Node *p_new_parent, List<Pair<NodePath,NodePath> > *p_renames); void perform_node_renames(Node* p_base,List<Pair<NodePath,NodePath> > *p_renames, Map<Ref<Animation>, Set<int> > *r_rem_anims=NULL); + SceneTreeEditor *get_tree_editor() { return scene_tree; } SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelection *p_editor_selection,EditorData &p_editor_data); }; diff --git a/tools/editor/scene_tree_editor.h b/tools/editor/scene_tree_editor.h index 3e57ffb497..b05a52a2da 100644 --- a/tools/editor/scene_tree_editor.h +++ b/tools/editor/scene_tree_editor.h @@ -125,6 +125,9 @@ public: void update_tree() { _update_tree(); } + + Tree* get_scene_tree() { return tree; } + SceneTreeEditor(bool p_label=true,bool p_can_rename=false, bool p_can_open_instance=false); ~SceneTreeEditor(); @@ -150,7 +153,7 @@ protected: static void _bind_methods(); public: - SceneTreeEditor *get_tree() { return tree; } + SceneTreeEditor *get_scene_tree() { return tree; } SceneTreeDialog(); ~SceneTreeDialog(); diff --git a/tools/export/blender25/io_scene_dae/export_dae.py b/tools/export/blender25/io_scene_dae/export_dae.py index 9568ccb645..5245f32b82 100644 --- a/tools/export/blender25/io_scene_dae/export_dae.py +++ b/tools/export/blender25/io_scene_dae/export_dae.py @@ -228,7 +228,7 @@ class DaeExporter: # imgpath="images/"+image.name+".png" self.writel(S_IMGS,1,'<image id="'+imgid+'" name="'+image.name+'">') - self.writel(S_IMGS,2,'<init_from>'+imgpath+'</init_from>"/>') + self.writel(S_IMGS,2,'<init_from>'+imgpath+'</init_from>') self.writel(S_IMGS,1,'</image>') self.image_cache[image]=imgid return imgid |