(ded4a3e0a) v0.9.0.7

This commit is contained in:
Joonas Rikkonen
2019-06-25 16:00:44 +03:00
parent e5ae622c77
commit 4a51db77b5
1777 changed files with 421528 additions and 917 deletions
@@ -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());
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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;
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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;
}
}
}
@@ -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();
}
}
}
}
@@ -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);
}
}
@@ -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()
{
}
}
}
@@ -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);
}
}
@@ -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;
}
}
}
@@ -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);
}
}
}
}
@@ -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));
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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;
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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");
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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;
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
}
@@ -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);
}
}
}
}
}
@@ -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.)
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
}
}
@@ -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);
}
}
}