/*************************************************************************/ /* editor_scene_import_plugin.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ /* "Software"), to deal in the Software without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to */ /* the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "editor_scene_import_plugin.h" #include "globals.h" #include "tools/editor/editor_node.h" #include "scene/resources/packed_scene.h" #include "scene/resources/box_shape.h" #include "os/file_access.h" #include "scene/3d/path.h" #include "scene/animation/animation_player.h" #include "io/resource_saver.h" #include "scene/3d/mesh_instance.h" #include "scene/3d/navigation.h" #include "scene/3d/room_instance.h" #include "scene/3d/body_shape.h" #include "scene/3d/physics_body.h" #include "scene/3d/portal.h" #include "scene/3d/vehicle_body.h" #include "scene/resources/sphere_shape.h" #include #include #include #include "tools/editor/create_dialog.h" #include "os/os.h" EditorSceneImporter::EditorSceneImporter() { } void EditorScenePostImport::_bind_methods() { BIND_VMETHOD( MethodInfo("post_import",PropertyInfo(Variant::OBJECT,"scene")) ); } Node *EditorScenePostImport::post_import(Node* p_scene) { if (get_script_instance()) return get_script_instance()->call("post_import",p_scene); return p_scene; } EditorScenePostImport::EditorScenePostImport() { } ///////////////////////////// class EditorImportAnimationOptions : public VBoxContainer { OBJ_TYPE( EditorImportAnimationOptions, VBoxContainer ); TreeItem *fps; TreeItem* optimize_linear_error; TreeItem* optimize_angular_error; TreeItem* optimize_max_angle; TreeItem *clips_base; TextEdit *filters; Vector clips; Tree *flags; Tree *clips_tree; Tree *optimization_tree; Vector items; bool updating; bool validating; void _changed(); void _item_edited(); void _button_action(Object *p_obj,int p_col,int p_id); protected: static void _bind_methods(); void _notification(int p_what); public: void set_flags(uint32_t p_flags); uint32_t get_flags() const; void set_fps(int p_fps); int get_fps() const; void set_optimize_linear_error(float p_error); float get_optimize_linear_error() const; void set_optimize_angular_error(float p_error); float get_optimize_angular_error() const; void set_optimize_max_angle(float p_error); float get_optimize_max_angle() const; void setup_clips(const Array& p_clips); Array get_clips() const; void set_filter(const String& p_filter); String get_filter() const; EditorImportAnimationOptions(); }; //////////////////////////// class EditorSceneImportDialog : public ConfirmationDialog { OBJ_TYPE(EditorSceneImportDialog,ConfirmationDialog); struct FlagInfo { int value; const char *category; const char *text; bool defval; }; static const FlagInfo scene_flag_names[]; EditorImportTextureOptions *texture_options; EditorImportAnimationOptions *animation_options; EditorSceneImportPlugin *plugin; EditorNode *editor; LineEdit *import_path; LineEdit *save_path; LineEdit *script_path; Tree *import_options; EditorFileDialog *file_select; EditorFileDialog *script_select; EditorDirDialog *save_select; OptionButton *texture_action; CreateDialog *root_type_choose; ConfirmationDialog *confirm_open; ConfirmationDialog *confirm_import; RichTextLabel *missing_files; Vector scene_flags; Map,Ref > collision_map; ConfirmationDialog *error_dialog; Button *root_type; CheckBox *root_default; void _root_default_pressed(); void _root_type_pressed(); void _set_root_type(); void _choose_file(const String& p_path); void _choose_save_file(const String& p_path); void _choose_script(const String& p_path); void _browse(); void _browse_target(); void _browse_script(); void _import(bool p_and_open=false); void _import_confirm(); Ref wip_rimd; Node *wip_import; String wip_save_file; bool wip_blocked; bool wip_open; void _dialog_hid(); void _open_and_import(); protected: void _notification(int p_what); static void _bind_methods(); public: void setup_popup(const String& p_from,const String& p_to_path) { _choose_file(p_from); _choose_save_file(p_to_path); } Error import(const String& p_from, const String& p_to, const String& p_preset); void popup_import(const String& p_from); EditorSceneImportDialog(EditorNode *p_editor,EditorSceneImportPlugin *p_plugin); }; /////////////////////////////////// static const char *anim_flag_names[]={ "Detect Loop (-loop,-cycle)", "Keep Value Tracks", "Optimize", "Force All Tracks in All Clips", NULL }; static const char *anim_flag_descript[]={ "Set loop flag for animation names that\ncontain 'cycle' or 'loop' in the name.", "When merging an existing aimation,\nkeep the user-created value-tracks.", "Remove redundant keyframes in\n transform tacks.", "Some exporters will rely on default pose for some bones.\nThis forces those bones to have at least one animation key.", NULL }; void EditorImportAnimationOptions::set_flags(uint32_t p_flags){ updating=true; for(int i=0;iset_checked(0,p_flags&(1<is_checked(0)) f|=(1<get_edited(); if (item==clips[clips.size()-1]) { //add new print_line("islast"); if (item->get_text(0).find("<")!=-1 || item->get_text(0).find(">")!=-1) { validating=false; return; //fuckit } item->set_editable(1,true); item->set_editable(2,true); item->add_button(0,EditorNode::get_singleton()->get_gui_base()->get_icon("Del","EditorIcons")); item->set_cell_mode(1,TreeItem::CELL_MODE_RANGE); item->set_range_config(1,0,3600,0.01); item->set_range(1,0); item->set_editable(1,true); item->set_cell_mode(2,TreeItem::CELL_MODE_RANGE); item->set_range_config(2,0,3600,0.01); item->set_range(2,0); item->set_cell_mode(3,TreeItem::CELL_MODE_CHECK); item->set_editable(3,true); TreeItem *newclip = clips_tree->create_item(clips_base); newclip->set_text(0,""); newclip->set_editable(0,true); newclip->set_editable(1,false); newclip->set_editable(2,false); clips.push_back(newclip); } //make name unique JUST IN CASE String name = item->get_text(0); name=name.replace("/","_").replace(":","_").strip_edges(); if (name=="") name=TTR("New Clip"); if (clips.size()>2) { int index=1; while(true) { bool valid = true; String try_name=name; if (index>1) try_name+=" "+itos(index); for(int i=0;iget_text(0)==try_name) { index++; valid=false; break; } } if (valid) { name=try_name; break; } } } if (item->get_text(0)!=name) item->set_text(0,name); validating=false; } void EditorImportAnimationOptions::_bind_methods() { ObjectTypeDB::bind_method("_changed",&EditorImportAnimationOptions::_changed); ObjectTypeDB::bind_method("_item_edited",&EditorImportAnimationOptions::_item_edited); ObjectTypeDB::bind_method("_button_action",&EditorImportAnimationOptions::_button_action); // ObjectTypeDB::bind_method("_changedp",&EditorImportAnimationOptions::_changedp); ADD_SIGNAL(MethodInfo("changed")); } void EditorImportAnimationOptions::_notification(int p_what) { if (p_what==NOTIFICATION_ENTER_TREE) { flags->connect("item_edited",this,"_changed"); clips_tree->connect("item_edited",this,"_item_edited"); clips_tree->connect("button_pressed",this,"_button_action",varray(),CONNECT_DEFERRED); // format->connect("item_selected",this,"_changedp"); } } Array EditorImportAnimationOptions::get_clips() const { Array arr; for(int i=0;iget_text(0)); arr.push_back(clips[i]->get_range(1)); arr.push_back(clips[i]->get_range(2)); arr.push_back(clips[i]->is_checked(3)); } return arr; } void EditorImportAnimationOptions::setup_clips(const Array& p_clips) { ERR_FAIL_COND(p_clips.size()%4!=0); for(int i=0;icreate_item(clips_base); clip->set_text(0,p_clips[i]); clip->add_button(0,EditorNode::get_singleton()->get_gui_base()->get_icon("Del","EditorIcons")); clip->set_editable(0,true); clip->set_cell_mode(1,TreeItem::CELL_MODE_RANGE); clip->set_range_config(1,0,3600,0.01); clip->set_range(1,p_clips[i+1]); clip->set_editable(1,true); clip->set_cell_mode(2,TreeItem::CELL_MODE_RANGE); clip->set_range_config(2,0,3600,0.01); clip->set_range(2,p_clips[i+2]); clip->set_editable(2,true); clip->set_cell_mode(3,TreeItem::CELL_MODE_CHECK); clip->set_editable(3,true); clip->set_checked(3,p_clips[i+3]); clips.push_back(clip); } TreeItem *newclip = clips_tree->create_item(clips_base); newclip->set_text(0,""); newclip->set_editable(0,true); newclip->set_editable(1,false); newclip->set_editable(2,false); newclip->set_editable(3,false); clips.push_back(newclip); } EditorImportAnimationOptions::EditorImportAnimationOptions() { updating=false; validating=false; TabContainer *tab= memnew(TabContainer); add_margin_child(TTR("Animation Options"),tab,true); flags = memnew( Tree ); flags->set_hide_root(true); tab->add_child(flags); flags->set_name(TTR("Flags")); TreeItem *root = flags->create_item(); const char ** fname=anim_flag_names; const char ** fdescr=anim_flag_descript; while( *fname ) { TreeItem*ti = flags->create_item(root); ti->set_cell_mode(0,TreeItem::CELL_MODE_CHECK); ti->set_text(0,*fname); ti->set_editable(0,true); ti->set_tooltip(0,*fdescr); items.push_back(ti); fname++; fdescr++; } TreeItem *fps_base = flags->create_item(root); fps_base->set_text(0,TTR("Bake FPS:")); fps_base->set_editable(0,false); fps = flags->create_item(fps_base); fps->set_cell_mode(0,TreeItem::CELL_MODE_RANGE); fps->set_editable(0,true); fps->set_range_config(0,1,120,1); fps->set_range(0,15); optimization_tree = memnew( Tree ); optimization_tree->set_columns(2); tab->add_child(optimization_tree); optimization_tree->set_name(TTR("Optimizer")); optimization_tree->set_column_expand(0,true); optimization_tree->set_column_expand(1,false); optimization_tree->set_column_min_width(1,80); optimization_tree->set_hide_root(true); TreeItem *optimize_root = optimization_tree->create_item(); optimize_linear_error = optimization_tree->create_item(optimize_root); optimize_linear_error->set_text(0,TTR("Max Linear Error")); optimize_linear_error->set_cell_mode(1,TreeItem::CELL_MODE_RANGE); optimize_linear_error->set_editable(1,true); optimize_linear_error->set_range_config(1,0,1,0.001); optimize_linear_error->set_range(1,0.05); optimize_angular_error = optimization_tree->create_item(optimize_root); optimize_angular_error->set_text(0,TTR("Max Angular Error")); optimize_angular_error->set_cell_mode(1,TreeItem::CELL_MODE_RANGE); optimize_angular_error->set_editable(1,true); optimize_angular_error->set_range_config(1,0,1,0.001); optimize_angular_error->set_range(1,0.01); optimize_max_angle = optimization_tree->create_item(optimize_root); optimize_max_angle->set_text(0,TTR("Max Angle")); optimize_max_angle->set_cell_mode(1,TreeItem::CELL_MODE_RANGE); optimize_max_angle->set_editable(1,true); optimize_max_angle->set_range_config(1,0,360,0.001); optimize_max_angle->set_range(1,int(180*0.125)); clips_tree = memnew( Tree ); clips_tree->set_hide_root(true); tab->add_child(clips_tree); clips_tree->set_name(TTR("Clips")); clips_tree->set_columns(4); clips_tree->set_column_expand(0,1); clips_tree->set_column_expand(1,0); clips_tree->set_column_expand(2,0); clips_tree->set_column_expand(3,0); clips_tree->set_column_min_width(1,60); clips_tree->set_column_min_width(2,60); clips_tree->set_column_min_width(3,40); clips_tree->set_column_titles_visible(true); clips_tree->set_column_title(0,TTR("Name")); clips_tree->set_column_title(1,TTR("Start(s)")); clips_tree->set_column_title(2,TTR("End(s)")); clips_tree->set_column_title(3,TTR("Loop")); clips_base =clips_tree->create_item(0); setup_clips(Array()); filters = memnew( TextEdit ); tab->add_child(filters); filters->set_name(TTR("Filters")); } void EditorImportAnimationOptions::set_fps(int p_fps) { fps->set_range(0,p_fps); } int EditorImportAnimationOptions::get_fps() const { return fps->get_range(0); } void EditorImportAnimationOptions::set_optimize_linear_error(float p_optimize_linear_error) { optimize_linear_error->set_range(1,p_optimize_linear_error); } float EditorImportAnimationOptions::get_optimize_linear_error() const { return optimize_linear_error->get_range(1); } void EditorImportAnimationOptions::set_optimize_angular_error(float p_optimize_angular_error) { optimize_angular_error->set_range(1,p_optimize_angular_error); } float EditorImportAnimationOptions::get_optimize_angular_error() const { return optimize_angular_error->get_range(1); } void EditorImportAnimationOptions::set_optimize_max_angle(float p_optimize_max_angle) { optimize_max_angle->set_range(1,p_optimize_max_angle); } float EditorImportAnimationOptions::get_optimize_max_angle() const { return optimize_max_angle->get_range(1); } void EditorImportAnimationOptions::set_filter(const String& p_filter) { filters->set_text(p_filter); } String EditorImportAnimationOptions::get_filter() const { return filters->get_text(); } //////////////////////////////////////////////////////// void EditorSceneImportDialog::_choose_file(const String& p_path) { #if 0 StringName sn = EditorImportDB::get_singleton()->find_source_path(p_path); if (sn!=StringName()) { EditorImportDB::ImportScene isc; if (EditorImportDB::get_singleton()->get_scene(sn,isc)==OK) { save_path->set_text(String(sn).get_base_dir()); texture_options->set_flags( isc.image_flags ); texture_options->set_quality( isc.image_quality ); texture_options->set_format( isc.image_format ); animation_options->set_flags( isc.anim_flags ); script_path->set_text( isc.import_script ); uint32_t f = isc.flags; for(int i=0;iset_checked(0,f&(1<set_text(""); //save_path->set_text(p_path.get_file().basename()+".scn"); #if 0 } #endif if (p_path!=String()) { String from_path = EditorFileSystem::get_singleton()->find_resource_from_source(EditorImportPlugin::validate_source_path(p_path)); print_line("from path.."+from_path); if (from_path!=String()) { popup_import(from_path); } } import_path->set_text(p_path); } void EditorSceneImportDialog::_choose_save_file(const String& p_path) { save_path->set_text(p_path); } void EditorSceneImportDialog::_choose_script(const String& p_path) { String p = Globals::get_singleton()->localize_path(p_path); if (!p.is_resource_file()) p=Globals::get_singleton()->get_resource_path().path_to(p_path.get_base_dir())+p_path.get_file(); script_path->set_text(p); } void EditorSceneImportDialog::_open_and_import() { bool unsaved=EditorNode::has_unsaved_changes(); if (unsaved) { confirm_open->popup_centered_minsize(Size2(300,80)*EDSCALE); } else { _import(true); } } void EditorSceneImportDialog::_import(bool p_and_open) { wip_open=p_and_open; //' ImportMonitorBlock imb; if (import_path->get_text().strip_edges()=="") { error_dialog->set_text(TTR("Source path is empty.")); error_dialog->popup_centered_minsize(); return; } if (save_path->get_text().strip_edges()=="") { error_dialog->set_text(TTR("Target path is empty.")); error_dialog->popup_centered_minsize(); return; } if (!save_path->get_text().begins_with("res://")) { error_dialog->set_text(TTR("Target path must be a complete resource path.")); error_dialog->popup_centered_minsize(); return; } if (!DirAccess::exists(save_path->get_text())) { error_dialog->set_text(TTR("Target path must exist.")); error_dialog->popup_centered_minsize(); return; } String dst_path; if (texture_action->get_selected()==0) dst_path=save_path->get_text();//.get_base_dir(); else dst_path=Globals::get_singleton()->get("import/shared_textures"); uint32_t flags=0; for(int i=0;iis_checked(0)) { int md = scene_flags[i]->get_metadata(0); flags|=md; } } if (script_path->get_text()!="") { Ref