|
@@ -78,12 +78,23 @@ class EditorImportAnimationOptions : public VBoxContainer {
|
|
OBJ_TYPE( EditorImportAnimationOptions, VBoxContainer );
|
|
OBJ_TYPE( EditorImportAnimationOptions, VBoxContainer );
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
+ TreeItem *fps;
|
|
|
|
+ TreeItem *clips_base;
|
|
|
|
+ TextEdit *filters;
|
|
|
|
+ Vector<TreeItem*> clips;
|
|
|
|
+
|
|
Tree *flags;
|
|
Tree *flags;
|
|
|
|
+ Tree *clips_tree;
|
|
Vector<TreeItem*> items;
|
|
Vector<TreeItem*> items;
|
|
|
|
|
|
bool updating;
|
|
bool updating;
|
|
|
|
+ bool validating;
|
|
|
|
|
|
void _changed();
|
|
void _changed();
|
|
|
|
+ void _item_edited();
|
|
|
|
+ void _button_action(Object *p_obj,int p_col,int p_id);
|
|
|
|
+
|
|
protected:
|
|
protected:
|
|
static void _bind_methods();
|
|
static void _bind_methods();
|
|
void _notification(int p_what);
|
|
void _notification(int p_what);
|
|
@@ -93,6 +104,14 @@ public:
|
|
void set_flags(uint32_t p_flags);
|
|
void set_flags(uint32_t p_flags);
|
|
uint32_t get_flags() const;
|
|
uint32_t get_flags() const;
|
|
|
|
|
|
|
|
+ void set_fps(int p_fps);
|
|
|
|
+ int get_fps() const;
|
|
|
|
+
|
|
|
|
+ void setup_clips(const Array& p_clips);
|
|
|
|
+ Array get_clips() const;
|
|
|
|
+
|
|
|
|
+ void set_filter(const String& p_filter);
|
|
|
|
+ String get_filter() const;
|
|
|
|
|
|
EditorImportAnimationOptions();
|
|
EditorImportAnimationOptions();
|
|
|
|
|
|
@@ -141,6 +160,9 @@ class EditorSceneImportDialog : public ConfirmationDialog {
|
|
Map<Ref<Mesh>,Ref<Shape> > collision_map;
|
|
Map<Ref<Mesh>,Ref<Shape> > collision_map;
|
|
ConfirmationDialog *error_dialog;
|
|
ConfirmationDialog *error_dialog;
|
|
|
|
|
|
|
|
+ OptionButton *this_import;
|
|
|
|
+ OptionButton *next_import;
|
|
|
|
+
|
|
void _choose_file(const String& p_path);
|
|
void _choose_file(const String& p_path);
|
|
void _choose_save_file(const String& p_path);
|
|
void _choose_save_file(const String& p_path);
|
|
void _choose_script(const String& p_path);
|
|
void _choose_script(const String& p_path);
|
|
@@ -178,7 +200,7 @@ static const char *anim_flag_names[]={
|
|
"Detect Loop (-loop,-cycle)",
|
|
"Detect Loop (-loop,-cycle)",
|
|
"Keep Value Tracks",
|
|
"Keep Value Tracks",
|
|
"Optimize",
|
|
"Optimize",
|
|
- "Force Tracks in All Bones",
|
|
|
|
|
|
+ "Force All Tracks in All Clips",
|
|
NULL
|
|
NULL
|
|
};
|
|
};
|
|
|
|
|
|
@@ -223,9 +245,101 @@ void EditorImportAnimationOptions::_changed() {
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+void EditorImportAnimationOptions::_button_action(Object *p_obj,int p_col,int p_id) {
|
|
|
|
+
|
|
|
|
+ memdelete(p_obj);
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+void EditorImportAnimationOptions::_item_edited() {
|
|
|
|
+
|
|
|
|
+ if (validating)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (clips.size()==0)
|
|
|
|
+ return;
|
|
|
|
+ validating=true;
|
|
|
|
+ print_line("edited");
|
|
|
|
+ TreeItem *item = clips_tree->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,"<new clip>");
|
|
|
|
+ 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="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;i<clips.size()-1;i++) {
|
|
|
|
+
|
|
|
|
+ if (clips[i]==item)
|
|
|
|
+ continue;
|
|
|
|
+ if (clips[i]->get_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() {
|
|
void EditorImportAnimationOptions::_bind_methods() {
|
|
|
|
|
|
ObjectTypeDB::bind_method("_changed",&EditorImportAnimationOptions::_changed);
|
|
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);
|
|
// ObjectTypeDB::bind_method("_changedp",&EditorImportAnimationOptions::_changedp);
|
|
|
|
|
|
ADD_SIGNAL(MethodInfo("changed"));
|
|
ADD_SIGNAL(MethodInfo("changed"));
|
|
@@ -237,17 +351,84 @@ void EditorImportAnimationOptions::_notification(int p_what) {
|
|
if (p_what==NOTIFICATION_ENTER_SCENE) {
|
|
if (p_what==NOTIFICATION_ENTER_SCENE) {
|
|
|
|
|
|
flags->connect("item_edited",this,"_changed");
|
|
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");
|
|
// format->connect("item_selected",this,"_changedp");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+Array EditorImportAnimationOptions::get_clips() const {
|
|
|
|
+
|
|
|
|
+ Array arr;
|
|
|
|
+ for(int i=0;i<clips.size()-1;i++) {
|
|
|
|
+
|
|
|
|
+ arr.push_back(clips[i]->get_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;i<clips.size();i++) {
|
|
|
|
+
|
|
|
|
+ memdelete(clips[i]);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ clips.clear();
|
|
|
|
+
|
|
|
|
+ for(int i=0;i<p_clips.size();i+=4) {
|
|
|
|
+
|
|
|
|
+ TreeItem *clip = clips_tree->create_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,"<new clip>");
|
|
|
|
+ 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() {
|
|
EditorImportAnimationOptions::EditorImportAnimationOptions() {
|
|
|
|
|
|
|
|
|
|
updating=false;
|
|
updating=false;
|
|
|
|
+ validating=false;
|
|
|
|
+
|
|
|
|
+ TabContainer *tab= memnew(TabContainer);
|
|
|
|
+ add_margin_child("Animation Options",tab,true);
|
|
|
|
|
|
flags = memnew( Tree );
|
|
flags = memnew( Tree );
|
|
flags->set_hide_root(true);
|
|
flags->set_hide_root(true);
|
|
|
|
+ tab->add_child(flags);
|
|
|
|
+ flags->set_name("Flags");
|
|
TreeItem *root = flags->create_item();
|
|
TreeItem *root = flags->create_item();
|
|
|
|
|
|
const char ** fname=anim_flag_names;
|
|
const char ** fname=anim_flag_names;
|
|
@@ -263,14 +444,69 @@ EditorImportAnimationOptions::EditorImportAnimationOptions() {
|
|
items.push_back(ti);
|
|
items.push_back(ti);
|
|
fname++;
|
|
fname++;
|
|
fdescr++;
|
|
fdescr++;
|
|
- }
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ TreeItem *fps_base = flags->create_item(root);
|
|
|
|
+ fps_base->set_text(0,"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(0,15);
|
|
|
|
+ fps->set_range_config(0,1,120,1);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ clips_tree = memnew( Tree );
|
|
|
|
+ clips_tree->set_hide_root(true);
|
|
|
|
+ tab->add_child(clips_tree);
|
|
|
|
+ clips_tree->set_name("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,"Name");
|
|
|
|
+ clips_tree->set_column_title(1,"Start(s)");
|
|
|
|
+ clips_tree->set_column_title(2,"End(s)");
|
|
|
|
+ clips_tree->set_column_title(3,"Loop");
|
|
|
|
+ clips_base =clips_tree->create_item(0);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ setup_clips(Array());
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ filters = memnew( TextEdit );
|
|
|
|
+ tab->add_child(filters);
|
|
|
|
+ filters->set_name("Filters");
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
- add_margin_child("Animation Options",flags,true);
|
|
|
|
|
|
|
|
|
|
+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_filter(const String& p_filter) {
|
|
|
|
+
|
|
|
|
+ filters->set_text(p_filter);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+String EditorImportAnimationOptions::get_filter() const {
|
|
|
|
+
|
|
|
|
+ return filters->get_text();
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -413,7 +649,12 @@ void EditorSceneImportDialog::_import(bool p_and_open) {
|
|
rim->set_option("texture_format",texture_options->get_format());
|
|
rim->set_option("texture_format",texture_options->get_format());
|
|
rim->set_option("texture_quality",texture_options->get_quality());
|
|
rim->set_option("texture_quality",texture_options->get_quality());
|
|
rim->set_option("animation_flags",animation_options->get_flags());
|
|
rim->set_option("animation_flags",animation_options->get_flags());
|
|
|
|
+ rim->set_option("animation_bake_fps",animation_options->get_fps());
|
|
|
|
+ rim->set_option("animation_filters",animation_options->get_filter());
|
|
|
|
+ rim->set_option("animation_clips",animation_options->get_clips());
|
|
rim->set_option("post_import_script",script_path->get_text()!=String()?EditorImportPlugin::validate_source_path(script_path->get_text()):String());
|
|
rim->set_option("post_import_script",script_path->get_text()!=String()?EditorImportPlugin::validate_source_path(script_path->get_text()):String());
|
|
|
|
+ rim->set_option("import_this_time",this_import->get_selected());
|
|
|
|
+ rim->set_option("import_next_time",next_import->get_selected());
|
|
rim->set_option("reimport",true);
|
|
rim->set_option("reimport",true);
|
|
|
|
|
|
List<String> missing;
|
|
List<String> missing;
|
|
@@ -526,7 +767,7 @@ void EditorSceneImportDialog::_browse_script() {
|
|
|
|
|
|
void EditorSceneImportDialog::popup_import(const String &p_from) {
|
|
void EditorSceneImportDialog::popup_import(const String &p_from) {
|
|
|
|
|
|
- popup_centered(Size2(700,500));
|
|
|
|
|
|
+ popup_centered(Size2(750,550));
|
|
if (p_from!="") {
|
|
if (p_from!="") {
|
|
Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_from);
|
|
Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_from);
|
|
if (rimd.is_null())
|
|
if (rimd.is_null())
|
|
@@ -544,7 +785,17 @@ void EditorSceneImportDialog::popup_import(const String &p_from) {
|
|
texture_options->set_format(EditorTextureImportPlugin::ImageFormat(int(rimd->get_option("texture_format"))));
|
|
texture_options->set_format(EditorTextureImportPlugin::ImageFormat(int(rimd->get_option("texture_format"))));
|
|
texture_options->set_quality(rimd->get_option("texture_quality"));
|
|
texture_options->set_quality(rimd->get_option("texture_quality"));
|
|
animation_options->set_flags(rimd->get_option("animation_flags"));
|
|
animation_options->set_flags(rimd->get_option("animation_flags"));
|
|
|
|
+ if (rimd->has_option("animation_clips"))
|
|
|
|
+ animation_options->setup_clips(rimd->get_option("animation_clips"));
|
|
|
|
+ if (rimd->has_option("animation_filters"))
|
|
|
|
+ animation_options->set_filter(rimd->get_option("animation_filters"));
|
|
|
|
+ if (rimd->has_option("animation_bake_fps"))
|
|
|
|
+ animation_options->set_fps(rimd->get_option("animation_bake_fps"));
|
|
script_path->set_text(rimd->get_option("post_import_script"));
|
|
script_path->set_text(rimd->get_option("post_import_script"));
|
|
|
|
+ if (rimd->has_option("import_this_time"))
|
|
|
|
+ this_import->select(rimd->get_option("import_this_time"));
|
|
|
|
+ if (rimd->has_option("import_next_time"))
|
|
|
|
+ next_import->select(rimd->get_option("import_next_time"));
|
|
|
|
|
|
save_path->set_text(p_from.get_base_dir());
|
|
save_path->set_text(p_from.get_base_dir());
|
|
import_path->set_text(EditorImportPlugin::expand_source_path(rimd->get_source_path(0)));
|
|
import_path->set_text(EditorImportPlugin::expand_source_path(rimd->get_source_path(0)));
|
|
@@ -619,7 +870,7 @@ void EditorSceneImportDialog::_bind_methods() {
|
|
ObjectTypeDB::bind_method("_choose_file",&EditorSceneImportDialog::_choose_file);
|
|
ObjectTypeDB::bind_method("_choose_file",&EditorSceneImportDialog::_choose_file);
|
|
ObjectTypeDB::bind_method("_choose_save_file",&EditorSceneImportDialog::_choose_save_file);
|
|
ObjectTypeDB::bind_method("_choose_save_file",&EditorSceneImportDialog::_choose_save_file);
|
|
ObjectTypeDB::bind_method("_choose_script",&EditorSceneImportDialog::_choose_script);
|
|
ObjectTypeDB::bind_method("_choose_script",&EditorSceneImportDialog::_choose_script);
|
|
- ObjectTypeDB::bind_method("_import",&EditorSceneImportDialog::_import);
|
|
|
|
|
|
+ ObjectTypeDB::bind_method("_import",&EditorSceneImportDialog::_import,DEFVAL(false));
|
|
ObjectTypeDB::bind_method("_browse",&EditorSceneImportDialog::_browse);
|
|
ObjectTypeDB::bind_method("_browse",&EditorSceneImportDialog::_browse);
|
|
ObjectTypeDB::bind_method("_browse_target",&EditorSceneImportDialog::_browse_target);
|
|
ObjectTypeDB::bind_method("_browse_target",&EditorSceneImportDialog::_browse_target);
|
|
ObjectTypeDB::bind_method("_browse_script",&EditorSceneImportDialog::_browse_script);
|
|
ObjectTypeDB::bind_method("_browse_script",&EditorSceneImportDialog::_browse_script);
|
|
@@ -792,6 +1043,20 @@ EditorSceneImportDialog::EditorSceneImportDialog(EditorNode *p_editor, EditorSce
|
|
error_dialog->get_ok()->set_text("Accept");
|
|
error_dialog->get_ok()->set_text("Accept");
|
|
// error_dialog->get_cancel()->hide();
|
|
// error_dialog->get_cancel()->hide();
|
|
|
|
|
|
|
|
+ this_import = memnew( OptionButton );
|
|
|
|
+ this_import->add_item("Overwrite Existing Scene");
|
|
|
|
+ this_import->add_item("Owerwrite Existing, Keep Materials");
|
|
|
|
+ this_import->add_item("Keep Existing, Merge with New");
|
|
|
|
+ this_import->add_item("Keep Existing, Ignore New");
|
|
|
|
+ vbc->add_margin_child("This Time:",this_import);
|
|
|
|
+
|
|
|
|
+ next_import = memnew( OptionButton );
|
|
|
|
+ next_import->add_item("Overwrite Existing Scene");
|
|
|
|
+ next_import->add_item("Owerwrite Existing, Keep Materials");
|
|
|
|
+ next_import->add_item("Keep Existing, Merge with New");
|
|
|
|
+ next_import->add_item("Keep Existing, Ignore New");
|
|
|
|
+ vbc->add_margin_child("Next Time:",next_import);
|
|
|
|
+
|
|
set_hide_on_ok(false);
|
|
set_hide_on_ok(false);
|
|
|
|
|
|
GLOBAL_DEF("import/shared_textures","res://");
|
|
GLOBAL_DEF("import/shared_textures","res://");
|
|
@@ -814,7 +1079,7 @@ EditorSceneImportDialog::EditorSceneImportDialog(EditorNode *p_editor, EditorSce
|
|
animation_options = memnew( EditorImportAnimationOptions );
|
|
animation_options = memnew( EditorImportAnimationOptions );
|
|
ovb->add_child(animation_options);
|
|
ovb->add_child(animation_options);
|
|
animation_options->set_v_size_flags(SIZE_EXPAND_FILL);
|
|
animation_options->set_v_size_flags(SIZE_EXPAND_FILL);
|
|
- animation_options->set_flags(EditorSceneAnimationImportPlugin::ANIMATION_DETECT_LOOP|EditorSceneAnimationImportPlugin::ANIMATION_KEEP_VALUE_TRACKS|EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE|EditorSceneAnimationImportPlugin::ANIMATION_FORCE_TRACKS_IN_ALL_BONES);
|
|
|
|
|
|
+ animation_options->set_flags(EditorSceneAnimationImportPlugin::ANIMATION_DETECT_LOOP|EditorSceneAnimationImportPlugin::ANIMATION_KEEP_VALUE_TRACKS|EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE|EditorSceneAnimationImportPlugin::ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS);
|
|
|
|
|
|
|
|
|
|
confirm_import = memnew( ConfirmationDialog );
|
|
confirm_import = memnew( ConfirmationDialog );
|
|
@@ -1815,6 +2080,79 @@ void EditorSceneImportPlugin::_merge_scenes(Node *p_node,Node *p_imported) {
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+void EditorSceneImportPlugin::_scan_materials(Node*p_base,Node *p_node,Map<String,Ref<Material> > &mesh_materials,Map<String,Ref<Material> >& override_materials) {
|
|
|
|
+
|
|
|
|
+ if (!p_base && p_node->get_owner()!=p_base)
|
|
|
|
+ return;
|
|
|
|
+ MeshInstance *mi=p_node->cast_to<MeshInstance>();
|
|
|
|
+
|
|
|
|
+ if (mi) {
|
|
|
|
+ if (mi->get_material_override().is_valid()) {
|
|
|
|
+ String path = p_base->get_path_to(p_node);
|
|
|
|
+ override_materials[path]=mi->get_material_override();
|
|
|
|
+ }
|
|
|
|
+ Ref<Mesh> mesh = mi->get_mesh();
|
|
|
|
+ if (mesh.is_valid()) {
|
|
|
|
+
|
|
|
|
+ for(int i=0;i<mesh->get_surface_count();i++) {
|
|
|
|
+
|
|
|
|
+ String name = mesh->get_name()+":"+mesh->surface_get_name(i);
|
|
|
|
+ if (!mesh_materials.has(name)) {
|
|
|
|
+ mesh_materials[name]=mesh->surface_get_material(i);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for(int i=0;i<p_node->get_child_count();i++) {
|
|
|
|
+ _scan_materials(p_base,p_node->get_child(i),mesh_materials,override_materials);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+void EditorSceneImportPlugin::_apply_materials(Node*p_base,Node *p_node,Map<String,Ref<Material> > &mesh_materials,Map<String,Ref<Material> >& override_materials,Set<Ref<Mesh> >& meshes_processed) {
|
|
|
|
+
|
|
|
|
+ if (!p_base && p_node->get_owner()!=p_base)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ MeshInstance *mi=p_node->cast_to<MeshInstance>();
|
|
|
|
+
|
|
|
|
+ if (mi) {
|
|
|
|
+
|
|
|
|
+ String path = p_base->get_path_to(p_node);
|
|
|
|
+ if (override_materials.has(path))
|
|
|
|
+ mi->set_material_override(override_materials[path]);
|
|
|
|
+
|
|
|
|
+ Ref<Mesh> mesh = mi->get_mesh();
|
|
|
|
+ if (mesh.is_valid() && !meshes_processed.has(mesh)) {
|
|
|
|
+ meshes_processed.insert(mesh);
|
|
|
|
+ for(int i=0;i<mesh->get_surface_count();i++) {
|
|
|
|
+
|
|
|
|
+ String name = mesh->get_name()+":"+mesh->surface_get_name(i);
|
|
|
|
+ if (mesh_materials.has(name)) {
|
|
|
|
+
|
|
|
|
+ Ref<Material> mat = mesh_materials[name];
|
|
|
|
+ mesh->surface_set_material(i,mat);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for(int i=0;i<p_node->get_child_count();i++) {
|
|
|
|
+ _apply_materials(p_base,p_node->get_child(i),mesh_materials,override_materials,meshes_processed);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void EditorSceneImportPlugin::_merge_materials(Node *p_node,Node *p_imported) {
|
|
|
|
+
|
|
|
|
+ Map<String,Ref<Material> > mesh_materials;
|
|
|
|
+ Map<String,Ref<Material> > override_materials;
|
|
|
|
+
|
|
|
|
+ _scan_materials(p_node,p_node,mesh_materials,override_materials);
|
|
|
|
+ Set<Ref<Mesh> > mp;
|
|
|
|
+ _apply_materials(p_imported,p_imported,mesh_materials,override_materials,mp);
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
|
|
#if 0
|
|
#if 0
|
|
|
|
|
|
@@ -1882,14 +2220,20 @@ Error EditorSceneImportPlugin::import1(const Ref<ResourceImportMetadata>& p_from
|
|
|
|
|
|
int animation_flags=p_from->get_option("animation_flags");
|
|
int animation_flags=p_from->get_option("animation_flags");
|
|
int scene_flags = from->get_option("flags");
|
|
int scene_flags = from->get_option("flags");
|
|
|
|
+ int fps = 24;
|
|
|
|
+ if (from->has_option("animation_bake_fps"))
|
|
|
|
+ fps=from->get_option("animation_bake_fps");
|
|
|
|
+ Array clips;
|
|
|
|
+ if (from->has_option("animation_clips"))
|
|
|
|
+ clips=from->get_option("animation_clips");
|
|
|
|
|
|
uint32_t import_flags=0;
|
|
uint32_t import_flags=0;
|
|
if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_DETECT_LOOP)
|
|
if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_DETECT_LOOP)
|
|
import_flags|=EditorSceneImporter::IMPORT_ANIMATION_DETECT_LOOP;
|
|
import_flags|=EditorSceneImporter::IMPORT_ANIMATION_DETECT_LOOP;
|
|
if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE)
|
|
if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE)
|
|
import_flags|=EditorSceneImporter::IMPORT_ANIMATION_OPTIMIZE;
|
|
import_flags|=EditorSceneImporter::IMPORT_ANIMATION_OPTIMIZE;
|
|
- if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_FORCE_TRACKS_IN_ALL_BONES)
|
|
|
|
- import_flags|=EditorSceneImporter::IMPORT_ANIMATION_FORCE_TRACKS_IN_ALL_BONES;
|
|
|
|
|
|
+ if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS)
|
|
|
|
+ import_flags|=EditorSceneImporter::IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS;
|
|
if (scene_flags&SCENE_FLAG_IMPORT_ANIMATIONS)
|
|
if (scene_flags&SCENE_FLAG_IMPORT_ANIMATIONS)
|
|
import_flags|=EditorSceneImporter::IMPORT_ANIMATION;
|
|
import_flags|=EditorSceneImporter::IMPORT_ANIMATION;
|
|
//if (scene_flags&SCENE_FLAG_FAIL_ON_MISSING_IMAGES)
|
|
//if (scene_flags&SCENE_FLAG_FAIL_ON_MISSING_IMAGES)
|
|
@@ -1902,7 +2246,7 @@ Error EditorSceneImportPlugin::import1(const Ref<ResourceImportMetadata>& p_from
|
|
|
|
|
|
|
|
|
|
Error err=OK;
|
|
Error err=OK;
|
|
- Node *scene = importer->import_scene(src_path,import_flags,r_missing,&err);
|
|
|
|
|
|
+ Node *scene = importer->import_scene(src_path,import_flags,fps,r_missing,&err);
|
|
if (!scene || err!=OK) {
|
|
if (!scene || err!=OK) {
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
@@ -1913,19 +2257,231 @@ Error EditorSceneImportPlugin::import1(const Ref<ResourceImportMetadata>& p_from
|
|
return OK;
|
|
return OK;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+void EditorSceneImportPlugin::_create_clips(Node *scene, const Array& p_clips,bool p_bake_all) {
|
|
|
|
+
|
|
|
|
+ if (!scene->has_node(String("AnimationPlayer")))
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ Node* n = scene->get_node(String("AnimationPlayer"));
|
|
|
|
+ ERR_FAIL_COND(!n);
|
|
|
|
+ AnimationPlayer *anim = n->cast_to<AnimationPlayer>();
|
|
|
|
+ ERR_FAIL_COND(!anim);
|
|
|
|
+
|
|
|
|
+ if (!anim->has_animation("default"))
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ Ref<Animation> default_anim = anim->get_animation("default");
|
|
|
|
+
|
|
|
|
+ for(int i=0;i<p_clips.size();i+=4) {
|
|
|
|
+
|
|
|
|
+ String name = p_clips[i];
|
|
|
|
+ float from=p_clips[i+1];
|
|
|
|
+ float to=p_clips[i+2];
|
|
|
|
+ bool loop=p_clips[i+3];
|
|
|
|
+ if (from>=to)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ Ref<Animation> new_anim = memnew( Animation );
|
|
|
|
+
|
|
|
|
+ for(int j=0;j<default_anim->get_track_count();j++) {
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ List<float> keys;
|
|
|
|
+ int kc = default_anim->track_get_key_count(j);
|
|
|
|
+ int dtrack=-1;
|
|
|
|
+ for(int k=0;k<kc;k++) {
|
|
|
|
+
|
|
|
|
+ float kt = default_anim->track_get_key_time(j,k);
|
|
|
|
+ if (kt>=from && kt<to) {
|
|
|
|
+
|
|
|
|
+ //found a key within range, so create track
|
|
|
|
+ if (dtrack==-1) {
|
|
|
|
+ new_anim->add_track(default_anim->track_get_type(j));
|
|
|
|
+ dtrack = new_anim->get_track_count()-1;
|
|
|
|
+ new_anim->track_set_path(dtrack,default_anim->track_get_path(j));
|
|
|
|
+
|
|
|
|
+ if (kt>(from+0.01) && k>0) {
|
|
|
|
+
|
|
|
|
+ if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
|
|
|
|
+ Quat q;
|
|
|
|
+ Vector3 p;
|
|
|
|
+ Vector3 s;
|
|
|
|
+ default_anim->transform_track_interpolate(j,from,&p,&q,&s);
|
|
|
|
+ new_anim->transform_track_insert_key(dtrack,0,p,q,s);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
|
|
|
|
+ Quat q;
|
|
|
|
+ Vector3 p;
|
|
|
|
+ Vector3 s;
|
|
|
|
+ default_anim->transform_track_get_key(j,k,&p,&q,&s);
|
|
|
|
+ new_anim->transform_track_insert_key(dtrack,kt-from,p,q,s);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (dtrack!=-1 && kt>=to) {
|
|
|
|
+
|
|
|
|
+ if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
|
|
|
|
+ Quat q;
|
|
|
|
+ Vector3 p;
|
|
|
|
+ Vector3 s;
|
|
|
|
+ default_anim->transform_track_interpolate(j,to,&p,&q,&s);
|
|
|
|
+ new_anim->transform_track_insert_key(dtrack,to-from,p,q,s);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (dtrack==-1 && p_bake_all) {
|
|
|
|
+ new_anim->add_track(default_anim->track_get_type(j));
|
|
|
|
+ dtrack = new_anim->get_track_count()-1;
|
|
|
|
+ new_anim->track_set_path(dtrack,default_anim->track_get_path(j));
|
|
|
|
+ if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ Quat q;
|
|
|
|
+ Vector3 p;
|
|
|
|
+ Vector3 s;
|
|
|
|
+ default_anim->transform_track_interpolate(j,from,&p,&q,&s);
|
|
|
|
+ new_anim->transform_track_insert_key(dtrack,0,p,q,s);
|
|
|
|
+ default_anim->transform_track_interpolate(j,to,&p,&q,&s);
|
|
|
|
+ new_anim->transform_track_insert_key(dtrack,to-from,p,q,s);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ new_anim->set_loop(loop);
|
|
|
|
+ new_anim->set_length(to-from);
|
|
|
|
+ anim->add_animation(name,new_anim);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ anim->remove_animation("default"); //remove default (no longer needed)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void EditorSceneImportPlugin::_filter_tracks(Node *scene, const String& p_text) {
|
|
|
|
+
|
|
|
|
+ if (!scene->has_node(String("AnimationPlayer")))
|
|
|
|
+ return;
|
|
|
|
+ Node* n = scene->get_node(String("AnimationPlayer"));
|
|
|
|
+ ERR_FAIL_COND(!n);
|
|
|
|
+ AnimationPlayer *anim = n->cast_to<AnimationPlayer>();
|
|
|
|
+ ERR_FAIL_COND(!anim);
|
|
|
|
+
|
|
|
|
+ Vector<String> strings = p_text.split("\n");
|
|
|
|
+ for(int i=0;i<strings.size();i++) {
|
|
|
|
+
|
|
|
|
+ strings[i]=strings[i].strip_edges();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ List<StringName> anim_names;
|
|
|
|
+ anim->get_animation_list(&anim_names);
|
|
|
|
+ Set<String> keep;
|
|
|
|
+ for(List<StringName>::Element *E=anim_names.front();E;E=E->next()) {
|
|
|
|
+
|
|
|
|
+ String name = E->get();
|
|
|
|
+ bool valid_for_this=false;
|
|
|
|
+
|
|
|
|
+ for(int i=0;i<strings.size();i++) {
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if (strings[i].begins_with("@")) {
|
|
|
|
+
|
|
|
|
+ valid_for_this=false;
|
|
|
|
+ keep.clear();
|
|
|
|
+
|
|
|
|
+ Vector<String> filters=strings[i].substr(1,strings[i].length()).split(",");
|
|
|
|
+ for(int j=0;j<filters.size();j++) {
|
|
|
|
+
|
|
|
|
+ String fname = filters[i].strip_edges();
|
|
|
|
+ if (fname=="")
|
|
|
|
+ continue;
|
|
|
|
+ int fc = fname[0];
|
|
|
|
+ bool plus;
|
|
|
|
+ if (fc=='+')
|
|
|
|
+ plus=true;
|
|
|
|
+ else if (fc=='-')
|
|
|
|
+ plus=false;
|
|
|
|
+ else
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ String filter=fname.substr(1,fname.length()).strip_edges();
|
|
|
|
+
|
|
|
|
+ if (!name.matchn(filter))
|
|
|
|
+ continue;
|
|
|
|
+ valid_for_this=plus;
|
|
|
|
+ }
|
|
|
|
+ } else if (valid_for_this) {
|
|
|
|
+
|
|
|
|
+ Ref<Animation> a = anim->get_animation(name);
|
|
|
|
+ if (!a.is_valid())
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ for(int j=0;j<a->get_track_count();j++) {
|
|
|
|
+
|
|
|
|
+ String path = a->track_get_path(j);
|
|
|
|
+
|
|
|
|
+ String tname = strings[i];
|
|
|
|
+ if (tname=="")
|
|
|
|
+ continue;
|
|
|
|
+ int fc = tname[0];
|
|
|
|
+ bool plus;
|
|
|
|
+ if (fc=='+')
|
|
|
|
+ plus=true;
|
|
|
|
+ else if (fc=='-')
|
|
|
|
+ plus=false;
|
|
|
|
+ else
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ String filter=tname.substr(1,tname.length()).strip_edges();
|
|
|
|
+
|
|
|
|
+ if (!path.matchn(filter))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ if (plus)
|
|
|
|
+ keep.insert(path);
|
|
|
|
+ else if (!keep.has(path)) {
|
|
|
|
+ a->remove_track(j);
|
|
|
|
+ j--;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, const Ref<ResourceImportMetadata>& p_from) {
|
|
Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, const Ref<ResourceImportMetadata>& p_from) {
|
|
|
|
|
|
Error err=OK;
|
|
Error err=OK;
|
|
Ref<ResourceImportMetadata> from=p_from;
|
|
Ref<ResourceImportMetadata> from=p_from;
|
|
String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0));
|
|
String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0));
|
|
int animation_flags=p_from->get_option("animation_flags");
|
|
int animation_flags=p_from->get_option("animation_flags");
|
|
|
|
+ Array animation_clips = p_from->get_option("animation_clips");
|
|
|
|
+ String animation_filter = p_from->get_option("animation_filters");
|
|
int scene_flags = from->get_option("flags");
|
|
int scene_flags = from->get_option("flags");
|
|
|
|
|
|
EditorProgress progress("import","Import Scene",104);
|
|
EditorProgress progress("import","Import Scene",104);
|
|
progress.step("Importing Scene..",2);
|
|
progress.step("Importing Scene..",2);
|
|
|
|
|
|
|
|
|
|
- bool merge = !bool(from->get_option("reimport"));
|
|
|
|
|
|
+ bool reimport = bool(from->get_option("reimport"));
|
|
|
|
+ int this_time_action = from->get_option("import_this_time");
|
|
|
|
+ int next_time_action = from->get_option("import_next_time");
|
|
|
|
+
|
|
|
|
+ int import_action = reimport?this_time_action:next_time_action;
|
|
|
|
|
|
from->set_source_md5(0,FileAccess::get_md5(src_path));
|
|
from->set_source_md5(0,FileAccess::get_md5(src_path));
|
|
from->set_editor(get_name());
|
|
from->set_editor(get_name());
|
|
@@ -1940,6 +2496,11 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c
|
|
Map< Ref<ImageTexture>,TextureRole > imagemap;
|
|
Map< Ref<ImageTexture>,TextureRole > imagemap;
|
|
|
|
|
|
scene=_fix_node(scene,scene,collision_map,scene_flags,imagemap);
|
|
scene=_fix_node(scene,scene,collision_map,scene_flags,imagemap);
|
|
|
|
+ if (animation_clips.size())
|
|
|
|
+ _create_clips(scene,animation_clips,animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS);
|
|
|
|
+
|
|
|
|
+ _filter_tracks(scene,animation_filter);
|
|
|
|
+
|
|
|
|
|
|
|
|
|
|
/// BEFORE ANYTHING, RUN SCRIPT
|
|
/// BEFORE ANYTHING, RUN SCRIPT
|
|
@@ -2063,7 +2624,7 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c
|
|
/// BEFORE SAVING - MERGE
|
|
/// BEFORE SAVING - MERGE
|
|
|
|
|
|
|
|
|
|
- if (merge) {
|
|
|
|
|
|
+ if (import_action!=SCENE_UPDATE_REPLACE_WITH_NEW) {
|
|
|
|
|
|
|
|
|
|
progress.step("Merging..",103);
|
|
progress.step("Merging..",103);
|
|
@@ -2082,10 +2643,30 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c
|
|
|
|
|
|
if (existing) {
|
|
if (existing) {
|
|
|
|
|
|
- _merge_scenes(existing,scene);
|
|
|
|
|
|
|
|
- memdelete(scene);
|
|
|
|
- scene=existing;
|
|
|
|
|
|
+ switch(import_action) {
|
|
|
|
+
|
|
|
|
+ case SCENE_UPDATE_REPLACE_WITH_NEW: break;
|
|
|
|
+ case SCENE_UPDATE_REPLACE_WITH_NEW_KEEP_MATERIALS: {
|
|
|
|
+
|
|
|
|
+ _merge_materials(existing,scene);
|
|
|
|
+ memdelete(existing);
|
|
|
|
+
|
|
|
|
+ } break;
|
|
|
|
+ case SCENE_UPDATE_KEEP_OLD_MERGE_CHANGES: {
|
|
|
|
+
|
|
|
|
+ _merge_scenes(existing,scene);
|
|
|
|
+ memdelete(scene);
|
|
|
|
+ scene=existing;
|
|
|
|
+
|
|
|
|
+ } break;
|
|
|
|
+ case SCENE_UPDATE_KEEP_OLD: {
|
|
|
|
+
|
|
|
|
+ memdelete(scene);
|
|
|
|
+ scene=existing;
|
|
|
|
+ } break;
|
|
|
|
+ }
|
|
|
|
+
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|