-Added options for scene import plugin to keep materials and user-added tracks to animations, please test! closes #4425

This commit is contained in:
Juan Linietsky 2016-06-20 00:19:04 -03:00
parent eff0bd2d48
commit 0db02f26b6
5 changed files with 201 additions and 3 deletions

View File

@ -74,6 +74,8 @@ bool Animation::_set(const StringName& p_name, const Variant& p_value) {
track_set_path(track,p_value);
else if (what=="interp")
track_set_interpolation_type(track,InterpolationType(p_value.operator int()));
else if (what=="imported")
track_set_imported(track,p_value);
else if (what == "keys" || what=="key_values") {
if (track_get_type(track)==TYPE_TRANSFORM) {
@ -171,6 +173,7 @@ bool Animation::_set(const StringName& p_name, const Variant& p_value) {
}
DVector<float> times=d["times"];
Array values=d["values"];
@ -290,6 +293,8 @@ bool Animation::_get(const StringName& p_name,Variant &r_ret) const {
r_ret=track_get_path(track);
else if (what=="interp")
r_ret = track_get_interpolation_type(track);
else if (what=="imported")
r_ret = track_is_imported(track);
else if (what=="keys") {
if (track_get_type(track)==TYPE_TRANSFORM) {
@ -437,6 +442,7 @@ void Animation::_get_property_list( List<PropertyInfo> *p_list) const {
p_list->push_back( PropertyInfo( Variant::STRING, "tracks/"+itos(i)+"/type", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
p_list->push_back( PropertyInfo( Variant::NODE_PATH, "tracks/"+itos(i)+"/path", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
p_list->push_back( PropertyInfo( Variant::INT, "tracks/"+itos(i)+"/interp", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
p_list->push_back( PropertyInfo( Variant::BOOL, "tracks/"+itos(i)+"/imported", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
p_list->push_back( PropertyInfo( Variant::ARRAY, "tracks/"+itos(i)+"/keys", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
}
}
@ -1648,6 +1654,20 @@ void Animation::track_move_up(int p_track) {
emit_changed();
}
void Animation::track_set_imported(int p_track,bool p_imported) {
ERR_FAIL_INDEX(p_track,tracks.size());
tracks[p_track]->imported=p_imported;
}
bool Animation::track_is_imported(int p_track) const{
ERR_FAIL_INDEX_V(p_track,tracks.size(),false);
return tracks[p_track]->imported;
}
void Animation::track_move_down(int p_track) {
if (p_track>0 && p_track<tracks.size()) {
@ -1682,6 +1702,10 @@ void Animation::_bind_methods() {
ObjectTypeDB::bind_method(_MD("track_move_up","idx"),&Animation::track_move_up);
ObjectTypeDB::bind_method(_MD("track_move_down","idx"),&Animation::track_move_down);
ObjectTypeDB::bind_method(_MD("track_set_imported","idx","imported"),&Animation::track_set_imported);
ObjectTypeDB::bind_method(_MD("track_is_imported","idx"),&Animation::track_is_imported);
ObjectTypeDB::bind_method(_MD("transform_track_insert_key","idx","time","loc","rot","scale"),&Animation::transform_track_insert_key);
ObjectTypeDB::bind_method(_MD("track_insert_key","idx","time","key","transition"),&Animation::track_insert_key,DEFVAL(1));
ObjectTypeDB::bind_method(_MD("track_remove_key","idx","key_idx"),&Animation::track_remove_key);

View File

@ -72,7 +72,8 @@ private:
TrackType type;
InterpolationType interpolation;
NodePath path; // path to something
Track() { interpolation=INTERPOLATION_LINEAR; }
bool imported;
Track() { interpolation=INTERPOLATION_LINEAR; imported=false;}
virtual ~Track() {}
};
@ -241,6 +242,9 @@ public:
void track_move_up(int p_track);
void track_move_down(int p_track);
void track_set_imported(int p_track,bool p_imported);
bool track_is_imported(int p_track) const;
int transform_track_insert_key(int p_track, float p_time, const Vector3 p_loc, const Quat& p_rot=Quat(), const Vector3& p_scale=Vector3());
void track_insert_key(int p_track, float p_time, const Variant& p_key, float p_transition=1);
void track_set_key_transition(int p_track, int p_key_idx,float p_transition);

View File

@ -2077,6 +2077,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
animation->add_track(Animation::TYPE_TRANSFORM);
int track = animation->get_track_count() -1;
animation->track_set_path( track , path );
animation->track_set_imported( track , true ); //helps merging later
Vector<float> snapshots = base_snapshots;
@ -2229,6 +2230,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
animation->add_track(Animation::TYPE_TRANSFORM);
int track = animation->get_track_count() -1;
animation->track_set_path( track , path );
animation->track_set_imported( track , true ); //helps merging later
Transform xform = cn->compute_transform(collada);
@ -2284,8 +2286,11 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
animation->add_track(Animation::TYPE_VALUE);
int track = animation->get_track_count() -1;
path = path +":"+at.param;
animation->track_set_path( track , path );
animation->track_set_imported( track , true ); //helps merging later
for(int i=0;i<at.keys.size();i++) {
@ -2376,6 +2381,7 @@ Node* EditorSceneImporterCollada::import_scene(const String& p_path, uint32_t p_
state.create_animations(p_flags&IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS);
AnimationPlayer *ap = memnew( AnimationPlayer );
ap->set_name("animations");
for(int i=0;i<state.animations.size();i++) {
String name;
if (state.animations[i]->get_name()=="")

View File

@ -1069,11 +1069,13 @@ const EditorSceneImportDialog::FlagInfo EditorSceneImportDialog::scene_flag_name
{EditorSceneImportPlugin::SCENE_FLAG_IMPORT_ANIMATIONS,("Actions"),"Import Animations",true},
{EditorSceneImportPlugin::SCENE_FLAG_COMPRESS_GEOMETRY,("Actions"),"Compress Geometry",false},
{EditorSceneImportPlugin::SCENE_FLAG_GENERATE_TANGENT_ARRAYS,("Actions"),"Force Generation of Tangent Arrays",false},
{EditorSceneImportPlugin::SCENE_FLAG_DETECT_ALPHA,("Materials"),"Set Alpha in Materials (-alpha)",true},
{EditorSceneImportPlugin::SCENE_FLAG_DETECT_VCOLOR,("Materials"),"Set Vert. Color in Materials (-vcol)",true},
{EditorSceneImportPlugin::SCENE_FLAG_LINEARIZE_DIFFUSE_TEXTURES,("Actions"),"SRGB->Linear Of Diffuse Textures",false},
{EditorSceneImportPlugin::SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY,("Actions"),"Convert Normal Maps to XY",true},
{EditorSceneImportPlugin::SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS,("Actions"),"Set Material Lightmap to UV2 if Tex2Array Exists",true},
{EditorSceneImportPlugin::SCENE_FLAG_MERGE_KEEP_MATERIALS,("Merge"),"Keep Materials after first import (delete them for re-import).",true},
{EditorSceneImportPlugin::SCENE_FLAG_MERGE_KEEP_EXTRA_ANIM_TRACKS,("Merge"),"Keep user-added Animation tracks.",true},
{EditorSceneImportPlugin::SCENE_FLAG_DETECT_ALPHA,("Materials"),"Set Alpha in Materials (-alpha)",true},
{EditorSceneImportPlugin::SCENE_FLAG_DETECT_VCOLOR,("Materials"),"Set Vert. Color in Materials (-vcol)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_COLLISIONS,("Create"),"Create Collisions and/or Rigid Bodies (-col,-colonly,-rigid)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_PORTALS,("Create"),"Create Portals (-portal)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_ROOMS,("Create"),"Create Rooms (-room)",true},
@ -2455,6 +2457,138 @@ void EditorSceneImportPlugin::_optimize_animations(Node *scene, float p_max_lin_
}
void EditorSceneImportPlugin::_find_resources_to_merge(Node *scene, Node *node, bool p_merge_material, Map<String, Ref<Material> > &materials, bool p_merge_anims, Map<String,Ref<Animation> >& merged_anims,Set<Ref<Mesh> > &tested_meshes) {
if (node->get_owner()!=scene)
return;
String path = scene->get_path_to(node);
if (p_merge_anims && node->cast_to<AnimationPlayer>()) {
AnimationPlayer *ap = node->cast_to<AnimationPlayer>();
List<StringName> anims;
ap->get_animation_list(&anims);
for (List<StringName>::Element *E=anims.front();E;E=E->next()) {
Ref<Animation> anim = ap->get_animation(E->get());
Ref<Animation> clone;
bool has_user_tracks=false;
for(int i=0;i<anim->get_track_count();i++) {
if (!anim->track_is_imported(i)) {
has_user_tracks=true;
break;
}
}
if (has_user_tracks) {
clone = anim->duplicate();
for(int i=0;i<clone->get_track_count();i++) {
if (clone->track_is_imported(i)) {
clone->remove_track(i);
i--;
}
}
merged_anims[path+"::"+String(E->get())]=clone;
}
}
}
if (p_merge_material && node->cast_to<MeshInstance>()) {
MeshInstance *mi=node->cast_to<MeshInstance>();
Ref<Mesh> mesh = mi->get_mesh();
if (mesh.is_valid() && mesh->get_name()!=String() && !tested_meshes.has(mesh)) {
for(int i=0;i<mesh->get_surface_count();i++) {
Ref<Material> material = mesh->surface_get_material(i);
materials[mesh->get_name()+":surf:"+mesh->surface_get_name(i)]=material;
}
tested_meshes.insert(mesh);
}
}
for(int i=0;i<node->get_child_count();i++) {
_find_resources_to_merge(scene,node->get_child(i),p_merge_material,materials,p_merge_anims,merged_anims,tested_meshes);
}
}
void EditorSceneImportPlugin::_merge_found_resources(Node *scene, Node *node, bool p_merge_material, const Map<String, Ref<Material> > &materials, bool p_merge_anims, const Map<String,Ref<Animation> >& merged_anims, Set<Ref<Mesh> > &tested_meshes) {
if (node->get_owner()!=scene)
return;
String path = scene->get_path_to(node);
if (node->cast_to<AnimationPlayer>()) {
AnimationPlayer *ap = node->cast_to<AnimationPlayer>();
List<StringName> anims;
ap->get_animation_list(&anims);
for (List<StringName>::Element *E=anims.front();E;E=E->next()) {
Ref<Animation> anim = ap->get_animation(E->get());
String anim_path = path+"::"+String(E->get());
if (merged_anims.has(anim_path)) {
Ref<Animation> user_tracks = merged_anims[anim_path];
for(int i=0;i<user_tracks->get_track_count();i++) {
int idx = anim->get_track_count();
anim->add_track(user_tracks->track_get_type(i));
anim->track_set_path(idx,user_tracks->track_get_path(i));
anim->track_set_interpolation_type(idx,user_tracks->track_get_interpolation_type(i));
for(int j=0;j<user_tracks->track_get_key_count(i);j++) {
float ofs = user_tracks->track_get_key_time(i,j);
float trans = user_tracks->track_get_key_transition(i,j);
Variant value = user_tracks->track_get_key_value(i,j);
anim->track_insert_key(idx,ofs,value,trans);
}
}
}
}
}
if (node->cast_to<MeshInstance>()) {
MeshInstance *mi=node->cast_to<MeshInstance>();
Ref<Mesh> mesh = mi->get_mesh();
if (mesh.is_valid() && mesh->get_name()!=String() && !tested_meshes.has(mesh)) {
for(int i=0;i<mesh->get_surface_count();i++) {
String sname = mesh->get_name()+":surf:"+mesh->surface_get_name(i);
if (materials.has(sname)) {
mesh->surface_set_material(i,materials[sname]);
}
}
tested_meshes.insert(mesh);
}
}
for(int i=0;i<node->get_child_count();i++) {
_merge_found_resources(scene,node->get_child(i),p_merge_material,materials,p_merge_anims,merged_anims,tested_meshes);
}
}
Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, const Ref<ResourceImportMetadata>& p_from) {
Error err=OK;
@ -2506,6 +2640,28 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c
_filter_tracks(scene,animation_filter);
if (scene_flags&(SCENE_FLAG_MERGE_KEEP_MATERIALS|SCENE_FLAG_MERGE_KEEP_EXTRA_ANIM_TRACKS) && FileAccess::exists(p_dest_path)) {
//must merge!
Ref<PackedScene> pscene = ResourceLoader::load(p_dest_path,"PackedScene",true);
if (pscene.is_valid()) {
Node *instance = pscene->instance();
if (instance) {
Map<String,Ref<Animation> > merged_anims;
Map<String,Ref<Material> > merged_materials;
Set<Ref<Mesh> > tested_meshes;
_find_resources_to_merge(instance,instance,scene_flags&SCENE_FLAG_MERGE_KEEP_MATERIALS,merged_materials,scene_flags&SCENE_FLAG_MERGE_KEEP_EXTRA_ANIM_TRACKS,merged_anims,tested_meshes);
tested_meshes.clear();
_merge_found_resources(instance,instance,scene_flags&SCENE_FLAG_MERGE_KEEP_MATERIALS,merged_materials,scene_flags&SCENE_FLAG_MERGE_KEEP_EXTRA_ANIM_TRACKS,merged_anims,tested_meshes);
memdelete(instance);
}
}
}
/// BEFORE ANYTHING, RUN SCRIPT

View File

@ -116,6 +116,10 @@ class EditorSceneImportPlugin : public EditorImportPlugin {
void _tag_import_paths(Node *p_scene,Node *p_node);
void _find_resources_to_merge(Node *scene, Node *node, bool p_merge_material, Map<String,Ref<Material> >&materials, bool p_merge_anims, Map<String,Ref<Animation> >& merged_anims, Set<Ref<Mesh> > &tested_meshes);
void _merge_found_resources(Node *scene, Node *node, bool p_merge_material, const Map<String, Ref<Material> > &materials, bool p_merge_anims, const Map<String,Ref<Animation> >& merged_anims, Set<Ref<Mesh> > &tested_meshes);
public:
enum SceneFlags {
@ -134,6 +138,9 @@ public:
SCENE_FLAG_CREATE_NAVMESH=1<<17,
SCENE_FLAG_DETECT_LIGHTMAP_LAYER=1<<18,
SCENE_FLAG_MERGE_KEEP_MATERIALS=1<<20,
SCENE_FLAG_MERGE_KEEP_EXTRA_ANIM_TRACKS=1<<21,
SCENE_FLAG_REMOVE_NOIMP=1<<24,
SCENE_FLAG_IMPORT_ANIMATIONS=1<<25,
SCENE_FLAG_COMPRESS_GEOMETRY=1<<26,
@ -144,6 +151,7 @@ public:
};
virtual String get_name() const;
virtual String get_visible_name() const;
virtual void import_dialog(const String& p_from="");