using System; using System.Collections.Generic; using System.IO; using System.Xml; using Oni.Metadata; namespace Oni.Totoro { internal class AnimationXmlWriter { private Animation animation; private XmlWriter xml; private string daeFileName; private int startFrame; private int endFrame; private AnimationXmlWriter() { } public static void Write(Animation animation, XmlWriter xml, string daeFileName, int startFrame, int endFrame) { var writer = new AnimationXmlWriter { xml = xml, animation = animation, daeFileName = daeFileName, startFrame = startFrame, endFrame = endFrame }; writer.Write(); } private void Write() { xml.WriteStartElement("Animation"); if (daeFileName != null) { xml.WriteStartElement("Import"); xml.WriteAttributeString("Path", daeFileName); if (startFrame > 0 || endFrame > 0) xml.WriteElementString("Start", XmlConvert.ToString(startFrame)); if (endFrame > 0) xml.WriteElementString("End", XmlConvert.ToString(endFrame)); xml.WriteEndElement(); } xml.WriteStartElement("Lookup"); xml.WriteElementString("Type", animation.Type.ToString()); xml.WriteElementString("AimingType", animation.AimingType.ToString()); xml.WriteElementString("FromState", animation.FromState.ToString()); xml.WriteElementString("ToState", animation.ToState.ToString()); xml.WriteElementString("Varient", MetaEnum.ToString(animation.Varient)); xml.WriteElementString("FirstLevel", XmlConvert.ToString(animation.FirstLevelAvailable)); WriteRawArray("Shortcuts", animation.Shortcuts, Write); xml.WriteEndElement(); xml.WriteElementString("Flags", MetaEnum.ToString(animation.Flags)); xml.WriteStartElement("Atomic"); xml.WriteElementString("Start", XmlConvert.ToString(animation.AtomicStart)); xml.WriteElementString("End", XmlConvert.ToString(animation.AtomicEnd)); xml.WriteEndElement(); xml.WriteStartElement("Invulnerable"); xml.WriteElementString("Start", XmlConvert.ToString(animation.InvulnerableStart)); xml.WriteElementString("End", XmlConvert.ToString(animation.InvulnerableEnd)); xml.WriteEndElement(); xml.WriteStartElement("Overlay"); xml.WriteElementString("UsedBones", MetaEnum.ToString(animation.OverlayUsedBones)); xml.WriteElementString("ReplacedBones", MetaEnum.ToString(animation.OverlayReplacedBones)); xml.WriteEndElement(); xml.WriteStartElement("DirectAnimations"); xml.WriteElementString("Link", animation.DirectAnimations[0]); xml.WriteElementString("Link", animation.DirectAnimations[1]); xml.WriteEndElement(); xml.WriteStartElement("Pause"); xml.WriteElementString("Hard", XmlConvert.ToString(animation.HardPause)); xml.WriteElementString("Soft", XmlConvert.ToString(animation.SoftPause)); xml.WriteEndElement(); xml.WriteStartElement("Interpolation"); xml.WriteElementString("End", XmlConvert.ToString(animation.InterpolationEnd)); xml.WriteElementString("Max", XmlConvert.ToString(animation.InterpolationMax)); xml.WriteEndElement(); xml.WriteElementString("FinalRotation", XmlConvert.ToString(MathHelper.ToDegrees(animation.FinalRotation))); xml.WriteElementString("Direction", animation.Direction.ToString()); xml.WriteElementString("Vocalization", XmlConvert.ToString(animation.Vocalization)); xml.WriteElementString("ActionFrame", XmlConvert.ToString(animation.ActionFrame)); xml.WriteElementString("Impact", animation.Impact); WriteRawArray("Particles", animation.Particles, Write); WriteRawArray("MotionBlur", animation.MotionBlur, Write); WriteRawArray("Footsteps", animation.Footsteps, Write); WriteRawArray("Sounds", animation.Sounds, Write); if (daeFileName == null) { WriteHeights(); WriteVelocities(); WriteRotations(); WritePositions(); } WriteThrowInfo(); WriteRawArray("SelfDamage", animation.SelfDamage, Write); if (animation.Attacks.Count > 0) { WriteRawArray("Attacks", animation.Attacks, Write); if (daeFileName == null) { WriteAttackRing(); } } xml.WriteEndElement(); } private void WriteRotations() { xml.WriteStartElement("Rotations"); foreach (var keys in animation.Rotations) { xml.WriteStartElement("Bone"); foreach (var key in keys) { if (animation.FrameSize == 6) { xml.WriteElementString("EKey", string.Format("{0} {1} {2} {3}", XmlConvert.ToString(key.Duration), XmlConvert.ToString(key.Rotation.X), XmlConvert.ToString(key.Rotation.Y), XmlConvert.ToString(key.Rotation.Z))); } else if (animation.FrameSize == 16) { xml.WriteElementString("QKey", string.Format("{0} {1} {2} {3} {4}", XmlConvert.ToString(key.Duration), XmlConvert.ToString(key.Rotation.X), XmlConvert.ToString(key.Rotation.Y), XmlConvert.ToString(key.Rotation.Z), XmlConvert.ToString(-key.Rotation.W))); } } xml.WriteEndElement(); } xml.WriteEndElement(); } private void WritePositions() { var positions = animation.Positions; xml.WriteStartElement("PositionOffset"); xml.WriteElementString("X", XmlConvert.ToString(positions.Count == 0 ? 0.0f : positions[0].X)); xml.WriteElementString("Z", XmlConvert.ToString(positions.Count == 0 ? 0.0f : positions[0].Z)); xml.WriteEndElement(); WriteRawArray("Positions", animation.Positions, Write); } private void WriteHeights() { xml.WriteStartElement("Heights"); foreach (float height in animation.Heights) { xml.WriteElementString("Height", XmlConvert.ToString(height)); } xml.WriteEndElement(); } private void WriteVelocities() { xml.WriteStartElement("Velocities"); foreach (Vector2 velocity in animation.Velocities) { xml.WriteElementString("Velocity", string.Format("{0} {1}", XmlConvert.ToString(velocity.X), XmlConvert.ToString(velocity.Y))); } xml.WriteEndElement(); } private void WriteAttackRing() { xml.WriteStartElement("AttackRing"); for (int i = 0; i < 36; i++) xml.WriteElementString("Length", XmlConvert.ToString(animation.AttackRing[i])); xml.WriteEndElement(); } private void WriteThrowInfo() { xml.WriteStartElement("ThrowSource"); ThrowInfo info = animation.ThrowSource; if (info != null) { xml.WriteStartElement("TargetAdjustment"); xml.WriteElementString("Position", string.Format("{0} {1} {2}", XmlConvert.ToString(info.Position.X), XmlConvert.ToString(info.Position.Y), XmlConvert.ToString(info.Position.Z))); xml.WriteElementString("Angle", XmlConvert.ToString(info.Angle)); xml.WriteEndElement(); xml.WriteElementString("Distance", XmlConvert.ToString(info.Distance)); xml.WriteElementString("TargetType", info.Type.ToString()); } xml.WriteEndElement(); } private void Write(Position position) { xml.WriteStartElement("Position"); xml.WriteElementString("Height", XmlConvert.ToString(position.Height)); xml.WriteElementString("YOffset", XmlConvert.ToString(position.YOffset)); xml.WriteEndElement(); } private void Write(AttackExtent extent) { xml.WriteStartElement("Extent"); xml.WriteElementString("Angle", XmlConvert.ToString(extent.Angle)); xml.WriteElementString("Length", XmlConvert.ToString(extent.Length)); xml.WriteElementString("MinY", XmlConvert.ToString(extent.MinY)); xml.WriteElementString("MaxY", XmlConvert.ToString(extent.MaxY)); xml.WriteEndElement(); } private void Write(Attack attack) { xml.WriteStartElement("Attack"); xml.WriteElementString("Start", XmlConvert.ToString(attack.Start)); xml.WriteElementString("End", XmlConvert.ToString(attack.End)); xml.WriteElementString("Bones", MetaEnum.ToString(attack.Bones)); xml.WriteElementString("Flags", MetaEnum.ToString(attack.Flags)); xml.WriteElementString("Knockback", XmlConvert.ToString(attack.Knockback)); xml.WriteElementString("HitPoints", XmlConvert.ToString(attack.HitPoints)); xml.WriteElementString("HitType", attack.HitType.ToString()); xml.WriteElementString("HitLength", XmlConvert.ToString(attack.HitLength)); xml.WriteElementString("StunLength", XmlConvert.ToString(attack.StunLength)); xml.WriteElementString("StaggerLength", XmlConvert.ToString(attack.StaggerLength)); if (daeFileName == null) { WriteRawArray("Extents", attack.Extents, Write); } xml.WriteEndElement(); } private void Write(Particle particle) { xml.WriteStartElement("Particle"); xml.WriteElementString("Start", XmlConvert.ToString(particle.Start)); xml.WriteElementString("End", XmlConvert.ToString(particle.End)); xml.WriteElementString("Bone", particle.Bone.ToString()); xml.WriteElementString("Name", particle.Name); xml.WriteEndElement(); } private void Write(Damage damage) { xml.WriteStartElement("Damage"); xml.WriteElementString("Points", XmlConvert.ToString(damage.Points)); xml.WriteElementString("Frame", XmlConvert.ToString(damage.Frame)); xml.WriteEndElement(); } private void Write(Sound sound) { xml.WriteStartElement("Sound"); xml.WriteElementString("Name", sound.Name); xml.WriteElementString("Start", XmlConvert.ToString(sound.Start)); xml.WriteEndElement(); } private void Write(Footstep footstep) { xml.WriteStartElement("Footstep"); xml.WriteElementString("Frame", XmlConvert.ToString(footstep.Frame)); xml.WriteElementString("Type", MetaEnum.ToString(footstep.Type)); xml.WriteEndElement(); } private void Write(Shortcut shortcut) { xml.WriteStartElement("Shortcut"); xml.WriteElementString("FromState", shortcut.FromState.ToString()); xml.WriteElementString("Length", XmlConvert.ToString(shortcut.Length)); xml.WriteElementString("ReplaceAtomic", shortcut.ReplaceAtomic ? "yes" : "no"); xml.WriteEndElement(); } private void Write(MotionBlur motionBlur) { xml.WriteStartElement("MotionBlur"); xml.WriteElementString("Bones", MetaEnum.ToString(motionBlur.Bones)); xml.WriteElementString("Start", XmlConvert.ToString(motionBlur.Start)); xml.WriteElementString("End", XmlConvert.ToString(motionBlur.End)); xml.WriteElementString("Lifetime", XmlConvert.ToString(motionBlur.Lifetime)); xml.WriteElementString("Alpha", XmlConvert.ToString(motionBlur.Alpha)); xml.WriteElementString("Interval", XmlConvert.ToString(motionBlur.Interval)); xml.WriteEndElement(); } private void WriteRawArray(string name, List list, Action elementWriter) { xml.WriteStartElement(name); foreach (T t in list) elementWriter(t); xml.WriteEndElement(); } } }