custom FbxImporter to import multi animations from single FBX file for xna 4.0
Thanks the original code, the link is here http://xnanimation.codeplex.com/discussions/254116 . I make some modification for xna 4.0 project.
Original xna fbx importer only import first animation in .fbx file, use this customer fbx importer to pick all animation from fbx file. I use blender2.6 to make multi action animations , and export to fbx format file with xna options checked.
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
// TODO: replace this with the type you want to import.
using TImport = Microsoft.Xna.Framework.Content.Pipeline.Graphics.NodeContent;
namespace SkinModelProcessor
{
/// <summary>
/// This class will be instantiated by the XNA Framework Content Pipeline
/// to import a file from disk into the specified type, TImport.
///
/// This should be part of a Content Pipeline Extension Library project.
///
/// TODO: change the ContentImporter attribute to specify the correct file
/// extension, display name, and default processor for this importer.
/// </summary>
[ContentImporter(".fbx", DisplayName = "Multi-take FBX Importer", DefaultProcessor = "SkinModelProcessor")]
public class SkinnedModelImporter : FbxImporter
{
private List<string> _animfiles;
private List<string> _fbxheader;
private TImport _master;
private ContentImporterContext _context;
public override TImport Import(string filename, ContentImporterContext context)
{
// TODO: read the specified file into an instance of the imported type.
_context = context;
// _animfiles will contain list of new temp anim files.
_animfiles = new List<string>();
// Decouple header and animation data.
ExtractAnimations(filename);
// Process master file (this will also process the first animation)
_master = base.Import(filename, context);
// Process the remaining animations.
foreach (string file in _animfiles)
{
NodeContent anim = base.Import(file, context);
// Append animation to master NodeContent.
AppendAnimation(_master, anim);
}
// Delete the temporary animation files.
DeleteTempFiles();
return _master;
//throw new NotImplementedException();
}
private void AppendAnimation(NodeContent masternode, NodeContent animnode)
{
foreach (KeyValuePair<string, AnimationContent> anim in animnode.Animations)
{
masternode.Animations.Add(anim.Key, anim.Value);
}
//foreach (NodeContent child in animnode.Children) {
// if (child != null) {
// AppendAnimation(child);
// }
//}
for (int i = 0; i < masternode.Children.Count; i++)
{
if (animnode.Children[i] != null)
{
AppendAnimation(masternode.Children[i], animnode.Children[i]);
}
}
}
private void ExtractAnimations(string filename)
{
List<string> masterFile = File.ReadAllLines(filename).ToList();
string path = Path.GetDirectoryName(filename);
int open_idx = 0,
length,
num_open = -1,
filenum = 0;
bool foundTake = false;
int idx = masterFile.IndexOf("Takes: {") + 1;
_fbxheader = masterFile.Take(idx).ToList();
List<string> anims = masterFile.Skip(idx).ToList();
// Extract each animation and create a temporary anim file.
for (int i = 0; i < anims.Count; i++)
{
if (anims[i].Contains("Take: "))
{
open_idx = i;
num_open = 0;
foundTake = true;
}
if (anims[i].Contains("{") &&
foundTake)
{
num_open++;
}
if (anims[i].Contains("}") &&
foundTake)
{
num_open--;
}
if (num_open == 0 &&
foundTake)
{
// Skip first animation since this is processed in the master
// fbx file.
if (filenum > 0)
{
length = i - open_idx + 1;
// Create temp file from header + anim data.
CreateTempFile(Path.Combine(path, "tmp.anim." + filenum + ".fbx"),
anims.Skip(open_idx).Take(length).ToArray());
}
filenum++;
foundTake = false;
}
}
}
private void CreateTempFile(string filename, string[] data)
{
List<string> completefile = new List<string>();
completefile.AddRange(_fbxheader);
completefile.AddRange(data);
try
{
// Write data to new temp file.
File.WriteAllLines(filename, completefile.ToArray());
// Store temp file name for processing.
_animfiles.Add(filename);
}
catch
{
// Error while creating temp file.
_context.Logger.LogWarning(null, null, "Error creating temp file: {0}", filename);
}
}
private void DeleteTempFiles()
{
foreach (string file in _animfiles)
{
File.Delete(file);
}
}
}
}
Run result
浙公网安备 33010602011771号