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\VertexBufferContent.cs" />
<Compile Include="Processors\VertexDeclarationContent.cs" /> <Compile Include="Processors\VertexDeclarationContent.cs" />
<Compile Include="Processors\VideoProcessor.cs" /> <Compile Include="Processors\VideoProcessor.cs" />
<Compile Include="Serialization\Compiler\ArrayWriter.cs" />
<Compile Include="Serialization\Compiler\BuiltInTypeWriter.cs" /> <Compile Include="Serialization\Compiler\BuiltInTypeWriter.cs" />
<Compile Include="Serialization\Compiler\ContentCompiler.cs" /> <Compile Include="Serialization\Compiler\ContentCompiler.cs" />
<Compile Include="Serialization\Compiler\ContentTypeWriter.cs" /> <Compile Include="Serialization\Compiler\ContentTypeWriter.cs" />
<Compile Include="Serialization\Compiler\ContentTypeWriterAttribute.cs" /> <Compile Include="Serialization\Compiler\ContentTypeWriterAttribute.cs" />
<Compile Include="Serialization\Compiler\ContentWriter.cs" /> <Compile Include="Serialization\Compiler\ContentWriter.cs" />
<Compile Include="Serialization\Compiler\EnumWriter.cs" />
<Compile Include="Serialization\Compiler\GenericContentTypeWriter.cs" /> <Compile Include="Serialization\Compiler\GenericContentTypeWriter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Serialization\Compiler\GraphicTypeWriters\EffectWriter.cs" /> <Compile Include="Serialization\Compiler\GraphicTypeWriters\EffectWriter.cs" />
<Compile Include="Serialization\Compiler\GraphicTypeWriters\Texture2DWriter.cs" /> <Compile Include="Serialization\Compiler\GraphicTypeWriters\Texture2DWriter.cs" />
<Compile Include="Serialization\Compiler\GraphicTypeWriters\SpriteFontWriter.cs" /> <Compile Include="Serialization\Compiler\GraphicTypeWriters\SpriteFontWriter.cs" />
<Compile Include="Serialization\Compiler\GraphicTypeWriters\TextureWriter.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\BoundingBoxWriter.cs" />
<Compile Include="Serialization\Compiler\MathTypeWriters\BoundingSphereWriter.cs" /> <Compile Include="Serialization\Compiler\MathTypeWriters\BoundingSphereWriter.cs" />
<Compile Include="Serialization\Compiler\MathTypeWriters\BoundingFrustumWriter.cs" /> <Compile Include="Serialization\Compiler\MathTypeWriters\BoundingFrustumWriter.cs" />
@ -178,6 +181,7 @@
<Compile Include="Serialization\Compiler\PrimitiveTypeWriters\ObjectWriter.cs" /> <Compile Include="Serialization\Compiler\PrimitiveTypeWriters\ObjectWriter.cs" />
<Compile Include="Serialization\Compiler\PrimitiveTypeWriters\StringWriter.cs" /> <Compile Include="Serialization\Compiler\PrimitiveTypeWriters\StringWriter.cs" />
<Compile Include="Serialization\Compiler\PrimitiveTypeWriters\SingleWriter.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\DateTimeWriter.cs" />
<Compile Include="Serialization\Compiler\SystemTypeWriters\DecimalWriter.cs" /> <Compile Include="Serialization\Compiler\SystemTypeWriters\DecimalWriter.cs" />
<Compile Include="Serialization\Compiler\SystemTypeWriters\NullableWriter.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 // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
// übernehmen, indem Sie "*" eingeben: // übernehmen, indem Sie "*" eingeben:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.1")] [assembly: AssemblyVersion("1.0.1.*")]
[assembly: AssemblyFileVersion("1.0.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 public sealed class ContentCompiler
{ {
#region Private Members
private Dictionary<Type, ContentTypeWriter> writerInstances = new Dictionary<Type, ContentTypeWriter>(); private Dictionary<Type, ContentTypeWriter> writerInstances = new Dictionary<Type, ContentTypeWriter>();
private Dictionary<Type, Type> genericHandlers = new Dictionary<Type, Type>();
#endregion
public ContentCompiler() public ContentCompiler()
{ {
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) 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); Type genericTypeDefinition = type.GetGenericTypeDefinition();
if (value.Length > 0) Type handler;
if (this.genericHandlers.TryGetValue(genericTypeDefinition, out handler))
{ {
if (!type.ContainsGenericParameters) Type genericType = handler.MakeGenericType(type.GetGenericArguments());
{ contentTypeWriter = ((object)Activator.CreateInstance(genericType)) as ContentTypeWriter;
ContentTypeWriter writer = (ContentTypeWriter)Activator.CreateInstance(type);
writerInstances[writer.TargetType] = writer;
}
else
{
//TODO: implement generic writer instances...
System.Diagnostics.Debugger.Break();
}
} }
} }
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) 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) private bool ShouldCompressContent(TargetPlatform targetPlatform, object value)
{ {
if (targetPlatform == TargetPlatform.WindowsPhone) if (targetPlatform == TargetPlatform.WindowsPhone)
@ -116,9 +134,37 @@ namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
return false; return false;
} }
ContentTypeWriter typeWriterInternal = this.GetTypeWriterInternal(value.GetType()); ContentTypeWriter typeWriterInternal = this.GetTypeWriter(value.GetType());
return typeWriterInternal.ShouldCompressContent(targetPlatform, value); 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) internal string GetGenericArgumentRuntimeTypes(TargetPlatform targetPlatform)
{ {
//TODO: implement
//System.Diagnostics.Debugger.Break();
//return "";
if (_genericArgumentWriters == null) if (_genericArgumentWriters == null)
{ {
return string.Empty; 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);
}
}
}