Browse Source

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

Juan Linietsky 9 years ago
parent
commit
0db02f26b6

+ 24 - 0
scene/resources/animation.cpp

@@ -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);

+ 5 - 1
scene/resources/animation.h

@@ -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);

+ 6 - 0
tools/editor/io_plugins/editor_import_collada.cpp

@@ -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()=="")

+ 158 - 2
tools/editor/io_plugins/editor_scene_import_plugin.cpp

@@ -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
 

+ 8 - 0
tools/editor/io_plugins/editor_scene_import_plugin.h

@@ -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="");