Show More
Commit Description:
Various UI improvements.
Commit Description:
Various UI improvements.
File last commit:
Show/Diff file:
Action:
FNA/src/Content/ContentReader.cs
360 lines | 7.7 KiB | text/x-csharp | CSharpLexer
#region License
/* FNA - XNA4 Reimplementation for Desktop Platforms
* Copyright 2009-2020 Ethan Lee and the MonoGame Team
*
* Released under the Microsoft Public License.
* See LICENSE for details.
*/
/* Derived from code by the Mono.Xna Team (Copyright 2006).
* Released under the MIT License. See monoxna.LICENSE for details.
*/
#endregion
#region Using Statements
using System;
using System.Collections.Generic;
using System.IO;
#endregion
namespace Microsoft.Xna.Framework.Content
{
public sealed class ContentReader : BinaryReader
{
#region Public Properties
public ContentManager ContentManager
{
get
{
return contentManager;
}
}
public string AssetName
{
get
{
return assetName;
}
}
#endregion
#region Internal Properties
internal ContentTypeReader[] TypeReaders
{
get
{
return typeReaders;
}
}
#endregion
#region Internal Variables
internal int version;
internal char platform;
#endregion
#region Private Variables
private ContentManager contentManager;
private Action<IDisposable> recordDisposableObject;
private ContentTypeReaderManager typeReaderManager;
private ContentTypeReader[] typeReaders;
private string assetName;
/* From what I can tell, shared resources work like this:
* A list of shared resources is stored at the end of the file,
* and while we're reading the whole object, the parts that ask
* for "shared" objects store the 1-based index of the shared
* resource in the list. For example, if there are two shared
* resources, a ReadSharedResource function will ask for either
* 1 or 2. For null references, the index will be 0.
*/
private int sharedResourceCount;
private List<Action<object>>[] sharedResourceFixups;
#endregion
#region Internal Constructor
internal ContentReader(
ContentManager manager,
Stream stream,
string assetName,
int version,
char platform,
Action<IDisposable> recordDisposableObject
) : base(stream) {
this.recordDisposableObject = recordDisposableObject;
this.contentManager = manager;
this.assetName = assetName;
this.version = version;
this.platform = platform;
}
#endregion
#region Public Read Methods
public T ReadExternalReference<T>()
{
string externalReference = ReadString();
if (!String.IsNullOrEmpty(externalReference))
{
return contentManager.Load<T>(
MonoGame.Utilities.FileHelpers.ResolveRelativePath(assetName, externalReference)
);
}
return default(T);
}
public Matrix ReadMatrix()
{
Matrix result = new Matrix();
result.M11 = ReadSingle();
result.M12 = ReadSingle();
result.M13 = ReadSingle();
result.M14 = ReadSingle();
result.M21 = ReadSingle();
result.M22 = ReadSingle();
result.M23 = ReadSingle();
result.M24 = ReadSingle();
result.M31 = ReadSingle();
result.M32 = ReadSingle();
result.M33 = ReadSingle();
result.M34 = ReadSingle();
result.M41 = ReadSingle();
result.M42 = ReadSingle();
result.M43 = ReadSingle();
result.M44 = ReadSingle();
return result;
}
public T ReadObject<T>()
{
return ReadObject(default(T));
}
public T ReadObject<T>(ContentTypeReader typeReader)
{
T result = (T) typeReader.Read(this, default(T));
RecordDisposable(result);
return result;
}
public T ReadObject<T>(T existingInstance)
{
return InnerReadObject(existingInstance);
}
public T ReadObject<T>(ContentTypeReader typeReader, T existingInstance)
{
if (!typeReader.TargetType.IsValueType)
{
return ReadObject(existingInstance);
}
T result = (T) typeReader.Read(this, existingInstance);
RecordDisposable(result);
return result;
}
public Quaternion ReadQuaternion()
{
Quaternion result = new Quaternion();
result.X = ReadSingle();
result.Y = ReadSingle();
result.Z = ReadSingle();
result.W = ReadSingle();
return result;
}
public T ReadRawObject<T>()
{
return (T) ReadRawObject<T>(default(T));
}
public T ReadRawObject<T>(ContentTypeReader typeReader)
{
return (T) ReadRawObject<T>(typeReader, default(T));
}
public T ReadRawObject<T>(T existingInstance)
{
Type objectType = typeof(T);
foreach (ContentTypeReader typeReader in typeReaders)
{
if (typeReader.TargetType == objectType)
{
return (T) ReadRawObject<T>(typeReader,existingInstance);
}
}
throw new NotSupportedException();
}
public T ReadRawObject<T>(ContentTypeReader typeReader, T existingInstance)
{
return (T) typeReader.Read(this, existingInstance);
}
public void ReadSharedResource<T>(Action<T> fixup)
{
int index = Read7BitEncodedInt();
if (index > 0)
{
sharedResourceFixups[index - 1].Add(
delegate(object v)
{
if (!(v is T))
{
throw new ContentLoadException(
String.Format(
"Error loading shared resource. Expected type {0}, received type {1}",
typeof(T).Name, v.GetType().Name
)
);
}
fixup((T) v);
}
);
}
}
public Vector2 ReadVector2()
{
Vector2 result = new Vector2();
result.X = ReadSingle();
result.Y = ReadSingle();
return result;
}
public Vector3 ReadVector3()
{
Vector3 result = new Vector3();
result.X = ReadSingle();
result.Y = ReadSingle();
result.Z = ReadSingle();
return result;
}
public Vector4 ReadVector4()
{
Vector4 result = new Vector4();
result.X = ReadSingle();
result.Y = ReadSingle();
result.Z = ReadSingle();
result.W = ReadSingle();
return result;
}
public Color ReadColor()
{
Color result = new Color();
result.R = ReadByte();
result.G = ReadByte();
result.B = ReadByte();
result.A = ReadByte();
return result;
}
#endregion
#region Internal Methods
internal object ReadAsset<T>()
{
InitializeTypeReaders();
// Read primary object
object result = ReadObject<T>();
// Read shared resources
ReadSharedResources();
return result;
}
internal void InitializeTypeReaders()
{
typeReaderManager = new ContentTypeReaderManager();
typeReaders = typeReaderManager.LoadAssetReaders(this);
sharedResourceCount = Read7BitEncodedInt();
sharedResourceFixups = new List<Action<object>>[sharedResourceCount];
for (int i = 0; i < sharedResourceCount; i += 1)
{
sharedResourceFixups[i] = new List<Action<object>>();
}
}
internal void ReadSharedResources()
{
for (int i = 0; i < sharedResourceCount; i += 1)
{
// Load the shared object...
object sharedResource = InnerReadObject<object>(null);
// ... then send it to each ReadSharedResource caller
foreach (Action<object> fixup in sharedResourceFixups[i])
{
fixup(sharedResource);
}
}
}
internal new int Read7BitEncodedInt()
{
return base.Read7BitEncodedInt();
}
internal BoundingSphere ReadBoundingSphere()
{
Vector3 position = ReadVector3();
float radius = ReadSingle();
return new BoundingSphere(position, radius);
}
#endregion
#region Private Methods
private T InnerReadObject<T>(T existingInstance)
{
int typeReaderIndex = Read7BitEncodedInt();
if (typeReaderIndex == 0)
{
return existingInstance;
}
if (typeReaderIndex > typeReaders.Length)
{
throw new ContentLoadException(
"Incorrect type reader index found!"
);
}
ContentTypeReader typeReader = typeReaders[typeReaderIndex - 1];
T result = (T) typeReader.Read(this, default(T));
RecordDisposable(result);
return result;
}
private void RecordDisposable<T>(T result)
{
IDisposable disposable = result as IDisposable;
if (disposable == null)
{
return;
}
if (recordDisposableObject != null)
{
recordDisposableObject(disposable);
}
else
{
contentManager.RecordDisposable(disposable);
}
}
#endregion
}
}