(ded4a3e0a) v0.9.0.7
This commit is contained in:
+23
@@ -0,0 +1,23 @@
|
||||
// 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 Microsoft.Xna.Framework.Content.Pipeline.Graphics;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
class AlphaTestEffectWriter : BuiltInContentWriter<AlphaTestMaterialContent>
|
||||
{
|
||||
protected internal override void Write(ContentWriter output, AlphaTestMaterialContent value)
|
||||
{
|
||||
output.WriteExternalReference(value.Textures.ContainsKey(AlphaTestMaterialContent.TextureKey) ? value.Texture : null);
|
||||
output.Write((int)(value.AlphaFunction.HasValue ? value.AlphaFunction.Value : CompareFunction.Greater));
|
||||
output.Write((int)(value.ReferenceAlpha.HasValue ? value.ReferenceAlpha.Value : 0));
|
||||
output.Write(value.DiffuseColor.GetValueOrDefault());
|
||||
output.Write(value.Alpha.GetValueOrDefault());
|
||||
output.Write(value.VertexColorEnabled.GetValueOrDefault());
|
||||
}
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// 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.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the array value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class ArrayWriter<T> : BuiltInContentWriter<T[]>
|
||||
{
|
||||
ContentTypeWriter _elementWriter;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal override void OnAddedToContentWriter(ContentWriter output)
|
||||
{
|
||||
base.OnAddedToContentWriter(output);
|
||||
|
||||
_elementWriter = output.GetTypeWriter(typeof(T));
|
||||
}
|
||||
|
||||
public override string GetRuntimeReader(TargetPlatform targetPlatform)
|
||||
{
|
||||
return string.Concat( typeof(ContentTypeReader).Namespace,
|
||||
".",
|
||||
"ArrayReader`1[[",
|
||||
_elementWriter.GetRuntimeType(targetPlatform),
|
||||
"]]");
|
||||
}
|
||||
|
||||
protected internal override void Write(ContentWriter output, T[] value)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
output.Write(value.Length);
|
||||
foreach (var element in value)
|
||||
output.WriteObject(element, _elementWriter);
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// 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 Microsoft.Xna.Framework.Content.Pipeline.Graphics;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
class BasicEffectWriter : BuiltInContentWriter<BasicMaterialContent>
|
||||
{
|
||||
protected internal override void Write(ContentWriter output, BasicMaterialContent value)
|
||||
{
|
||||
output.WriteExternalReference(value.Textures.ContainsKey(BasicMaterialContent.TextureKey) ? value.Texture : null);
|
||||
output.Write(value.DiffuseColor ?? new Vector3(1, 1, 1));
|
||||
output.Write(value.EmissiveColor ?? new Vector3(0, 0, 0));
|
||||
output.Write(value.SpecularColor ?? new Vector3(1, 1, 1));
|
||||
output.Write(value.SpecularPower ?? 16);
|
||||
output.Write(value.Alpha ?? 1);
|
||||
output.Write(value.VertexColorEnabled ?? false);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = System.Boolean;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the boolean value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class BooleanWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// 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 TOutput = Microsoft.Xna.Framework.BoundingBox;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the BoundingBox value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class BoundingBoxWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value.Min);
|
||||
output.Write(value.Max);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = Microsoft.Xna.Framework.BoundingFrustum;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the BoundingFrustum value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class BoundingFrustumWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value.Matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// 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 TOutput = Microsoft.Xna.Framework.BoundingSphere;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the BoundingSphere value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class BoundingSphereWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value.Center);
|
||||
output.Write(value.Radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
// 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.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for the built-in content type writers where the content type is the same as the runtime type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type being written.</typeparam>
|
||||
class BuiltInContentWriter<T> : ContentTypeWriter<T>
|
||||
{
|
||||
private List<ContentTypeWriter> _genericTypes;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal override void OnAddedToContentWriter(ContentWriter output)
|
||||
{
|
||||
base.OnAddedToContentWriter(output);
|
||||
|
||||
if (TargetType.IsGenericType)
|
||||
{
|
||||
_genericTypes = new List<ContentTypeWriter>();
|
||||
var arguments = TargetType.GetGenericArguments();
|
||||
foreach (var arg in arguments)
|
||||
_genericTypes.Add(output.GetTypeWriter(arg));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, T value)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assembly qualified name of the runtime loader for this type.
|
||||
/// </summary>
|
||||
/// <param name="targetPlatform">Name of the platform.</param>
|
||||
/// <returns>Name of the runtime loader.</returns>
|
||||
public override string GetRuntimeReader(TargetPlatform targetPlatform)
|
||||
{
|
||||
// Change "Writer" in this class name to "Reader" and use the runtime type namespace and assembly
|
||||
var readerClassName = this.GetType().Name.Replace("Writer", "Reader");
|
||||
|
||||
// Add generic arguments if they exist.
|
||||
if (_genericTypes != null)
|
||||
{
|
||||
readerClassName += "[";
|
||||
foreach (var argWriter in _genericTypes)
|
||||
{
|
||||
readerClassName += "[";
|
||||
readerClassName += argWriter.GetRuntimeType(targetPlatform);
|
||||
readerClassName += "]";
|
||||
// Important: Do not add a space char after the comma because
|
||||
// this will not work with Type.GetType in Xamarin.Android!
|
||||
readerClassName += ",";
|
||||
}
|
||||
readerClassName = readerClassName.TrimEnd(',', ' ');
|
||||
readerClassName += "]";
|
||||
}
|
||||
|
||||
// From looking at XNA-produced XNBs, it appears built-in
|
||||
// type readers don't need assembly qualification.
|
||||
var readerNamespace = typeof(ContentTypeReader).Namespace;
|
||||
return readerNamespace + "." + readerClassName;
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = System.Byte;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the unsigned byte value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class ByteWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = System.Char;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the character value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class CharWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = Microsoft.Xna.Framework.Color;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the Color value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class ColorWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 Microsoft.Xna.Framework.Content.Pipeline.Processors;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
class CompiledEffectContentWriter : BuiltInContentWriter<CompiledEffectContent>
|
||||
{
|
||||
protected internal override void Write(ContentWriter output, CompiledEffectContent value)
|
||||
{
|
||||
var code = value.GetEffectCode();
|
||||
output.Write(code.Length);
|
||||
output.Write(code);
|
||||
}
|
||||
|
||||
public override string GetRuntimeReader(TargetPlatform targetPlatform)
|
||||
{
|
||||
var type = typeof(ContentReader);
|
||||
var readerType = type.Namespace + ".EffectReader, " + type.Assembly.FullName;
|
||||
return readerType;
|
||||
}
|
||||
}
|
||||
}
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
// 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.IO;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides methods for writing compiled binary format.
|
||||
/// </summary>
|
||||
public sealed class ContentCompiler
|
||||
{
|
||||
readonly Dictionary<Type, Type> typeWriterMap = new Dictionary<Type, Type>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of ContentCompiler.
|
||||
/// </summary>
|
||||
public ContentCompiler()
|
||||
{
|
||||
GetTypeWriters();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Iterates through all loaded assemblies and finds the content type writers.
|
||||
/// </summary>
|
||||
void GetTypeWriters()
|
||||
{
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
Type[] exportedTypes;
|
||||
try
|
||||
{
|
||||
exportedTypes = assembly.GetTypes();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var contentTypeWriterType = typeof(ContentTypeWriter<>);
|
||||
foreach (var type in exportedTypes)
|
||||
{
|
||||
if (type.IsAbstract)
|
||||
continue;
|
||||
if (Attribute.IsDefined(type, typeof(ContentTypeWriterAttribute)))
|
||||
{
|
||||
// Find the content type this writer implements
|
||||
Type baseType = type.BaseType;
|
||||
while ((baseType != null) && (baseType.GetGenericTypeDefinition() != contentTypeWriterType))
|
||||
baseType = baseType.BaseType;
|
||||
if (baseType != null)
|
||||
typeWriterMap.Add(baseType, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the worker writer for the specified type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns>The worker writer.</returns>
|
||||
/// <remarks>This should be called from the ContentTypeWriter.Initialize method.</remarks>
|
||||
public ContentTypeWriter GetTypeWriter(Type type)
|
||||
{
|
||||
ContentTypeWriter result = null;
|
||||
var contentTypeWriterType = typeof(ContentTypeWriter<>).MakeGenericType(type);
|
||||
Type typeWriterType;
|
||||
|
||||
if (type == typeof(Array))
|
||||
result = new ArrayWriter<Array>();
|
||||
else if (typeWriterMap.TryGetValue(contentTypeWriterType, out typeWriterType))
|
||||
result = (ContentTypeWriter)Activator.CreateInstance(typeWriterType);
|
||||
else if (type.IsArray)
|
||||
{
|
||||
var writerType = type.GetArrayRank() == 1 ? typeof(ArrayWriter<>) : typeof(MultiArrayWriter<>);
|
||||
|
||||
result = (ContentTypeWriter)Activator.CreateInstance(writerType.MakeGenericType(type.GetElementType()));
|
||||
typeWriterMap.Add(contentTypeWriterType, result.GetType());
|
||||
}
|
||||
else if (type.IsEnum)
|
||||
{
|
||||
result = (ContentTypeWriter)Activator.CreateInstance(typeof(EnumWriter<>).MakeGenericType(type));
|
||||
typeWriterMap.Add(contentTypeWriterType, result.GetType());
|
||||
}
|
||||
else if (type.IsGenericType)
|
||||
{
|
||||
var inputTypeDef = type.GetGenericTypeDefinition();
|
||||
|
||||
Type chosen = null;
|
||||
foreach (var kvp in typeWriterMap)
|
||||
{
|
||||
var args = kvp.Key.GetGenericArguments();
|
||||
|
||||
if (args.Length == 0)
|
||||
continue;
|
||||
|
||||
if (!kvp.Value.IsGenericTypeDefinition)
|
||||
continue;
|
||||
|
||||
if (!args[0].IsGenericType)
|
||||
continue;
|
||||
|
||||
// Compare generic type definition
|
||||
var keyTypeDef = args[0].GetGenericTypeDefinition();
|
||||
if (inputTypeDef == keyTypeDef)
|
||||
{
|
||||
chosen = kvp.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (chosen == null)
|
||||
result = (ContentTypeWriter)Activator.CreateInstance(typeof(ReflectiveWriter<>).MakeGenericType(type));
|
||||
else
|
||||
{
|
||||
var concreteType = type.GetGenericArguments();
|
||||
result = (ContentTypeWriter)Activator.CreateInstance(chosen.MakeGenericType(concreteType));
|
||||
}
|
||||
|
||||
// save it for next time.
|
||||
typeWriterMap.Add(contentTypeWriterType, result.GetType());
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new InvalidContentException(String.Format("Could not find ContentTypeWriter for type '{0}'", type.Name));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (ContentTypeWriter)Activator.CreateInstance(typeof(ReflectiveWriter<>).MakeGenericType(type));
|
||||
typeWriterMap.Add(contentTypeWriterType, result.GetType());
|
||||
}
|
||||
|
||||
|
||||
var initMethod = result.GetType().GetMethod("Initialize", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
initMethod.Invoke(result, new object[] { this });
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the content to a XNB file.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to write the XNB file to.</param>
|
||||
/// <param name="content">The content to write to the XNB file.</param>
|
||||
/// <param name="targetPlatform">The platform the XNB is intended for.</param>
|
||||
/// <param name="targetProfile">The graphics profile of the target.</param>
|
||||
/// <param name="compressContent">True if the content should be compressed.</param>
|
||||
/// <param name="rootDirectory">The root directory of the content.</param>
|
||||
/// <param name="referenceRelocationPath">The path of the XNB file, used to calculate relative paths for external references.</param>
|
||||
public void Compile(Stream stream, object content, TargetPlatform targetPlatform, GraphicsProfile targetProfile, bool compressContent, string rootDirectory, string referenceRelocationPath)
|
||||
{
|
||||
using (var writer = new ContentWriter(this, stream, targetPlatform, targetProfile, compressContent, rootDirectory, referenceRelocationPath))
|
||||
{
|
||||
writer.WriteObject(content);
|
||||
writer.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
// 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.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides methods and properties for compiling a specific managed type into a binary format.
|
||||
/// </summary>
|
||||
public abstract class ContentTypeWriter
|
||||
{
|
||||
private readonly Type _targetType;
|
||||
protected int _typeVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Determines if deserialization into an existing object is possible.
|
||||
/// </summary>
|
||||
/// <value>true if the object can be deserialized into; false otherwise.</value>
|
||||
public virtual bool CanDeserializeIntoExistingObject
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type handled by this compiler component.
|
||||
/// </summary>
|
||||
/// <value>The type handled by this compiler component.</value>
|
||||
public Type TargetType { get { return _targetType; } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a format version number for this type.
|
||||
/// </summary>
|
||||
/// <value>A format version number for this type.</value>
|
||||
public virtual int TypeVersion { get { return _typeVersion; } }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ContentTypeWriter class.
|
||||
/// </summary>
|
||||
/// <param name="targetType"></param>
|
||||
protected ContentTypeWriter(Type targetType)
|
||||
{
|
||||
if (targetType == null)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
_targetType = targetType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assembly qualified name of the runtime loader for this type.
|
||||
/// </summary>
|
||||
/// <param name="targetPlatform">Name of the platform.</param>
|
||||
/// <returns>Name of the runtime loader.</returns>
|
||||
public abstract string GetRuntimeReader(TargetPlatform targetPlatform);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assembly qualified name of the runtime target type. The runtime target type often matches the design time type, but may differ.
|
||||
/// </summary>
|
||||
/// <param name="targetPlatform">The target platform.</param>
|
||||
/// <returns>The qualified name.</returns>
|
||||
public virtual string GetRuntimeType(TargetPlatform targetPlatform)
|
||||
{
|
||||
return _targetType.FullName + ", " + _targetType.Assembly.FullName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves and caches nested type writers and allows for reflection over the target data type. Called by the framework at creation time.
|
||||
/// </summary>
|
||||
/// <param name="compiler">The content compiler.</param>
|
||||
protected virtual void Initialize(ContentCompiler compiler)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows type writers to add their element type writers to the content writer.
|
||||
/// </summary>
|
||||
/// <param name="writer">The content writer.</param>
|
||||
internal virtual void OnAddedToContentWriter(ContentWriter writer)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether a given type of content should be compressed.
|
||||
/// </summary>
|
||||
/// <param name="targetPlatform">The target platform of the content build.</param>
|
||||
/// <param name="value">The object about to be serialized, or null if a collection of objects is to be serialized.</param>
|
||||
/// <returns>true if the content of the requested type should be compressed; false otherwise.</returns>
|
||||
/// <remarks>This base class implementation of this method always returns true. It should be overridden
|
||||
/// to return false if there would be little or no useful reduction in size of the content type's data
|
||||
/// from a general-purpose lossless compression algorithm.
|
||||
/// The implementations for Song Class and SoundEffect Class data return false because data for these
|
||||
/// content types is already in compressed form.</remarks>
|
||||
protected internal virtual bool ShouldCompressContent(TargetPlatform targetPlatform, object value)
|
||||
{
|
||||
// For now, only support uncompressed
|
||||
return false;
|
||||
|
||||
//switch (targetPlatform)
|
||||
//{
|
||||
// case TargetPlatform.Windows:
|
||||
// case TargetPlatform.Linux:
|
||||
// case TargetPlatform.MacOSX:
|
||||
// case TargetPlatform.WindowsStoreApp:
|
||||
// return true;
|
||||
// default:
|
||||
// return false;
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compiles an object into binary format.
|
||||
/// </summary>
|
||||
/// <param name="output">The content writer serializing the value.</param>
|
||||
/// <param name="value">The resultant object.</param>
|
||||
protected internal abstract void Write(ContentWriter output, object value);
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// 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.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Identifies the components of a type writer. Custom content writers must apply this attribute to their class as well as extend the ContentTypeWriter class.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class ContentTypeWriterAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ContentTypeWriterAttribute class.
|
||||
/// </summary>
|
||||
public ContentTypeWriterAttribute()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// 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.
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a generic implementation of ContentTypeWriter methods and properties for compiling a specific managed type into a binary format.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to write</typeparam>
|
||||
/// <remarks>This is a generic implementation of ContentTypeWriter and, therefore, can handle strongly typed content data.</remarks>
|
||||
public abstract class ContentTypeWriter<T> : ContentTypeWriter
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ContentTypeWriter class.
|
||||
/// </summary>
|
||||
protected ContentTypeWriter()
|
||||
: base(typeof(T))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compiles a strongly typed object into binary format.
|
||||
/// </summary>
|
||||
/// <param name="output">The content writer serializing the value.</param>
|
||||
/// <param name="value">The value to write.</param>
|
||||
protected internal override void Write(ContentWriter output, object value)
|
||||
{
|
||||
Write(output, (T)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compiles a strongly typed object into binary format.
|
||||
/// </summary>
|
||||
/// <param name="output">The content writer serializing the value.</param>
|
||||
/// <param name="value">The value to write.</param>
|
||||
protected internal abstract void Write(ContentWriter output, T value);
|
||||
}
|
||||
}
|
||||
+528
@@ -0,0 +1,528 @@
|
||||
// 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.IO;
|
||||
using Microsoft.Xna.Framework.Content.Pipeline.Utilities.LZ4;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using MonoGame.Framework.Content.Pipeline.Builder;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation for many of the ContentCompiler methods including compilation, state tracking for shared resources and creation of the header type manifest.
|
||||
/// </summary>
|
||||
/// <remarks>A new ContentWriter is constructed for each compilation operation.</remarks>
|
||||
public sealed class ContentWriter : BinaryWriter
|
||||
{
|
||||
const byte XnbFormatVersion = 5;
|
||||
const byte HiDefContent = 0x01;
|
||||
const byte ContentCompressedLzx = 0x80;
|
||||
const byte ContentCompressedLz4 = 0x40;
|
||||
const int HeaderSize = 6;
|
||||
|
||||
ContentCompiler compiler;
|
||||
TargetPlatform targetPlatform;
|
||||
GraphicsProfile targetProfile;
|
||||
string rootDirectory;
|
||||
string referenceRelocationPath;
|
||||
bool compressContent;
|
||||
bool disposed;
|
||||
List<ContentTypeWriter> typeWriters = new List<ContentTypeWriter>();
|
||||
Dictionary<Type, int> typeWriterMap = new Dictionary<Type, int>();
|
||||
Dictionary<Type, ContentTypeWriter> typeMap = new Dictionary<Type, ContentTypeWriter>();
|
||||
List<object> sharedResources = new List<object>();
|
||||
Dictionary<object, int> sharedResourceMap = new Dictionary<object, int>();
|
||||
Stream outputStream;
|
||||
Stream bodyStream;
|
||||
|
||||
// This array must remain in sync with TargetPlatform
|
||||
static char[] targetPlatformIdentifiers = new[]
|
||||
{
|
||||
'w', // Windows (DirectX)
|
||||
'x', // Xbox360
|
||||
'i', // iOS
|
||||
'a', // Android
|
||||
'd', // DesktopGL
|
||||
'X', // MacOSX
|
||||
'W', // WindowsStoreApp
|
||||
'n', // NativeClient
|
||||
'p', // PlayStationMobile
|
||||
'M', // WindowsPhone8
|
||||
'r', // RaspberryPi
|
||||
'P', // PlayStation4
|
||||
'v', // PSVita
|
||||
'O', // XboxOne
|
||||
'S', // Nintendo Switch
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content build target platform.
|
||||
/// </summary>
|
||||
public TargetPlatform TargetPlatform { get { return targetPlatform; } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the target graphics profile.
|
||||
/// </summary>
|
||||
public GraphicsProfile TargetProfile { get { return targetProfile; } }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of ContentWriter.
|
||||
/// </summary>
|
||||
/// <param name="compiler">The compiler object that created this writer.</param>
|
||||
/// <param name="output">The stream to write the XNB file to.</param>
|
||||
/// <param name="targetPlatform">The platform the XNB is intended for.</param>
|
||||
/// <param name="targetProfile">The graphics profile of the target.</param>
|
||||
/// <param name="compressContent">True if the content should be compressed.</param>
|
||||
/// <param name="rootDirectory">The root directory of the content.</param>
|
||||
/// <param name="referenceRelocationPath">The path of the XNB file, used to calculate relative paths for external references.</param>
|
||||
internal ContentWriter(ContentCompiler compiler, Stream output, TargetPlatform targetPlatform, GraphicsProfile targetProfile, bool compressContent, string rootDirectory, string referenceRelocationPath)
|
||||
: base(output)
|
||||
{
|
||||
this.compiler = compiler;
|
||||
this.targetPlatform = targetPlatform;
|
||||
this.targetProfile = targetProfile;
|
||||
this.compressContent = compressContent;
|
||||
this.rootDirectory = rootDirectory;
|
||||
|
||||
// Normalize the directory format so PathHelper.GetRelativePath will compute external references correctly.
|
||||
this.referenceRelocationPath = PathHelper.NormalizeDirectory(referenceRelocationPath);
|
||||
|
||||
outputStream = this.OutStream;
|
||||
bodyStream = new MemoryStream();
|
||||
this.OutStream = bodyStream;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases the resources used by the IDisposable class.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// Make sure the binary writer has the original stream back
|
||||
this.OutStream = outputStream;
|
||||
|
||||
// Dispose managed resources we allocated
|
||||
if (bodyStream != null)
|
||||
bodyStream.Dispose();
|
||||
bodyStream = null;
|
||||
}
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// All content has been written, so now finalize the header, footer and anything else that needs finalizing.
|
||||
/// </summary>
|
||||
public override void Flush()
|
||||
{
|
||||
// Write shared resources to the end of body stream
|
||||
WriteSharedResources();
|
||||
|
||||
using (var contentStream = new MemoryStream())
|
||||
{
|
||||
this.OutStream = contentStream;
|
||||
WriteTypeWriters();
|
||||
bodyStream.Position = 0;
|
||||
bodyStream.CopyTo(contentStream);
|
||||
contentStream.Position = 0;
|
||||
|
||||
// Before we write the header, try to compress the body stream. If compression fails, we want to
|
||||
// turn off the compressContent flag so the correct flags are written in the header
|
||||
Stream compressedStream = null;
|
||||
try
|
||||
{
|
||||
if (compressContent)
|
||||
{
|
||||
compressedStream = new MemoryStream();
|
||||
this.OutStream = compressedStream;
|
||||
if (!WriteCompressedStream(contentStream))
|
||||
{
|
||||
// The compression failed (sometimes LZ4 does fail, for various reasons), so just write
|
||||
// it out uncompressed.
|
||||
compressContent = false;
|
||||
compressedStream.Dispose();
|
||||
compressedStream = null;
|
||||
}
|
||||
}
|
||||
|
||||
this.OutStream = outputStream;
|
||||
WriteHeader();
|
||||
if (compressedStream != null)
|
||||
{
|
||||
compressedStream.Position = 0;
|
||||
compressedStream.CopyTo(outputStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteUncompressedStream(contentStream);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (compressedStream != null)
|
||||
compressedStream.Dispose();
|
||||
}
|
||||
}
|
||||
base.Flush();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the table of content type writers.
|
||||
/// </summary>
|
||||
void WriteTypeWriters()
|
||||
{
|
||||
Write7BitEncodedInt(typeWriters.Count);
|
||||
foreach (var typeWriter in typeWriters)
|
||||
{
|
||||
Write(typeWriter.GetRuntimeReader(targetPlatform));
|
||||
Write(typeWriter.TypeVersion);
|
||||
}
|
||||
Write7BitEncodedInt(sharedResources.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the header to the output stream.
|
||||
/// </summary>
|
||||
void WriteHeader()
|
||||
{
|
||||
Write('X');
|
||||
Write('N');
|
||||
Write('B');
|
||||
Write(targetPlatformIdentifiers[(int)targetPlatform]);
|
||||
Write(XnbFormatVersion);
|
||||
// We cannot use LZX compression, so we use the public domain LZ4 compression. Use one of the spare bits in the flags byte to specify LZ4.
|
||||
byte flags = (byte)((targetProfile == GraphicsProfile.HiDef ? HiDefContent : (byte)0) | (compressContent ? ContentCompressedLz4 : (byte)0));
|
||||
Write(flags);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write all shared resources at the end of the file.
|
||||
/// </summary>
|
||||
void WriteSharedResources()
|
||||
{
|
||||
for (int i = 0; i < sharedResources.Count; i++)
|
||||
{
|
||||
var resource = sharedResources[i];
|
||||
WriteObject<object>(resource);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compress the stream and write it to the output.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to compress and write to the output.</param>
|
||||
/// <returns>true if the write succeeds</returns>
|
||||
bool WriteCompressedStream(MemoryStream stream)
|
||||
{
|
||||
// Compress stream
|
||||
var maxLength = LZ4Codec.MaximumOutputLength((int)stream.Length);
|
||||
var outputArray = new byte[maxLength * 2];
|
||||
int resultLength = LZ4Codec.Encode32HC(stream.GetBuffer(), 0, (int)stream.Length, outputArray, 0, maxLength);
|
||||
if (resultLength < 0)
|
||||
return false;
|
||||
UInt32 totalSize = (UInt32)(HeaderSize + resultLength + sizeof(UInt32) + sizeof(UInt32));
|
||||
Write(totalSize);
|
||||
Write((int)stream.Length);
|
||||
OutStream.Write(outputArray, 0, resultLength);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the uncompressed stream to the output.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to write to the output.</param>
|
||||
/// <returns>true if the write succeeds</returns>
|
||||
bool WriteUncompressedStream(Stream stream)
|
||||
{
|
||||
UInt32 totalSize = (UInt32)(HeaderSize + stream.Length + sizeof(UInt32));
|
||||
Write(totalSize);
|
||||
stream.CopyTo(OutStream);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a ContentTypeWriter for the given type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type of the object to write.</param>
|
||||
/// <returns>The ContentTypeWriter for the type.</returns>
|
||||
internal ContentTypeWriter GetTypeWriter(Type type)
|
||||
{
|
||||
ContentTypeWriter typeWriter = null;
|
||||
if (!typeMap.TryGetValue(type, out typeWriter))
|
||||
{
|
||||
int index = typeWriters.Count;
|
||||
typeWriter = compiler.GetTypeWriter(type);
|
||||
|
||||
typeWriters.Add(typeWriter);
|
||||
if (!typeWriterMap.ContainsKey(typeWriter.GetType()))
|
||||
typeWriterMap.Add(typeWriter.GetType(), index);
|
||||
|
||||
typeMap.Add(type, typeWriter);
|
||||
|
||||
typeWriter.OnAddedToContentWriter(this);
|
||||
}
|
||||
return typeWriter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the name of an external file to the output binary.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of reference.</typeparam>
|
||||
/// <param name="reference">External reference to a data file for the content item.</param>
|
||||
public void WriteExternalReference<T>(ExternalReference<T> reference)
|
||||
{
|
||||
if (reference == null)
|
||||
{
|
||||
Write(string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
string fileName = reference.Filename;
|
||||
if (string.IsNullOrEmpty(fileName))
|
||||
{
|
||||
Write(string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure the filename ends with .xnb
|
||||
if (!fileName.EndsWith(".xnb"))
|
||||
throw new ArgumentException(string.Format("ExternalReference '{0}' must reference a .xnb file", fileName));
|
||||
// Make sure it is in the same root directory
|
||||
if (!fileName.StartsWith(rootDirectory, StringComparison.OrdinalIgnoreCase))
|
||||
throw new ArgumentException(string.Format("ExternalReference '{0}' must be in the root directory '{1}'", fileName, rootDirectory));
|
||||
// Strip the .xnb extension
|
||||
fileName = fileName.Substring(0, fileName.Length - 4);
|
||||
// Get the relative directory
|
||||
fileName = PathHelper.GetRelativePath(referenceRelocationPath, fileName);
|
||||
Write(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a single object preceded by a type identifier to the output binary.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of value.</typeparam>
|
||||
/// <param name="value">The value to write.</param>
|
||||
/// <remarks>This method can be called recursively with a null value.</remarks>
|
||||
public void WriteObject<T>(T value)
|
||||
{
|
||||
if (value == null)
|
||||
Write7BitEncodedInt(0);
|
||||
else
|
||||
{
|
||||
var typeWriter = GetTypeWriter(value.GetType());
|
||||
|
||||
// Because zero means null object, we add one to
|
||||
// the index before writing it to the file.
|
||||
var index = typeWriterMap[typeWriter.GetType()];
|
||||
Write7BitEncodedInt(index + 1);
|
||||
|
||||
typeWriter.Write(this, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a single object to the output binary, using the specified type hint and writer worker.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of value.</typeparam>
|
||||
/// <param name="value">The value to write.</param>
|
||||
/// <param name="typeWriter">The content type writer.</param>
|
||||
/// <remarks>The type hint should be retrieved from the Initialize method of the ContentTypeWriter
|
||||
/// that is calling WriteObject, by calling GetTypeWriter and passing it the type of the field used
|
||||
/// to hold the value being serialized.
|
||||
/// </remarks>
|
||||
public void WriteObject<T>(T value, ContentTypeWriter typeWriter)
|
||||
{
|
||||
if (typeWriter == null)
|
||||
throw new ArgumentNullException("typeWriter");
|
||||
|
||||
if (typeWriter.TargetType.IsValueType)
|
||||
typeWriter.Write(this, value);
|
||||
else
|
||||
WriteObject(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a single object to the output binary as an instance of the specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of value.</typeparam>
|
||||
/// <param name="value">The value to write.</param>
|
||||
/// <remarks>If you specify a base class of the actual object value only data from this base type
|
||||
/// will be written. This method does not write any type identifier so it cannot support null or
|
||||
/// polymorphic values, and the reader must specify an identical type while loading the compiled data.</remarks>
|
||||
public void WriteRawObject<T>(T value)
|
||||
{
|
||||
WriteRawObject<T>(value, GetTypeWriter(typeof(T)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a single object to the output binary using the specified writer worker.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of value.</typeparam>
|
||||
/// <param name="value">The value to write.</param>
|
||||
/// <param name="typeWriter">The writer worker. This should be looked up from the Initialize method
|
||||
/// of the ContentTypeWriter that is calling WriteRawObject, by calling GetTypeWriter.</param>
|
||||
/// <remarks>WriteRawObject does not write any type identifier, so it cannot support null or polymorphic
|
||||
/// values, and the reader must specify an identical type while loading the compiled data.</remarks>
|
||||
public void WriteRawObject<T>(T value, ContentTypeWriter typeWriter)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
if (typeWriter == null)
|
||||
throw new ArgumentNullException("typeWriter");
|
||||
|
||||
typeWriter.Write(this, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a shared reference to the output binary and records the object to be serialized later.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of value.</typeparam>
|
||||
/// <param name="value">The object to record.</param>
|
||||
public void WriteSharedResource<T>(T value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
// Zero means a null value
|
||||
Write7BitEncodedInt(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int index;
|
||||
if (!sharedResourceMap.TryGetValue(value, out index))
|
||||
{
|
||||
// Add it to the list of shared resources
|
||||
index = sharedResources.Count;
|
||||
sharedResources.Add(value);
|
||||
sharedResourceMap.Add(value, index);
|
||||
}
|
||||
// Because zero means null value, we add one before writing the index to the file
|
||||
Write7BitEncodedInt(index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a Color value.
|
||||
/// </summary>
|
||||
/// <param name="value">Value of a color using Red, Green, Blue, and Alpha values to write.</param>
|
||||
public void Write(Color value)
|
||||
{
|
||||
Write(value.R);
|
||||
Write(value.G);
|
||||
Write(value.B);
|
||||
Write(value.A);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a Matrix value.
|
||||
/// </summary>
|
||||
/// <param name="value">Value to write.</param>
|
||||
public void Write(Matrix value)
|
||||
{
|
||||
Write(value.M11);
|
||||
Write(value.M12);
|
||||
Write(value.M13);
|
||||
Write(value.M14);
|
||||
Write(value.M21);
|
||||
Write(value.M22);
|
||||
Write(value.M23);
|
||||
Write(value.M24);
|
||||
Write(value.M31);
|
||||
Write(value.M32);
|
||||
Write(value.M33);
|
||||
Write(value.M34);
|
||||
Write(value.M41);
|
||||
Write(value.M42);
|
||||
Write(value.M43);
|
||||
Write(value.M44);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a Matrix value.
|
||||
/// </summary>
|
||||
/// <param name="value">Value to write.</param>
|
||||
public void Write(Quaternion value)
|
||||
{
|
||||
Write(value.X);
|
||||
Write(value.Y);
|
||||
Write(value.Z);
|
||||
Write(value.W);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a Vector2 value.
|
||||
/// </summary>
|
||||
/// <param name="value">Value to write.</param>
|
||||
public void Write(Vector2 value)
|
||||
{
|
||||
Write(value.X);
|
||||
Write(value.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a Vector3 value.
|
||||
/// </summary>
|
||||
/// <param name="value">Value to write.</param>
|
||||
public void Write(Vector3 value)
|
||||
{
|
||||
Write(value.X);
|
||||
Write(value.Y);
|
||||
Write(value.Z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a Vector4 value.
|
||||
/// </summary>
|
||||
/// <param name="value">Value to write.</param>
|
||||
public void Write(Vector4 value)
|
||||
{
|
||||
Write(value.X);
|
||||
Write(value.Y);
|
||||
Write(value.Z);
|
||||
Write(value.W);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a BoundingSphere value.
|
||||
/// </summary>
|
||||
/// <param name="value">Value to write.</param>
|
||||
internal void Write(BoundingSphere value)
|
||||
{
|
||||
Write(value.Center);
|
||||
Write(value.Radius);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a Rectangle value.
|
||||
/// </summary>
|
||||
/// <param name="value">Value to write.</param>
|
||||
internal void Write(Rectangle value)
|
||||
{
|
||||
Write(value.X);
|
||||
Write(value.Y);
|
||||
Write(value.Width);
|
||||
Write(value.Height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper for checking if a type can be deserialized into an existing object.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to check.</param>
|
||||
/// <returns>True if the type can be deserialized into an existing object.</returns>
|
||||
internal bool CanDeserializeIntoExistingObject(Type type)
|
||||
{
|
||||
var typeWriter = compiler.GetTypeWriter(type);
|
||||
return typeWriter != null && typeWriter.CanDeserializeIntoExistingObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -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 TOutput = Microsoft.Xna.Framework.Curve;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the Curve value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class CurveWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write((Int32)value.PreLoop);
|
||||
output.Write((Int32)value.PostLoop);
|
||||
output.Write(value.Keys.Count);
|
||||
foreach (var key in value.Keys)
|
||||
{
|
||||
output.Write(key.Position);
|
||||
output.Write(key.Value);
|
||||
output.Write(key.TangentIn);
|
||||
output.Write(key.TangentOut);
|
||||
output.Write((Int32)key.Continuity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -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;
|
||||
using TOutput = System.DateTime;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the DateTime value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class DateTimeWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
UInt64 ticks = (UInt64)value.Ticks & ~((UInt64)0xC << 62);
|
||||
UInt64 kind = (UInt64)value.Kind << 62;
|
||||
output.Write((UInt64)(ticks | kind));
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = System.Decimal;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the decimal value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class DecimalWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
// 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.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the dictionary to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class DictionaryWriter<K,V> : BuiltInContentWriter<Dictionary<K,V>>
|
||||
{
|
||||
ContentTypeWriter _keyWriter;
|
||||
ContentTypeWriter _valueWriter;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal override void OnAddedToContentWriter(ContentWriter output)
|
||||
{
|
||||
base.OnAddedToContentWriter(output);
|
||||
|
||||
_keyWriter = output.GetTypeWriter(typeof(K));
|
||||
_valueWriter = output.GetTypeWriter(typeof(V));
|
||||
}
|
||||
|
||||
public override bool CanDeserializeIntoExistingObject
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
protected internal override void Write(ContentWriter output, Dictionary<K,V> value)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
output.Write(value.Count);
|
||||
foreach (var element in value)
|
||||
{
|
||||
output.WriteObject(element.Key, _keyWriter);
|
||||
output.WriteObject(element.Value, _valueWriter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = System.Double;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the double precision floating point value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class DoubleWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// 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 Microsoft.Xna.Framework.Content.Pipeline.Graphics;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
class DualTextureEffectWriter : BuiltInContentWriter<DualTextureMaterialContent>
|
||||
{
|
||||
protected internal override void Write(ContentWriter output, DualTextureMaterialContent value)
|
||||
{
|
||||
output.WriteExternalReference(value.Textures.ContainsKey(DualTextureMaterialContent.TextureKey) ? value.Texture : null);
|
||||
output.WriteExternalReference(value.Textures.ContainsKey(DualTextureMaterialContent.Texture2Key) ? value.Texture2 : null);
|
||||
output.Write(value.DiffuseColor.HasValue ? value.DiffuseColor.Value : Vector3.One);
|
||||
output.Write(value.Alpha.HasValue ? value.Alpha.Value : 1.0f);
|
||||
output.Write(value.VertexColorEnabled.HasValue ? value.VertexColorEnabled.Value : false);
|
||||
}
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// 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 Microsoft.Xna.Framework.Content.Pipeline.Graphics;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
class EffectMaterialWriter : BuiltInContentWriter<EffectMaterialContent>
|
||||
{
|
||||
protected internal override void Write(ContentWriter output, EffectMaterialContent value)
|
||||
{
|
||||
output.WriteExternalReference(value.CompiledEffect);
|
||||
var dict = new Dictionary<string, object>();
|
||||
foreach (var item in value.Textures)
|
||||
{
|
||||
dict.Add(item.Key, item.Value);
|
||||
}
|
||||
foreach (var item in value.OpaqueData)
|
||||
{
|
||||
if (item.Key != EffectMaterialContent.EffectKey && item.Key != EffectMaterialContent.CompiledEffectKey)
|
||||
dict.Add(item.Key, item.Value);
|
||||
}
|
||||
output.WriteObject(dict);
|
||||
}
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// 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.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the enum value to the output. Usually 32 bit, but can be other sizes if T is not integer.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The enum type to write.</typeparam>
|
||||
[ContentTypeWriter]
|
||||
class EnumWriter<T> : BuiltInContentWriter<T>
|
||||
{
|
||||
Type _underlyingType;
|
||||
ContentTypeWriter _underlyingTypeWriter;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal override void OnAddedToContentWriter(ContentWriter output)
|
||||
{
|
||||
base.OnAddedToContentWriter(output);
|
||||
_underlyingType = Enum.GetUnderlyingType(typeof(T));
|
||||
_underlyingTypeWriter = output.GetTypeWriter(_underlyingType);
|
||||
}
|
||||
|
||||
public override string GetRuntimeReader(TargetPlatform targetPlatform)
|
||||
{
|
||||
return "Microsoft.Xna.Framework.Content.EnumReader`1[[" + GetRuntimeType(targetPlatform) + "]]";
|
||||
}
|
||||
|
||||
protected internal override void Write(ContentWriter output, T value)
|
||||
{
|
||||
output.WriteRawObject(Convert.ChangeType(value, _underlyingType), _underlyingTypeWriter);
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// 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 Microsoft.Xna.Framework.Content.Pipeline.Graphics;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
class EnvironmentMapEffectWriter : BuiltInContentWriter<EnvironmentMapMaterialContent>
|
||||
{
|
||||
protected internal override void Write(ContentWriter output, EnvironmentMapMaterialContent value)
|
||||
{
|
||||
output.WriteExternalReference(value.Textures.ContainsKey(EnvironmentMapMaterialContent.TextureKey) ? value.Texture : null);
|
||||
output.WriteExternalReference(value.Textures.ContainsKey(EnvironmentMapMaterialContent.EnvironmentMapKey) ? value.EnvironmentMap : null);
|
||||
output.Write(value.EnvironmentMapAmount.HasValue ? value.EnvironmentMapAmount.Value : 1.0f);
|
||||
output.Write(value.EnvironmentMapSpecular.HasValue ? value.EnvironmentMapSpecular.Value : Vector3.Zero);
|
||||
output.Write(value.DiffuseColor.HasValue ? value.DiffuseColor.Value : Vector3.One);
|
||||
output.Write(value.EmissiveColor.HasValue ? value.EmissiveColor.Value : Vector3.Zero);
|
||||
output.Write(value.Alpha.HasValue ? value.Alpha.Value : 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
// 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.
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the external reference to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class ExternalReferenceWriter<T> : BuiltInContentWriter<ExternalReference<T>>
|
||||
{
|
||||
private ContentTypeWriter _targetWriter;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal override void OnAddedToContentWriter(ContentWriter output)
|
||||
{
|
||||
base.OnAddedToContentWriter(output);
|
||||
_targetWriter = output.GetTypeWriter(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, ExternalReference<T> value)
|
||||
{
|
||||
output.WriteExternalReference(value);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string GetRuntimeReader(TargetPlatform targetPlatform)
|
||||
{
|
||||
var type = typeof(ContentReader);
|
||||
var readerType = type.Namespace + ".ExternalReferenceReader, " + type.Assembly.FullName;
|
||||
return readerType;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string GetRuntimeType(TargetPlatform targetPlatform)
|
||||
{
|
||||
return _targetWriter.GetRuntimeType(targetPlatform);
|
||||
}
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
// 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 Microsoft.Xna.Framework.Content.Pipeline.Graphics;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
class IndexBufferWriter : BuiltInContentWriter<IndexCollection>
|
||||
{
|
||||
protected internal override void Write(ContentWriter output, IndexCollection value)
|
||||
{
|
||||
// Check if the buffer and can be saved as Int16.
|
||||
var shortIndices = true;
|
||||
foreach(var index in value)
|
||||
{
|
||||
if(index > ushort.MaxValue)
|
||||
{
|
||||
shortIndices = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
output.Write(shortIndices);
|
||||
|
||||
var byteCount = shortIndices
|
||||
? value.Count * 2
|
||||
: value.Count * 4;
|
||||
|
||||
output.Write(byteCount);
|
||||
if (shortIndices)
|
||||
{
|
||||
foreach (var item in value)
|
||||
output.Write((ushort)item);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var item in value)
|
||||
output.Write(item);
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetRuntimeReader(TargetPlatform targetPlatform)
|
||||
{
|
||||
var type = typeof(ContentReader);
|
||||
var readerType = type.Namespace + ".IndexBufferReader, " + type.Assembly.FullName;
|
||||
return readerType;
|
||||
}
|
||||
|
||||
public override string GetRuntimeType(TargetPlatform targetPlatform)
|
||||
{
|
||||
var type = typeof(ContentReader);
|
||||
var readerType = type.Namespace + ".IndexBufferReader, " + type.AssemblyQualifiedName;
|
||||
return readerType;
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = System.Int16;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the signed short value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class Int16Writer : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = System.Int32;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the signed integer value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class Int32Writer : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = System.Int64;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the signed long value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class Int64Writer : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
@@ -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.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the list to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class ListWriter<T> : BuiltInContentWriter<List<T>>
|
||||
{
|
||||
ContentTypeWriter _elementWriter;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal override void OnAddedToContentWriter(ContentWriter output)
|
||||
{
|
||||
base.OnAddedToContentWriter(output);
|
||||
|
||||
_elementWriter = output.GetTypeWriter(typeof(T));
|
||||
}
|
||||
|
||||
public override bool CanDeserializeIntoExistingObject
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, List<T> value)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
output.Write(value.Count);
|
||||
foreach (var element in value)
|
||||
{
|
||||
output.WriteObject(element, _elementWriter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = Microsoft.Xna.Framework.Matrix;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the Matrix value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class MatrixWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
// 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 Microsoft.Xna.Framework.Content.Pipeline.Processors;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
class ModelWriter : BuiltInContentWriter<ModelContent>
|
||||
{
|
||||
protected internal override void Write(ContentWriter output, ModelContent value)
|
||||
{
|
||||
WriteBones(output, value.Bones);
|
||||
|
||||
output.Write((uint)value.Meshes.Count);
|
||||
foreach (var mesh in value.Meshes)
|
||||
{
|
||||
output.WriteObject(mesh.Name);
|
||||
WriteBoneReference(output, mesh.ParentBone, value.Bones);
|
||||
output.Write(mesh.BoundingSphere);
|
||||
output.WriteObject(mesh.Tag);
|
||||
|
||||
output.Write((uint)mesh.MeshParts.Count);
|
||||
foreach (var part in mesh.MeshParts)
|
||||
{
|
||||
output.Write((uint)part.VertexOffset);
|
||||
output.Write((uint)part.NumVertices);
|
||||
output.Write((uint)part.StartIndex);
|
||||
output.Write((uint)part.PrimitiveCount);
|
||||
output.WriteObject(part.Tag);
|
||||
|
||||
output.WriteSharedResource(part.VertexBuffer);
|
||||
output.WriteSharedResource(part.IndexBuffer);
|
||||
output.WriteSharedResource(part.Material);
|
||||
}
|
||||
}
|
||||
|
||||
WriteBoneReference(output, value.Root, value.Bones);
|
||||
output.WriteObject(value.Tag);
|
||||
}
|
||||
|
||||
private void WriteBones(ContentWriter output, ModelBoneContentCollection bones)
|
||||
{
|
||||
output.Write((uint)bones.Count);
|
||||
|
||||
// Bone properties
|
||||
foreach (var bone in bones)
|
||||
{
|
||||
output.WriteObject(bone.Name);
|
||||
output.Write(bone.Transform);
|
||||
}
|
||||
|
||||
// Hierarchy
|
||||
foreach (var bone in bones)
|
||||
{
|
||||
WriteBoneReference(output, bone.Parent, bones);
|
||||
|
||||
output.Write((uint)bone.Children.Count);
|
||||
foreach (var child in bone.Children)
|
||||
WriteBoneReference(output, child, bones);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteBoneReference(ContentWriter output, ModelBoneContent bone, ModelBoneContentCollection bones)
|
||||
{
|
||||
var boneCount = bones != null ? bones.Count : 0;
|
||||
var boneId = bone != null
|
||||
? bone.Index + 1
|
||||
: 0;
|
||||
|
||||
if (boneCount < 255)
|
||||
output.Write((byte)boneId);
|
||||
else
|
||||
output.Write((uint)boneId);
|
||||
}
|
||||
}
|
||||
}
|
||||
+75
@@ -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;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the array value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class MultiArrayWriter<T> : BuiltInContentWriter<Array>
|
||||
{
|
||||
ContentTypeWriter _elementWriter;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal override void OnAddedToContentWriter(ContentWriter output)
|
||||
{
|
||||
base.OnAddedToContentWriter(output);
|
||||
|
||||
_elementWriter = output.GetTypeWriter(typeof(T));
|
||||
}
|
||||
|
||||
public override string GetRuntimeReader(TargetPlatform targetPlatform)
|
||||
{
|
||||
return string.Concat(typeof(ContentTypeReader).Namespace,
|
||||
".",
|
||||
"MultiArrayReader`1[[",
|
||||
_elementWriter.GetRuntimeType(targetPlatform),
|
||||
"]]");
|
||||
}
|
||||
|
||||
protected internal override void Write(ContentWriter output, Array value)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
var rank = value.Rank;
|
||||
|
||||
// Dimension sizes
|
||||
output.Write(rank);
|
||||
for (int dimension = 0; dimension < rank; dimension++)
|
||||
output.Write(value.GetLength(dimension));
|
||||
|
||||
// Values
|
||||
var indices = new int[rank];
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
CalcIndices(value, i, indices);
|
||||
output.WriteObject(value.GetValue(indices), _elementWriter);
|
||||
}
|
||||
}
|
||||
|
||||
static void CalcIndices(Array array, int index, int[] indices)
|
||||
{
|
||||
if (array.Rank != indices.Length)
|
||||
throw new Exception("indices");
|
||||
|
||||
for (int d = 0; d < indices.Length; d++)
|
||||
{
|
||||
if (index == 0)
|
||||
indices[d] = 0;
|
||||
else
|
||||
{
|
||||
indices[d] = index % array.GetLength(d);
|
||||
index /= array.GetLength(d);
|
||||
}
|
||||
}
|
||||
|
||||
if (index != 0)
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
}
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// 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.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the nullable value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class NullableWriter<T> : BuiltInContentWriter<Nullable<T>> where T: struct
|
||||
{
|
||||
ContentTypeWriter _elementWriter;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal override void OnAddedToContentWriter(ContentWriter output)
|
||||
{
|
||||
base.OnAddedToContentWriter(output);
|
||||
|
||||
_elementWriter = output.GetTypeWriter(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, Nullable<T> value)
|
||||
{
|
||||
output.Write(value.HasValue);
|
||||
if (value.HasValue)
|
||||
output.WriteObject(value.Value, _elementWriter);
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// 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 TOutput = Microsoft.Xna.Framework.Plane;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the Plane value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class PlaneWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value.Normal);
|
||||
output.Write(value.D);
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// 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 TOutput = Microsoft.Xna.Framework.Point;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the Point value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class PointWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value.X);
|
||||
output.Write(value.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = Microsoft.Xna.Framework.Quaternion;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the Quaternion value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class QuaternionWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// 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 TOutput = Microsoft.Xna.Framework.Ray;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the Ray value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class RayWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value.Position);
|
||||
output.Write(value.Direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// 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 TOutput = Microsoft.Xna.Framework.Rectangle;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the Rectangle value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class RectangleWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value.X);
|
||||
output.Write(value.Y);
|
||||
output.Write(value.Width);
|
||||
output.Write(value.Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
// 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.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using MonoGame.Utilities;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
class ReflectiveWriter<T> : ContentTypeWriter
|
||||
{
|
||||
private PropertyInfo[] _properties;
|
||||
private FieldInfo[] _fields;
|
||||
|
||||
private Type _baseType;
|
||||
|
||||
private string _runtimeType;
|
||||
private ContentCompiler _compiler;
|
||||
private static HashSet<MemberInfo> _sharedResources = new HashSet<MemberInfo>();
|
||||
|
||||
public ReflectiveWriter()
|
||||
: base(typeof(T))
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanDeserializeIntoExistingObject
|
||||
{
|
||||
get { return TargetType.IsClass; }
|
||||
}
|
||||
|
||||
protected override void Initialize(ContentCompiler compiler)
|
||||
{
|
||||
_compiler = compiler;
|
||||
var type = ReflectionHelpers.GetBaseType(TargetType);
|
||||
if (type != null && type != typeof(object) && !TargetType.IsValueType)
|
||||
_baseType = type;
|
||||
|
||||
var runtimeType = TargetType.GetCustomAttributes(typeof(ContentSerializerRuntimeTypeAttribute), false).FirstOrDefault() as ContentSerializerRuntimeTypeAttribute;
|
||||
if (runtimeType != null)
|
||||
_runtimeType = runtimeType.RuntimeType;
|
||||
|
||||
var typeVersion = TargetType.GetCustomAttributes(typeof(ContentSerializerTypeVersionAttribute), false).FirstOrDefault() as ContentSerializerTypeVersionAttribute;
|
||||
if (typeVersion != null)
|
||||
_typeVersion = typeVersion.TypeVersion;
|
||||
|
||||
_properties = TargetType.GetAllProperties().Where(IsValidProperty).ToArray();
|
||||
_fields = TargetType.GetAllFields().Where(IsValidField).ToArray();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal override void OnAddedToContentWriter(ContentWriter output)
|
||||
{
|
||||
base.OnAddedToContentWriter(output);
|
||||
|
||||
foreach (var property in _properties)
|
||||
output.GetTypeWriter(property.PropertyType);
|
||||
|
||||
foreach (var field in _fields)
|
||||
output.GetTypeWriter(field.FieldType);
|
||||
}
|
||||
|
||||
private bool IsValidProperty(PropertyInfo property)
|
||||
{
|
||||
// Properties must have at least a getter.
|
||||
if (property.CanRead == false)
|
||||
return false;
|
||||
|
||||
// Skip over indexer properties.
|
||||
if (property.Name == "Item" && property.GetIndexParameters().Length > 0)
|
||||
return false;
|
||||
|
||||
// Are we explicitly asked to ignore this item?
|
||||
if (ReflectionHelpers.GetCustomAttribute<ContentSerializerIgnoreAttribute>(property) != null)
|
||||
return false;
|
||||
|
||||
var contentSerializerAttribute = ReflectionHelpers.GetCustomAttribute<ContentSerializerAttribute>(property);
|
||||
if (contentSerializerAttribute == null)
|
||||
{
|
||||
// There is no ContentSerializerAttribute, so non-public
|
||||
// properties cannot be serialized.
|
||||
if (!ReflectionHelpers.PropertyIsPublic(property))
|
||||
return false;
|
||||
|
||||
// Check the type reader to see if it is safe to
|
||||
// deserialize into the existing type.
|
||||
if (!property.CanWrite)
|
||||
{
|
||||
if (!_compiler.GetTypeWriter(property.PropertyType).CanDeserializeIntoExistingObject)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (contentSerializerAttribute.SharedResource)
|
||||
{
|
||||
_sharedResources.Add(property);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool IsValidField(FieldInfo field)
|
||||
{
|
||||
// Are we explicitly asked to ignore this item?
|
||||
if (ReflectionHelpers.GetCustomAttribute<ContentSerializerIgnoreAttribute>(field) != null)
|
||||
return false;
|
||||
|
||||
var contentSerializerAttribute = ReflectionHelpers.GetCustomAttribute<ContentSerializerAttribute>(field);
|
||||
if (contentSerializerAttribute == null)
|
||||
{
|
||||
// There is no ContentSerializerAttribute, so non-public
|
||||
// fields cannot be deserialized.
|
||||
if (!field.IsPublic)
|
||||
return false;
|
||||
|
||||
// evolutional: Added check to skip initialise only fields
|
||||
if (field.IsInitOnly)
|
||||
return false;
|
||||
}
|
||||
else if (contentSerializerAttribute.SharedResource)
|
||||
{
|
||||
_sharedResources.Add(field);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void Write(object parent, ContentWriter output, MemberInfo member)
|
||||
{
|
||||
var property = member as PropertyInfo;
|
||||
var field = member as FieldInfo;
|
||||
Debug.Assert(field != null || property != null);
|
||||
|
||||
Type elementType;
|
||||
object memberObject;
|
||||
|
||||
if (property != null)
|
||||
{
|
||||
elementType = property.PropertyType;
|
||||
memberObject = property.GetValue(parent, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
elementType = field.FieldType;
|
||||
memberObject = field.GetValue(parent);
|
||||
}
|
||||
|
||||
if (_sharedResources.Contains(member))
|
||||
output.WriteSharedResource(memberObject);
|
||||
else
|
||||
{
|
||||
var writer = output.GetTypeWriter(elementType);
|
||||
if (writer == null || elementType == typeof(object) || elementType == typeof(Array))
|
||||
output.WriteObject(memberObject);
|
||||
else
|
||||
output.WriteObject(memberObject, writer);
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetRuntimeType(TargetPlatform targetPlatform)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_runtimeType))
|
||||
return base.GetRuntimeType(targetPlatform);
|
||||
|
||||
return _runtimeType;
|
||||
}
|
||||
|
||||
public override string GetRuntimeReader(TargetPlatform targetPlatform)
|
||||
{
|
||||
return "Microsoft.Xna.Framework.Content.ReflectiveReader`1[[" +
|
||||
GetRuntimeType(targetPlatform)
|
||||
+ "]]";
|
||||
}
|
||||
|
||||
protected internal override void Write(ContentWriter output, object value)
|
||||
{
|
||||
if (_baseType != null)
|
||||
{
|
||||
var baseTypeWriter = output.GetTypeWriter(_baseType);
|
||||
baseTypeWriter.Write(output, value);
|
||||
}
|
||||
|
||||
foreach (var property in _properties)
|
||||
Write(value, output, property);
|
||||
|
||||
foreach (var field in _fields)
|
||||
Write(value, output, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = System.SByte;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the signed byte value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class SByteWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = System.Single;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the single precision floating point value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class SingleWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// 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 Microsoft.Xna.Framework.Content.Pipeline.Graphics;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
class SkinnedEffectWriter : BuiltInContentWriter<SkinnedMaterialContent>
|
||||
{
|
||||
protected internal override void Write(ContentWriter output, SkinnedMaterialContent value)
|
||||
{
|
||||
output.WriteExternalReference(value.Textures.ContainsKey(SkinnedMaterialContent.TextureKey) ? value.Texture : null);
|
||||
output.Write(value.WeightsPerVertex.GetValueOrDefault(4));
|
||||
output.Write(value.DiffuseColor.HasValue ? value.DiffuseColor.Value : Vector3.One);
|
||||
output.Write(value.EmissiveColor.HasValue ? value.EmissiveColor.Value : Vector3.Zero);
|
||||
output.Write(value.SpecularColor.HasValue ? value.SpecularColor.Value : Vector3.Zero);
|
||||
output.Write(value.SpecularPower.HasValue ? value.SpecularPower.Value : 0);
|
||||
output.Write(value.Alpha.HasValue ? value.Alpha.Value : 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// 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 Microsoft.Xna.Framework.Content.Pipeline.Processors;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
class SongWriter : BuiltInContentWriter<SongContent>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, SongContent value)
|
||||
{
|
||||
output.Write(value.fileName);
|
||||
output.WriteObject((int)value.duration.TotalMilliseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
// 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 Microsoft.Xna.Framework.Content.Pipeline.Processors;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
class SoundEffectWriter : BuiltInContentWriter<SoundEffectContent>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, SoundEffectContent value)
|
||||
{
|
||||
output.Write(value.format.Length);
|
||||
output.Write(value.format);
|
||||
|
||||
output.Write(value.data.Length);
|
||||
output.Write(value.data);
|
||||
|
||||
output.Write(value.loopStart);
|
||||
output.Write(value.loopLength);
|
||||
output.Write(value.duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
// 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.Text;
|
||||
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
public class SpriteFontContentWriter : ContentTypeWriter<SpriteFontContent>
|
||||
{
|
||||
protected internal override void Write(ContentWriter output, SpriteFontContent value)
|
||||
{
|
||||
output.WriteObject(value.Texture);
|
||||
output.WriteObject(value.Glyphs);
|
||||
output.WriteObject(value.Cropping);
|
||||
output.WriteObject(value.CharacterMap);
|
||||
output.Write(value.VerticalLineSpacing);
|
||||
output.Write(value.HorizontalSpacing);
|
||||
output.WriteObject(value.Kerning);
|
||||
var hasDefChar = value.DefaultCharacter.HasValue;
|
||||
output.Write(hasDefChar);
|
||||
if (hasDefChar)
|
||||
output.Write(value.DefaultCharacter.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assembly qualified name of the runtime loader for this type.
|
||||
/// </summary>
|
||||
/// <param name="targetPlatform">Name of the platform.</param>
|
||||
/// <returns>Name of the runtime loader.</returns>
|
||||
public override string GetRuntimeReader(TargetPlatform targetPlatform)
|
||||
{
|
||||
// Base the reader type string from a known public class in the same namespace in the same assembly
|
||||
Type type = typeof(ContentReader);
|
||||
string readerType = type.Namespace + ".SpriteFontReader, " + type.Assembly.FullName;
|
||||
return readerType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assembly qualified name of the runtime target type. The runtime target type often matches the design time type, but may differ.
|
||||
/// </summary>
|
||||
/// <param name="targetPlatform">The target platform.</param>
|
||||
/// <returns>The qualified name.</returns>
|
||||
public override string GetRuntimeType(TargetPlatform targetPlatform)
|
||||
{
|
||||
// Base the reader type string from a known public class in the same namespace in the same assembly
|
||||
Type type = typeof(ContentReader);
|
||||
string readerType = type.Namespace + ".SpriteFontReader, " + type.AssemblyQualifiedName;
|
||||
return readerType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether a given type of content should be compressed.
|
||||
/// </summary>
|
||||
/// <param name="targetPlatform">The target platform of the content build.</param>
|
||||
/// <param name="value">The object about to be serialized, or null if a collection of objects is to be serialized.</param>
|
||||
/// <returns>true if the content of the requested type should be compressed; false otherwise.</returns>
|
||||
/// <remarks>This base class implementation of this method always returns true. It should be overridden
|
||||
/// to return false if there would be little or no useful reduction in size of the content type's data
|
||||
/// from a general-purpose lossless compression algorithm.
|
||||
/// The implementations for Song Class and SoundEffect Class data return false because data for these
|
||||
/// content types is already in compressed form.</remarks>
|
||||
protected internal override bool ShouldCompressContent(TargetPlatform targetPlatform, object value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = System.String;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the string value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class StringWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -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 Microsoft.Xna.Framework.Content.Pipeline.Graphics;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
class Texture2DWriter : BuiltInContentWriter<Texture2DContent>
|
||||
{
|
||||
protected internal override void Write(ContentWriter output, Texture2DContent value)
|
||||
{
|
||||
var mipmaps = value.Faces[0]; // Mipmap chain.
|
||||
var level0 = mipmaps[0]; // Most detailed mipmap level.
|
||||
|
||||
SurfaceFormat format;
|
||||
if (!level0.TryGetFormat(out format))
|
||||
throw new Exception("Couldn't get Format for TextureContent.");
|
||||
|
||||
output.Write((int)format);
|
||||
output.Write(level0.Width);
|
||||
output.Write(level0.Height);
|
||||
output.Write(mipmaps.Count); // Number of mipmap levels.
|
||||
|
||||
foreach (var level in mipmaps)
|
||||
{
|
||||
var pixelData = level.GetPixelData();
|
||||
output.Write(pixelData.Length);
|
||||
output.Write(pixelData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// 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 Microsoft.Xna.Framework.Content.Pipeline.Graphics;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
internal class TextureCubeWriter : BuiltInContentWriter<TextureCubeContent>
|
||||
{
|
||||
protected internal override void Write(ContentWriter output, TextureCubeContent value)
|
||||
{
|
||||
var mipmaps0 = value.Faces[0]; // Mipmap chain of face 0 (+X).
|
||||
var level0 = mipmaps0[0]; // Most detailed mipmap level of face 0.
|
||||
|
||||
SurfaceFormat format;
|
||||
if (!level0.TryGetFormat(out format))
|
||||
throw new Exception("Couldn't get format for TextureCubeContent.");
|
||||
|
||||
output.Write((int)format); // Surface format
|
||||
output.Write(level0.Width); // Cube map size
|
||||
output.Write(mipmaps0.Count); // Number of mipmap levels
|
||||
|
||||
// The number of faces in TextureCubeContent is guaranteed to be 6.
|
||||
foreach (var mipmaps in value.Faces)
|
||||
{
|
||||
foreach (var level in mipmaps)
|
||||
{
|
||||
byte[] pixelData = level.GetPixelData();
|
||||
output.Write(pixelData.Length);
|
||||
output.Write(pixelData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// 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 Microsoft.Xna.Framework.Content.Pipeline.Graphics;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
internal class TextureWriter : BuiltInContentWriter<TextureContent>
|
||||
{
|
||||
protected internal override void Write(ContentWriter output, TextureContent value)
|
||||
{
|
||||
// Do nothing.
|
||||
// The TextureWriter is not used to write anything, but it is used by
|
||||
// the ExternalReferenceWriter when an ExternalReference<TextureContent>
|
||||
// is written! (See ExternalReferenceWriter implementation.)
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = System.TimeSpan;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the TimeSpan value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class TimeSpanWriter : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value.Ticks);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = System.UInt16;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the unsigned short value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class UInt16Writer : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = System.UInt32;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the unsigned integer value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class UInt32Writer : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = System.UInt64;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the unsigned long value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class UInt64Writer : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = Microsoft.Xna.Framework.Vector2;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the Vector2 value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class Vector2Writer : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = Microsoft.Xna.Framework.Vector3;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the Vector3 value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class Vector3Writer : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 TOutput = Microsoft.Xna.Framework.Vector4;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the Vector4 value to the output.
|
||||
/// </summary>
|
||||
[ContentTypeWriter]
|
||||
class Vector4Writer : BuiltInContentWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the value to the output.
|
||||
/// </summary>
|
||||
/// <param name="output">The output writer object.</param>
|
||||
/// <param name="value">The value to write to the output.</param>
|
||||
protected internal override void Write(ContentWriter output, TOutput value)
|
||||
{
|
||||
output.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// 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 Microsoft.Xna.Framework.Content.Pipeline.Processors;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
class VertexBufferWriter : BuiltInContentWriter<VertexBufferContent>
|
||||
{
|
||||
protected internal override void Write(ContentWriter output, VertexBufferContent value)
|
||||
{
|
||||
output.WriteRawObject(value.VertexDeclaration);
|
||||
output.Write((uint)(value.VertexData.Length / value.VertexDeclaration.VertexStride));
|
||||
output.Write(value.VertexData);
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// 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 Microsoft.Xna.Framework.Content.Pipeline.Processors;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
class VertexDeclarationWriter : BuiltInContentWriter<VertexDeclarationContent>
|
||||
{
|
||||
protected internal override void Write(ContentWriter output, VertexDeclarationContent value)
|
||||
{
|
||||
// If fpr whatever reason there isn't a vertex stride defined, it's going to
|
||||
// cause problems after reading it in, so better to fail early here.
|
||||
output.Write((uint)value.VertexStride.Value);
|
||||
output.Write((uint)value.VertexElements.Count);
|
||||
foreach (var element in value.VertexElements)
|
||||
{
|
||||
output.Write((uint)element.Offset);
|
||||
output.Write((int)element.VertexElementFormat);
|
||||
output.Write((int)element.VertexElementUsage);
|
||||
output.Write((uint)element.UsageIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// 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.
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
class VideoWriter : BuiltInContentWriter<VideoContent>
|
||||
{
|
||||
protected internal override void Write(ContentWriter output, VideoContent value)
|
||||
{
|
||||
output.WriteObject<string>(value.Filename);
|
||||
output.WriteObject<int>((int)value.Duration.TotalMilliseconds);
|
||||
output.WriteObject<int>(value.Width);
|
||||
output.WriteObject<int>(value.Height);
|
||||
output.WriteObject<float>(value.FramesPerSecond);
|
||||
output.WriteObject<int>((int)value.VideoSoundtrackType);
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
@@ -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<T> : ContentTypeSerializer<T[]>
|
||||
{
|
||||
private readonly ListSerializer<T> _listSerializer;
|
||||
|
||||
public ArraySerializer() :
|
||||
base("array")
|
||||
{
|
||||
_listSerializer = new ListSerializer<T>();
|
||||
}
|
||||
|
||||
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<T>(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<T>(value), format);
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -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<bool>
|
||||
{
|
||||
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<string> results)
|
||||
{
|
||||
results.Add(XmlConvert.ToString(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -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<byte>
|
||||
{
|
||||
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<string> results)
|
||||
{
|
||||
results.Add(XmlConvert.ToString(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
@@ -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<char>
|
||||
{
|
||||
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<string> results)
|
||||
{
|
||||
results.Add(XmlConvert.ToString(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
+35
@@ -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<Color>
|
||||
{
|
||||
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<string> 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
@@ -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);
|
||||
}
|
||||
}
|
||||
+62
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to identify custom ContentTypeSerializer classes.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
|
||||
public sealed class ContentTypeSerializerAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes an instance of the ContentTypeSerializerAttribute.
|
||||
/// </summary>
|
||||
public ContentTypeSerializerAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
private static readonly object _lock = new object();
|
||||
|
||||
private static ReadOnlyCollection<Type> _types;
|
||||
|
||||
static internal ReadOnlyCollection<Type> GetTypes()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_types == null)
|
||||
{
|
||||
var found = new List<Type>();
|
||||
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<Type>(found);
|
||||
}
|
||||
}
|
||||
|
||||
return _types;
|
||||
}
|
||||
}
|
||||
}
|
||||
+59
@@ -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<T> : 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+81
@@ -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<CurveKeyCollection>
|
||||
{
|
||||
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<string>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+92
@@ -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<TKey,TValue> : ContentTypeSerializer<Dictionary<TKey,TValue>>
|
||||
{
|
||||
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<TKey, TValue> value)
|
||||
{
|
||||
return value.Count == 0;
|
||||
}
|
||||
|
||||
protected internal override void ScanChildren(IntermediateSerializer serializer, ChildCallback callback, Dictionary<TKey, TValue> value)
|
||||
{
|
||||
foreach (var kvp in value)
|
||||
{
|
||||
callback(_keySerializer, kvp.Key);
|
||||
callback(_valueSerializer, kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
protected internal override Dictionary<TKey, TValue> Deserialize(IntermediateReader input, ContentSerializerAttribute format, Dictionary<TKey, TValue> existingInstance)
|
||||
{
|
||||
var result = existingInstance ?? new Dictionary<TKey, TValue>();
|
||||
|
||||
while (input.MoveToElement(format.CollectionItemName))
|
||||
{
|
||||
input.Xml.ReadStartElement();
|
||||
|
||||
var key = input.ReadObject<TKey>(_keyFormat, _keySerializer);
|
||||
var value = input.ReadObject<TValue>(_valueFormat, _valueSerializer);
|
||||
result.Add(key,value);
|
||||
|
||||
input.Xml.ReadEndElement();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected internal override void Serialize(IntermediateWriter output, Dictionary<TKey, TValue> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -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<double>
|
||||
{
|
||||
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<string> results)
|
||||
{
|
||||
results.Add(XmlConvert.ToString(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
+75
@@ -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<T> : ContentTypeSerializer<T>
|
||||
{
|
||||
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<string> results);
|
||||
|
||||
|
||||
|
||||
protected internal void Deserialize(IntermediateReader input, List<T> 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<T> values)
|
||||
{
|
||||
var elements = new List<string>();
|
||||
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<string>();
|
||||
Serialize(value, elements);
|
||||
var str = PackedElementsHelper.JoinElements(elements);
|
||||
output.Xml.WriteString(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// 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
|
||||
{
|
||||
[ContentTypeSerializer]
|
||||
class ExternalReferenceSerializer<T> : ContentTypeSerializer<ExternalReference<T>>
|
||||
{
|
||||
public ExternalReferenceSerializer() :
|
||||
base("ExternalReference")
|
||||
{
|
||||
}
|
||||
|
||||
protected internal override ExternalReference<T> Deserialize(IntermediateReader input, ContentSerializerAttribute format, ExternalReference<T> existingInstance)
|
||||
{
|
||||
var result = existingInstance ?? new ExternalReference<T>();
|
||||
input.ReadExternalReference(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected internal override void Serialize(IntermediateWriter output, ExternalReference<T> value, ContentSerializerAttribute format)
|
||||
{
|
||||
output.WriteExternalReference(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -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<float>
|
||||
{
|
||||
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<string> results)
|
||||
{
|
||||
results.Add(XmlConvert.ToString(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
+83
@@ -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<object>(itemFormat, _contentSerializer) });
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -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 IntSerializer : ElementSerializer<int>
|
||||
{
|
||||
public IntSerializer() :
|
||||
base("int", 1)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal override int Deserialize(string[] inputs, ref int index)
|
||||
{
|
||||
return XmlConvert.ToInt32(inputs[index++]);
|
||||
}
|
||||
|
||||
protected internal override void Serialize(int value, List<string> results)
|
||||
{
|
||||
results.Add(XmlConvert.ToString(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
+261
@@ -0,0 +1,261 @@
|
||||
// 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.IO;
|
||||
using System.Xml;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
|
||||
{
|
||||
public sealed class IntermediateReader
|
||||
{
|
||||
private readonly string _filePath;
|
||||
|
||||
private readonly Dictionary<string, Action<object>> _resourceFixups;
|
||||
|
||||
private readonly Dictionary<string, List<Action<Type, string>>> _externalReferences;
|
||||
|
||||
public XmlReader Xml { get; private set; }
|
||||
|
||||
public IntermediateSerializer Serializer { get; private set; }
|
||||
|
||||
internal IntermediateReader(IntermediateSerializer serializer, XmlReader xmlReader, string filePath)
|
||||
{
|
||||
Serializer = serializer;
|
||||
Xml = xmlReader;
|
||||
_filePath = filePath;
|
||||
_resourceFixups = new Dictionary<string, Action<object>>();
|
||||
_externalReferences = new Dictionary<string, List<Action<Type, string>>>();
|
||||
}
|
||||
|
||||
public bool MoveToElement(string elementName)
|
||||
{
|
||||
var nodeType = Xml.MoveToContent();
|
||||
return nodeType == XmlNodeType.Element &&
|
||||
Xml.Name == elementName;
|
||||
}
|
||||
|
||||
public T ReadObject<T>(ContentSerializerAttribute format)
|
||||
{
|
||||
return ReadObject(format, Serializer.GetTypeSerializer(typeof(T)), default(T));
|
||||
}
|
||||
|
||||
public T ReadObject<T>(ContentSerializerAttribute format, ContentTypeSerializer typeSerializer)
|
||||
{
|
||||
return ReadObject(format, typeSerializer, default(T));
|
||||
}
|
||||
|
||||
public T ReadObject<T>(ContentSerializerAttribute format, ContentTypeSerializer typeSerializer, T existingInstance)
|
||||
{
|
||||
if (!format.FlattenContent)
|
||||
{
|
||||
if (!MoveToElement(format.ElementName))
|
||||
throw NewInvalidContentException(null, "Element '{0}' was not found.", format.ElementName);
|
||||
|
||||
// Is the object null?
|
||||
var isNull = Xml.GetAttribute("Null");
|
||||
if (isNull != null && XmlConvert.ToBoolean(isNull))
|
||||
{
|
||||
if (!format.AllowNull)
|
||||
throw NewInvalidContentException(null, "Element '{0}' cannot be null.", format.ElementName);
|
||||
|
||||
Xml.Skip();
|
||||
return default(T);
|
||||
}
|
||||
|
||||
// Is the object overloading the serialized type?
|
||||
if (Xml.MoveToAttribute("Type"))
|
||||
{
|
||||
var type = ReadTypeName();
|
||||
if (type == null)
|
||||
throw NewInvalidContentException(null, "Could not resolve type '{0}'.", Xml.ReadContentAsString());
|
||||
if (!typeSerializer.TargetType.IsAssignableFrom(type))
|
||||
throw NewInvalidContentException(null, "Type '{0}' is not assignable to '{1}'.", type.FullName, typeSerializer.TargetType.FullName);
|
||||
|
||||
typeSerializer = Serializer.GetTypeSerializer(type);
|
||||
Xml.MoveToElement();
|
||||
}
|
||||
}
|
||||
|
||||
return ReadRawObject(format, typeSerializer, existingInstance);
|
||||
}
|
||||
|
||||
public T ReadObject<T>(ContentSerializerAttribute format, T existingInstance)
|
||||
{
|
||||
return ReadObject(format, Serializer.GetTypeSerializer(typeof(T)), existingInstance);
|
||||
}
|
||||
|
||||
public T ReadRawObject<T>(ContentSerializerAttribute format)
|
||||
{
|
||||
return ReadRawObject(format, Serializer.GetTypeSerializer(typeof(T)), default(T));
|
||||
}
|
||||
|
||||
public T ReadRawObject<T>(ContentSerializerAttribute format, ContentTypeSerializer typeSerializer)
|
||||
{
|
||||
return ReadRawObject(format, typeSerializer, default(T));
|
||||
}
|
||||
|
||||
public T ReadRawObject<T>(ContentSerializerAttribute format, ContentTypeSerializer typeSerializer, T existingInstance)
|
||||
{
|
||||
if (format.FlattenContent)
|
||||
{
|
||||
Xml.MoveToContent();
|
||||
return (T)typeSerializer.Deserialize(this, format, existingInstance);
|
||||
}
|
||||
|
||||
if (!MoveToElement(format.ElementName))
|
||||
throw NewInvalidContentException(null, "Element '{0}' was not found.", format.ElementName);
|
||||
|
||||
var isEmpty = Xml.IsEmptyElement;
|
||||
if (!isEmpty)
|
||||
Xml.ReadStartElement();
|
||||
|
||||
var result = typeSerializer.Deserialize(this, format, existingInstance);
|
||||
|
||||
if (isEmpty)
|
||||
Xml.Skip();
|
||||
|
||||
if (!isEmpty)
|
||||
Xml.ReadEndElement();
|
||||
|
||||
return (T)result;
|
||||
}
|
||||
|
||||
public T ReadRawObject<T>(ContentSerializerAttribute format, T existingInstance)
|
||||
{
|
||||
return ReadRawObject(format, Serializer.GetTypeSerializer(typeof(T)), existingInstance);
|
||||
}
|
||||
|
||||
public void ReadSharedResource<T>(ContentSerializerAttribute format, Action<T> fixup)
|
||||
{
|
||||
string str;
|
||||
|
||||
if (format.FlattenContent)
|
||||
str = Xml.ReadContentAsString();
|
||||
else
|
||||
{
|
||||
if (!MoveToElement(format.ElementName))
|
||||
throw NewInvalidContentException(null, "Element '{0}' was not found.", format.ElementName);
|
||||
|
||||
str = Xml.ReadElementContentAsString();
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(str))
|
||||
return;
|
||||
|
||||
// Do we already have one for this?
|
||||
Action<object> prevFixup;
|
||||
if (!_resourceFixups.TryGetValue(str, out prevFixup))
|
||||
_resourceFixups.Add(str, (o) => fixup((T)o));
|
||||
else
|
||||
{
|
||||
_resourceFixups[str] = (o) =>
|
||||
{
|
||||
prevFixup(o);
|
||||
fixup((T)o);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal void ReadSharedResources()
|
||||
{
|
||||
if (!MoveToElement("Resources"))
|
||||
return;
|
||||
|
||||
var resources = new Dictionary<string, object>();
|
||||
var resourceFormat = new ContentSerializerAttribute { ElementName = "Resource" };
|
||||
|
||||
// Read all the resources.
|
||||
Xml.ReadStartElement();
|
||||
while (MoveToElement("Resource"))
|
||||
{
|
||||
var id = Xml.GetAttribute("ID");
|
||||
var resource = ReadObject<object>(resourceFormat);
|
||||
resources.Add(id, resource);
|
||||
}
|
||||
Xml.ReadEndElement();
|
||||
|
||||
// Execute the fixups.
|
||||
foreach (var fixup in _resourceFixups)
|
||||
{
|
||||
object resource;
|
||||
if (!resources.TryGetValue(fixup.Key, out resource))
|
||||
throw new InvalidContentException("Missing shared resource \"" + fixup.Key + "\".");
|
||||
fixup.Value(resource);
|
||||
}
|
||||
}
|
||||
|
||||
public void ReadExternalReference<T>(ExternalReference<T> existingInstance)
|
||||
{
|
||||
if (!MoveToElement("Reference"))
|
||||
return;
|
||||
|
||||
var str = Xml.ReadElementContentAsString();
|
||||
|
||||
Action<Type, string> fixup = (type, filename) =>
|
||||
{
|
||||
if (type != typeof(T))
|
||||
throw NewInvalidContentException(null, "Invalid external reference type");
|
||||
|
||||
existingInstance.Filename = filename;
|
||||
};
|
||||
|
||||
List<Action<Type, string>> fixups;
|
||||
if (!_externalReferences.TryGetValue(str, out fixups))
|
||||
_externalReferences.Add(str, fixups = new List<Action<Type, string>>());
|
||||
fixups.Add(fixup);
|
||||
}
|
||||
|
||||
internal void ReadExternalReferences()
|
||||
{
|
||||
if (!MoveToElement("ExternalReferences"))
|
||||
return;
|
||||
|
||||
var currentDir = Path.GetDirectoryName(_filePath);
|
||||
|
||||
// Read all the external references.
|
||||
Xml.ReadStartElement();
|
||||
while (MoveToElement("ExternalReference"))
|
||||
{
|
||||
List<Action<Type, string>> fixups;
|
||||
var id = Xml.GetAttribute("ID");
|
||||
if (!_externalReferences.TryGetValue(id, out fixups))
|
||||
throw NewInvalidContentException(null, "Unknown external reference id '{0}'!", id);
|
||||
|
||||
Xml.MoveToAttribute("TargetType");
|
||||
var targetType = ReadTypeName();
|
||||
if (targetType == null)
|
||||
throw NewInvalidContentException(null, "Could not resolve type '{0}'.", Xml.ReadContentAsString());
|
||||
|
||||
Xml.MoveToElement();
|
||||
var filename = Xml.ReadElementString();
|
||||
filename = Path.Combine(currentDir, filename);
|
||||
|
||||
// Apply the fixups.
|
||||
foreach (var fixup in fixups)
|
||||
fixup(targetType, filename);
|
||||
}
|
||||
Xml.ReadEndElement();
|
||||
}
|
||||
|
||||
internal InvalidContentException NewInvalidContentException(Exception innerException, string message, params object[] args)
|
||||
{
|
||||
var xmlInfo = (IXmlLineInfo)Xml;
|
||||
var lineAndColumn = string.Format("{0},{1}", xmlInfo.LineNumber, xmlInfo.LinePosition);
|
||||
var identity = new ContentIdentity(_filePath, string.Empty, lineAndColumn);
|
||||
return new InvalidContentException(string.Format(message, args), identity, innerException);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the next type in the
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Type ReadTypeName()
|
||||
{
|
||||
var typeName = Xml.ReadContentAsString();
|
||||
return Serializer.FindType(typeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
+361
@@ -0,0 +1,361 @@
|
||||
// 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;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
|
||||
{
|
||||
// The intermediate serializer implementation is based on testing XNA behavior and the following sources:
|
||||
//
|
||||
// http://msdn.microsoft.com/en-us/library/Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate.aspx
|
||||
// http://blogs.msdn.com/b/shawnhar/archive/2008/08/12/everything-you-ever-wanted-to-know-about-intermediateserializer.aspx
|
||||
// http://blogs.msdn.com/b/shawnhar/archive/2008/08/26/customizing-intermediateserializer-part-1.aspx
|
||||
// http://blogs.msdn.com/b/shawnhar/archive/2008/08/26/customizing-intermediateserializer-part-2.aspx
|
||||
// http://blogs.msdn.com/b/shawnhar/archive/2008/08/27/why-intermediateserializer-control-attributes-are-not-part-of-the-content-pipeline.aspx
|
||||
//
|
||||
|
||||
|
||||
public class IntermediateSerializer
|
||||
{
|
||||
/// <summary>
|
||||
/// According to the examples on Sean Hargreaves' blog, explicit types
|
||||
/// can also specify the type aliases from C#. This maps those names
|
||||
/// to the actual .NET framework types for parsing.
|
||||
/// </summary>
|
||||
private static readonly Dictionary<string, Type> _typeAliases = new Dictionary<string, Type>
|
||||
{
|
||||
{ "bool", typeof(bool) },
|
||||
{ "byte", typeof(byte) },
|
||||
{ "sbyte", typeof(sbyte) },
|
||||
{ "char", typeof(char) },
|
||||
{ "decimal",typeof(decimal) },
|
||||
{ "double", typeof(double) },
|
||||
{ "float", typeof(float) },
|
||||
{ "int", typeof(int) },
|
||||
{ "uint", typeof(uint) },
|
||||
{ "long", typeof(long) },
|
||||
{ "ulong", typeof(ulong) },
|
||||
{ "object", typeof(object) },
|
||||
{ "short", typeof(short) },
|
||||
{ "ushort", typeof(ushort) },
|
||||
{ "string", typeof(string) }
|
||||
};
|
||||
|
||||
private static readonly Dictionary<Type, string> _typeAliasesReverse;
|
||||
|
||||
static IntermediateSerializer()
|
||||
{
|
||||
_typeAliasesReverse = _typeAliases.ToDictionary(x => x.Value, x => x.Key);
|
||||
}
|
||||
|
||||
private IntermediateSerializer()
|
||||
{
|
||||
_scannedObjects = new List<object>();
|
||||
_namespaceAliasHelper = new NamespaceAliasHelper(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps "ShortName:" -> "My.Namespace.LongName." for type lookups.
|
||||
/// </summary>
|
||||
private Dictionary<string, string> _namespaceLookup;
|
||||
|
||||
private Dictionary<Type, ContentTypeSerializer> _serializers;
|
||||
private Dictionary<Type, GenericCollectionHelper> _collectionHelpers;
|
||||
|
||||
private Dictionary<Type, Type> _genericSerializerTypes;
|
||||
|
||||
private readonly NamespaceAliasHelper _namespaceAliasHelper;
|
||||
|
||||
private readonly List<object> _scannedObjects;
|
||||
|
||||
public static T Deserialize<T>(XmlReader input, string referenceRelocationPath)
|
||||
{
|
||||
var serializer = new IntermediateSerializer();
|
||||
var reader = new IntermediateReader(serializer, input, referenceRelocationPath);
|
||||
var asset = default(T);
|
||||
|
||||
try
|
||||
{
|
||||
if (!reader.MoveToElement("XnaContent"))
|
||||
throw new InvalidContentException(string.Format("Could not find XnaContent element in '{0}'.",
|
||||
referenceRelocationPath));
|
||||
|
||||
// Initialize the namespace lookups from
|
||||
// the attributes on the XnaContent element.
|
||||
serializer.CreateNamespaceLookup(input);
|
||||
|
||||
// Move past the XnaContent.
|
||||
input.ReadStartElement();
|
||||
|
||||
// Read the asset.
|
||||
var format = new ContentSerializerAttribute {ElementName = "Asset"};
|
||||
asset = reader.ReadObject<T>(format);
|
||||
|
||||
// Process the shared resources and external references.
|
||||
reader.ReadSharedResources();
|
||||
reader.ReadExternalReferences();
|
||||
|
||||
// Move past the closing XnaContent element.
|
||||
input.ReadEndElement();
|
||||
}
|
||||
catch (XmlException xmlException)
|
||||
{
|
||||
throw reader.NewInvalidContentException(xmlException, "An error occured parsing.");
|
||||
}
|
||||
|
||||
return asset;
|
||||
}
|
||||
|
||||
public ContentTypeSerializer GetTypeSerializer(Type type)
|
||||
{
|
||||
// Create the known serializers if we haven't already.
|
||||
if (_serializers == null)
|
||||
{
|
||||
_serializers = new Dictionary<Type, ContentTypeSerializer>();
|
||||
_genericSerializerTypes = new Dictionary<Type, Type>();
|
||||
|
||||
var types = ContentTypeSerializerAttribute.GetTypes();
|
||||
foreach (var t in types)
|
||||
{
|
||||
if (t.IsGenericType)
|
||||
{
|
||||
var genericType = t.BaseType.GetGenericArguments()[0];
|
||||
_genericSerializerTypes.Add(genericType.GetGenericTypeDefinition(), t);
|
||||
}
|
||||
else
|
||||
{
|
||||
var cts = Activator.CreateInstance(t) as ContentTypeSerializer;
|
||||
cts.Initialize(this);
|
||||
_serializers.Add(cts.TargetType, cts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Look it up.
|
||||
ContentTypeSerializer serializer;
|
||||
if (_serializers.TryGetValue(type, out serializer))
|
||||
return serializer;
|
||||
|
||||
Type serializerType;
|
||||
|
||||
if (type.IsArray)
|
||||
{
|
||||
if (type.GetArrayRank() != 1)
|
||||
throw new RankException("We only support single dimension arrays.");
|
||||
|
||||
var arrayType = typeof(ArraySerializer<>).MakeGenericType(new[] { type.GetElementType() });
|
||||
serializer = (ContentTypeSerializer)Activator.CreateInstance(arrayType);
|
||||
}
|
||||
else if (type.IsGenericType && _genericSerializerTypes.TryGetValue(type.GetGenericTypeDefinition(), out serializerType))
|
||||
{
|
||||
serializerType = serializerType.MakeGenericType(type.GetGenericArguments());
|
||||
serializer = (ContentTypeSerializer)Activator.CreateInstance(serializerType);
|
||||
}
|
||||
else if (type.IsEnum)
|
||||
{
|
||||
serializer = new EnumSerializer(type);
|
||||
}
|
||||
else if (typeof(IList).IsAssignableFrom(type) && !GenericCollectionHelper.IsGenericCollectionType(type, true))
|
||||
{
|
||||
// Special handling for non-generic IList types. By the time we get here,
|
||||
// generic collection types will already have been handled by one of the known serializers.
|
||||
serializer = new NonGenericIListSerializer(type);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The reflective serializer is not for primitive types!
|
||||
if (type.IsPrimitive)
|
||||
throw new NotImplementedException(string.Format("Unhandled primitive type `{0}`!", type.FullName));
|
||||
|
||||
// We still don't have a serializer then we
|
||||
// fallback to the reflection based serializer.
|
||||
serializer = new ReflectiveSerializer(type);
|
||||
}
|
||||
|
||||
Debug.Assert(serializer.TargetType == type, "Target type mismatch!");
|
||||
|
||||
// We cache the serializer before we initialize it to
|
||||
// avoid a stack overflow on recursive types.
|
||||
_serializers.Add(type, serializer);
|
||||
serializer.Initialize(this);
|
||||
|
||||
return serializer;
|
||||
}
|
||||
|
||||
internal GenericCollectionHelper GetCollectionHelper(Type type)
|
||||
{
|
||||
if (_collectionHelpers == null)
|
||||
_collectionHelpers = new Dictionary<Type, GenericCollectionHelper>();
|
||||
|
||||
GenericCollectionHelper result;
|
||||
if (!_collectionHelpers.TryGetValue(type, out result))
|
||||
{
|
||||
result = new GenericCollectionHelper(this, type);
|
||||
_collectionHelpers.Add(type, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void Serialize<T>(XmlWriter output, T value, string referenceRelocationPath)
|
||||
{
|
||||
var serializer = new IntermediateSerializer();
|
||||
var writer = new IntermediateWriter(serializer, output, referenceRelocationPath);
|
||||
output.WriteStartElement("XnaContent");
|
||||
|
||||
serializer._namespaceAliasHelper.WriteNamespaces(output, value);
|
||||
|
||||
// Write the asset.
|
||||
var format = new ContentSerializerAttribute { ElementName = "Asset" };
|
||||
writer.WriteObject<object>(value, format);
|
||||
|
||||
// Process the shared resources and external references.
|
||||
writer.WriteSharedResources();
|
||||
writer.WriteExternalReferences();
|
||||
|
||||
// Close the XnaContent element.
|
||||
output.WriteEndElement();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds a lookup table from a short name to the full namespace.
|
||||
/// </summary>
|
||||
private void CreateNamespaceLookup(XmlReader reader)
|
||||
{
|
||||
_namespaceLookup = new Dictionary<string, string>();
|
||||
|
||||
for (var i=0; i < reader.AttributeCount; i++)
|
||||
{
|
||||
reader.MoveToAttribute(i);
|
||||
|
||||
if (reader.Prefix != "xmlns")
|
||||
continue;
|
||||
|
||||
_namespaceLookup.Add(reader.LocalName + ":", reader.Value + ".");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the type in any assembly loaded into the AppDomain.
|
||||
/// </summary>
|
||||
internal Type FindType(string typeName)
|
||||
{
|
||||
Type foundType;
|
||||
|
||||
typeName = typeName.Trim();
|
||||
|
||||
// Shortcut for friendly C# names
|
||||
if (_typeAliases.TryGetValue(typeName, out foundType))
|
||||
return foundType;
|
||||
|
||||
// If this is an array then handle it separately.
|
||||
if (typeName.EndsWith("[]"))
|
||||
{
|
||||
var arrayType = typeName.Substring(0, typeName.Length - 2);
|
||||
foundType = FindType(arrayType);
|
||||
return foundType == null ? null : foundType.MakeArrayType();
|
||||
}
|
||||
|
||||
// Expand any namespaces in the asset type
|
||||
foreach (var pair in _namespaceLookup)
|
||||
typeName = typeName.Replace(pair.Key, pair.Value);
|
||||
var expandedName = typeName;
|
||||
|
||||
// If this a generic type, handle it separately.
|
||||
if (typeName.EndsWith("]"))
|
||||
{
|
||||
var openBracketIndex = typeName.IndexOf("[");
|
||||
|
||||
var typeNameWithoutArguments = typeName.Substring(0, openBracketIndex);
|
||||
|
||||
var genericArgumentsString = typeName.Substring(openBracketIndex + 1, typeName.Length - openBracketIndex - 2);
|
||||
var genericArgumentsArray = genericArgumentsString.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
var genericArguments = genericArgumentsArray.Select(FindType).ToArray();
|
||||
|
||||
foundType = FindType(typeNameWithoutArguments + "`" + genericArguments.Length);
|
||||
return (foundType == null) ? null : foundType.MakeGenericType(genericArguments);
|
||||
}
|
||||
|
||||
foundType = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
|
||||
from type in assembly.GetTypes()
|
||||
where type.FullName == typeName || type.Name == typeName
|
||||
select type).FirstOrDefault();
|
||||
|
||||
if (foundType == null)
|
||||
foundType = Type.GetType(expandedName, false, true);
|
||||
|
||||
return foundType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the (potentially) aliased name for any type.
|
||||
/// </summary>
|
||||
internal string GetFullTypeName(Type type)
|
||||
{
|
||||
string typeName;
|
||||
|
||||
// Shortcut for friendly C# names
|
||||
if (_typeAliasesReverse.TryGetValue(type, out typeName))
|
||||
return typeName;
|
||||
|
||||
// Look for aliased namespace.
|
||||
if (_namespaceAliasHelper.TryGetAliasedTypeName(type, out typeName))
|
||||
return typeName;
|
||||
|
||||
// Fallback to full type name.
|
||||
var typeNamespace = type.Namespace;
|
||||
if (!string.IsNullOrEmpty(typeNamespace))
|
||||
typeName = typeNamespace + ".";
|
||||
typeName += GetTypeName(type);
|
||||
|
||||
return typeName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the name of the type, without the namespace.
|
||||
/// For generic types, we add the type parameters in square brackets.
|
||||
/// i.e. List<int> becomes List[int]
|
||||
/// </summary>
|
||||
internal string GetTypeName(Type type)
|
||||
{
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
var typeName = type.Name;
|
||||
int genericBacktickIndex = typeName.IndexOf("`");
|
||||
if (genericBacktickIndex >= 0)
|
||||
typeName = typeName.Substring(0, genericBacktickIndex);
|
||||
|
||||
var result = typeName + "[";
|
||||
result += string.Join(",", type.GetGenericArguments().Select(GetFullTypeName));
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
|
||||
if (type.IsArray)
|
||||
return GetTypeName(type.GetElementType()) + "[]";
|
||||
|
||||
if (type.IsNested)
|
||||
return type.DeclaringType.Name + "+" + type.Name;
|
||||
|
||||
return type.Name;
|
||||
}
|
||||
|
||||
internal bool AlreadyScanned(object value)
|
||||
{
|
||||
if (_scannedObjects.Contains(value))
|
||||
return true;
|
||||
_scannedObjects.Add(value);
|
||||
return false;
|
||||
}
|
||||
|
||||
internal bool HasTypeAlias(Type type)
|
||||
{
|
||||
return _typeAliasesReverse.ContainsKey(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
+222
@@ -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.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
|
||||
{
|
||||
public sealed class IntermediateWriter
|
||||
{
|
||||
private readonly Stack<object> _currentObjectStack;
|
||||
private readonly Dictionary<object, string> _sharedResources;
|
||||
private readonly Dictionary<object, ExternalReference> _externalReferences;
|
||||
private readonly string _filePath;
|
||||
|
||||
internal IntermediateWriter(IntermediateSerializer serializer, XmlWriter xmlWriter, string filePath)
|
||||
{
|
||||
Serializer = serializer;
|
||||
Xml = xmlWriter;
|
||||
_filePath = filePath;
|
||||
|
||||
_currentObjectStack = new Stack<object>();
|
||||
_sharedResources = new Dictionary<object, string>();
|
||||
_externalReferences = new Dictionary<object, ExternalReference>();
|
||||
}
|
||||
|
||||
public XmlWriter Xml { get; private set; }
|
||||
|
||||
public IntermediateSerializer Serializer { get; private set; }
|
||||
|
||||
public void WriteExternalReference<T>(ExternalReference<T> value)
|
||||
{
|
||||
ExternalReference externalReference;
|
||||
if (!_externalReferences.TryGetValue(value, out externalReference))
|
||||
_externalReferences.Add(value, externalReference = new ExternalReference
|
||||
{
|
||||
ID = "#External" + (_externalReferences.Count + 1),
|
||||
TargetType = typeof(T).FullName,
|
||||
FileName = MakeRelativePath(value.Filename)
|
||||
});
|
||||
|
||||
Xml.WriteElementString("Reference", externalReference.ID);
|
||||
}
|
||||
|
||||
private string MakeRelativePath(string path)
|
||||
{
|
||||
var fullReferencePath = Path.GetFullPath(Path.GetDirectoryName(_filePath)) + Path.DirectorySeparatorChar;
|
||||
var fullPath = Path.GetFullPath(path);
|
||||
return new Uri(fullReferencePath).MakeRelativeUri(new Uri(fullPath)).ToString();
|
||||
}
|
||||
|
||||
private class ExternalReference
|
||||
{
|
||||
public string ID;
|
||||
public string TargetType;
|
||||
public string FileName;
|
||||
}
|
||||
|
||||
public void WriteObject<T>(T value, ContentSerializerAttribute format)
|
||||
{
|
||||
WriteObject(value, format, Serializer.GetTypeSerializer(typeof(T)));
|
||||
}
|
||||
|
||||
public void WriteObject<T>(T value, ContentSerializerAttribute format, ContentTypeSerializer typeSerializer)
|
||||
{
|
||||
WriteObjectInternal(value, format, typeSerializer, typeof(T));
|
||||
}
|
||||
|
||||
internal void WriteObjectInternal(object value, ContentSerializerAttribute format, ContentTypeSerializer typeSerializer, Type declaredType)
|
||||
{
|
||||
if (format.Optional && (value == null || typeSerializer.ObjectIsEmpty(value)))
|
||||
return;
|
||||
|
||||
var isReferenceObject = false;
|
||||
if (value != null && !typeSerializer.TargetType.IsValueType)
|
||||
{
|
||||
if (_currentObjectStack.Contains(value))
|
||||
throw new InvalidOperationException("Cyclic reference found during serialization. You may be missing a [ContentSerializer(SharedResource=true)] attribute.");
|
||||
_currentObjectStack.Push(value);
|
||||
isReferenceObject = true;
|
||||
}
|
||||
|
||||
if (!format.FlattenContent)
|
||||
{
|
||||
Xml.WriteStartElement(format.ElementName);
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
if (!format.AllowNull)
|
||||
throw new InvalidOperationException(string.Format("Element {0} cannot be null.", format.ElementName));
|
||||
|
||||
Xml.WriteAttributeString("Null", "true");
|
||||
}
|
||||
else if (value.GetType() != typeSerializer.TargetType && !IsNullableType(declaredType))
|
||||
{
|
||||
Xml.WriteStartAttribute("Type");
|
||||
WriteTypeName(value.GetType());
|
||||
Xml.WriteEndAttribute();
|
||||
|
||||
typeSerializer = Serializer.GetTypeSerializer(value.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
if (value != null && !typeSerializer.ObjectIsEmpty(value))
|
||||
typeSerializer.Serialize(this, value, format);
|
||||
|
||||
if (!format.FlattenContent)
|
||||
Xml.WriteEndElement();
|
||||
|
||||
if (isReferenceObject)
|
||||
_currentObjectStack.Pop();
|
||||
}
|
||||
|
||||
private static bool IsNullableType(Type type)
|
||||
{
|
||||
return Nullable.GetUnderlyingType(type) != null;
|
||||
}
|
||||
|
||||
public void WriteRawObject<T>(T value, ContentSerializerAttribute format)
|
||||
{
|
||||
WriteRawObject(value, format, Serializer.GetTypeSerializer(typeof(T)));
|
||||
}
|
||||
|
||||
public void WriteRawObject<T>(T value, ContentSerializerAttribute format, ContentTypeSerializer typeSerializer)
|
||||
{
|
||||
if (!format.FlattenContent)
|
||||
Xml.WriteStartElement(format.ElementName);
|
||||
|
||||
typeSerializer.Serialize(this, value, format);
|
||||
|
||||
if (!format.FlattenContent)
|
||||
Xml.WriteEndElement();
|
||||
}
|
||||
|
||||
public void WriteSharedResource<T>(T value, ContentSerializerAttribute format)
|
||||
{
|
||||
var sharedResourceID = GetSharedResourceID(value);
|
||||
|
||||
if (format.FlattenContent)
|
||||
Xml.WriteValue(sharedResourceID);
|
||||
else
|
||||
Xml.WriteElementString(format.ElementName, sharedResourceID);
|
||||
}
|
||||
|
||||
private string GetSharedResourceID(object value)
|
||||
{
|
||||
if (value == null)
|
||||
return null;
|
||||
|
||||
string id;
|
||||
if (!_sharedResources.TryGetValue(value, out id))
|
||||
_sharedResources.Add(value, id = "#Resource" + (_sharedResources.Count + 1));
|
||||
return id;
|
||||
}
|
||||
|
||||
internal void WriteSharedResources()
|
||||
{
|
||||
if (!_sharedResources.Any())
|
||||
return;
|
||||
|
||||
Xml.WriteStartElement("Resources");
|
||||
|
||||
// Loop like this because we might create more shared resources while we're serializing.
|
||||
var writtenSharedResources = new List<string>();
|
||||
while (_sharedResources.Any(x => !writtenSharedResources.Contains(x.Value)))
|
||||
{
|
||||
var sharedResource = _sharedResources.First(x => !writtenSharedResources.Contains(x.Value));
|
||||
writtenSharedResources.Add(sharedResource.Value);
|
||||
|
||||
WriteSharedResource(sharedResource.Value, sharedResource.Key);
|
||||
}
|
||||
|
||||
Xml.WriteEndElement();
|
||||
}
|
||||
|
||||
private void WriteSharedResource(string id, object sharedResource)
|
||||
{
|
||||
Xml.WriteStartElement("Resource");
|
||||
|
||||
Xml.WriteAttributeString("ID", id);
|
||||
|
||||
Xml.WriteStartAttribute("Type");
|
||||
WriteTypeName(sharedResource.GetType());
|
||||
Xml.WriteEndAttribute();
|
||||
|
||||
Serializer.GetTypeSerializer(sharedResource.GetType()).Serialize(this, sharedResource, new ContentSerializerAttribute());
|
||||
|
||||
Xml.WriteEndElement();
|
||||
}
|
||||
|
||||
internal void WriteExternalReferences()
|
||||
{
|
||||
if (!_externalReferences.Any())
|
||||
return;
|
||||
|
||||
Xml.WriteStartElement("ExternalReferences");
|
||||
|
||||
foreach (var externalReference in _externalReferences.Values)
|
||||
{
|
||||
Xml.WriteStartElement("ExternalReference");
|
||||
|
||||
Xml.WriteAttributeString("ID", externalReference.ID);
|
||||
Xml.WriteAttributeString("TargetType", externalReference.TargetType);
|
||||
|
||||
Xml.WriteValue(externalReference.FileName);
|
||||
|
||||
Xml.WriteEndElement();
|
||||
}
|
||||
|
||||
Xml.WriteEndElement();
|
||||
}
|
||||
|
||||
public void WriteTypeName(Type type)
|
||||
{
|
||||
Xml.WriteString(Serializer.GetFullTypeName(type));
|
||||
}
|
||||
}
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
// 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 ListSerializer<T> : ContentTypeSerializer<List<T>>
|
||||
{
|
||||
private ContentTypeSerializer _itemSerializer;
|
||||
|
||||
public ListSerializer() :
|
||||
base("list")
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanDeserializeIntoExistingObject
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
protected internal override void Initialize(IntermediateSerializer serializer)
|
||||
{
|
||||
_itemSerializer = serializer.GetTypeSerializer(typeof(T));
|
||||
}
|
||||
|
||||
public override bool ObjectIsEmpty(List<T> value)
|
||||
{
|
||||
return value.Count == 0;
|
||||
}
|
||||
|
||||
protected internal override void ScanChildren(IntermediateSerializer serializer, ChildCallback callback, List<T> value)
|
||||
{
|
||||
foreach (var item in value)
|
||||
callback(_itemSerializer, item);
|
||||
}
|
||||
|
||||
protected internal override List<T> Deserialize(IntermediateReader input, ContentSerializerAttribute format, List<T> existingInstance)
|
||||
{
|
||||
var result = existingInstance ?? new List<T>();
|
||||
|
||||
var elementSerializer = _itemSerializer as ElementSerializer<T>;
|
||||
if (elementSerializer != null)
|
||||
elementSerializer.Deserialize(input, result);
|
||||
else
|
||||
{
|
||||
// Create the item serializer attribute.
|
||||
var itemFormat = new ContentSerializerAttribute();
|
||||
itemFormat.ElementName = format.CollectionItemName;
|
||||
|
||||
// Read all the items.
|
||||
while (input.MoveToElement(itemFormat.ElementName))
|
||||
{
|
||||
var value = input.ReadObject<T>(itemFormat, _itemSerializer);
|
||||
result.Add(value);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected internal override void Serialize(IntermediateWriter output, List<T> value, ContentSerializerAttribute format)
|
||||
{
|
||||
var elementSerializer = _itemSerializer as ElementSerializer<T>;
|
||||
if (elementSerializer != null)
|
||||
elementSerializer.Serialize(output, value);
|
||||
else
|
||||
{
|
||||
// Create the item serializer attribute.
|
||||
var itemFormat = new ContentSerializerAttribute();
|
||||
itemFormat.ElementName = format.CollectionItemName;
|
||||
|
||||
// Read all the items.
|
||||
foreach (var item in value)
|
||||
output.WriteObject(item, itemFormat, _itemSerializer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -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 LongSerializer : ElementSerializer<long>
|
||||
{
|
||||
public LongSerializer() :
|
||||
base("long", 1)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal override long Deserialize(string[] inputs, ref int index)
|
||||
{
|
||||
return XmlConvert.ToInt64(inputs[index++]);
|
||||
}
|
||||
|
||||
protected internal override void Serialize(long value, List<string> results)
|
||||
{
|
||||
results.Add(XmlConvert.ToString(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
// 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 MatrixSerializer : ElementSerializer<Matrix>
|
||||
{
|
||||
public MatrixSerializer() :
|
||||
base("Matrix", 16)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal override Matrix Deserialize(string[] inputs, ref int index)
|
||||
{
|
||||
return new Matrix(XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]));
|
||||
}
|
||||
|
||||
protected internal override void Serialize(Matrix value, List<string> results)
|
||||
{
|
||||
results.Add(XmlConvert.ToString(value.M11));
|
||||
results.Add(XmlConvert.ToString(value.M12));
|
||||
results.Add(XmlConvert.ToString(value.M13));
|
||||
results.Add(XmlConvert.ToString(value.M14));
|
||||
results.Add(XmlConvert.ToString(value.M21));
|
||||
results.Add(XmlConvert.ToString(value.M22));
|
||||
results.Add(XmlConvert.ToString(value.M23));
|
||||
results.Add(XmlConvert.ToString(value.M24));
|
||||
results.Add(XmlConvert.ToString(value.M31));
|
||||
results.Add(XmlConvert.ToString(value.M32));
|
||||
results.Add(XmlConvert.ToString(value.M33));
|
||||
results.Add(XmlConvert.ToString(value.M34));
|
||||
results.Add(XmlConvert.ToString(value.M41));
|
||||
results.Add(XmlConvert.ToString(value.M42));
|
||||
results.Add(XmlConvert.ToString(value.M43));
|
||||
results.Add(XmlConvert.ToString(value.M44));
|
||||
}
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
// 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.
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
|
||||
{
|
||||
[ContentTypeSerializer]
|
||||
class NamedValueDictionarySerializer<T> : ContentTypeSerializer<NamedValueDictionary<T>>
|
||||
{
|
||||
private ContentTypeSerializer _keySerializer;
|
||||
|
||||
private ContentSerializerAttribute _keyFormat;
|
||||
private ContentSerializerAttribute _valueFormat;
|
||||
|
||||
public NamedValueDictionarySerializer() :
|
||||
base("namedValueDictionary")
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanDeserializeIntoExistingObject
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
protected internal override void Initialize(IntermediateSerializer serializer)
|
||||
{
|
||||
_keySerializer = serializer.GetTypeSerializer(typeof(string));
|
||||
|
||||
_keyFormat = new ContentSerializerAttribute
|
||||
{
|
||||
ElementName = "Key",
|
||||
AllowNull = false
|
||||
};
|
||||
|
||||
_valueFormat = new ContentSerializerAttribute
|
||||
{
|
||||
ElementName = "Value",
|
||||
AllowNull = typeof(T).IsValueType
|
||||
};
|
||||
}
|
||||
|
||||
public override bool ObjectIsEmpty(NamedValueDictionary<T> value)
|
||||
{
|
||||
return value.Count == 0;
|
||||
}
|
||||
|
||||
protected internal override void ScanChildren(IntermediateSerializer serializer, ChildCallback callback, NamedValueDictionary<T> value)
|
||||
{
|
||||
foreach (var kvp in value)
|
||||
callback(serializer.GetTypeSerializer(typeof(T)), kvp.Value);
|
||||
}
|
||||
|
||||
protected internal override NamedValueDictionary<T> Deserialize(IntermediateReader input, ContentSerializerAttribute format, NamedValueDictionary<T> existingInstance)
|
||||
{
|
||||
var result = existingInstance ?? new NamedValueDictionary<T>();
|
||||
|
||||
var valueSerializer = input.Serializer.GetTypeSerializer(result.DefaultSerializerType);
|
||||
|
||||
while (input.MoveToElement(format.CollectionItemName))
|
||||
{
|
||||
input.Xml.ReadStartElement();
|
||||
|
||||
var key = input.ReadObject<string>(_keyFormat, _keySerializer);
|
||||
var value = input.ReadObject<T>(_valueFormat, valueSerializer);
|
||||
result.Add(key,value);
|
||||
|
||||
input.Xml.ReadEndElement();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected internal override void Serialize(IntermediateWriter output, NamedValueDictionary<T> value, ContentSerializerAttribute format)
|
||||
{
|
||||
var valueSerializer = output.Serializer.GetTypeSerializer(value.DefaultSerializerType);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
|
||||
{
|
||||
internal class NamespaceAliasHelper
|
||||
{
|
||||
private readonly IntermediateSerializer _serializer;
|
||||
|
||||
/// <summary>
|
||||
/// Maps "My.Namespace.LongName" -> "ShortName" for type lookups.
|
||||
/// </summary>
|
||||
private Dictionary<string, AliasedNamespace> _namespaceLookupReverse;
|
||||
|
||||
private class AliasedNamespace
|
||||
{
|
||||
public string Alias;
|
||||
public string TypePrefix;
|
||||
}
|
||||
|
||||
public NamespaceAliasHelper(IntermediateSerializer serializer)
|
||||
{
|
||||
_serializer = serializer;
|
||||
}
|
||||
|
||||
public void WriteNamespaces<T>(XmlWriter writer, T value)
|
||||
{
|
||||
// Maps "My.Namespace.LongName" -> "ShortName" for type lookups.
|
||||
_namespaceLookupReverse = new Dictionary<string, AliasedNamespace>();
|
||||
|
||||
// Get all namespaces of types used by "value" or its children.
|
||||
var childNamespaces = GetAllUsedNamespaces(value).Distinct().ToList();
|
||||
|
||||
// Do first pass to determine what our aliases are. We do this on a sorted
|
||||
// list of namespaces so that more-nested namespaces will be processed last,
|
||||
// by which time we will have already created the aliases for parent namespaces.
|
||||
var sortedChildNamespaces = new List<string>(childNamespaces);
|
||||
sortedChildNamespaces.Sort();
|
||||
var tempAliases = new Dictionary<string, AliasedNamespace>();
|
||||
foreach (var childNamespace in sortedChildNamespaces)
|
||||
{
|
||||
var alias = FindAlias(tempAliases, childNamespace);
|
||||
if (alias != null)
|
||||
tempAliases.Add(childNamespace, alias);
|
||||
}
|
||||
|
||||
// Do second pass on the namespaces as they were originally ordered, to match XNA.
|
||||
foreach (var childNamespace in childNamespaces)
|
||||
{
|
||||
AliasedNamespace alias;
|
||||
if (tempAliases.TryGetValue(childNamespace, out alias))
|
||||
_namespaceLookupReverse.Add(childNamespace, alias);
|
||||
}
|
||||
|
||||
foreach (var kvp in _namespaceLookupReverse)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(kvp.Value.TypePrefix))
|
||||
continue;
|
||||
writer.WriteAttributeString("xmlns", kvp.Value.Alias, null, kvp.Key);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetAllUsedNamespaces<T>(T value)
|
||||
{
|
||||
var result = new List<string>();
|
||||
ContentTypeSerializer.ChildCallback onScanChild = (contentTypeSerializer, child) =>
|
||||
{
|
||||
if (child == null)
|
||||
return;
|
||||
|
||||
var childType = child.GetType();
|
||||
|
||||
if (contentTypeSerializer.TargetType == childType)
|
||||
return;
|
||||
|
||||
if (contentTypeSerializer.TargetType.IsGenericType
|
||||
&& contentTypeSerializer.TargetType.GetGenericTypeDefinition() == typeof(Nullable<>)
|
||||
&& contentTypeSerializer.TargetType.GetGenericArguments()[0] == childType)
|
||||
return;
|
||||
|
||||
if (_serializer.HasTypeAlias(childType))
|
||||
return;
|
||||
|
||||
var childNamespace = childType.Namespace;
|
||||
|
||||
if (string.IsNullOrEmpty(childNamespace))
|
||||
return;
|
||||
|
||||
result.Add(childNamespace);
|
||||
};
|
||||
|
||||
// Force top-level object type to be included.
|
||||
onScanChild(_serializer.GetTypeSerializer(typeof(object)), value);
|
||||
|
||||
// Scan child objects.
|
||||
var serializer = _serializer.GetTypeSerializer(typeof(T));
|
||||
serializer.ScanChildren(_serializer, onScanChild, value);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static AliasedNamespace FindAlias(Dictionary<string, AliasedNamespace> aliases, string childNamespace)
|
||||
{
|
||||
if (string.IsNullOrEmpty(childNamespace))
|
||||
return null;
|
||||
|
||||
// If there isn't yet an alias for the last part of the namespace, use that.
|
||||
var alias = childNamespace.Substring(childNamespace.LastIndexOf('.') + 1);
|
||||
if (aliases.All(x => x.Value.Alias != alias))
|
||||
return new AliasedNamespace
|
||||
{
|
||||
Alias = alias,
|
||||
TypePrefix = string.Empty
|
||||
};
|
||||
|
||||
// Otherwise, find the longest parent namespace, and use that, with a TypePrefix to make
|
||||
// this namespace relative to that one.
|
||||
if (aliases.Any(x => childNamespace.StartsWith(x.Key)))
|
||||
{
|
||||
string longestParentNamespace = string.Empty;
|
||||
foreach (var kvp in aliases.Where(x => string.IsNullOrEmpty(x.Value.TypePrefix)))
|
||||
{
|
||||
if (childNamespace.StartsWith(kvp.Key) && kvp.Key.Length > longestParentNamespace.Length)
|
||||
longestParentNamespace = kvp.Key;
|
||||
}
|
||||
return new AliasedNamespace
|
||||
{
|
||||
Alias = aliases[longestParentNamespace].Alias,
|
||||
TypePrefix = GetRelativeNamespace(longestParentNamespace, childNamespace) + "."
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns just the portion <paramref name="namespace"/> relative to <paramref name="namespaceParent"/>.
|
||||
/// For example, given namespaceParent=Foo.Bar and @namespace=Foo.Bar.Baz, will return Baz.
|
||||
/// </summary>
|
||||
private static string GetRelativeNamespace(string namespaceParent, string @namespace)
|
||||
{
|
||||
if (@namespace.StartsWith(namespaceParent))
|
||||
return @namespace.Substring(namespaceParent.Length + 1);
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
public bool TryGetAliasedTypeName(Type type, out string typeName)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(type.Namespace))
|
||||
{
|
||||
AliasedNamespace namespaceAlias;
|
||||
if (_namespaceLookupReverse.TryGetValue(type.Namespace, out namespaceAlias))
|
||||
{
|
||||
typeName = namespaceAlias.Alias + ":" + namespaceAlias.TypePrefix + _serializer.GetTypeName(type);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
typeName = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
|
||||
{
|
||||
class NonGenericIListSerializer : ContentTypeSerializer
|
||||
{
|
||||
public NonGenericIListSerializer(Type targetType) :
|
||||
base(targetType, targetType.Name)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanDeserializeIntoExistingObject
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override bool ObjectIsEmpty(object value)
|
||||
{
|
||||
return ((IList) value).Count == 0;
|
||||
}
|
||||
|
||||
protected internal override object Deserialize(IntermediateReader input, ContentSerializerAttribute format, object existingInstance)
|
||||
{
|
||||
var result = (IList) (existingInstance ?? Activator.CreateInstance(TargetType));
|
||||
|
||||
// Create the item serializer attribute.
|
||||
var itemFormat = new ContentSerializerAttribute();
|
||||
itemFormat.ElementName = format.CollectionItemName;
|
||||
|
||||
// Read all the items.
|
||||
while (input.MoveToElement(itemFormat.ElementName))
|
||||
{
|
||||
var value = input.ReadObject<object>(itemFormat);
|
||||
result.Add(value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected internal override void Serialize(IntermediateWriter output, object value, ContentSerializerAttribute format)
|
||||
{
|
||||
// Create the item serializer attribute.
|
||||
var itemFormat = new ContentSerializerAttribute();
|
||||
itemFormat.ElementName = format.CollectionItemName;
|
||||
|
||||
// Read all the items.
|
||||
foreach (var item in (IList) value)
|
||||
output.WriteObject(item, itemFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
|
||||
{
|
||||
[ContentTypeSerializer]
|
||||
class NullableSerializer<T> : ContentTypeSerializer<T?> where T : struct
|
||||
{
|
||||
private ContentTypeSerializer _serializer;
|
||||
private ContentSerializerAttribute _format;
|
||||
|
||||
protected internal override void Initialize(IntermediateSerializer serializer)
|
||||
{
|
||||
_serializer = serializer.GetTypeSerializer(typeof(T));
|
||||
_format = new ContentSerializerAttribute
|
||||
{
|
||||
FlattenContent = true
|
||||
};
|
||||
}
|
||||
|
||||
protected internal override T? Deserialize(IntermediateReader input, ContentSerializerAttribute format, T? existingInstance)
|
||||
{
|
||||
return input.ReadRawObject<T>(_format, _serializer);
|
||||
}
|
||||
|
||||
protected internal override void Serialize(IntermediateWriter output, T? value, ContentSerializerAttribute format)
|
||||
{
|
||||
output.WriteRawObject<T>(value.Value, _format, _serializer);
|
||||
}
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
|
||||
{
|
||||
internal static class PackedElementsHelper
|
||||
{
|
||||
private static readonly char[] _seperators = { ' ', '\t', '\n' };
|
||||
|
||||
private const string _writeSeperator = " ";
|
||||
|
||||
internal static string[] ReadElements(IntermediateReader input)
|
||||
{
|
||||
if (input.Xml.IsEmptyElement)
|
||||
return new string[0];
|
||||
|
||||
string str = string.Empty;
|
||||
while (input.Xml.NodeType != XmlNodeType.EndElement)
|
||||
{
|
||||
if (input.Xml.NodeType == XmlNodeType.Comment)
|
||||
input.Xml.Read();
|
||||
else
|
||||
str += input.Xml.ReadString();
|
||||
}
|
||||
|
||||
// Special case for char ' '
|
||||
if (str.Length > 0 && str.Trim() == string.Empty)
|
||||
return new string[] { str };
|
||||
|
||||
var elements = str.Split(_seperators, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (elements.Length == 1 && string.IsNullOrEmpty(elements[0]))
|
||||
return new string[0];
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
public static string JoinElements(IEnumerable<string> elements)
|
||||
{
|
||||
return string.Join(_writeSeperator, elements);
|
||||
}
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// 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 PlaneSerializer : ElementSerializer<Plane>
|
||||
{
|
||||
public PlaneSerializer() :
|
||||
base("Plane", 4)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal override Plane Deserialize(string[] inputs, ref int index)
|
||||
{
|
||||
return new Plane( XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]));
|
||||
}
|
||||
|
||||
protected internal override void Serialize(Plane value, List<string> results)
|
||||
{
|
||||
results.Add(XmlConvert.ToString(value.Normal.X));
|
||||
results.Add(XmlConvert.ToString(value.Normal.Y));
|
||||
results.Add(XmlConvert.ToString(value.Normal.Z));
|
||||
results.Add(XmlConvert.ToString(value.D));
|
||||
}
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
// 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 PointSerializer : ElementSerializer<Point>
|
||||
{
|
||||
public PointSerializer() :
|
||||
base("Point", 2)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal override Point Deserialize(string[] inputs, ref int index)
|
||||
{
|
||||
return new Point( XmlConvert.ToInt32(inputs[index++]),
|
||||
XmlConvert.ToInt32(inputs[index++]));
|
||||
}
|
||||
|
||||
protected internal override void Serialize(Point value, List<string> results)
|
||||
{
|
||||
results.Add(XmlConvert.ToString(value.X));
|
||||
results.Add(XmlConvert.ToString(value.Y));
|
||||
}
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// 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 QuaternionSerializer : ElementSerializer<Quaternion>
|
||||
{
|
||||
public QuaternionSerializer() :
|
||||
base("Quaternion", 4)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal override Quaternion Deserialize(string[] inputs, ref int index)
|
||||
{
|
||||
return new Quaternion( XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]),
|
||||
XmlConvert.ToSingle(inputs[index++]));
|
||||
}
|
||||
|
||||
protected internal override void Serialize(Quaternion value, List<string> results)
|
||||
{
|
||||
results.Add(XmlConvert.ToString(value.X));
|
||||
results.Add(XmlConvert.ToString(value.Y));
|
||||
results.Add(XmlConvert.ToString(value.Z));
|
||||
results.Add(XmlConvert.ToString(value.W));
|
||||
}
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// 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 RectangleSerializer : ElementSerializer<Rectangle>
|
||||
{
|
||||
public RectangleSerializer() :
|
||||
base("Rectangle", 4)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal override Rectangle Deserialize(string[] inputs, ref int index)
|
||||
{
|
||||
return new Rectangle( XmlConvert.ToInt32(inputs[index++]),
|
||||
XmlConvert.ToInt32(inputs[index++]),
|
||||
XmlConvert.ToInt32(inputs[index++]),
|
||||
XmlConvert.ToInt32(inputs[index++]));
|
||||
}
|
||||
|
||||
protected internal override void Serialize(Rectangle value, List<string> results)
|
||||
{
|
||||
results.Add(XmlConvert.ToString(value.X));
|
||||
results.Add(XmlConvert.ToString(value.Y));
|
||||
results.Add(XmlConvert.ToString(value.Width));
|
||||
results.Add(XmlConvert.ToString(value.Height));
|
||||
}
|
||||
}
|
||||
}
|
||||
+262
@@ -0,0 +1,262 @@
|
||||
// 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.Reflection;
|
||||
using System.Xml;
|
||||
using MonoGame.Utilities;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
|
||||
{
|
||||
internal class ReflectiveSerializer : ContentTypeSerializer
|
||||
{
|
||||
const BindingFlags _bindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
|
||||
|
||||
private struct ElementInfo
|
||||
{
|
||||
public ContentSerializerAttribute Attribute;
|
||||
public ContentTypeSerializer Serializer;
|
||||
public Action<object, object> Setter;
|
||||
public Func<object, object> Getter;
|
||||
};
|
||||
|
||||
private readonly List<ElementInfo> _elements = new List<ElementInfo>();
|
||||
|
||||
private ContentTypeSerializer _baseSerializer;
|
||||
private GenericCollectionHelper _collectionHelper;
|
||||
|
||||
private bool GetElementInfo(IntermediateSerializer serializer, MemberInfo member, out ElementInfo info)
|
||||
{
|
||||
info = new ElementInfo();
|
||||
|
||||
// Are we ignoring this property?
|
||||
if (ReflectionHelpers.GetCustomAttribute<ContentSerializerIgnoreAttribute>(member) != null)
|
||||
return false;
|
||||
|
||||
var prop = member as PropertyInfo;
|
||||
var field = member as FieldInfo;
|
||||
|
||||
var attrib = ReflectionHelpers.GetCustomAttribute<ContentSerializerAttribute>(member);
|
||||
if (attrib != null)
|
||||
{
|
||||
// Store the attribute for later use.
|
||||
info.Attribute = attrib.Clone();
|
||||
|
||||
// Default the to member name as the element name.
|
||||
if (string.IsNullOrEmpty(attrib.ElementName))
|
||||
info.Attribute.ElementName = member.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We don't have a serializer attribute, so we can
|
||||
// only access this member thru a public field/property.
|
||||
|
||||
if (prop != null)
|
||||
{
|
||||
// If we don't have at least a public getter then this
|
||||
// property can't be serialized or deserialized in any way.
|
||||
if (prop.GetGetMethod() == null)
|
||||
return false;
|
||||
|
||||
// If there is a setter, but it's private, then don't include this element
|
||||
// (although technically we could, as long as we have a serializer with
|
||||
// CanDeserializeIntoExistingObject=true for this property type)
|
||||
var setter = prop.GetSetMethod(true);
|
||||
if (setter != null && !setter.IsPublic)
|
||||
return false;
|
||||
|
||||
// If there is no setter, and we don't have a type serializer
|
||||
// that can deserialize into an existing object, then we have no way
|
||||
// for it to be deserialized.
|
||||
if (setter == null && !serializer.GetTypeSerializer(prop.PropertyType).CanDeserializeIntoExistingObject)
|
||||
return false;
|
||||
|
||||
// Don't serialize or deserialize indexers.
|
||||
if (prop.GetIndexParameters().Any())
|
||||
return false;
|
||||
}
|
||||
else if (field != null)
|
||||
{
|
||||
if (!field.IsPublic)
|
||||
return false;
|
||||
}
|
||||
|
||||
info.Attribute = new ContentSerializerAttribute();
|
||||
info.Attribute.ElementName = member.Name;
|
||||
}
|
||||
|
||||
if (prop != null)
|
||||
{
|
||||
info.Serializer = serializer.GetTypeSerializer(prop.PropertyType);
|
||||
if (prop.CanWrite)
|
||||
info.Setter = (o, v) => prop.SetValue(o, v, null);
|
||||
info.Getter = o => prop.GetValue(o, null);
|
||||
}
|
||||
else if (field != null)
|
||||
{
|
||||
info.Serializer = serializer.GetTypeSerializer(field.FieldType);
|
||||
info.Setter = field.SetValue;
|
||||
info.Getter = field.GetValue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public ReflectiveSerializer(Type targetType) :
|
||||
base(targetType, string.Empty)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal override void Initialize(IntermediateSerializer serializer)
|
||||
{
|
||||
// If we have a base type then we need to deserialize it first.
|
||||
if (TargetType.BaseType != null)
|
||||
_baseSerializer = serializer.GetTypeSerializer(TargetType.BaseType);
|
||||
|
||||
// Cache all our serializable properties.
|
||||
var properties = TargetType.GetProperties(_bindingFlags);
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
ElementInfo info;
|
||||
if (GetElementInfo(serializer, prop, out info))
|
||||
_elements.Add(info);
|
||||
}
|
||||
|
||||
// Cache all our serializable fields.
|
||||
var fields = TargetType.GetFields(_bindingFlags);
|
||||
foreach (var field in fields)
|
||||
{
|
||||
ElementInfo info;
|
||||
if (GetElementInfo(serializer, field, out info))
|
||||
_elements.Add(info);
|
||||
}
|
||||
|
||||
if (GenericCollectionHelper.IsGenericCollectionType(TargetType, false))
|
||||
_collectionHelper = serializer.GetCollectionHelper(TargetType);
|
||||
}
|
||||
|
||||
public override bool CanDeserializeIntoExistingObject
|
||||
{
|
||||
get { return TargetType.IsClass && TargetType.BaseType != null; }
|
||||
}
|
||||
|
||||
protected internal override object Deserialize(IntermediateReader input, ContentSerializerAttribute format, object existingInstance)
|
||||
{
|
||||
var result = existingInstance;
|
||||
if (result == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
result = Activator.CreateInstance(TargetType, true);
|
||||
}
|
||||
catch (MissingMethodException e)
|
||||
{
|
||||
throw new Exception(string.Format("Couldn't create object of type {0}: {1}", TargetType.Name, e.Message), e);
|
||||
}
|
||||
}
|
||||
|
||||
// First deserialize the base type.
|
||||
if (_baseSerializer != null)
|
||||
_baseSerializer.Deserialize(input, format, result);
|
||||
|
||||
// Now deserialize our own elements.
|
||||
foreach (var info in _elements)
|
||||
{
|
||||
if (!info.Attribute.FlattenContent)
|
||||
{
|
||||
if (!input.MoveToElement(info.Attribute.ElementName))
|
||||
{
|
||||
// If the the element was optional then we can
|
||||
// safely skip it and continue.
|
||||
if (info.Attribute.Optional)
|
||||
continue;
|
||||
|
||||
// We failed to find a required element.
|
||||
throw new InvalidContentException(string.Format("The Xml element `{0}` is required, but element `{1}` was found at line {2}:{3}. Try changing the element order or adding missing elements.", info.Attribute.ElementName, input.Xml.Name, ((IXmlLineInfo)input.Xml).LineNumber, ((IXmlLineInfo)input.Xml).LinePosition));
|
||||
}
|
||||
}
|
||||
|
||||
if (info.Attribute.SharedResource)
|
||||
{
|
||||
Action<object> fixup = (o) => info.Setter(result, o);
|
||||
input.ReadSharedResource(info.Attribute, fixup);
|
||||
}
|
||||
else if (info.Setter == null)
|
||||
{
|
||||
var value = info.Getter(result);
|
||||
input.ReadObject(info.Attribute, info.Serializer, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
var value = input.ReadObject<object>(info.Attribute, info.Serializer);
|
||||
info.Setter(result, value);
|
||||
}
|
||||
}
|
||||
|
||||
if (_collectionHelper != null)
|
||||
_collectionHelper.Deserialize(input, result, format);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override bool ObjectIsEmpty(object value)
|
||||
{
|
||||
if (_baseSerializer != null)
|
||||
return _baseSerializer.ObjectIsEmpty(value);
|
||||
if (_collectionHelper != null)
|
||||
return _collectionHelper.ObjectIsEmpty(value);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected internal override void ScanChildren(IntermediateSerializer serializer, ChildCallback callback, object value)
|
||||
{
|
||||
if (serializer.AlreadyScanned(value))
|
||||
return;
|
||||
|
||||
// First scan the base type.
|
||||
if (_baseSerializer != null)
|
||||
_baseSerializer.ScanChildren(serializer, callback, value);
|
||||
|
||||
// Now scan our own elements.
|
||||
foreach (var info in _elements)
|
||||
{
|
||||
var elementValue = info.Getter(value);
|
||||
|
||||
callback(info.Serializer, elementValue);
|
||||
|
||||
var elementSerializer = info.Serializer;
|
||||
if (elementValue != null)
|
||||
elementSerializer = serializer.GetTypeSerializer(elementValue.GetType());
|
||||
|
||||
elementSerializer.ScanChildren(serializer, callback, elementValue);
|
||||
}
|
||||
|
||||
if (_collectionHelper != null)
|
||||
_collectionHelper.ScanChildren(callback, value);
|
||||
}
|
||||
|
||||
protected internal override void Serialize(IntermediateWriter output, object value, ContentSerializerAttribute format)
|
||||
{
|
||||
// First serialize the base type.
|
||||
if (_baseSerializer != null)
|
||||
_baseSerializer.Serialize(output, value, format);
|
||||
|
||||
// Now serialize our own elements.
|
||||
foreach (var info in _elements)
|
||||
{
|
||||
var elementValue = info.Getter(value);
|
||||
|
||||
if (info.Attribute.SharedResource)
|
||||
output.WriteSharedResource(elementValue, info.Attribute);
|
||||
else
|
||||
output.WriteObjectInternal(elementValue, info.Attribute, info.Serializer, info.Serializer.TargetType);
|
||||
}
|
||||
|
||||
if (_collectionHelper != null)
|
||||
_collectionHelper.Serialize(output, value, format);
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -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 SByteSerializer : ElementSerializer<sbyte>
|
||||
{
|
||||
public SByteSerializer() :
|
||||
base("sbyte", 1)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal override sbyte Deserialize(string[] inputs, ref int index)
|
||||
{
|
||||
return XmlConvert.ToSByte(inputs[index++]);
|
||||
}
|
||||
|
||||
protected internal override void Serialize(sbyte value, List<string> results)
|
||||
{
|
||||
results.Add(XmlConvert.ToString(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -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 ShortSerializer : ElementSerializer<short>
|
||||
{
|
||||
public ShortSerializer() :
|
||||
base("short", 1)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal override short Deserialize(string[] inputs, ref int index)
|
||||
{
|
||||
return XmlConvert.ToInt16(inputs[index++]);
|
||||
}
|
||||
|
||||
protected internal override void Serialize(short value, List<string> results)
|
||||
{
|
||||
results.Add(XmlConvert.ToString(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// 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.
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
|
||||
{
|
||||
[ContentTypeSerializer]
|
||||
class StringSerializer : ContentTypeSerializer<string>
|
||||
{
|
||||
public StringSerializer() :
|
||||
base("string")
|
||||
{
|
||||
}
|
||||
|
||||
protected internal override string Deserialize(IntermediateReader input, ContentSerializerAttribute format, string existingInstance)
|
||||
{
|
||||
return input.Xml.ReadString();
|
||||
}
|
||||
|
||||
protected internal override void Serialize(IntermediateWriter output, string value, ContentSerializerAttribute format)
|
||||
{
|
||||
output.Xml.WriteString(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// 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.Xml;
|
||||
|
||||
namespace Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate
|
||||
{
|
||||
[ContentTypeSerializer]
|
||||
class TimeSpanSerializer : ElementSerializer<TimeSpan>
|
||||
{
|
||||
public TimeSpanSerializer() :
|
||||
base("TimeSpan", 1)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal override TimeSpan Deserialize(string[] inputs, ref int index)
|
||||
{
|
||||
return XmlConvert.ToTimeSpan(inputs[index++]);
|
||||
}
|
||||
|
||||
protected internal override void Serialize(TimeSpan value, List<string> results)
|
||||
{
|
||||
results.Add(XmlConvert.ToString(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -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 UIntSerializer : ElementSerializer<uint>
|
||||
{
|
||||
public UIntSerializer() :
|
||||
base("int", 1)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal override uint Deserialize(string[] inputs, ref int index)
|
||||
{
|
||||
return XmlConvert.ToUInt32(inputs[index++]);
|
||||
}
|
||||
|
||||
protected internal override void Serialize(uint value, List<string> results)
|
||||
{
|
||||
results.Add(XmlConvert.ToString(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user