diff --git a/AnimationEditor/AnimationEditor.csproj b/AnimationEditor/AnimationEditor.csproj
index 6b90702..ef1d283 100644
--- a/AnimationEditor/AnimationEditor.csproj
+++ b/AnimationEditor/AnimationEditor.csproj
@@ -69,6 +69,53 @@
Form1.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AnimationEditor/Form1.cs b/AnimationEditor/Form1.cs
index f7e05c8..7ce412b 100644
--- a/AnimationEditor/Form1.cs
+++ b/AnimationEditor/Form1.cs
@@ -13,6 +13,8 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using QURO.AnimationLibrary;
using QURO;
+using System.Xml;
+using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate;
namespace AnimationEditor
{
@@ -41,17 +43,24 @@ namespace AnimationEditor
if (loadSpriteMapDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
- XmlSerializer mapSerializer = new XmlSerializer(typeof(List));
- TextReader mapReader = new StreamReader(loadSpriteMapDialog.FileName);
+ Dictionary loadedSpriteMap;
+ using (XmlReader xmlRead = XmlReader.Create(loadSpriteMapDialog.FileName))
+ {
+ loadedSpriteMap = IntermediateSerializer.Deserialize>(xmlRead, null);
+ }
+
+ Sprites = new BindingList();
+ foreach (KeyValuePair sprite in loadedSpriteMap)
+ {
+ Sprites.Add(sprite.Value);
+ }
- Sprites = new BindingList((List)mapSerializer.Deserialize(mapReader));
spriteListBox.DataSource = Sprites;
spriteListBox.DisplayMember = "Name";
spriteListBox.ValueMember = "Bounds";
Rectangle[] frames = new Rectangle[] { Sprites[0].Bounds, Sprites[1].Bounds, Sprites[2].Bounds };
animationPreview.CurrentAnimation = new Animation("Test", frames, 1f / 60f, true);
animationPreview.PreviewSprite = new AnimatedSprite(animationPreview.SpriteSheet, animationPreview.CurrentAnimation);
- mapReader.Close();
}
}
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/ContentIdentity.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/ContentIdentity.cs
new file mode 100644
index 0000000..5e5beff
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/ContentIdentity.cs
@@ -0,0 +1,70 @@
+// MonoGame - Copyright (C) The MonoGame Team
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE.txt', which is part of this source code package.
+
+using System;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline
+{
+ ///
+ /// Provides properties describing the origin of the game asset, such as the original source file and creation tool. This information is used for error reporting, and by processors that need to determine from what directory the asset was originally loaded.
+ ///
+ [Serializable]
+ public class ContentIdentity
+ {
+ ///
+ /// Gets or sets the specific location of the content item within the larger source file.
+ ///
+ public string FragmentIdentifier { get; set; }
+
+ ///
+ /// Gets or sets the file name of the asset source.
+ ///
+ public string SourceFilename { get; set; }
+
+ ///
+ /// Gets or sets the creation tool of the asset.
+ ///
+ public string SourceTool { get; set; }
+
+ ///
+ /// Initializes a new instance of ContentIdentity.
+ ///
+ public ContentIdentity()
+ : this(string.Empty, string.Empty, null)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of ContentIdentity with the specified values.
+ ///
+ /// The absolute path to the file name of the asset source.
+ public ContentIdentity(string sourceFilename)
+ : this(sourceFilename, string.Empty, null)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of ContentIdentity with the specified values.
+ ///
+ /// The absolute path to the file name of the asset source.
+ /// The name of the digital content creation (DCC) tool that created the asset.
+ public ContentIdentity(string sourceFilename, string sourceTool)
+ : this(sourceFilename, sourceTool, null)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of ContentIdentity with the specified values.
+ ///
+ /// The absolute path to the file name of the asset source.
+ /// The name of the digital content creation (DCC) tool that created the asset.
+ /// Specific location of the content item within the larger source file. For example, this could be a line number in the file.
+ public ContentIdentity(string sourceFilename, string sourceTool, string fragmentIdentifier)
+ {
+ SourceFilename = sourceFilename;
+ SourceTool = sourceTool;
+ FragmentIdentifier = fragmentIdentifier;
+ }
+ }
+}
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/InvalidContentException.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/InvalidContentException.cs
new file mode 100644
index 0000000..97d6e78
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/InvalidContentException.cs
@@ -0,0 +1,108 @@
+// MonoGame - Copyright (C) The MonoGame Team
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE.txt', which is part of this source code package.
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline
+{
+ ///
+ /// Thrown when errors are encountered in content during processing.
+ ///
+ [SerializableAttribute]
+ public class InvalidContentException : Exception
+ {
+ ///
+ /// Gets or sets the identity of the content item that caused the exception.
+ ///
+ public ContentIdentity ContentIdentity { get; set; }
+
+ ///
+ /// Initializes a new instance of the InvalidContentException class
+ ///
+ public InvalidContentException()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the InvalidContentException class with information on serialization and streaming context for the related content item.
+ ///
+ /// Information necessary for serialization and deserialization of the content item.
+ /// Information necessary for the source and destination of a given serialized stream. Also provides an additional caller-defined context.
+ protected InvalidContentException(
+ SerializationInfo serializationInfo,
+ StreamingContext streamingContext
+ )
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the InvalidContentException class with the specified error message.
+ ///
+ /// A message that describes the error.
+ public InvalidContentException(
+ string message
+ )
+ : this(message, null, null)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the InvalidContentException class with the specified error message and the identity of the content throwing the exception.
+ ///
+ /// A message that describes the error.
+ /// Information about the content item that caused this error, including the file name. In some cases, a location within the file (of the problem) is specified.
+ public InvalidContentException(
+ string message,
+ ContentIdentity contentIdentity
+ )
+ : this(message, contentIdentity, null)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the InvalidContentException class with the specified error message, the identity of the content throwing the exception, and a reference to the inner exception that is the cause of this exception.
+ ///
+ /// A message that describes the error.
+ /// Information about the content item that caused this error, including the file name. In some cases, a location within the file (of the problem) is specified.
+ /// The exception that is the cause of the current exception. If innerException is not a null reference, the current exception is raised in a catch block that handles the inner exception.
+ public InvalidContentException(
+ string message,
+ ContentIdentity contentIdentity,
+ Exception innerException
+ )
+ : base(message, innerException)
+ {
+ ContentIdentity = contentIdentity;
+ }
+
+ ///
+ /// Initializes a new instance of the InvalidContentException class with the specified error message and a reference to the inner exception that is the cause of this exception.
+ ///
+ /// A message that describes the error.
+ /// The exception that is the cause of the current exception. If innerException is not a null reference, the current exception is raised in a catch block that handles the inner exception.
+ public InvalidContentException(
+ string message,
+ Exception innerException
+ )
+ : this(message, null, innerException)
+ {
+ }
+
+ ///
+ /// When overridden in a derived class, returns information about the exception.
+ /// In addition to the base behavior, this method provides serialization functionality.
+ ///
+ /// Information necessary for serialization and deserialization of the content item.
+ /// Information necessary for the source and destination of a given serialized stream. Also provides an additional caller-defined context.
+ public override void GetObjectData(
+ SerializationInfo info,
+ StreamingContext context
+ )
+ {
+ base.GetObjectData(info, context);
+ // TODO: Complete me...
+ }
+ }
+}
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/NamedValueDictionary.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/NamedValueDictionary.cs
new file mode 100644
index 0000000..23f7210
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/NamedValueDictionary.cs
@@ -0,0 +1,222 @@
+// MonoGame - Copyright (C) The MonoGame Team
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE.txt', which is part of this source code package.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline
+{
+ public class NamedValueDictionary : IDictionary
+ {
+ readonly Dictionary dict = new Dictionary();
+
+ ///
+ /// Initializes an instance of NamedValueDictionary.
+ ///
+ public NamedValueDictionary()
+ {
+ }
+
+ ///
+ /// Adds the specified key and value to the dictionary.
+ ///
+ /// Identity of the key of the new data pair.
+ /// The value of the new data pair.
+ public void Add(string key, T value)
+ {
+ dict.Add(key, value);
+ }
+
+ ///
+ /// Determines whether the specified key is present in the dictionary.
+ ///
+ /// Identity of a key.
+ ///
+ public bool ContainsKey(string key)
+ {
+ return dict.ContainsKey(key);
+ }
+
+ ///
+ /// Gets all keys contained in the dictionary.
+ ///
+ public ICollection Keys
+ {
+ get { return dict.Keys; }
+ }
+
+ ///
+ /// Removes the specified key and value from the dictionary.
+ ///
+ /// Identity of the key to be removed.
+ /// true if the value is present; false otherwise.
+ public bool Remove(string key)
+ {
+ return dict.Remove(key);
+ }
+
+ ///
+ /// Gets the value associated with the specified key.
+ ///
+ /// Identity of the key of the element whose value is to be retrieved.
+ /// The current value of the element.
+ /// true if the value is present; false otherwise.
+ public bool TryGetValue(string key, out T value)
+ {
+ return dict.TryGetValue(key, out value);
+ }
+
+ ///
+ /// Specifies the type hint for the intermediate serializer. Values of this type do not store an explicit type attribute in the related XML source.
+ ///
+ protected internal virtual Type DefaultSerializerType
+ {
+ get { return typeof(T); }
+ }
+
+ ///
+ /// Gets all values contained in the dictionary.
+ ///
+ public ICollection Values
+ {
+ get { return dict.Values; }
+ }
+
+ ///
+ /// Gets or sets the specified item.
+ ///
+ /// Identity of a key.
+ public T this[string key]
+ {
+ get
+ {
+ return dict[key];
+ }
+ set
+ {
+ dict[key] = value;
+ }
+ }
+
+ ///
+ /// Adds an item to the collection.
+ ///
+ /// The item to add to the collection.
+ void ICollection>.Add(KeyValuePair item)
+ {
+ ((ICollection>)dict).Add(item);
+ }
+
+ ///
+ /// Removes all keys and values from the dictionary.
+ ///
+ public void Clear()
+ {
+ dict.Clear();
+ }
+
+ ///
+ /// Determines whether the collection contains a specific value.
+ ///
+ /// The object to locate in the collection.
+ /// true if the collection contains the object; false otherwise.
+ bool ICollection>.Contains(KeyValuePair item)
+ {
+ return ((ICollection>)dict).Contains(item);
+ }
+
+ ///
+ /// Copies the elements of the collection to an array, starting at a specified index.
+ ///
+ /// The destination array.
+ /// The index at which to begin the copy.
+ void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex)
+ {
+ ((ICollection>)dict).CopyTo(array, arrayIndex);
+ }
+
+ ///
+ /// Gets the number of items in the dictionary.
+ ///
+ public int Count
+ {
+ get { return dict.Count; }
+ }
+
+ ///
+ /// Gets a value indicating if this object is read-only.
+ ///
+ bool ICollection>.IsReadOnly
+ {
+ get { return false; }
+ }
+
+ ///
+ /// Removes the first occurrence of the specified object from the collection.
+ ///
+ /// The item to remove from the collection.
+ /// true if the item was successfully removed from the collection; false otherwise.
+ bool ICollection>.Remove(KeyValuePair item)
+ {
+ return ((ICollection>)dict).Remove(item);
+ }
+
+ ///
+ /// Gets an enumerator that iterates through items in a dictionary.
+ ///
+ /// Enumerator for iterating through the dictionary.
+ public IEnumerator> GetEnumerator()
+ {
+ return dict.GetEnumerator();
+ }
+
+ ///
+ /// Returns an enumerator that can iterate through this collection.
+ ///
+ /// An enumerator that can iterate through this collection
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return dict.GetEnumerator();
+ }
+
+ ///
+ /// Adds an element to the dictionary.
+ ///
+ /// Identity of the key of the new element.
+ /// The value of the new element.
+ protected virtual void AddItem(string key, T value)
+ {
+ dict.Add(key, value);
+ }
+
+ ///
+ /// Removes all elements from the dictionary.
+ ///
+ protected virtual void ClearItems()
+ {
+ dict.Clear();
+ }
+
+ ///
+ /// Removes the specified element from the dictionary.
+ ///
+ /// Identity of the key of the data pair to be removed.
+ /// true if the value is present; false otherwise.
+ protected virtual bool RemoveItem(string key)
+ {
+ return dict.Remove(key);
+ }
+
+ ///
+ /// Modifies the value of an existing element.
+ ///
+ /// Identity of the element to be modified.
+ /// The value to be set.
+ protected virtual void SetItem(string key, T value)
+ {
+ dict[key] = value;
+ }
+ }
+}
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ArraySerializer.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ArraySerializer.cs
new file mode 100644
index 0000000..70b9d93
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ArraySerializer.cs
@@ -0,0 +1,48 @@
+// MonoGame - Copyright (C) The MonoGame Team
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE.txt', which is part of this source code package.
+
+using System;
+using System.Collections.Generic;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
+{
+ class ArraySerializer : ContentTypeSerializer
+ {
+ private readonly ListSerializer _listSerializer;
+
+ public ArraySerializer() :
+ base("array")
+ {
+ _listSerializer = new ListSerializer();
+ }
+
+ protected internal override void Initialize(IntermediateSerializer serializer)
+ {
+ _listSerializer.Initialize(serializer);
+ }
+
+ public override bool ObjectIsEmpty(T[] value)
+ {
+ return value.Length == 0;
+ }
+
+ protected internal override void ScanChildren(IntermediateSerializer serializer, ChildCallback callback, T[] value)
+ {
+ _listSerializer.ScanChildren(serializer, callback, new List(value));
+ }
+
+ protected internal override T[] Deserialize(IntermediateReader input, ContentSerializerAttribute format, T[] existingInstance)
+ {
+ if (existingInstance != null)
+ throw new InvalidOperationException("You cannot deserialize an array into a getter-only property.");
+ var result = _listSerializer.Deserialize(input, format, null);
+ return result.ToArray();
+ }
+
+ protected internal override void Serialize(IntermediateWriter output, T[] value, ContentSerializerAttribute format)
+ {
+ _listSerializer.Serialize(output, new List(value), format);
+ }
+ }
+}
\ No newline at end of file
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/BoolSerializer.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/BoolSerializer.cs
new file mode 100644
index 0000000..bec40f9
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/BoolSerializer.cs
@@ -0,0 +1,28 @@
+// MonoGame - Copyright (C) The MonoGame Team
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE.txt', which is part of this source code package.
+
+using System.Collections.Generic;
+using System.Xml;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
+{
+ [ContentTypeSerializer]
+ class BoolSerializer : ElementSerializer
+ {
+ public BoolSerializer() :
+ base("bool", 1)
+ {
+ }
+
+ protected internal override bool Deserialize(string[] inputs, ref int index)
+ {
+ return XmlConvert.ToBoolean(inputs[index++]);
+ }
+
+ protected internal override void Serialize(bool value, List results)
+ {
+ results.Add(XmlConvert.ToString(value));
+ }
+ }
+}
\ No newline at end of file
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ByteSerializer.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ByteSerializer.cs
new file mode 100644
index 0000000..319debb
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ByteSerializer.cs
@@ -0,0 +1,28 @@
+// MonoGame - Copyright (C) The MonoGame Team
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE.txt', which is part of this source code package.
+
+using System.Collections.Generic;
+using System.Xml;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
+{
+ [ContentTypeSerializer]
+ class ByteSerializer : ElementSerializer
+ {
+ public ByteSerializer() :
+ base("byte", 1)
+ {
+ }
+
+ protected internal override byte Deserialize(string[] inputs, ref int index)
+ {
+ return XmlConvert.ToByte(inputs[index++]);
+ }
+
+ protected internal override void Serialize(byte value, List results)
+ {
+ results.Add(XmlConvert.ToString(value));
+ }
+ }
+}
\ No newline at end of file
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/CharSerializer.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/CharSerializer.cs
new file mode 100644
index 0000000..8647f91
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/CharSerializer.cs
@@ -0,0 +1,38 @@
+// MonoGame - Copyright (C) The MonoGame Team
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE.txt', which is part of this source code package.
+
+using System.Collections.Generic;
+using System.Xml;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
+{
+ [ContentTypeSerializer]
+ class CharSerializer : ElementSerializer
+ {
+ public CharSerializer() :
+ base("char", 1)
+ {
+ }
+
+ protected internal override char Deserialize(string[] inputs, ref int index)
+ {
+ var str = inputs[index++];
+ if (str.Length == 1)
+ return XmlConvert.ToChar(str);
+
+ // Try parsing it as a UTF code.
+ int val;
+ if (int.TryParse(str, out val))
+ return char.ConvertFromUtf32(val)[0];
+
+ // Last ditch effort to decode it as XML escape value.
+ return XmlConvert.ToChar(XmlConvert.DecodeName(str));
+ }
+
+ protected internal override void Serialize(char value, List results)
+ {
+ results.Add(XmlConvert.ToString(value));
+ }
+ }
+}
\ No newline at end of file
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ColorSerializer.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ColorSerializer.cs
new file mode 100644
index 0000000..9bbf75a
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ColorSerializer.cs
@@ -0,0 +1,35 @@
+// MonoGame - Copyright (C) The MonoGame Team
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE.txt', which is part of this source code package.
+
+using System.Collections.Generic;
+using System.Globalization;
+using System.Xml;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
+{
+ [ContentTypeSerializer]
+ class ColorSerializer : ElementSerializer
+ {
+ public ColorSerializer() :
+ base("Color", 1)
+ {
+ }
+
+ protected internal override Color Deserialize(string[] inputs, ref int index)
+ {
+ // NOTE: The value is serialized in ARGB format.
+ var value = uint.Parse(inputs[index++], NumberStyles.HexNumber, CultureInfo.InvariantCulture);
+ return new Color( (int)(value >> 16 & 0xFF),
+ (int)(value >> 8 & 0xFF),
+ (int)(value >> 0 & 0xFF),
+ (int)(value >> 24 & 0xFF));
+ }
+
+ protected internal override void Serialize(Color value, List results)
+ {
+ // NOTE: The value is serialized in ARGB format.
+ results.Add(string.Format("{0:X2}{1:X2}{2:X2}{3:X2}", value.A, value.R, value.G, value.B));
+ }
+ }
+}
\ No newline at end of file
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ContentTypeSerializer.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ContentTypeSerializer.cs
new file mode 100644
index 0000000..662c5a2
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ContentTypeSerializer.cs
@@ -0,0 +1,45 @@
+// MonoGame - Copyright (C) The MonoGame Team
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE.txt', which is part of this source code package.
+
+using System;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
+{
+ public abstract class ContentTypeSerializer
+ {
+ protected ContentTypeSerializer(Type targetType, string xmlTypeName)
+ {
+ TargetType = targetType;
+ XmlTypeName = xmlTypeName;
+ }
+
+ public virtual bool CanDeserializeIntoExistingObject
+ {
+ get { return false; }
+ }
+
+ public Type TargetType { get; private set; }
+
+ public string XmlTypeName { get; private set; }
+
+ protected internal abstract object Deserialize(IntermediateReader input, ContentSerializerAttribute format, object existingInstance);
+
+ protected internal virtual void Initialize(IntermediateSerializer serializer)
+ {
+ }
+
+ public virtual bool ObjectIsEmpty(object value)
+ {
+ return false;
+ }
+
+ protected internal virtual void ScanChildren(IntermediateSerializer serializer, ChildCallback callback, object value)
+ {
+ }
+
+ protected internal abstract void Serialize(IntermediateWriter output, object value, ContentSerializerAttribute format);
+
+ internal protected delegate void ChildCallback(ContentTypeSerializer typeSerializer, object value);
+ }
+}
\ No newline at end of file
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ContentTypeSerializerAttribute.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ContentTypeSerializerAttribute.cs
new file mode 100644
index 0000000..24dd3b9
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ContentTypeSerializerAttribute.cs
@@ -0,0 +1,62 @@
+// MonoGame - Copyright (C) The MonoGame Team
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE.txt', which is part of this source code package.
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
+{
+ ///
+ /// Used to identify custom ContentTypeSerializer classes.
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
+ public sealed class ContentTypeSerializerAttribute : Attribute
+ {
+ ///
+ /// Initializes an instance of the ContentTypeSerializerAttribute.
+ ///
+ public ContentTypeSerializerAttribute()
+ {
+ }
+
+
+ private static readonly object _lock = new object();
+
+ private static ReadOnlyCollection _types;
+
+ static internal ReadOnlyCollection GetTypes()
+ {
+ lock (_lock)
+ {
+ if (_types == null)
+ {
+ var found = new List();
+ var assemblies = AppDomain.CurrentDomain.GetAssemblies();
+ foreach (var assembly in assemblies)
+ {
+ try
+ {
+ var types = assembly.GetTypes();
+ foreach (var type in types)
+ {
+ var attributes = type.GetCustomAttributes(typeof (ContentTypeSerializerAttribute), false);
+ if (attributes.Length > 0)
+ found.Add(type);
+ }
+ }
+ catch (System.Reflection.ReflectionTypeLoadException ex)
+ {
+ Console.WriteLine("Warning: " + ex.Message);
+ }
+ }
+
+ _types = new ReadOnlyCollection(found);
+ }
+ }
+
+ return _types;
+ }
+ }
+}
\ No newline at end of file
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ContentTypeSerializerT.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ContentTypeSerializerT.cs
new file mode 100644
index 0000000..fd8c26d
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ContentTypeSerializerT.cs
@@ -0,0 +1,59 @@
+// MonoGame - Copyright (C) The MonoGame Team
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE.txt', which is part of this source code package.
+
+using System;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
+{
+ public abstract class ContentTypeSerializer : ContentTypeSerializer
+ {
+ protected ContentTypeSerializer() :
+ this(string.Empty)
+ {
+ }
+
+ protected ContentTypeSerializer(string xmlTypeName) :
+ base(typeof(T), xmlTypeName)
+ {
+ }
+
+ protected internal abstract T Deserialize(IntermediateReader input, ContentSerializerAttribute format, T existingInstance);
+
+ protected internal override object Deserialize(IntermediateReader input, ContentSerializerAttribute format, object existingInstance)
+ {
+ var cast = existingInstance == null ? default(T) : (T)existingInstance;
+ return Deserialize(input, format, cast);
+ }
+
+ public virtual bool ObjectIsEmpty(T value)
+ {
+ return base.ObjectIsEmpty(value);
+ }
+
+ public override bool ObjectIsEmpty(object value)
+ {
+ var cast = value == null ? default(T) : (T)value;
+ return ObjectIsEmpty(cast);
+ }
+
+ protected internal virtual void ScanChildren(IntermediateSerializer serializer, ChildCallback callback, T value)
+ {
+ }
+
+ protected internal override void ScanChildren(IntermediateSerializer serializer, ChildCallback callback, object value)
+ {
+ if (value == null)
+ return;
+ ScanChildren(serializer, callback, (T)value);
+ }
+
+ protected internal abstract void Serialize(IntermediateWriter output, T value, ContentSerializerAttribute format);
+
+ protected internal override void Serialize(IntermediateWriter output, object value, ContentSerializerAttribute format)
+ {
+ var cast = value == null ? default(T) : (T)value;
+ Serialize(output, cast, format);
+ }
+ }
+}
\ No newline at end of file
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/CurveKeyCollectionSerializer.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/CurveKeyCollectionSerializer.cs
new file mode 100644
index 0000000..38fcd0f
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/CurveKeyCollectionSerializer.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Generic;
+using System.Xml;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
+{
+ [ContentTypeSerializer]
+ class CurveKeyCollectionSerializer : ContentTypeSerializer
+ {
+ public CurveKeyCollectionSerializer() :
+ base("Keys")
+ { }
+
+ public override bool CanDeserializeIntoExistingObject
+ { get { return true; } }
+
+ protected internal override CurveKeyCollection Deserialize(
+ IntermediateReader input,
+ ContentSerializerAttribute format,
+ CurveKeyCollection existingInstance)
+ {
+ var result = existingInstance ?? new CurveKeyCollection();
+
+ if (input.Xml.HasValue)
+ {
+ var elements = PackedElementsHelper.ReadElements(input);
+ if (elements.Length > 0)
+ {
+ // Each CurveKey consists of 5 elements
+ if (elements.Length % 5 != 0)
+ throw new InvalidContentException(
+ "Elements count in CurveKeyCollection is inncorect!");
+ try
+ {
+ // Parse all CurveKeys
+ for (int i = 0; i < elements.Length; i += 5)
+ {
+ // Order: Position, Value, TangentIn, TangentOut and Continuity
+ var curveKey = new CurveKey
+ (XmlConvert.ToSingle(elements[i]),
+ XmlConvert.ToSingle(elements[i + 1]),
+ XmlConvert.ToSingle(elements[i + 2]),
+ XmlConvert.ToSingle(elements[i + 3]),
+ (CurveContinuity)Enum.Parse(
+ typeof(CurveContinuity),
+ elements[i + 4],
+ true));
+ result.Add(curveKey);
+ }
+ }
+ catch (Exception e)
+ {
+ throw new InvalidContentException
+ ("Error parsing CurveKey", e);
+ }
+ }
+ }
+ return result;
+ }
+
+
+ protected internal override void Serialize(
+ IntermediateWriter output,
+ CurveKeyCollection value,
+ ContentSerializerAttribute format)
+ {
+ var elements = new List();
+ foreach (var curveKey in value)
+ {
+ // Order: Position, Value, TangentIn, TangentOut and Continuity
+ elements.Add(XmlConvert.ToString(curveKey.Position));
+ elements.Add(XmlConvert.ToString(curveKey.Value));
+ elements.Add(XmlConvert.ToString(curveKey.TangentIn));
+ elements.Add(XmlConvert.ToString(curveKey.TangentOut));
+ elements.Add(curveKey.Continuity.ToString());
+ }
+ var str = PackedElementsHelper.JoinElements(elements);
+ output.Xml.WriteString(str);
+ }
+ }
+}
\ No newline at end of file
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/DictionarySerializer.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/DictionarySerializer.cs
new file mode 100644
index 0000000..a321012
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/DictionarySerializer.cs
@@ -0,0 +1,92 @@
+// MonoGame - Copyright (C) The MonoGame Team
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE.txt', which is part of this source code package.
+
+using System;
+using System.Collections.Generic;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
+{
+ [ContentTypeSerializer]
+ class DictionarySerializer : ContentTypeSerializer>
+ {
+ private ContentTypeSerializer _keySerializer;
+ private ContentTypeSerializer _valueSerializer;
+
+ private ContentSerializerAttribute _keyFormat;
+ private ContentSerializerAttribute _valueFormat;
+
+ public DictionarySerializer() :
+ base("dictionary")
+ {
+ }
+
+ public override bool CanDeserializeIntoExistingObject
+ {
+ get { return true; }
+ }
+
+ protected internal override void Initialize(IntermediateSerializer serializer)
+ {
+ _keySerializer = serializer.GetTypeSerializer(typeof(TKey));
+ _valueSerializer = serializer.GetTypeSerializer(typeof(TValue));
+
+ _keyFormat = new ContentSerializerAttribute
+ {
+ ElementName = "Key",
+ AllowNull = false
+ };
+
+ _valueFormat = new ContentSerializerAttribute()
+ {
+ ElementName = "Value",
+ AllowNull = typeof(TValue).IsValueType
+ };
+ }
+
+ public override bool ObjectIsEmpty(Dictionary value)
+ {
+ return value.Count == 0;
+ }
+
+ protected internal override void ScanChildren(IntermediateSerializer serializer, ChildCallback callback, Dictionary value)
+ {
+ foreach (var kvp in value)
+ {
+ callback(_keySerializer, kvp.Key);
+ callback(_valueSerializer, kvp.Value);
+ }
+ }
+
+ protected internal override Dictionary Deserialize(IntermediateReader input, ContentSerializerAttribute format, Dictionary existingInstance)
+ {
+ var result = existingInstance ?? new Dictionary();
+
+ while (input.MoveToElement(format.CollectionItemName))
+ {
+ input.Xml.ReadStartElement();
+
+ var key = input.ReadObject(_keyFormat, _keySerializer);
+ var value = input.ReadObject(_valueFormat, _valueSerializer);
+ result.Add(key,value);
+
+ input.Xml.ReadEndElement();
+ }
+
+ return result;
+ }
+
+ protected internal override void Serialize(IntermediateWriter output, Dictionary value, ContentSerializerAttribute format)
+ {
+ foreach (var kvp in value)
+ {
+ output.Xml.WriteStartElement(format.CollectionItemName);
+
+ output.WriteObject(kvp.Key, _keyFormat, _keySerializer);
+ output.WriteObject(kvp.Value, _valueFormat, _valueSerializer);
+
+ output.Xml.WriteEndElement();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/DoubleSerializer.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/DoubleSerializer.cs
new file mode 100644
index 0000000..6009291
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/DoubleSerializer.cs
@@ -0,0 +1,28 @@
+// MonoGame - Copyright (C) The MonoGame Team
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE.txt', which is part of this source code package.
+
+using System.Collections.Generic;
+using System.Xml;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
+{
+ [ContentTypeSerializer]
+ class DoubleSerializer : ElementSerializer
+ {
+ public DoubleSerializer() :
+ base("double", 1)
+ {
+ }
+
+ protected internal override double Deserialize(string[] inputs, ref int index)
+ {
+ return XmlConvert.ToDouble(inputs[index++]);
+ }
+
+ protected internal override void Serialize(double value, List results)
+ {
+ results.Add(XmlConvert.ToString(value));
+ }
+ }
+}
\ No newline at end of file
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ElementSerializerT.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ElementSerializerT.cs
new file mode 100644
index 0000000..4b9a81a
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/ElementSerializerT.cs
@@ -0,0 +1,75 @@
+// MonoGame - Copyright (C) The MonoGame Team
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE.txt', which is part of this source code package.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
+{
+ abstract class ElementSerializer : ContentTypeSerializer
+ {
+ private readonly int _elementCount;
+
+ protected ElementSerializer(string xmlTypeName, int elementCount) :
+ base(xmlTypeName)
+ {
+ _elementCount = elementCount;
+ }
+
+ protected void ThrowElementCountException()
+ {
+ throw new InvalidContentException("Not have enough entries in space-separated list!");
+ }
+
+ protected internal abstract T Deserialize(string [] inputs, ref int index);
+
+ protected internal abstract void Serialize(T value, List results);
+
+
+
+ protected internal void Deserialize(IntermediateReader input, List results)
+ {
+ var elements = PackedElementsHelper.ReadElements(input);
+
+ for (var index = 0; index < elements.Length;)
+ {
+ if (elements.Length - index < _elementCount)
+ ThrowElementCountException();
+
+ var elem = Deserialize(elements, ref index);
+ results.Add(elem);
+ }
+ }
+
+ protected internal override T Deserialize(IntermediateReader input, ContentSerializerAttribute format, T existingInstance)
+ {
+ var elements = PackedElementsHelper.ReadElements(input);
+
+ if (elements.Length < _elementCount)
+ ThrowElementCountException();
+
+ var index = 0;
+ return Deserialize(elements, ref index);
+ }
+
+ protected internal void Serialize(IntermediateWriter output, List values)
+ {
+ var elements = new List();
+ for (var i = 0; i < values.Count; i++)
+ Serialize(values[i], elements);
+ var str = PackedElementsHelper.JoinElements(elements);
+ output.Xml.WriteString(str);
+ }
+
+ protected internal override void Serialize(IntermediateWriter output, T value, ContentSerializerAttribute format)
+ {
+ var elements = new List();
+ Serialize(value, elements);
+ var str = PackedElementsHelper.JoinElements(elements);
+ output.Xml.WriteString(str);
+ }
+ }
+}
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/EnumSerializer.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/EnumSerializer.cs
new file mode 100644
index 0000000..51b8029
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/EnumSerializer.cs
@@ -0,0 +1,36 @@
+// MonoGame - Copyright (C) The MonoGame Team
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE.txt', which is part of this source code package.
+
+using System;
+using System.Diagnostics;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
+{
+ class EnumSerializer : ContentTypeSerializer
+ {
+ public EnumSerializer(Type targetType) :
+ base(targetType, targetType.Name)
+ {
+ }
+
+ protected internal override object Deserialize(IntermediateReader input, ContentSerializerAttribute format, object existingInstance)
+ {
+ var str = input.Xml.ReadString();
+ try
+ {
+ return Enum.Parse(TargetType, str, true);
+ }
+ catch (Exception ex)
+ {
+ throw input.NewInvalidContentException(ex, "Invalid enum value '{0}' for type '{1}'", str, TargetType.Name);
+ }
+ }
+
+ protected internal override void Serialize(IntermediateWriter output, object value, ContentSerializerAttribute format)
+ {
+ Debug.Assert(value.GetType() == TargetType, "Got invalid value type!");
+ output.Xml.WriteString(value.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/FloatSerializer.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/FloatSerializer.cs
new file mode 100644
index 0000000..0fbd56d
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/FloatSerializer.cs
@@ -0,0 +1,28 @@
+// MonoGame - Copyright (C) The MonoGame Team
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE.txt', which is part of this source code package.
+
+using System.Collections.Generic;
+using System.Xml;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
+{
+ [ContentTypeSerializer]
+ class FloatSerializer : ElementSerializer
+ {
+ public FloatSerializer() :
+ base("float", 1)
+ {
+ }
+
+ protected internal override float Deserialize(string[] inputs, ref int index)
+ {
+ return XmlConvert.ToSingle(inputs[index++]);
+ }
+
+ protected internal override void Serialize(float value, List results)
+ {
+ results.Add(XmlConvert.ToString(value));
+ }
+ }
+}
\ No newline at end of file
diff --git a/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/GenericCollectionHelper.cs b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/GenericCollectionHelper.cs
new file mode 100644
index 0000000..411b417
--- /dev/null
+++ b/AnimationEditor/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/GenericCollectionHelper.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
+{
+ internal class GenericCollectionHelper
+ {
+ public static bool IsGenericCollectionType(Type type, bool checkAncestors)
+ {
+ return GetCollectionElementType(type, checkAncestors) != null;
+ }
+
+ private static Type GetCollectionElementType(Type type, bool checkAncestors)
+ {
+ if (!checkAncestors && type.BaseType != null && FindCollectionInterface(type.BaseType) != null)
+ return null;
+
+ var collectionInterface = FindCollectionInterface(type);
+ if (collectionInterface == null)
+ return null;
+
+ return collectionInterface.GetGenericArguments()[0];
+ }
+
+ private static Type FindCollectionInterface(Type type)
+ {
+ var interfaces = type.FindInterfaces((t, o) =>
+ {
+ if (t.IsGenericType)
+ return t.GetGenericTypeDefinition() == typeof(ICollection<>);
+ return false;
+ }, null);
+
+ return (interfaces.Length == 1)
+ ? interfaces[0]
+ : null;
+ }
+
+ private readonly ContentTypeSerializer _contentSerializer;
+ private readonly PropertyInfo _countProperty;
+ private readonly MethodInfo _addMethod;
+
+ public GenericCollectionHelper(IntermediateSerializer serializer, Type type)
+ {
+ var collectionElementType = GetCollectionElementType(type, false);
+ _contentSerializer = serializer.GetTypeSerializer(collectionElementType);
+
+ var collectionType = typeof(ICollection<>).MakeGenericType(collectionElementType);
+ _countProperty = collectionType.GetProperty("Count");
+ _addMethod = collectionType.GetMethod("Add", new[] { collectionElementType });
+ }
+
+ public bool ObjectIsEmpty(object list)
+ {
+ return (int) _countProperty.GetValue(list, null) == 0;
+ }
+
+ public void ScanChildren(ContentTypeSerializer.ChildCallback callback, object collection)
+ {
+ foreach (var item in (IEnumerable) collection)
+ if (item != null)
+ callback(_contentSerializer, item);
+ }
+
+ public void Serialize(IntermediateWriter output, object collection, ContentSerializerAttribute format)
+ {
+ var itemFormat = new ContentSerializerAttribute();
+ itemFormat.ElementName = format.CollectionItemName;
+ foreach (var item in (IEnumerable) collection)
+ output.WriteObject(item, itemFormat, _contentSerializer);
+ }
+
+ public void Deserialize(IntermediateReader input, object collection, ContentSerializerAttribute format)
+ {
+ var itemFormat = new ContentSerializerAttribute();
+ itemFormat.ElementName = format.CollectionItemName;
+ while (input.MoveToElement(format.CollectionItemName))
+ _addMethod.Invoke(collection, new[] { input.ReadObject