Added (basic) generic writer support to content pipeline. SpriteFont importing and compiling now looks fine.

This commit is contained in:
Glatzemann 2012-10-29 12:15:18 +00:00 committed by Konstantin Koch
parent 82aa31def8
commit 9fe9d4bf89
8 changed files with 280 additions and 45 deletions

View File

@ -143,17 +143,20 @@
<Compile Include="Processors\VertexBufferContent.cs" />
<Compile Include="Processors\VertexDeclarationContent.cs" />
<Compile Include="Processors\VideoProcessor.cs" />
<Compile Include="Serialization\Compiler\ArrayWriter.cs" />
<Compile Include="Serialization\Compiler\BuiltInTypeWriter.cs" />
<Compile Include="Serialization\Compiler\ContentCompiler.cs" />
<Compile Include="Serialization\Compiler\ContentTypeWriter.cs" />
<Compile Include="Serialization\Compiler\ContentTypeWriterAttribute.cs" />
<Compile Include="Serialization\Compiler\ContentWriter.cs" />
<Compile Include="Serialization\Compiler\EnumWriter.cs" />
<Compile Include="Serialization\Compiler\GenericContentTypeWriter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Serialization\Compiler\GraphicTypeWriters\EffectWriter.cs" />
<Compile Include="Serialization\Compiler\GraphicTypeWriters\Texture2DWriter.cs" />
<Compile Include="Serialization\Compiler\GraphicTypeWriters\SpriteFontWriter.cs" />
<Compile Include="Serialization\Compiler\GraphicTypeWriters\TextureWriter.cs" />
<Compile Include="Serialization\Compiler\ListWriter.cs" />
<Compile Include="Serialization\Compiler\MathTypeWriters\BoundingBoxWriter.cs" />
<Compile Include="Serialization\Compiler\MathTypeWriters\BoundingSphereWriter.cs" />
<Compile Include="Serialization\Compiler\MathTypeWriters\BoundingFrustumWriter.cs" />
@ -178,6 +181,7 @@
<Compile Include="Serialization\Compiler\PrimitiveTypeWriters\ObjectWriter.cs" />
<Compile Include="Serialization\Compiler\PrimitiveTypeWriters\StringWriter.cs" />
<Compile Include="Serialization\Compiler\PrimitiveTypeWriters\SingleWriter.cs" />
<Compile Include="Serialization\Compiler\SystemTypeWriters\CharWriter.cs" />
<Compile Include="Serialization\Compiler\SystemTypeWriters\DateTimeWriter.cs" />
<Compile Include="Serialization\Compiler\SystemTypeWriters\DecimalWriter.cs" />
<Compile Include="Serialization\Compiler\SystemTypeWriters\NullableWriter.cs" />

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
// übernehmen, indem Sie "*" eingeben:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.1")]
[assembly: AssemblyFileVersion("1.0.0.1")]
[assembly: AssemblyVersion("1.0.1.*")]
[assembly: AssemblyFileVersion("1.0.1.0")]

View File

@ -0,0 +1,81 @@
#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
#endregion
// This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license.
// For details see: http://anxframework.codeplex.com/license
namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
{
internal class ArrayWriter<T> : ContentTypeWriter<T[]>
{
private ContentTypeWriter elementWriter;
protected override void Initialize(ContentCompiler compiler)
{
this.elementWriter = compiler.GetTypeWriter(typeof(T));
}
protected internal override void Write(ContentWriter output, T[] value)
{
output.Write(value.Length);
for (int i = 0; i < value.Length; i++)
{
T value2 = value[i];
output.WriteObject<T>(value2, this.elementWriter);
}
}
public override string GetRuntimeReader(TargetPlatform targetPlatform)
{
return string.Concat(new object[]
{
typeof(ContentTypeReader).Namespace,
'.',
"ArrayReader`1[[",
this.elementWriter.GetRuntimeType(targetPlatform),
"]]"
});
}
public override string GetRuntimeType(TargetPlatform targetPlatform)
{
string runtimeType = this.elementWriter.GetRuntimeType(targetPlatform);
int num = 0;
for (int i = 0; i < runtimeType.Length; i++)
{
char c = runtimeType[i];
if (c != ',')
{
switch (c)
{
case '[':
num++;
break;
case ']':
num--;
break;
}
}
else
{
if (num == 0)
{
return runtimeType.Insert(i, "[]");
}
}
}
return runtimeType + "[]";
}
protected internal override bool ShouldCompressContent(TargetPlatform targetPlatform, object value)
{
return this.elementWriter.ShouldCompressContent(targetPlatform, null);
}
}
}

View File

@ -15,30 +15,73 @@ namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
{
public sealed class ContentCompiler
{
#region Private Members
private Dictionary<Type, ContentTypeWriter> writerInstances = new Dictionary<Type, ContentTypeWriter>();
private Dictionary<Type, Type> genericHandlers = new Dictionary<Type, Type>();
#endregion
public ContentCompiler()
{
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (Type type in assembly.GetTypes())
AddContentWriterAssembly(assembly);
}
}
public ContentTypeWriter GetTypeWriter(Type type)
{
if (type == null)
{
throw new ArgumentNullException("type");
}
ContentTypeWriter contentTypeWriter;
if (!this.writerInstances.TryGetValue(type, out contentTypeWriter))
{
if (type.IsGenericType)
{
ContentTypeWriterAttribute[] value = (ContentTypeWriterAttribute[])type.GetCustomAttributes(typeof(ContentTypeWriterAttribute), true);
if (value.Length > 0)
Type genericTypeDefinition = type.GetGenericTypeDefinition();
Type handler;
if (this.genericHandlers.TryGetValue(genericTypeDefinition, out handler))
{
if (!type.ContainsGenericParameters)
{
ContentTypeWriter writer = (ContentTypeWriter)Activator.CreateInstance(type);
writerInstances[writer.TargetType] = writer;
}
else
{
//TODO: implement generic writer instances...
System.Diagnostics.Debugger.Break();
}
Type genericType = handler.MakeGenericType(type.GetGenericArguments());
contentTypeWriter = ((object)Activator.CreateInstance(genericType)) as ContentTypeWriter;
}
}
else
{
contentTypeWriter = default(ContentTypeWriter);
}
if (contentTypeWriter == null)
{
if (type.IsArray)
{
if (type.GetArrayRank() != 1)
{
throw new RankException("can't serialize multidimensional arrays");
}
contentTypeWriter = Activator.CreateInstance(typeof(ArrayWriter<>).MakeGenericType(new Type[] { type.GetElementType() })) as ContentTypeWriter;
}
if (type.IsEnum)
{
contentTypeWriter = Activator.CreateInstance(typeof(EnumWriter<>).MakeGenericType(new Type[] { type.GetElementType() })) as ContentTypeWriter;
}
//TODO: return new ReflectiveWriter(type);
}
if (contentTypeWriter != null)
{
this.writerInstances.Add(type, contentTypeWriter);
contentTypeWriter.DoInitialize(this);
}
}
return contentTypeWriter;
}
internal void Compile(Stream output, object value, TargetPlatform targetPlatform, GraphicsProfile targetProfile, bool compressContent, string rootDirectory, string referenceRelocationPath)
@ -84,31 +127,6 @@ namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
}
}
public ContentTypeWriter GetTypeWriter(Type type)
{
if (type == null)
{
throw new ArgumentNullException("type");
}
ContentTypeWriter typeWriterInternal = this.GetTypeWriterInternal(type);
//TODO: this.RecordDependency(typeWriterInternal.TargetType);
return typeWriterInternal;
}
private ContentTypeWriter GetTypeWriterInternal(Type type)
{
ContentTypeWriter contentTypeWriter;
if (!this.writerInstances.TryGetValue(type, out contentTypeWriter))
{
//contentTypeWriter = this.typeWriterFactory.CreateWriter(type);
//this.AddTypeWriter(contentTypeWriter);
//this.InitializeTypeWriter(contentTypeWriter);
}
return contentTypeWriter;
}
private bool ShouldCompressContent(TargetPlatform targetPlatform, object value)
{
if (targetPlatform == TargetPlatform.WindowsPhone)
@ -116,9 +134,37 @@ namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
return false;
}
ContentTypeWriter typeWriterInternal = this.GetTypeWriterInternal(value.GetType());
ContentTypeWriter typeWriterInternal = this.GetTypeWriter(value.GetType());
return typeWriterInternal.ShouldCompressContent(targetPlatform, value);
}
public void AddContentWriterAssembly(Assembly assembly)
{
foreach (Type type in assembly.GetTypes())
{
ContentTypeWriterAttribute[] value = (ContentTypeWriterAttribute[])type.GetCustomAttributes(typeof(ContentTypeWriterAttribute), true);
if (value.Length > 0)
{
if (!type.ContainsGenericParameters)
{
ContentTypeWriter writer = (ContentTypeWriter)Activator.CreateInstance(type);
writerInstances[writer.TargetType] = writer;
}
else
{
Type baseType = type.BaseType;
while (!baseType.IsGenericType || baseType.GetGenericTypeDefinition() != typeof(ContentTypeWriter<>))
{
baseType = baseType.BaseType;
}
Type genericType = baseType.GetGenericArguments()[0];
Type genericTypeDefinition = genericType.GetGenericTypeDefinition();
genericHandlers.Add(genericTypeDefinition, type);
}
}
}
}
}
}

View File

@ -156,10 +156,6 @@ namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
internal string GetGenericArgumentRuntimeTypes(TargetPlatform targetPlatform)
{
//TODO: implement
//System.Diagnostics.Debugger.Break();
//return "";
if (_genericArgumentWriters == null)
{
return string.Empty;

View File

@ -0,0 +1,44 @@
#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
#endregion
// This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license.
// For details see: http://anxframework.codeplex.com/license
namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
{
internal class EnumWriter<T> : ContentTypeWriter<T> where T : struct, IConvertible
{
private Type underlyingType = Enum.GetUnderlyingType(typeof(T));
private ContentTypeWriter underlyingTypeWriter;
protected override void Initialize(ContentCompiler compiler)
{
this.underlyingTypeWriter = compiler.GetTypeWriter(this.underlyingType);
}
protected internal override void Write(ContentWriter output, T value)
{
object value2 = value.ToType(this.underlyingType, CultureInfo.InvariantCulture);
output.WriteRawObject<object>(value2, this.underlyingTypeWriter);
}
public override string GetRuntimeReader(TargetPlatform targetPlatform)
{
return string.Concat(new object[]
{
typeof(ContentTypeReader).Namespace,
'.',
"EnumReader`1[[",
this.GetRuntimeType(targetPlatform),
"]]"
});
}
}
}

View File

@ -0,0 +1,47 @@
#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
#endregion
// This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license.
// For details see: http://anxframework.codeplex.com/license
namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
{
[ContentTypeWriter]
internal class ListWriter<T> : BuiltinTypeWriter<List<T>>
{
private ContentTypeWriter elementWriter;
public override bool CanDeserializeIntoExistingObject
{
get
{
return true;
}
}
protected override void Initialize(ContentCompiler compiler)
{
this.elementWriter = compiler.GetTypeWriter(typeof(T));
}
protected internal override void Write(ContentWriter output, List<T> value)
{
output.Write(value.Count);
foreach (T current in value)
{
output.WriteObject<T>(current, this.elementWriter);
}
}
protected internal override bool ShouldCompressContent(TargetPlatform targetPlatform, object value)
{
return this.elementWriter.ShouldCompressContent(targetPlatform, null);
}
}
}

View File

@ -0,0 +1,17 @@
using System;
// This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license.
// For details see: http://anxframework.codeplex.com/license
namespace ANX.Framework.Content.Pipeline.Serialization.Compiler.SystemTypeWriters
{
[ContentTypeWriter]
internal class ByteWriter : BuiltinTypeWriter<char>
{
protected internal override void Write(ContentWriter output, char value)
{
output.Write(value);
}
}
}