(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,538 @@
// MIT License - Copyright (C) The Mono.Xna 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.Runtime.Serialization;
namespace Microsoft.Xna.Framework
{
[DataContract]
[DebuggerDisplay("{DebugDisplayString,nq}")]
public struct BoundingBox : IEquatable<BoundingBox>
{
#region Public Fields
[DataMember]
public Vector3 Min;
[DataMember]
public Vector3 Max;
public const int CornerCount = 8;
#endregion Public Fields
#region Public Constructors
public BoundingBox(Vector3 min, Vector3 max)
{
this.Min = min;
this.Max = max;
}
#endregion Public Constructors
#region Public Methods
public ContainmentType Contains(BoundingBox box)
{
//test if all corner is in the same side of a face by just checking min and max
if (box.Max.X < Min.X
|| box.Min.X > Max.X
|| box.Max.Y < Min.Y
|| box.Min.Y > Max.Y
|| box.Max.Z < Min.Z
|| box.Min.Z > Max.Z)
return ContainmentType.Disjoint;
if (box.Min.X >= Min.X
&& box.Max.X <= Max.X
&& box.Min.Y >= Min.Y
&& box.Max.Y <= Max.Y
&& box.Min.Z >= Min.Z
&& box.Max.Z <= Max.Z)
return ContainmentType.Contains;
return ContainmentType.Intersects;
}
public void Contains(ref BoundingBox box, out ContainmentType result)
{
result = Contains(box);
}
public ContainmentType Contains(BoundingFrustum frustum)
{
//TODO: bad done here need a fix.
//Because question is not frustum contain box but reverse and this is not the same
int i;
ContainmentType contained;
Vector3[] corners = frustum.GetCorners();
// First we check if frustum is in box
for (i = 0; i < corners.Length; i++)
{
this.Contains(ref corners[i], out contained);
if (contained == ContainmentType.Disjoint)
break;
}
if (i == corners.Length) // This means we checked all the corners and they were all contain or instersect
return ContainmentType.Contains;
if (i != 0) // if i is not equal to zero, we can fastpath and say that this box intersects
return ContainmentType.Intersects;
// If we get here, it means the first (and only) point we checked was actually contained in the frustum.
// So we assume that all other points will also be contained. If one of the points is disjoint, we can
// exit immediately saying that the result is Intersects
i++;
for (; i < corners.Length; i++)
{
this.Contains(ref corners[i], out contained);
if (contained != ContainmentType.Contains)
return ContainmentType.Intersects;
}
// If we get here, then we know all the points were actually contained, therefore result is Contains
return ContainmentType.Contains;
}
public ContainmentType Contains(BoundingSphere sphere)
{
if (sphere.Center.X - Min.X >= sphere.Radius
&& sphere.Center.Y - Min.Y >= sphere.Radius
&& sphere.Center.Z - Min.Z >= sphere.Radius
&& Max.X - sphere.Center.X >= sphere.Radius
&& Max.Y - sphere.Center.Y >= sphere.Radius
&& Max.Z - sphere.Center.Z >= sphere.Radius)
return ContainmentType.Contains;
double dmin = 0;
double e = sphere.Center.X - Min.X;
if (e < 0)
{
if (e < -sphere.Radius)
{
return ContainmentType.Disjoint;
}
dmin += e * e;
}
else
{
e = sphere.Center.X - Max.X;
if (e > 0)
{
if (e > sphere.Radius)
{
return ContainmentType.Disjoint;
}
dmin += e * e;
}
}
e = sphere.Center.Y - Min.Y;
if (e < 0)
{
if (e < -sphere.Radius)
{
return ContainmentType.Disjoint;
}
dmin += e * e;
}
else
{
e = sphere.Center.Y - Max.Y;
if (e > 0)
{
if (e > sphere.Radius)
{
return ContainmentType.Disjoint;
}
dmin += e * e;
}
}
e = sphere.Center.Z - Min.Z;
if (e < 0)
{
if (e < -sphere.Radius)
{
return ContainmentType.Disjoint;
}
dmin += e * e;
}
else
{
e = sphere.Center.Z - Max.Z;
if (e > 0)
{
if (e > sphere.Radius)
{
return ContainmentType.Disjoint;
}
dmin += e * e;
}
}
if (dmin <= sphere.Radius * sphere.Radius)
return ContainmentType.Intersects;
return ContainmentType.Disjoint;
}
public void Contains(ref BoundingSphere sphere, out ContainmentType result)
{
result = this.Contains(sphere);
}
public ContainmentType Contains(Vector3 point)
{
ContainmentType result;
this.Contains(ref point, out result);
return result;
}
public void Contains(ref Vector3 point, out ContainmentType result)
{
//first we get if point is out of box
if (point.X < this.Min.X
|| point.X > this.Max.X
|| point.Y < this.Min.Y
|| point.Y > this.Max.Y
|| point.Z < this.Min.Z
|| point.Z > this.Max.Z)
{
result = ContainmentType.Disjoint;
}
else
{
result = ContainmentType.Contains;
}
}
private static readonly Vector3 MaxVector3 = new Vector3(float.MaxValue);
private static readonly Vector3 MinVector3 = new Vector3(float.MinValue);
/// <summary>
/// Create a bounding box from the given list of points.
/// </summary>
/// <param name="points">The list of Vector3 instances defining the point cloud to bound</param>
/// <returns>A bounding box that encapsulates the given point cloud.</returns>
/// <exception cref="System.ArgumentException">Thrown if the given list has no points.</exception>
public static BoundingBox CreateFromPoints(IEnumerable<Vector3> points)
{
if (points == null)
throw new ArgumentNullException();
var empty = true;
var minVec = MaxVector3;
var maxVec = MinVector3;
foreach (var ptVector in points)
{
minVec.X = (minVec.X < ptVector.X) ? minVec.X : ptVector.X;
minVec.Y = (minVec.Y < ptVector.Y) ? minVec.Y : ptVector.Y;
minVec.Z = (minVec.Z < ptVector.Z) ? minVec.Z : ptVector.Z;
maxVec.X = (maxVec.X > ptVector.X) ? maxVec.X : ptVector.X;
maxVec.Y = (maxVec.Y > ptVector.Y) ? maxVec.Y : ptVector.Y;
maxVec.Z = (maxVec.Z > ptVector.Z) ? maxVec.Z : ptVector.Z;
empty = false;
}
if (empty)
throw new ArgumentException();
return new BoundingBox(minVec, maxVec);
}
public static BoundingBox CreateFromSphere(BoundingSphere sphere)
{
BoundingBox result;
CreateFromSphere(ref sphere, out result);
return result;
}
public static void CreateFromSphere(ref BoundingSphere sphere, out BoundingBox result)
{
var corner = new Vector3(sphere.Radius);
result.Min = sphere.Center - corner;
result.Max = sphere.Center + corner;
}
public static BoundingBox CreateMerged(BoundingBox original, BoundingBox additional)
{
BoundingBox result;
CreateMerged(ref original, ref additional, out result);
return result;
}
public static void CreateMerged(ref BoundingBox original, ref BoundingBox additional, out BoundingBox result)
{
result.Min.X = Math.Min(original.Min.X, additional.Min.X);
result.Min.Y = Math.Min(original.Min.Y, additional.Min.Y);
result.Min.Z = Math.Min(original.Min.Z, additional.Min.Z);
result.Max.X = Math.Max(original.Max.X, additional.Max.X);
result.Max.Y = Math.Max(original.Max.Y, additional.Max.Y);
result.Max.Z = Math.Max(original.Max.Z, additional.Max.Z);
}
public bool Equals(BoundingBox other)
{
return (this.Min == other.Min) && (this.Max == other.Max);
}
public override bool Equals(object obj)
{
return (obj is BoundingBox) ? this.Equals((BoundingBox)obj) : false;
}
public Vector3[] GetCorners()
{
return new Vector3[] {
new Vector3(this.Min.X, this.Max.Y, this.Max.Z),
new Vector3(this.Max.X, this.Max.Y, this.Max.Z),
new Vector3(this.Max.X, this.Min.Y, this.Max.Z),
new Vector3(this.Min.X, this.Min.Y, this.Max.Z),
new Vector3(this.Min.X, this.Max.Y, this.Min.Z),
new Vector3(this.Max.X, this.Max.Y, this.Min.Z),
new Vector3(this.Max.X, this.Min.Y, this.Min.Z),
new Vector3(this.Min.X, this.Min.Y, this.Min.Z)
};
}
public void GetCorners(Vector3[] corners)
{
if (corners == null)
{
throw new ArgumentNullException("corners");
}
if (corners.Length < 8)
{
throw new ArgumentOutOfRangeException("corners", "Not Enought Corners");
}
corners[0].X = this.Min.X;
corners[0].Y = this.Max.Y;
corners[0].Z = this.Max.Z;
corners[1].X = this.Max.X;
corners[1].Y = this.Max.Y;
corners[1].Z = this.Max.Z;
corners[2].X = this.Max.X;
corners[2].Y = this.Min.Y;
corners[2].Z = this.Max.Z;
corners[3].X = this.Min.X;
corners[3].Y = this.Min.Y;
corners[3].Z = this.Max.Z;
corners[4].X = this.Min.X;
corners[4].Y = this.Max.Y;
corners[4].Z = this.Min.Z;
corners[5].X = this.Max.X;
corners[5].Y = this.Max.Y;
corners[5].Z = this.Min.Z;
corners[6].X = this.Max.X;
corners[6].Y = this.Min.Y;
corners[6].Z = this.Min.Z;
corners[7].X = this.Min.X;
corners[7].Y = this.Min.Y;
corners[7].Z = this.Min.Z;
}
public override int GetHashCode()
{
return this.Min.GetHashCode() + this.Max.GetHashCode();
}
public bool Intersects(BoundingBox box)
{
bool result;
Intersects(ref box, out result);
return result;
}
public void Intersects(ref BoundingBox box, out bool result)
{
if ((this.Max.X >= box.Min.X) && (this.Min.X <= box.Max.X))
{
if ((this.Max.Y < box.Min.Y) || (this.Min.Y > box.Max.Y))
{
result = false;
return;
}
result = (this.Max.Z >= box.Min.Z) && (this.Min.Z <= box.Max.Z);
return;
}
result = false;
return;
}
public bool Intersects(BoundingFrustum frustum)
{
return frustum.Intersects(this);
}
public bool Intersects(BoundingSphere sphere)
{
if (sphere.Center.X - Min.X > sphere.Radius
&& sphere.Center.Y - Min.Y > sphere.Radius
&& sphere.Center.Z - Min.Z > sphere.Radius
&& Max.X - sphere.Center.X > sphere.Radius
&& Max.Y - sphere.Center.Y > sphere.Radius
&& Max.Z - sphere.Center.Z > sphere.Radius)
return true;
double dmin = 0;
if (sphere.Center.X - Min.X <= sphere.Radius)
dmin += (sphere.Center.X - Min.X) * (sphere.Center.X - Min.X);
else if (Max.X - sphere.Center.X <= sphere.Radius)
dmin += (sphere.Center.X - Max.X) * (sphere.Center.X - Max.X);
if (sphere.Center.Y - Min.Y <= sphere.Radius)
dmin += (sphere.Center.Y - Min.Y) * (sphere.Center.Y - Min.Y);
else if (Max.Y - sphere.Center.Y <= sphere.Radius)
dmin += (sphere.Center.Y - Max.Y) * (sphere.Center.Y - Max.Y);
if (sphere.Center.Z - Min.Z <= sphere.Radius)
dmin += (sphere.Center.Z - Min.Z) * (sphere.Center.Z - Min.Z);
else if (Max.Z - sphere.Center.Z <= sphere.Radius)
dmin += (sphere.Center.Z - Max.Z) * (sphere.Center.Z - Max.Z);
if (dmin <= sphere.Radius * sphere.Radius)
return true;
return false;
}
public void Intersects(ref BoundingSphere sphere, out bool result)
{
result = Intersects(sphere);
}
public PlaneIntersectionType Intersects(Plane plane)
{
PlaneIntersectionType result;
Intersects(ref plane, out result);
return result;
}
public void Intersects(ref Plane plane, out PlaneIntersectionType result)
{
// See http://zach.in.tu-clausthal.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html
Vector3 positiveVertex;
Vector3 negativeVertex;
if (plane.Normal.X >= 0)
{
positiveVertex.X = Max.X;
negativeVertex.X = Min.X;
}
else
{
positiveVertex.X = Min.X;
negativeVertex.X = Max.X;
}
if (plane.Normal.Y >= 0)
{
positiveVertex.Y = Max.Y;
negativeVertex.Y = Min.Y;
}
else
{
positiveVertex.Y = Min.Y;
negativeVertex.Y = Max.Y;
}
if (plane.Normal.Z >= 0)
{
positiveVertex.Z = Max.Z;
negativeVertex.Z = Min.Z;
}
else
{
positiveVertex.Z = Min.Z;
negativeVertex.Z = Max.Z;
}
// Inline Vector3.Dot(plane.Normal, negativeVertex) + plane.D;
var distance = plane.Normal.X * negativeVertex.X + plane.Normal.Y * negativeVertex.Y + plane.Normal.Z * negativeVertex.Z + plane.D;
if (distance > 0)
{
result = PlaneIntersectionType.Front;
return;
}
// Inline Vector3.Dot(plane.Normal, positiveVertex) + plane.D;
distance = plane.Normal.X * positiveVertex.X + plane.Normal.Y * positiveVertex.Y + plane.Normal.Z * positiveVertex.Z + plane.D;
if (distance < 0)
{
result = PlaneIntersectionType.Back;
return;
}
result = PlaneIntersectionType.Intersecting;
}
public Nullable<float> Intersects(Ray ray)
{
return ray.Intersects(this);
}
public void Intersects(ref Ray ray, out Nullable<float> result)
{
result = Intersects(ray);
}
public static bool operator ==(BoundingBox a, BoundingBox b)
{
return a.Equals(b);
}
public static bool operator !=(BoundingBox a, BoundingBox b)
{
return !a.Equals(b);
}
internal string DebugDisplayString
{
get
{
return string.Concat(
"Min( ", this.Min.DebugDisplayString, " ) \r\n",
"Max( ",this.Max.DebugDisplayString, " )"
);
}
}
public override string ToString()
{
return "{{Min:" + this.Min.ToString() + " Max:" + this.Max.ToString() + "}}";
}
/// <summary>
/// Deconstruction method for <see cref="BoundingBox"/>.
/// </summary>
/// <param name="min"></param>
/// <param name="max"></param>
public void Deconstruct(out Vector3 min, out Vector3 max)
{
min = Min;
max = Max;
}
#endregion Public Methods
}
}
@@ -0,0 +1,578 @@
// MIT License - Copyright (C) The Mono.Xna Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
using System.Diagnostics;
namespace Microsoft.Xna.Framework
{
/// <summary>
/// Defines a viewing frustum for intersection operations.
/// </summary>
[DebuggerDisplay("{DebugDisplayString,nq}")]
public class BoundingFrustum : IEquatable<BoundingFrustum>
{
#region Private Fields
private Matrix _matrix;
private readonly Vector3[] _corners = new Vector3[CornerCount];
private readonly Plane[] _planes = new Plane[PlaneCount];
#endregion
#region Public Fields
/// <summary>
/// The number of planes in the frustum.
/// </summary>
public const int PlaneCount = 6;
/// <summary>
/// The number of corner points in the frustum.
/// </summary>
public const int CornerCount = 8;
#endregion
#region Properties
/// <summary>
/// Gets or sets the <see cref="Matrix"/> of the frustum.
/// </summary>
public Matrix Matrix
{
get { return this._matrix; }
set
{
this._matrix = value;
this.CreatePlanes(); // FIXME: The odds are the planes will be used a lot more often than the matrix
this.CreateCorners(); // is updated, so this should help performance. I hope ;)
}
}
/// <summary>
/// Gets the near plane of the frustum.
/// </summary>
public Plane Near
{
get { return this._planes[0]; }
}
/// <summary>
/// Gets the far plane of the frustum.
/// </summary>
public Plane Far
{
get { return this._planes[1]; }
}
/// <summary>
/// Gets the left plane of the frustum.
/// </summary>
public Plane Left
{
get { return this._planes[2]; }
}
/// <summary>
/// Gets the right plane of the frustum.
/// </summary>
public Plane Right
{
get { return this._planes[3]; }
}
/// <summary>
/// Gets the top plane of the frustum.
/// </summary>
public Plane Top
{
get { return this._planes[4]; }
}
/// <summary>
/// Gets the bottom plane of the frustum.
/// </summary>
public Plane Bottom
{
get { return this._planes[5]; }
}
#endregion
#region Internal Properties
internal string DebugDisplayString
{
get
{
return string.Concat(
"Near( ", this._planes[0].DebugDisplayString, " ) \r\n",
"Far( ", this._planes[1].DebugDisplayString, " ) \r\n",
"Left( ", this._planes[2].DebugDisplayString, " ) \r\n",
"Right( ", this._planes[3].DebugDisplayString, " ) \r\n",
"Top( ", this._planes[4].DebugDisplayString, " ) \r\n",
"Bottom( ", this._planes[5].DebugDisplayString, " ) "
);
}
}
#endregion
#region Constructors
/// <summary>
/// Constructs the frustum by extracting the view planes from a matrix.
/// </summary>
/// <param name="value">Combined matrix which usually is (View * Projection).</param>
public BoundingFrustum(Matrix value)
{
this._matrix = value;
this.CreatePlanes();
this.CreateCorners();
}
#endregion
#region Operators
/// <summary>
/// Compares whether two <see cref="BoundingFrustum"/> instances are equal.
/// </summary>
/// <param name="a"><see cref="BoundingFrustum"/> instance on the left of the equal sign.</param>
/// <param name="b"><see cref="BoundingFrustum"/> instance on the right of the equal sign.</param>
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
public static bool operator ==(BoundingFrustum a, BoundingFrustum b)
{
if (Equals(a, null))
return (Equals(b, null));
if (Equals(b, null))
return (Equals(a, null));
return a._matrix == (b._matrix);
}
/// <summary>
/// Compares whether two <see cref="BoundingFrustum"/> instances are not equal.
/// </summary>
/// <param name="a"><see cref="BoundingFrustum"/> instance on the left of the not equal sign.</param>
/// <param name="b"><see cref="BoundingFrustum"/> instance on the right of the not equal sign.</param>
/// <returns><c>true</c> if the instances are not equal; <c>false</c> otherwise.</returns>
public static bool operator !=(BoundingFrustum a, BoundingFrustum b)
{
return !(a == b);
}
#endregion
#region Public Methods
#region Contains
/// <summary>
/// Containment test between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingBox"/>.
/// </summary>
/// <param name="box">A <see cref="BoundingBox"/> for testing.</param>
/// <returns>Result of testing for containment between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingBox"/>.</returns>
public ContainmentType Contains(BoundingBox box)
{
var result = default(ContainmentType);
this.Contains(ref box, out result);
return result;
}
/// <summary>
/// Containment test between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingBox"/>.
/// </summary>
/// <param name="box">A <see cref="BoundingBox"/> for testing.</param>
/// <param name="result">Result of testing for containment between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingBox"/> as an output parameter.</param>
public void Contains(ref BoundingBox box, out ContainmentType result)
{
var intersects = false;
for (var i = 0; i < PlaneCount; ++i)
{
var planeIntersectionType = default(PlaneIntersectionType);
box.Intersects(ref this._planes[i], out planeIntersectionType);
switch (planeIntersectionType)
{
case PlaneIntersectionType.Front:
result = ContainmentType.Disjoint;
return;
case PlaneIntersectionType.Intersecting:
intersects = true;
break;
}
}
result = intersects ? ContainmentType.Intersects : ContainmentType.Contains;
}
/// <summary>
/// Containment test between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingFrustum"/>.
/// </summary>
/// <param name="frustum">A <see cref="BoundingFrustum"/> for testing.</param>
/// <returns>Result of testing for containment between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingFrustum"/>.</returns>
public ContainmentType Contains(BoundingFrustum frustum)
{
if (this == frustum) // We check to see if the two frustums are equal
return ContainmentType.Contains;// If they are, there's no need to go any further.
var intersects = false;
for (var i = 0; i < PlaneCount; ++i)
{
PlaneIntersectionType planeIntersectionType;
frustum.Intersects(ref _planes[i], out planeIntersectionType);
switch (planeIntersectionType)
{
case PlaneIntersectionType.Front:
return ContainmentType.Disjoint;
case PlaneIntersectionType.Intersecting:
intersects = true;
break;
}
}
return intersects ? ContainmentType.Intersects : ContainmentType.Contains;
}
/// <summary>
/// Containment test between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingSphere"/>.
/// </summary>
/// <param name="sphere">A <see cref="BoundingSphere"/> for testing.</param>
/// <returns>Result of testing for containment between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingSphere"/>.</returns>
public ContainmentType Contains(BoundingSphere sphere)
{
var result = default(ContainmentType);
this.Contains(ref sphere, out result);
return result;
}
/// <summary>
/// Containment test between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingSphere"/>.
/// </summary>
/// <param name="sphere">A <see cref="BoundingSphere"/> for testing.</param>
/// <param name="result">Result of testing for containment between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingSphere"/> as an output parameter.</param>
public void Contains(ref BoundingSphere sphere, out ContainmentType result)
{
var intersects = false;
for (var i = 0; i < PlaneCount; ++i)
{
var planeIntersectionType = default(PlaneIntersectionType);
// TODO: we might want to inline this for performance reasons
sphere.Intersects(ref this._planes[i], out planeIntersectionType);
switch (planeIntersectionType)
{
case PlaneIntersectionType.Front:
result = ContainmentType.Disjoint;
return;
case PlaneIntersectionType.Intersecting:
intersects = true;
break;
}
}
result = intersects ? ContainmentType.Intersects : ContainmentType.Contains;
}
/// <summary>
/// Containment test between this <see cref="BoundingFrustum"/> and specified <see cref="Vector3"/>.
/// </summary>
/// <param name="point">A <see cref="Vector3"/> for testing.</param>
/// <returns>Result of testing for containment between this <see cref="BoundingFrustum"/> and specified <see cref="Vector3"/>.</returns>
public ContainmentType Contains(Vector3 point)
{
var result = default(ContainmentType);
this.Contains(ref point, out result);
return result;
}
/// <summary>
/// Containment test between this <see cref="BoundingFrustum"/> and specified <see cref="Vector3"/>.
/// </summary>
/// <param name="point">A <see cref="Vector3"/> for testing.</param>
/// <param name="result">Result of testing for containment between this <see cref="BoundingFrustum"/> and specified <see cref="Vector3"/> as an output parameter.</param>
public void Contains(ref Vector3 point, out ContainmentType result)
{
for (var i = 0; i < PlaneCount; ++i)
{
// TODO: we might want to inline this for performance reasons
if (PlaneHelper.ClassifyPoint(ref point, ref this._planes[i]) > 0)
{
result = ContainmentType.Disjoint;
return;
}
}
result = ContainmentType.Contains;
}
#endregion
/// <summary>
/// Compares whether current instance is equal to specified <see cref="BoundingFrustum"/>.
/// </summary>
/// <param name="other">The <see cref="BoundingFrustum"/> to compare.</param>
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
public bool Equals(BoundingFrustum other)
{
return (this == other);
}
/// <summary>
/// Compares whether current instance is equal to specified <see cref="BoundingFrustum"/>.
/// </summary>
/// <param name="obj">The <see cref="Object"/> to compare.</param>
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
public override bool Equals(object obj)
{
return (obj is BoundingFrustum) && this == ((BoundingFrustum)obj);
}
/// <summary>
/// Returns a copy of internal corners array.
/// </summary>
/// <returns>The array of corners.</returns>
public Vector3[] GetCorners()
{
return (Vector3[])this._corners.Clone();
}
/// <summary>
/// Returns a copy of internal corners array.
/// </summary>
/// <param name="corners">The array which values will be replaced to corner values of this instance. It must have size of <see cref="BoundingFrustum.CornerCount"/>.</param>
public void GetCorners(Vector3[] corners)
{
if (corners == null) throw new ArgumentNullException("corners");
if (corners.Length < CornerCount) throw new ArgumentOutOfRangeException("corners");
this._corners.CopyTo(corners, 0);
}
/// <summary>
/// Gets the hash code of this <see cref="BoundingFrustum"/>.
/// </summary>
/// <returns>Hash code of this <see cref="BoundingFrustum"/>.</returns>
public override int GetHashCode()
{
return this._matrix.GetHashCode();
}
/// <summary>
/// Gets whether or not a specified <see cref="BoundingBox"/> intersects with this <see cref="BoundingFrustum"/>.
/// </summary>
/// <param name="box">A <see cref="BoundingBox"/> for intersection test.</param>
/// <returns><c>true</c> if specified <see cref="BoundingBox"/> intersects with this <see cref="BoundingFrustum"/>; <c>false</c> otherwise.</returns>
public bool Intersects(BoundingBox box)
{
var result = false;
this.Intersects(ref box, out result);
return result;
}
/// <summary>
/// Gets whether or not a specified <see cref="BoundingBox"/> intersects with this <see cref="BoundingFrustum"/>.
/// </summary>
/// <param name="box">A <see cref="BoundingBox"/> for intersection test.</param>
/// <param name="result"><c>true</c> if specified <see cref="BoundingBox"/> intersects with this <see cref="BoundingFrustum"/>; <c>false</c> otherwise as an output parameter.</param>
public void Intersects(ref BoundingBox box, out bool result)
{
var containment = default(ContainmentType);
this.Contains(ref box, out containment);
result = containment != ContainmentType.Disjoint;
}
/// <summary>
/// Gets whether or not a specified <see cref="BoundingFrustum"/> intersects with this <see cref="BoundingFrustum"/>.
/// </summary>
/// <param name="frustum">An other <see cref="BoundingFrustum"/> for intersection test.</param>
/// <returns><c>true</c> if other <see cref="BoundingFrustum"/> intersects with this <see cref="BoundingFrustum"/>; <c>false</c> otherwise.</returns>
public bool Intersects(BoundingFrustum frustum)
{
return Contains(frustum) != ContainmentType.Disjoint;
}
/// <summary>
/// Gets whether or not a specified <see cref="BoundingSphere"/> intersects with this <see cref="BoundingFrustum"/>.
/// </summary>
/// <param name="sphere">A <see cref="BoundingSphere"/> for intersection test.</param>
/// <returns><c>true</c> if specified <see cref="BoundingSphere"/> intersects with this <see cref="BoundingFrustum"/>; <c>false</c> otherwise.</returns>
public bool Intersects(BoundingSphere sphere)
{
var result = default(bool);
this.Intersects(ref sphere, out result);
return result;
}
/// <summary>
/// Gets whether or not a specified <see cref="BoundingSphere"/> intersects with this <see cref="BoundingFrustum"/>.
/// </summary>
/// <param name="sphere">A <see cref="BoundingSphere"/> for intersection test.</param>
/// <param name="result"><c>true</c> if specified <see cref="BoundingSphere"/> intersects with this <see cref="BoundingFrustum"/>; <c>false</c> otherwise as an output parameter.</param>
public void Intersects(ref BoundingSphere sphere, out bool result)
{
var containment = default(ContainmentType);
this.Contains(ref sphere, out containment);
result = containment != ContainmentType.Disjoint;
}
/// <summary>
/// Gets type of intersection between specified <see cref="Plane"/> and this <see cref="BoundingFrustum"/>.
/// </summary>
/// <param name="plane">A <see cref="Plane"/> for intersection test.</param>
/// <returns>A plane intersection type.</returns>
public PlaneIntersectionType Intersects(Plane plane)
{
PlaneIntersectionType result;
Intersects(ref plane, out result);
return result;
}
/// <summary>
/// Gets type of intersection between specified <see cref="Plane"/> and this <see cref="BoundingFrustum"/>.
/// </summary>
/// <param name="plane">A <see cref="Plane"/> for intersection test.</param>
/// <param name="result">A plane intersection type as an output parameter.</param>
public void Intersects(ref Plane plane, out PlaneIntersectionType result)
{
result = plane.Intersects(ref _corners[0]);
for (int i = 1; i < _corners.Length; i++)
if (plane.Intersects(ref _corners[i]) != result)
result = PlaneIntersectionType.Intersecting;
}
/// <summary>
/// Gets the distance of intersection of <see cref="Ray"/> and this <see cref="BoundingFrustum"/> or null if no intersection happens.
/// </summary>
/// <param name="ray">A <see cref="Ray"/> for intersection test.</param>
/// <returns>Distance at which ray intersects with this <see cref="BoundingFrustum"/> or null if no intersection happens.</returns>
public float? Intersects(Ray ray)
{
float? result;
Intersects(ref ray, out result);
return result;
}
/// <summary>
/// Gets the distance of intersection of <see cref="Ray"/> and this <see cref="BoundingFrustum"/> or null if no intersection happens.
/// </summary>
/// <param name="ray">A <see cref="Ray"/> for intersection test.</param>
/// <param name="result">Distance at which ray intersects with this <see cref="BoundingFrustum"/> or null if no intersection happens as an output parameter.</param>
public void Intersects(ref Ray ray, out float? result)
{
ContainmentType ctype;
this.Contains(ref ray.Position, out ctype);
switch (ctype)
{
case ContainmentType.Disjoint:
result = null;
return;
case ContainmentType.Contains:
result = 0.0f;
return;
case ContainmentType.Intersects:
throw new NotImplementedException();
default:
throw new ArgumentOutOfRangeException();
}
}
/// <summary>
/// Returns a <see cref="String"/> representation of this <see cref="BoundingFrustum"/> in the format:
/// {Near:[nearPlane] Far:[farPlane] Left:[leftPlane] Right:[rightPlane] Top:[topPlane] Bottom:[bottomPlane]}
/// </summary>
/// <returns><see cref="String"/> representation of this <see cref="BoundingFrustum"/>.</returns>
public override string ToString()
{
return "{Near: " + this._planes[0] +
" Far:" + this._planes[1] +
" Left:" + this._planes[2] +
" Right:" + this._planes[3] +
" Top:" + this._planes[4] +
" Bottom:" + this._planes[5] +
"}";
}
#endregion
#region Private Methods
private void CreateCorners()
{
IntersectionPoint(ref this._planes[0], ref this._planes[2], ref this._planes[4], out this._corners[0]);
IntersectionPoint(ref this._planes[0], ref this._planes[3], ref this._planes[4], out this._corners[1]);
IntersectionPoint(ref this._planes[0], ref this._planes[3], ref this._planes[5], out this._corners[2]);
IntersectionPoint(ref this._planes[0], ref this._planes[2], ref this._planes[5], out this._corners[3]);
IntersectionPoint(ref this._planes[1], ref this._planes[2], ref this._planes[4], out this._corners[4]);
IntersectionPoint(ref this._planes[1], ref this._planes[3], ref this._planes[4], out this._corners[5]);
IntersectionPoint(ref this._planes[1], ref this._planes[3], ref this._planes[5], out this._corners[6]);
IntersectionPoint(ref this._planes[1], ref this._planes[2], ref this._planes[5], out this._corners[7]);
}
private void CreatePlanes()
{
this._planes[0] = new Plane(-this._matrix.M13, -this._matrix.M23, -this._matrix.M33, -this._matrix.M43);
this._planes[1] = new Plane(this._matrix.M13 - this._matrix.M14, this._matrix.M23 - this._matrix.M24, this._matrix.M33 - this._matrix.M34, this._matrix.M43 - this._matrix.M44);
this._planes[2] = new Plane(-this._matrix.M14 - this._matrix.M11, -this._matrix.M24 - this._matrix.M21, -this._matrix.M34 - this._matrix.M31, -this._matrix.M44 - this._matrix.M41);
this._planes[3] = new Plane(this._matrix.M11 - this._matrix.M14, this._matrix.M21 - this._matrix.M24, this._matrix.M31 - this._matrix.M34, this._matrix.M41 - this._matrix.M44);
this._planes[4] = new Plane(this._matrix.M12 - this._matrix.M14, this._matrix.M22 - this._matrix.M24, this._matrix.M32 - this._matrix.M34, this._matrix.M42 - this._matrix.M44);
this._planes[5] = new Plane(-this._matrix.M14 - this._matrix.M12, -this._matrix.M24 - this._matrix.M22, -this._matrix.M34 - this._matrix.M32, -this._matrix.M44 - this._matrix.M42);
this.NormalizePlane(ref this._planes[0]);
this.NormalizePlane(ref this._planes[1]);
this.NormalizePlane(ref this._planes[2]);
this.NormalizePlane(ref this._planes[3]);
this.NormalizePlane(ref this._planes[4]);
this.NormalizePlane(ref this._planes[5]);
}
private static void IntersectionPoint(ref Plane a, ref Plane b, ref Plane c, out Vector3 result)
{
// Formula used
// d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
//P = -------------------------------------------------------------------------
// N1 . ( N2 * N3 )
//
// Note: N refers to the normal, d refers to the displacement. '.' means dot product. '*' means cross product
Vector3 v1, v2, v3;
Vector3 cross;
Vector3.Cross(ref b.Normal, ref c.Normal, out cross);
float f;
Vector3.Dot(ref a.Normal, ref cross, out f);
f *= -1.0f;
Vector3.Cross(ref b.Normal, ref c.Normal, out cross);
Vector3.Multiply(ref cross, a.D, out v1);
//v1 = (a.D * (Vector3.Cross(b.Normal, c.Normal)));
Vector3.Cross(ref c.Normal, ref a.Normal, out cross);
Vector3.Multiply(ref cross, b.D, out v2);
//v2 = (b.D * (Vector3.Cross(c.Normal, a.Normal)));
Vector3.Cross(ref a.Normal, ref b.Normal, out cross);
Vector3.Multiply(ref cross, c.D, out v3);
//v3 = (c.D * (Vector3.Cross(a.Normal, b.Normal)));
result.X = (v1.X + v2.X + v3.X) / f;
result.Y = (v1.Y + v2.Y + v3.Y) / f;
result.Z = (v1.Z + v2.Z + v3.Z) / f;
}
private void NormalizePlane(ref Plane p)
{
float factor = 1f / p.Normal.Length();
p.Normal.X *= factor;
p.Normal.Y *= factor;
p.Normal.Z *= factor;
p.D *= factor;
}
#endregion
}
}
@@ -0,0 +1,640 @@
// MIT License - Copyright (C) The Mono.Xna 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.Runtime.Serialization;
namespace Microsoft.Xna.Framework
{
/// <summary>
/// Describes a sphere in 3D-space for bounding operations.
/// </summary>
[DataContract]
[DebuggerDisplay("{DebugDisplayString,nq}")]
public struct BoundingSphere : IEquatable<BoundingSphere>
{
#region Public Fields
/// <summary>
/// The sphere center.
/// </summary>
[DataMember]
public Vector3 Center;
/// <summary>
/// The sphere radius.
/// </summary>
[DataMember]
public float Radius;
#endregion
#region Internal Properties
internal string DebugDisplayString
{
get
{
return string.Concat(
"Center( ", this.Center.DebugDisplayString, " ) \r\n",
"Radius( ", this.Radius.ToString(), " )"
);
}
}
#endregion
#region Constructors
/// <summary>
/// Constructs a bounding sphere with the specified center and radius.
/// </summary>
/// <param name="center">The sphere center.</param>
/// <param name="radius">The sphere radius.</param>
public BoundingSphere(Vector3 center, float radius)
{
this.Center = center;
this.Radius = radius;
}
#endregion
#region Public Methods
#region Contains
/// <summary>
/// Test if a bounding box is fully inside, outside, or just intersecting the sphere.
/// </summary>
/// <param name="box">The box for testing.</param>
/// <returns>The containment type.</returns>
public ContainmentType Contains(BoundingBox box)
{
//check if all corner is in sphere
bool inside = true;
foreach (Vector3 corner in box.GetCorners())
{
if (this.Contains(corner) == ContainmentType.Disjoint)
{
inside = false;
break;
}
}
if (inside)
return ContainmentType.Contains;
//check if the distance from sphere center to cube face < radius
double dmin = 0;
if (Center.X < box.Min.X)
dmin += (Center.X - box.Min.X) * (Center.X - box.Min.X);
else if (Center.X > box.Max.X)
dmin += (Center.X - box.Max.X) * (Center.X - box.Max.X);
if (Center.Y < box.Min.Y)
dmin += (Center.Y - box.Min.Y) * (Center.Y - box.Min.Y);
else if (Center.Y > box.Max.Y)
dmin += (Center.Y - box.Max.Y) * (Center.Y - box.Max.Y);
if (Center.Z < box.Min.Z)
dmin += (Center.Z - box.Min.Z) * (Center.Z - box.Min.Z);
else if (Center.Z > box.Max.Z)
dmin += (Center.Z - box.Max.Z) * (Center.Z - box.Max.Z);
if (dmin <= Radius * Radius)
return ContainmentType.Intersects;
//else disjoint
return ContainmentType.Disjoint;
}
/// <summary>
/// Test if a bounding box is fully inside, outside, or just intersecting the sphere.
/// </summary>
/// <param name="box">The box for testing.</param>
/// <param name="result">The containment type as an output parameter.</param>
public void Contains(ref BoundingBox box, out ContainmentType result)
{
result = this.Contains(box);
}
/// <summary>
/// Test if a frustum is fully inside, outside, or just intersecting the sphere.
/// </summary>
/// <param name="frustum">The frustum for testing.</param>
/// <returns>The containment type.</returns>
public ContainmentType Contains(BoundingFrustum frustum)
{
//check if all corner is in sphere
bool inside = true;
Vector3[] corners = frustum.GetCorners();
foreach (Vector3 corner in corners)
{
if (this.Contains(corner) == ContainmentType.Disjoint)
{
inside = false;
break;
}
}
if (inside)
return ContainmentType.Contains;
//check if the distance from sphere center to frustrum face < radius
double dmin = 0;
//TODO : calcul dmin
if (dmin <= Radius * Radius)
return ContainmentType.Intersects;
//else disjoint
return ContainmentType.Disjoint;
}
/// <summary>
/// Test if a frustum is fully inside, outside, or just intersecting the sphere.
/// </summary>
/// <param name="frustum">The frustum for testing.</param>
/// <param name="result">The containment type as an output parameter.</param>
public void Contains(ref BoundingFrustum frustum,out ContainmentType result)
{
result = this.Contains(frustum);
}
/// <summary>
/// Test if a sphere is fully inside, outside, or just intersecting the sphere.
/// </summary>
/// <param name="sphere">The other sphere for testing.</param>
/// <returns>The containment type.</returns>
public ContainmentType Contains(BoundingSphere sphere)
{
ContainmentType result;
Contains(ref sphere, out result);
return result;
}
/// <summary>
/// Test if a sphere is fully inside, outside, or just intersecting the sphere.
/// </summary>
/// <param name="sphere">The other sphere for testing.</param>
/// <param name="result">The containment type as an output parameter.</param>
public void Contains(ref BoundingSphere sphere, out ContainmentType result)
{
float sqDistance;
Vector3.DistanceSquared(ref sphere.Center, ref Center, out sqDistance);
if (sqDistance > (sphere.Radius + Radius) * (sphere.Radius + Radius))
result = ContainmentType.Disjoint;
else if (sqDistance <= (Radius - sphere.Radius) * (Radius - sphere.Radius))
result = ContainmentType.Contains;
else
result = ContainmentType.Intersects;
}
/// <summary>
/// Test if a point is fully inside, outside, or just intersecting the sphere.
/// </summary>
/// <param name="point">The vector in 3D-space for testing.</param>
/// <returns>The containment type.</returns>
public ContainmentType Contains(Vector3 point)
{
ContainmentType result;
Contains(ref point, out result);
return result;
}
/// <summary>
/// Test if a point is fully inside, outside, or just intersecting the sphere.
/// </summary>
/// <param name="point">The vector in 3D-space for testing.</param>
/// <param name="result">The containment type as an output parameter.</param>
public void Contains(ref Vector3 point, out ContainmentType result)
{
float sqRadius = Radius * Radius;
float sqDistance;
Vector3.DistanceSquared(ref point, ref Center, out sqDistance);
if (sqDistance > sqRadius)
result = ContainmentType.Disjoint;
else if (sqDistance < sqRadius)
result = ContainmentType.Contains;
else
result = ContainmentType.Intersects;
}
#endregion
#region CreateFromBoundingBox
/// <summary>
/// Creates the smallest <see cref="BoundingSphere"/> that can contain a specified <see cref="BoundingBox"/>.
/// </summary>
/// <param name="box">The box to create the sphere from.</param>
/// <returns>The new <see cref="BoundingSphere"/>.</returns>
public static BoundingSphere CreateFromBoundingBox(BoundingBox box)
{
BoundingSphere result;
CreateFromBoundingBox(ref box, out result);
return result;
}
/// <summary>
/// Creates the smallest <see cref="BoundingSphere"/> that can contain a specified <see cref="BoundingBox"/>.
/// </summary>
/// <param name="box">The box to create the sphere from.</param>
/// <param name="result">The new <see cref="BoundingSphere"/> as an output parameter.</param>
public static void CreateFromBoundingBox(ref BoundingBox box, out BoundingSphere result)
{
// Find the center of the box.
Vector3 center = new Vector3((box.Min.X + box.Max.X) / 2.0f,
(box.Min.Y + box.Max.Y) / 2.0f,
(box.Min.Z + box.Max.Z) / 2.0f);
// Find the distance between the center and one of the corners of the box.
float radius = Vector3.Distance(center, box.Max);
result = new BoundingSphere(center, radius);
}
#endregion
/// <summary>
/// Creates the smallest <see cref="BoundingSphere"/> that can contain a specified <see cref="BoundingFrustum"/>.
/// </summary>
/// <param name="frustum">The frustum to create the sphere from.</param>
/// <returns>The new <see cref="BoundingSphere"/>.</returns>
public static BoundingSphere CreateFromFrustum(BoundingFrustum frustum)
{
return CreateFromPoints(frustum.GetCorners());
}
/// <summary>
/// Creates the smallest <see cref="BoundingSphere"/> that can contain a specified list of points in 3D-space.
/// </summary>
/// <param name="points">List of point to create the sphere from.</param>
/// <returns>The new <see cref="BoundingSphere"/>.</returns>
public static BoundingSphere CreateFromPoints(IEnumerable<Vector3> points)
{
if (points == null )
throw new ArgumentNullException("points");
// From "Real-Time Collision Detection" (Page 89)
var minx = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
var maxx = -minx;
var miny = minx;
var maxy = -minx;
var minz = minx;
var maxz = -minx;
// Find the most extreme points along the principle axis.
var numPoints = 0;
foreach (var pt in points)
{
++numPoints;
if (pt.X < minx.X)
minx = pt;
if (pt.X > maxx.X)
maxx = pt;
if (pt.Y < miny.Y)
miny = pt;
if (pt.Y > maxy.Y)
maxy = pt;
if (pt.Z < minz.Z)
minz = pt;
if (pt.Z > maxz.Z)
maxz = pt;
}
if (numPoints == 0)
throw new ArgumentException("You should have at least one point in points.");
var sqDistX = Vector3.DistanceSquared(maxx, minx);
var sqDistY = Vector3.DistanceSquared(maxy, miny);
var sqDistZ = Vector3.DistanceSquared(maxz, minz);
// Pick the pair of most distant points.
var min = minx;
var max = maxx;
if (sqDistY > sqDistX && sqDistY > sqDistZ)
{
max = maxy;
min = miny;
}
if (sqDistZ > sqDistX && sqDistZ > sqDistY)
{
max = maxz;
min = minz;
}
var center = (min + max) * 0.5f;
var radius = Vector3.Distance(max, center);
// Test every point and expand the sphere.
// The current bounding sphere is just a good approximation and may not enclose all points.
// From: Mathematics for 3D Game Programming and Computer Graphics, Eric Lengyel, Third Edition.
// Page 218
float sqRadius = radius * radius;
foreach (var pt in points)
{
Vector3 diff = (pt-center);
float sqDist = diff.LengthSquared();
if (sqDist > sqRadius)
{
float distance = (float)Math.Sqrt(sqDist); // equal to diff.Length();
Vector3 direction = diff / distance;
Vector3 G = center - radius * direction;
center = (G + pt) / 2;
radius = Vector3.Distance(pt, center);
sqRadius = radius * radius;
}
}
return new BoundingSphere(center, radius);
}
/// <summary>
/// Creates the smallest <see cref="BoundingSphere"/> that can contain two spheres.
/// </summary>
/// <param name="original">First sphere.</param>
/// <param name="additional">Second sphere.</param>
/// <returns>The new <see cref="BoundingSphere"/>.</returns>
public static BoundingSphere CreateMerged(BoundingSphere original, BoundingSphere additional)
{
BoundingSphere result;
CreateMerged(ref original, ref additional, out result);
return result;
}
/// <summary>
/// Creates the smallest <see cref="BoundingSphere"/> that can contain two spheres.
/// </summary>
/// <param name="original">First sphere.</param>
/// <param name="additional">Second sphere.</param>
/// <param name="result">The new <see cref="BoundingSphere"/> as an output parameter.</param>
public static void CreateMerged(ref BoundingSphere original, ref BoundingSphere additional, out BoundingSphere result)
{
Vector3 ocenterToaCenter = Vector3.Subtract(additional.Center, original.Center);
float distance = ocenterToaCenter.Length();
if (distance <= original.Radius + additional.Radius)//intersect
{
if (distance <= original.Radius - additional.Radius)//original contain additional
{
result = original;
return;
}
if (distance <= additional.Radius - original.Radius)//additional contain original
{
result = additional;
return;
}
}
//else find center of new sphere and radius
float leftRadius = Math.Max(original.Radius - distance, additional.Radius);
float Rightradius = Math.Max(original.Radius + distance, additional.Radius);
ocenterToaCenter = ocenterToaCenter + (((leftRadius - Rightradius) / (2 * ocenterToaCenter.Length())) * ocenterToaCenter);//oCenterToResultCenter
result = new BoundingSphere();
result.Center = original.Center + ocenterToaCenter;
result.Radius = (leftRadius + Rightradius) / 2;
}
/// <summary>
/// Compares whether current instance is equal to specified <see cref="BoundingSphere"/>.
/// </summary>
/// <param name="other">The <see cref="BoundingSphere"/> to compare.</param>
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
public bool Equals(BoundingSphere other)
{
return this.Center == other.Center && this.Radius == other.Radius;
}
/// <summary>
/// Compares whether current instance is equal to specified <see cref="Object"/>.
/// </summary>
/// <param name="obj">The <see cref="Object"/> to compare.</param>
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
public override bool Equals(object obj)
{
if (obj is BoundingSphere)
return this.Equals((BoundingSphere)obj);
return false;
}
/// <summary>
/// Gets the hash code of this <see cref="BoundingSphere"/>.
/// </summary>
/// <returns>Hash code of this <see cref="BoundingSphere"/>.</returns>
public override int GetHashCode()
{
return this.Center.GetHashCode() + this.Radius.GetHashCode();
}
#region Intersects
/// <summary>
/// Gets whether or not a specified <see cref="BoundingBox"/> intersects with this sphere.
/// </summary>
/// <param name="box">The box for testing.</param>
/// <returns><c>true</c> if <see cref="BoundingBox"/> intersects with this sphere; <c>false</c> otherwise.</returns>
public bool Intersects(BoundingBox box)
{
return box.Intersects(this);
}
/// <summary>
/// Gets whether or not a specified <see cref="BoundingBox"/> intersects with this sphere.
/// </summary>
/// <param name="box">The box for testing.</param>
/// <param name="result"><c>true</c> if <see cref="BoundingBox"/> intersects with this sphere; <c>false</c> otherwise. As an output parameter.</param>
public void Intersects(ref BoundingBox box, out bool result)
{
box.Intersects(ref this, out result);
}
/*
TODO : Make the public bool Intersects(BoundingFrustum frustum) overload
public bool Intersects(BoundingFrustum frustum)
{
if (frustum == null)
throw new NullReferenceException();
throw new NotImplementedException();
}
*/
/// <summary>
/// Gets whether or not the other <see cref="BoundingSphere"/> intersects with this sphere.
/// </summary>
/// <param name="sphere">The other sphere for testing.</param>
/// <returns><c>true</c> if other <see cref="BoundingSphere"/> intersects with this sphere; <c>false</c> otherwise.</returns>
public bool Intersects(BoundingSphere sphere)
{
bool result;
Intersects(ref sphere, out result);
return result;
}
/// <summary>
/// Gets whether or not the other <see cref="BoundingSphere"/> intersects with this sphere.
/// </summary>
/// <param name="sphere">The other sphere for testing.</param>
/// <param name="result"><c>true</c> if other <see cref="BoundingSphere"/> intersects with this sphere; <c>false</c> otherwise. As an output parameter.</param>
public void Intersects(ref BoundingSphere sphere, out bool result)
{
float sqDistance;
Vector3.DistanceSquared(ref sphere.Center, ref Center, out sqDistance);
if (sqDistance > (sphere.Radius + Radius) * (sphere.Radius + Radius))
result = false;
else
result = true;
}
/// <summary>
/// Gets whether or not a specified <see cref="Plane"/> intersects with this sphere.
/// </summary>
/// <param name="plane">The plane for testing.</param>
/// <returns>Type of intersection.</returns>
public PlaneIntersectionType Intersects(Plane plane)
{
var result = default(PlaneIntersectionType);
// TODO: we might want to inline this for performance reasons
this.Intersects(ref plane, out result);
return result;
}
/// <summary>
/// Gets whether or not a specified <see cref="Plane"/> intersects with this sphere.
/// </summary>
/// <param name="plane">The plane for testing.</param>
/// <param name="result">Type of intersection as an output parameter.</param>
public void Intersects(ref Plane plane, out PlaneIntersectionType result)
{
var distance = default(float);
// TODO: we might want to inline this for performance reasons
Vector3.Dot(ref plane.Normal, ref this.Center, out distance);
distance += plane.D;
if (distance > this.Radius)
result = PlaneIntersectionType.Front;
else if (distance < -this.Radius)
result = PlaneIntersectionType.Back;
else
result = PlaneIntersectionType.Intersecting;
}
/// <summary>
/// Gets whether or not a specified <see cref="Ray"/> intersects with this sphere.
/// </summary>
/// <param name="ray">The ray for testing.</param>
/// <returns>Distance of ray intersection or <c>null</c> if there is no intersection.</returns>
public float? Intersects(Ray ray)
{
return ray.Intersects(this);
}
/// <summary>
/// Gets whether or not a specified <see cref="Ray"/> intersects with this sphere.
/// </summary>
/// <param name="ray">The ray for testing.</param>
/// <param name="result">Distance of ray intersection or <c>null</c> if there is no intersection as an output parameter.</param>
public void Intersects(ref Ray ray, out float? result)
{
ray.Intersects(ref this, out result);
}
#endregion
/// <summary>
/// Returns a <see cref="String"/> representation of this <see cref="BoundingSphere"/> in the format:
/// {Center:[<see cref="Center"/>] Radius:[<see cref="Radius"/>]}
/// </summary>
/// <returns>A <see cref="String"/> representation of this <see cref="BoundingSphere"/>.</returns>
public override string ToString()
{
return "{Center:" + this.Center + " Radius:" + this.Radius + "}";
}
#region Transform
/// <summary>
/// Creates a new <see cref="BoundingSphere"/> that contains a transformation of translation and scale from this sphere by the specified <see cref="Matrix"/>.
/// </summary>
/// <param name="matrix">The transformation <see cref="Matrix"/>.</param>
/// <returns>Transformed <see cref="BoundingSphere"/>.</returns>
public BoundingSphere Transform(Matrix matrix)
{
BoundingSphere sphere = new BoundingSphere();
sphere.Center = Vector3.Transform(this.Center, matrix);
sphere.Radius = this.Radius * ((float)Math.Sqrt((double)Math.Max(((matrix.M11 * matrix.M11) + (matrix.M12 * matrix.M12)) + (matrix.M13 * matrix.M13), Math.Max(((matrix.M21 * matrix.M21) + (matrix.M22 * matrix.M22)) + (matrix.M23 * matrix.M23), ((matrix.M31 * matrix.M31) + (matrix.M32 * matrix.M32)) + (matrix.M33 * matrix.M33)))));
return sphere;
}
/// <summary>
/// Creates a new <see cref="BoundingSphere"/> that contains a transformation of translation and scale from this sphere by the specified <see cref="Matrix"/>.
/// </summary>
/// <param name="matrix">The transformation <see cref="Matrix"/>.</param>
/// <param name="result">Transformed <see cref="BoundingSphere"/> as an output parameter.</param>
public void Transform(ref Matrix matrix, out BoundingSphere result)
{
result.Center = Vector3.Transform(this.Center, matrix);
result.Radius = this.Radius * ((float)Math.Sqrt((double)Math.Max(((matrix.M11 * matrix.M11) + (matrix.M12 * matrix.M12)) + (matrix.M13 * matrix.M13), Math.Max(((matrix.M21 * matrix.M21) + (matrix.M22 * matrix.M22)) + (matrix.M23 * matrix.M23), ((matrix.M31 * matrix.M31) + (matrix.M32 * matrix.M32)) + (matrix.M33 * matrix.M33)))));
}
#endregion
/// <summary>
/// Deconstruction method for <see cref="BoundingSphere"/>.
/// </summary>
/// <param name="center"></param>
/// <param name="radius"></param>
public void Deconstruct(out Vector3 center, out float radius)
{
center = Center;
radius = Radius;
}
#endregion
#region Operators
/// <summary>
/// Compares whether two <see cref="BoundingSphere"/> instances are equal.
/// </summary>
/// <param name="a"><see cref="BoundingSphere"/> instance on the left of the equal sign.</param>
/// <param name="b"><see cref="BoundingSphere"/> instance on the right of the equal sign.</param>
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
public static bool operator == (BoundingSphere a, BoundingSphere b)
{
return a.Equals(b);
}
/// <summary>
/// Compares whether two <see cref="BoundingSphere"/> instances are not equal.
/// </summary>
/// <param name="a"><see cref="BoundingSphere"/> instance on the left of the not equal sign.</param>
/// <param name="b"><see cref="BoundingSphere"/> instance on the right of the not equal sign.</param>
/// <returns><c>true</c> if the instances are not equal; <c>false</c> otherwise.</returns>
public static bool operator != (BoundingSphere a, BoundingSphere b)
{
return !a.Equals(b);
}
#endregion
}
}
@@ -0,0 +1,17 @@
//TODO: maybe make this compile even if SDL isn't available
namespace Microsoft.Xna.Framework
{
public static class Clipboard
{
public static string GetText()
{
return Sdl.GetClipboardText();
}
public static void SetText(string text)
{
Sdl.SetClipboardText(text);
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,25 @@
// MIT License - Copyright (C) The Mono.Xna 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
{
/// <summary>
/// Defines how the bounding volumes intersects or contain one another.
/// </summary>
public enum ContainmentType
{
/// <summary>
/// Indicates that there is no overlap between two bounding volumes.
/// </summary>
Disjoint,
/// <summary>
/// Indicates that one bounding volume completely contains another volume.
/// </summary>
Contains,
/// <summary>
/// Indicates that bounding volumes partially overlap one another.
/// </summary>
Intersects
}
}
@@ -0,0 +1,68 @@
using System;
using System.Reflection;
using System.Linq;
namespace Microsoft.Xna.Framework.Content
{
internal static class ContentExtensions
{
public static ConstructorInfo GetDefaultConstructor(this Type type)
{
#if NET45
var typeInfo = type.GetTypeInfo();
var ctor = typeInfo.DeclaredConstructors.FirstOrDefault(c => !c.IsStatic && c.GetParameters().Length == 0);
return ctor;
#else
var attrs = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
return type.GetConstructor(attrs, null, new Type[0], null);
#endif
}
public static PropertyInfo[] GetAllProperties(this Type type)
{
// Sometimes, overridden properties of abstract classes can show up even with
// BindingFlags.DeclaredOnly is passed to GetProperties. Make sure that
// all properties in this list are defined in this class by comparing
// its get method with that of it's base class. If they're the same
// Then it's an overridden property.
#if NET45
PropertyInfo[] infos= type.GetTypeInfo().DeclaredProperties.ToArray();
var nonStaticPropertyInfos = from p in infos
where (p.GetMethod != null) && (!p.GetMethod.IsStatic) &&
(p.GetMethod == p.GetMethod.GetRuntimeBaseDefinition())
select p;
return nonStaticPropertyInfos.ToArray();
#else
const BindingFlags attrs = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
var allProps = type.GetProperties(attrs).ToList();
var props = allProps.FindAll(p => p.GetGetMethod(true) != null && p.GetGetMethod(true) == p.GetGetMethod(true).GetBaseDefinition()).ToArray();
return props;
#endif
}
public static FieldInfo[] GetAllFields(this Type type)
{
#if NET45
FieldInfo[] fields= type.GetTypeInfo().DeclaredFields.ToArray();
var nonStaticFields = from field in fields
where !field.IsStatic
select field;
return nonStaticFields.ToArray();
#else
var attrs = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
return type.GetFields(attrs);
#endif
}
public static bool IsClass(this Type type)
{
#if NET45
return type.GetTypeInfo().IsClass;
#else
return type.IsClass;
#endif
}
}
}
@@ -0,0 +1,60 @@
#region License
/*
Microsoft Public License (Ms-PL)
MonoGame - Copyright © 2009 The MonoGame Team
All rights reserved.
This license governs use of the accompanying software. If you use the software, you accept this license. If you do not
accept the license, do not use the software.
1. Definitions
The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under
U.S. copyright law.
A "contribution" is the original software, or any additions or changes to the software.
A "contributor" is any person that distributes its contribution under this license.
"Licensed patents" are a contributor's patent claims that read directly on its contribution.
2. Grant of Rights
(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3,
each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3,
each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
3. Conditions and Limitations
(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software,
your patent license from such contributor to the software ends automatically.
(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution
notices that are present in the software.
(D) If you distribute any portion of the software in source code form, you may do so only under this license by including
a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object
code form, you may only do so under a license that complies with this license.
(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees
or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent
permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular
purpose and non-infringement.
*/
#endregion License
using System;
namespace Microsoft.Xna.Framework.Content
{
public class ContentLoadException : Exception
{
public ContentLoadException() : base()
{
}
public ContentLoadException(string message) : base(message)
{
}
public ContentLoadException(string message, Exception innerException) : base(message,innerException)
{
}
}
}
@@ -0,0 +1,505 @@
// 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.IO;
using System.Reflection;
using MonoGame.Utilities;
using Microsoft.Xna.Framework.Graphics;
using System.Globalization;
namespace Microsoft.Xna.Framework.Content
{
public partial class ContentManager : IDisposable
{
const byte ContentCompressedLzx = 0x80;
const byte ContentCompressedLz4 = 0x40;
private string _rootDirectory = string.Empty;
private IServiceProvider serviceProvider;
private IGraphicsDeviceService graphicsDeviceService;
private Dictionary<string, object> loadedAssets = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
private List<IDisposable> disposableAssets = new List<IDisposable>();
private bool disposed;
private byte[] scratchBuffer;
private static object ContentManagerLock = new object();
private static List<WeakReference> ContentManagers = new List<WeakReference>();
private static readonly List<char> targetPlatformIdentifiers = new List<char>()
{
'w', // Windows (XNA & DirectX)
'x', // Xbox360 (XNA)
'm', // WindowsPhone7.0 (XNA)
'i', // iOS
'a', // Android
'd', // DesktopGL
'X', // MacOSX
'W', // WindowsStoreApp
'n', // NativeClient
'M', // WindowsPhone8
'r', // RaspberryPi
'P', // PlayStation4
'v', // PSVita
'O', // XboxOne
'S', // Nintendo Switch
// NOTE: There are additional idenfiers for consoles that
// are not defined in this repository. Be sure to ask the
// console port maintainers to ensure no collisions occur.
// Legacy identifiers... these could be reused in the
// future if we feel enough time has passed.
'p', // PlayStationMobile
'g', // Windows (OpenGL)
'l', // Linux
};
static partial void PlatformStaticInit();
static ContentManager()
{
// Allow any per-platform static initialization to occur.
PlatformStaticInit();
}
private static void AddContentManager(ContentManager contentManager)
{
lock (ContentManagerLock)
{
// Check if the list contains this content manager already. Also take
// the opportunity to prune the list of any finalized content managers.
bool contains = false;
for (int i = ContentManagers.Count - 1; i >= 0; --i)
{
var contentRef = ContentManagers[i];
if (ReferenceEquals(contentRef.Target, contentManager))
contains = true;
if (!contentRef.IsAlive)
ContentManagers.RemoveAt(i);
}
if (!contains)
ContentManagers.Add(new WeakReference(contentManager));
}
}
private static void RemoveContentManager(ContentManager contentManager)
{
lock (ContentManagerLock)
{
// Check if the list contains this content manager and remove it. Also
// take the opportunity to prune the list of any finalized content managers.
for (int i = ContentManagers.Count - 1; i >= 0; --i)
{
var contentRef = ContentManagers[i];
if (!contentRef.IsAlive || ReferenceEquals(contentRef.Target, contentManager))
ContentManagers.RemoveAt(i);
}
}
}
internal static void ReloadGraphicsContent()
{
lock (ContentManagerLock)
{
// Reload the graphic assets of each content manager. Also take the
// opportunity to prune the list of any finalized content managers.
for (int i = ContentManagers.Count - 1; i >= 0; --i)
{
var contentRef = ContentManagers[i];
if (contentRef.IsAlive)
{
var contentManager = (ContentManager)contentRef.Target;
if (contentManager != null)
contentManager.ReloadGraphicsAssets();
}
else
{
ContentManagers.RemoveAt(i);
}
}
}
}
// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method
// does not get called.
// It gives your base class the opportunity to finalize.
// Do not provide destructors in types derived from this class.
~ContentManager()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);
}
public ContentManager(IServiceProvider serviceProvider)
{
if (serviceProvider == null)
{
throw new ArgumentNullException("serviceProvider");
}
this.serviceProvider = serviceProvider;
AddContentManager(this);
}
public ContentManager(IServiceProvider serviceProvider, string rootDirectory)
{
if (serviceProvider == null)
{
throw new ArgumentNullException("serviceProvider");
}
if (rootDirectory == null)
{
throw new ArgumentNullException("rootDirectory");
}
this.RootDirectory = rootDirectory;
this.serviceProvider = serviceProvider;
AddContentManager(this);
}
public void Dispose()
{
Dispose(true);
// Tell the garbage collector not to call the finalizer
// since all the cleanup will already be done.
GC.SuppressFinalize(this);
// Once disposed, content manager wont be used again
RemoveContentManager(this);
}
// If disposing is true, it was called explicitly and we should dispose managed objects.
// If disposing is false, it was called by the finalizer and managed objects should not be disposed.
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
Unload();
}
scratchBuffer = null;
disposed = true;
}
}
public virtual T LoadLocalized<T> (string assetName)
{
string [] cultureNames =
{
CultureInfo.CurrentCulture.Name, // eg. "en-US"
CultureInfo.CurrentCulture.TwoLetterISOLanguageName // eg. "en"
};
// Look first for a specialized language-country version of the asset,
// then if that fails, loop back around to see if we can find one that
// specifies just the language without the country part.
foreach (string cultureName in cultureNames) {
string localizedAssetName = assetName + '.' + cultureName;
try {
return Load<T> (localizedAssetName);
} catch (ContentLoadException) { }
}
// If we didn't find any localized asset, fall back to the default name.
return Load<T> (assetName);
}
public virtual T Load<T>(string assetName)
{
if (string.IsNullOrEmpty(assetName))
{
throw new ArgumentNullException("assetName");
}
if (disposed)
{
throw new ObjectDisposedException("ContentManager");
}
T result = default(T);
// On some platforms, name and slash direction matter.
// We store the asset by a /-seperating key rather than how the
// path to the file was passed to us to avoid
// loading "content/asset1.xnb" and "content\\ASSET1.xnb" as if they were two
// different files. This matches stock XNA behavior.
// The dictionary will ignore case differences
var key = assetName.Replace('\\', '/');
// Check for a previously loaded asset first
object asset = null;
if (loadedAssets.TryGetValue(key, out asset))
{
if (asset is T)
{
return (T)asset;
}
}
// Load the asset.
result = ReadAsset<T>(assetName, null);
loadedAssets[key] = result;
return result;
}
protected virtual Stream OpenStream(string assetName)
{
Stream stream;
try
{
var assetPath = Path.Combine(RootDirectory, assetName) + ".xnb";
// This is primarily for editor support.
// Setting the RootDirectory to an absolute path is useful in editor
// situations, but TitleContainer can ONLY be passed relative paths.
#if DESKTOPGL || WINDOWS
if (Path.IsPathRooted(assetPath))
stream = File.OpenRead(assetPath);
else
#endif
stream = TitleContainer.OpenStream(assetPath);
#if ANDROID
// Read the asset into memory in one go. This results in a ~50% reduction
// in load times on Android due to slow Android asset streams.
MemoryStream memStream = new MemoryStream();
stream.CopyTo(memStream);
memStream.Seek(0, SeekOrigin.Begin);
stream.Close();
stream = memStream;
#endif
}
catch (FileNotFoundException fileNotFound)
{
throw new ContentLoadException("The content file was not found.", fileNotFound);
}
#if !WINDOWS_UAP
catch (DirectoryNotFoundException directoryNotFound)
{
throw new ContentLoadException("The directory was not found.", directoryNotFound);
}
#endif
catch (Exception exception)
{
throw new ContentLoadException("Opening stream error.", exception);
}
return stream;
}
protected T ReadAsset<T>(string assetName, Action<IDisposable> recordDisposableObject)
{
if (string.IsNullOrEmpty(assetName))
{
throw new ArgumentNullException("assetName");
}
if (disposed)
{
throw new ObjectDisposedException("ContentManager");
}
string originalAssetName = assetName;
object result = null;
if (this.graphicsDeviceService == null)
{
this.graphicsDeviceService = serviceProvider.GetService(typeof(IGraphicsDeviceService)) as IGraphicsDeviceService;
if (this.graphicsDeviceService == null)
{
throw new InvalidOperationException("No Graphics Device Service");
}
}
// Try to load as XNB file
var stream = OpenStream(assetName);
using (var xnbReader = new BinaryReader(stream))
{
using (var reader = GetContentReaderFromXnb(assetName, stream, xnbReader, recordDisposableObject))
{
result = reader.ReadAsset<T>();
if (result is GraphicsResource)
((GraphicsResource)result).Name = originalAssetName;
}
}
if (result == null)
throw new ContentLoadException("Could not load " + originalAssetName + " asset!");
return (T)result;
}
private ContentReader GetContentReaderFromXnb(string originalAssetName, Stream stream, BinaryReader xnbReader, Action<IDisposable> recordDisposableObject)
{
// The first 4 bytes should be the "XNB" header. i use that to detect an invalid file
byte x = xnbReader.ReadByte();
byte n = xnbReader.ReadByte();
byte b = xnbReader.ReadByte();
byte platform = xnbReader.ReadByte();
if (x != 'X' || n != 'N' || b != 'B' ||
!(targetPlatformIdentifiers.Contains((char)platform)))
{
throw new ContentLoadException("Asset does not appear to be a valid XNB file. Did you process your content for Windows?");
}
byte version = xnbReader.ReadByte();
byte flags = xnbReader.ReadByte();
bool compressedLzx = (flags & ContentCompressedLzx) != 0;
bool compressedLz4 = (flags & ContentCompressedLz4) != 0;
if (version != 5 && version != 4)
{
throw new ContentLoadException("Invalid XNB version");
}
// The next int32 is the length of the XNB file
int xnbLength = xnbReader.ReadInt32();
Stream decompressedStream = null;
if (compressedLzx || compressedLz4)
{
// Decompress the xnb
int decompressedSize = xnbReader.ReadInt32();
if (compressedLzx)
{
int compressedSize = xnbLength - 14;
decompressedStream = new LzxDecoderStream(stream, decompressedSize, compressedSize);
}
else if (compressedLz4)
{
decompressedStream = new Lz4DecoderStream(stream);
}
}
else
{
decompressedStream = stream;
}
var reader = new ContentReader(this, decompressedStream, this.graphicsDeviceService.GraphicsDevice,
originalAssetName, version, recordDisposableObject);
return reader;
}
internal void RecordDisposable(IDisposable disposable)
{
Debug.Assert(disposable != null, "The disposable is null!");
// Avoid recording disposable objects twice. ReloadAsset will try to record the disposables again.
// We don't know which asset recorded which disposable so just guard against storing multiple of the same instance.
if (!disposableAssets.Contains(disposable))
disposableAssets.Add(disposable);
}
/// <summary>
/// Virtual property to allow a derived ContentManager to have it's assets reloaded
/// </summary>
protected virtual Dictionary<string, object> LoadedAssets
{
get { return loadedAssets; }
}
protected virtual void ReloadGraphicsAssets()
{
foreach (var asset in LoadedAssets)
{
// This never executes as asset.Key is never null. This just forces the
// linker to include the ReloadAsset function when AOT compiled.
if (asset.Key == null)
ReloadAsset(asset.Key, Convert.ChangeType(asset.Value, asset.Value.GetType()));
var methodInfo = ReflectionHelpers.GetMethodInfo(typeof(ContentManager), "ReloadAsset");
var genericMethod = methodInfo.MakeGenericMethod(asset.Value.GetType());
genericMethod.Invoke(this, new object[] { asset.Key, Convert.ChangeType(asset.Value, asset.Value.GetType()) });
}
}
protected virtual void ReloadAsset<T>(string originalAssetName, T currentAsset)
{
string assetName = originalAssetName;
if (string.IsNullOrEmpty(assetName))
{
throw new ArgumentNullException("assetName");
}
if (disposed)
{
throw new ObjectDisposedException("ContentManager");
}
if (this.graphicsDeviceService == null)
{
this.graphicsDeviceService = serviceProvider.GetService(typeof(IGraphicsDeviceService)) as IGraphicsDeviceService;
if (this.graphicsDeviceService == null)
{
throw new InvalidOperationException("No Graphics Device Service");
}
}
var stream = OpenStream(assetName);
using (var xnbReader = new BinaryReader(stream))
{
using (var reader = GetContentReaderFromXnb(assetName, stream, xnbReader, null))
{
reader.ReadAsset<T>(currentAsset);
}
}
}
public virtual void Unload()
{
// Look for disposable assets.
foreach (var disposable in disposableAssets)
{
if (disposable != null)
disposable.Dispose();
}
disposableAssets.Clear();
loadedAssets.Clear();
}
public string RootDirectory
{
get
{
return _rootDirectory;
}
set
{
_rootDirectory = value;
}
}
internal string RootDirectoryFullPath
{
get
{
return Path.Combine(TitleContainer.Location, RootDirectory);
}
}
public IServiceProvider ServiceProvider
{
get
{
return this.serviceProvider;
}
}
internal byte[] GetScratchBuffer(int size)
{
size = Math.Max(size, 1024 * 1024);
if (scratchBuffer == null || scratchBuffer.Length < size)
scratchBuffer = new byte[size];
return scratchBuffer;
}
}
}
@@ -0,0 +1,308 @@
// MIT License - Copyright (C) The Mono.Xna Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Xna.Framework.Graphics;
using MonoGame.Utilities;
namespace Microsoft.Xna.Framework.Content
{
public sealed class ContentReader : BinaryReader
{
private ContentManager contentManager;
private Action<IDisposable> recordDisposableObject;
private ContentTypeReaderManager typeReaderManager;
private GraphicsDevice graphicsDevice;
private string assetName;
private List<KeyValuePair<int, Action<object>>> sharedResourceFixups;
private ContentTypeReader[] typeReaders;
internal int version;
internal int sharedResourceCount;
internal ContentTypeReader[] TypeReaders
{
get
{
return typeReaders;
}
}
internal GraphicsDevice GraphicsDevice
{
get
{
return this.graphicsDevice;
}
}
internal ContentReader(ContentManager manager, Stream stream, GraphicsDevice graphicsDevice, string assetName, int version, Action<IDisposable> recordDisposableObject)
: base(stream)
{
this.graphicsDevice = graphicsDevice;
this.recordDisposableObject = recordDisposableObject;
this.contentManager = manager;
this.assetName = assetName;
this.version = version;
}
public ContentManager ContentManager
{
get
{
return contentManager;
}
}
public string AssetName
{
get
{
return assetName;
}
}
internal object ReadAsset<T>()
{
InitializeTypeReaders();
// Read primary object
object result = ReadObject<T>();
// Read shared resources
ReadSharedResources();
return result;
}
internal object ReadAsset<T>(T existingInstance)
{
InitializeTypeReaders();
// Read primary object
object result = ReadObject<T>(existingInstance);
// Read shared resources
ReadSharedResources();
return result;
}
internal void InitializeTypeReaders()
{
typeReaderManager = new ContentTypeReaderManager();
typeReaders = typeReaderManager.LoadAssetReaders(this);
sharedResourceCount = Read7BitEncodedInt();
sharedResourceFixups = new List<KeyValuePair<int, Action<object>>>();
}
internal void ReadSharedResources()
{
if (sharedResourceCount <= 0)
return;
var sharedResources = new object[sharedResourceCount];
for (var i = 0; i < sharedResourceCount; ++i)
sharedResources[i] = InnerReadObject<object>(null);
// Fixup shared resources by calling each registered action
foreach (var fixup in sharedResourceFixups)
fixup.Value(sharedResources[fixup.Key]);
}
public T ReadExternalReference<T>()
{
var externalReference = ReadString();
if (!String.IsNullOrEmpty(externalReference))
{
return contentManager.Load<T>(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;
}
private void RecordDisposable<T>(T result)
{
var disposable = result as IDisposable;
if (disposable == null)
return;
if (recordDisposableObject != null)
recordDisposableObject(disposable);
else
contentManager.RecordDisposable(disposable);
}
public T ReadObject<T>()
{
return InnerReadObject(default(T));
}
public T ReadObject<T>(ContentTypeReader typeReader)
{
var result = (T)typeReader.Read(this, default(T));
RecordDisposable(result);
return result;
}
public T ReadObject<T>(T existingInstance)
{
return InnerReadObject(existingInstance);
}
private T InnerReadObject<T>(T existingInstance)
{
var typeReaderIndex = Read7BitEncodedInt();
if (typeReaderIndex == 0)
return existingInstance;
if (typeReaderIndex > typeReaders.Length)
throw new ContentLoadException("Incorrect type reader index found!");
var typeReader = typeReaders[typeReaderIndex - 1];
var result = (T)typeReader.Read(this, existingInstance);
RecordDisposable(result);
return result;
}
public T ReadObject<T>(ContentTypeReader typeReader, T existingInstance)
{
if (!ReflectionHelpers.IsValueType(typeReader.TargetType))
return ReadObject(existingInstance);
var 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.Add(new KeyValuePair<int, Action<object>>(index - 1, 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;
}
internal new int Read7BitEncodedInt()
{
return base.Read7BitEncodedInt();
}
internal BoundingSphere ReadBoundingSphere()
{
var position = ReadVector3();
var radius = ReadSingle();
return new BoundingSphere(position, radius);
}
}
}
@@ -0,0 +1,24 @@
// 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.Graphics;
namespace Microsoft.Xna.Framework.Content
{
class AlphaTestEffectReader : ContentTypeReader<AlphaTestEffect>
{
protected internal override AlphaTestEffect Read(ContentReader input, AlphaTestEffect existingInstance)
{
var effect = new AlphaTestEffect(input.GraphicsDevice);
effect.Texture = input.ReadExternalReference<Texture>() as Texture2D;
effect.AlphaFunction = (CompareFunction)input.ReadInt32();
effect.ReferenceAlpha = (int)input.ReadUInt32();
effect.DiffuseColor = input.ReadVector3();
effect.Alpha = input.ReadSingle();
effect.VertexColorEnabled = input.ReadBoolean();
return effect;
}
}
}
@@ -0,0 +1,49 @@
// 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 MonoGame.Utilities;
namespace Microsoft.Xna.Framework.Content
{
internal class ArrayReader<T> : ContentTypeReader<T[]>
{
ContentTypeReader elementReader;
public ArrayReader()
{
}
protected internal override void Initialize(ContentTypeReaderManager manager)
{
Type readerType = typeof(T);
elementReader = manager.GetTypeReader(readerType);
}
protected internal override T[] Read(ContentReader input, T[] existingInstance)
{
uint count = input.ReadUInt32();
T[] array = existingInstance;
if (array == null)
array = new T[count];
if (ReflectionHelpers.IsValueType(typeof(T)))
{
for (uint i = 0; i < count; i++)
{
array[i] = input.ReadObject<T>(elementReader);
}
}
else
{
for (uint i = 0; i < count; i++)
{
var readerType = input.Read7BitEncodedInt();
array[i] = readerType > 0 ? input.ReadObject<T>(input.TypeReaders[readerType - 1]) : default(T);
}
}
return array;
}
}
}
@@ -0,0 +1,30 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using Microsoft.Xna.Framework.Graphics;
namespace Microsoft.Xna.Framework.Content
{
internal class BasicEffectReader : ContentTypeReader<BasicEffect>
{
protected internal override BasicEffect Read(ContentReader input, BasicEffect existingInstance)
{
var effect = new BasicEffect(input.GraphicsDevice);
var texture = input.ReadExternalReference<Texture>() as Texture2D;
if (texture != null)
{
effect.Texture = texture;
effect.TextureEnabled = true;
}
effect.DiffuseColor = input.ReadVector3();
effect.EmissiveColor = input.ReadVector3();
effect.SpecularColor = input.ReadVector3();
effect.SpecularPower = input.ReadSingle();
effect.Alpha = input.ReadSingle();
effect.VertexColorEnabled = input.ReadBoolean();
return effect;
}
}
}
@@ -0,0 +1,25 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace Microsoft.Xna.Framework.Content
{
internal class BooleanReader : ContentTypeReader<bool>
{
public BooleanReader()
{
}
protected internal override bool Read(ContentReader input, bool existingInstance)
{
return input.ReadBoolean();
}
}
}
@@ -0,0 +1,17 @@
// 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
{
class BoundingBoxReader : ContentTypeReader<BoundingBox>
{
protected internal override BoundingBox Read(ContentReader input, BoundingBox existingInstance)
{
var min = input.ReadVector3();
var max = input.ReadVector3();
var result = new BoundingBox(min, max);
return result;
}
}
}
@@ -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 System;
using Microsoft.Xna.Framework;
namespace Microsoft.Xna.Framework.Content
{
internal class BoundingFrustumReader : ContentTypeReader<BoundingFrustum>
{
public BoundingFrustumReader()
{
}
protected internal override BoundingFrustum Read(ContentReader input, BoundingFrustum existingInstance)
{
return new BoundingFrustum(input.ReadMatrix());
}
}
}
@@ -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 System;
using Microsoft.Xna.Framework;
namespace Microsoft.Xna.Framework.Content
{
internal class BoundingSphereReader : ContentTypeReader<BoundingSphere>
{
public BoundingSphereReader()
{
}
protected internal override BoundingSphere Read(ContentReader input, BoundingSphere existingInstance)
{
Vector3 center = input.ReadVector3();
float radius = input.ReadSingle();
return new BoundingSphere(center, radius);
}
}
}
@@ -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 System;
namespace Microsoft.Xna.Framework.Content
{
internal class ByteReader : ContentTypeReader<byte>
{
public ByteReader()
{
}
protected internal override byte Read(ContentReader input, byte existingInstance)
{
return input.ReadByte();
}
}
}
@@ -0,0 +1,25 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace Microsoft.Xna.Framework.Content
{
internal class CharReader : ContentTypeReader<char>
{
public CharReader()
{
}
protected internal override char Read(ContentReader input, char existingInstance)
{
return input.ReadChar();
}
}
}
@@ -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 Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;
namespace Microsoft.Xna.Framework.Content
{
internal class ColorReader : ContentTypeReader<Color>
{
public ColorReader ()
{
}
protected internal override Color Read (ContentReader input, Color existingInstance)
{
// Read RGBA as four separate bytes to make sure we comply with XNB format document
byte r = input.ReadByte();
byte g = input.ReadByte();
byte b = input.ReadByte();
byte a = input.ReadByte();
return new Color(r, g, b, a);
}
}
}
@@ -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;
namespace Microsoft.Xna.Framework.Content
{
internal class CurveReader : ContentTypeReader<Curve>
{
protected internal override Curve Read(ContentReader input, Curve existingInstance)
{
Curve curve = existingInstance;
if (curve == null)
{
curve = new Curve();
}
curve.PreLoop = (CurveLoopType)input.ReadInt32();
curve.PostLoop = (CurveLoopType)input.ReadInt32();
int num6 = input.ReadInt32();
for (int i = 0; i < num6; i++)
{
float position = input.ReadSingle();
float num4 = input.ReadSingle();
float tangentIn = input.ReadSingle();
float tangentOut = input.ReadSingle();
CurveContinuity continuity = (CurveContinuity)input.ReadInt32();
curve.Keys.Add(new CurveKey(position, num4, tangentIn, tangentOut, continuity));
}
return curve;
}
}
}
@@ -0,0 +1,24 @@
// 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
{
internal class DateTimeReader : ContentTypeReader<DateTime>
{
public DateTimeReader()
{
}
protected internal override DateTime Read(ContentReader input, DateTime existingInstance)
{
UInt64 value = input.ReadUInt64();
UInt64 mask = (UInt64)3 << 62;
long ticks = (long)(value & ~mask);
DateTimeKind kind = (DateTimeKind)((value >> 62) & 3);
return new DateTime(ticks, kind);
}
}
}
@@ -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 System;
namespace Microsoft.Xna.Framework.Content
{
internal class DecimalReader : ContentTypeReader<decimal>
{
public DecimalReader()
{
}
protected internal override decimal Read(ContentReader input, decimal existingInstance)
{
return input.ReadDecimal();
}
}
}
@@ -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 System;
using System.Collections.Generic;
using MonoGame.Utilities;
namespace Microsoft.Xna.Framework.Content
{
internal class DictionaryReader<TKey, TValue> : ContentTypeReader<Dictionary<TKey, TValue>>
{
ContentTypeReader keyReader;
ContentTypeReader valueReader;
Type keyType;
Type valueType;
public DictionaryReader()
{
}
protected internal override void Initialize(ContentTypeReaderManager manager)
{
keyType = typeof(TKey);
valueType = typeof(TValue);
keyReader = manager.GetTypeReader(keyType);
valueReader = manager.GetTypeReader(valueType);
}
public override bool CanDeserializeIntoExistingObject
{
get { return true; }
}
protected internal override Dictionary<TKey, TValue> Read(ContentReader input, Dictionary<TKey, TValue> existingInstance)
{
int count = input.ReadInt32();
Dictionary<TKey, TValue> dictionary = existingInstance;
if (dictionary == null)
dictionary = new Dictionary<TKey, TValue>(count);
else
dictionary.Clear();
for (int i = 0; i < count; i++)
{
TKey key;
TValue value;
if (ReflectionHelpers.IsValueType(keyType))
{
key = input.ReadObject<TKey>(keyReader);
}
else
{
var readerType = input.Read7BitEncodedInt();
key = readerType > 0 ? input.ReadObject<TKey>(input.TypeReaders[readerType - 1]) : default(TKey);
}
if (ReflectionHelpers.IsValueType(valueType))
{
value = input.ReadObject<TValue>(valueReader);
}
else
{
var readerType = input.Read7BitEncodedInt();
value = readerType > 0 ? input.ReadObject<TValue>(input.TypeReaders[readerType - 1]) : default(TValue);
}
dictionary.Add(key, value);
}
return dictionary;
}
}
}
@@ -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 System;
namespace Microsoft.Xna.Framework.Content
{
internal class DoubleReader : ContentTypeReader<double>
{
public DoubleReader()
{
}
protected internal override double Read(ContentReader input, double existingInstance)
{
return input.ReadDouble();
}
}
}
@@ -0,0 +1,25 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
using Microsoft.Xna.Framework.Graphics;
namespace Microsoft.Xna.Framework.Content
{
class DualTextureEffectReader : ContentTypeReader<DualTextureEffect>
{
protected internal override DualTextureEffect Read(ContentReader input, DualTextureEffect existingInstance)
{
DualTextureEffect effect = new DualTextureEffect(input.GraphicsDevice);
effect.Texture = input.ReadExternalReference<Texture>() as Texture2D;
effect.Texture2 = input.ReadExternalReference<Texture>() as Texture2D;
effect.DiffuseColor = input.ReadVector3 ();
effect.Alpha = input.ReadSingle ();
effect.VertexColorEnabled = input.ReadBoolean ();
return effect;
}
}
}
@@ -0,0 +1,81 @@
// 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 Microsoft.Xna.Framework.Graphics;
using MonoGame.Utilities;
namespace Microsoft.Xna.Framework.Content
{
internal class EffectMaterialReader : ContentTypeReader<EffectMaterial>
{
protected internal override EffectMaterial Read (ContentReader input, EffectMaterial existingInstance)
{
var effect = input.ReadExternalReference<Effect> ();
var effectMaterial = new EffectMaterial (effect);
var dict = input.ReadObject<Dictionary<string, object>> ();
foreach (KeyValuePair<string, object> item in dict) {
var parameter = effectMaterial.Parameters [item.Key];
if (parameter != null) {
Type itemType = item.Value.GetType();
if (ReflectionHelpers.IsAssignableFromType(typeof(Texture), itemType)) {
parameter.SetValue ((Texture)item.Value);
}
else if (ReflectionHelpers.IsAssignableFromType(typeof(int), itemType)) {
parameter.SetValue((int) item.Value);
}
else if (ReflectionHelpers.IsAssignableFromType(typeof(bool), itemType)) {
parameter.SetValue((bool) item.Value);
}
else if (ReflectionHelpers.IsAssignableFromType(typeof(float), itemType)) {
parameter.SetValue((float) item.Value);
}
else if (ReflectionHelpers.IsAssignableFromType(typeof(float []), itemType)) {
parameter.SetValue((float[]) item.Value);
}
else if (ReflectionHelpers.IsAssignableFromType(typeof(Vector2), itemType)) {
parameter.SetValue((Vector2) item.Value);
}
else if (ReflectionHelpers.IsAssignableFromType(typeof(Vector2 []), itemType)) {
parameter.SetValue((Vector2 []) item.Value);
}
else if (ReflectionHelpers.IsAssignableFromType(typeof(Vector3), itemType)) {
parameter.SetValue((Vector3) item.Value);
}
else if (ReflectionHelpers.IsAssignableFromType(typeof(Vector3 []), itemType)) {
parameter.SetValue((Vector3 []) item.Value);
}
else if (ReflectionHelpers.IsAssignableFromType(typeof(Vector4), itemType)) {
parameter.SetValue((Vector4) item.Value);
}
else if (ReflectionHelpers.IsAssignableFromType(typeof(Vector4 []), itemType)) {
parameter.SetValue((Vector4 []) item.Value);
}
else if (ReflectionHelpers.IsAssignableFromType(typeof(Matrix), itemType)) {
parameter.SetValue((Matrix) item.Value);
}
else if (ReflectionHelpers.IsAssignableFromType(typeof(Matrix []), itemType)) {
parameter.SetValue((Matrix[]) item.Value);
}
else if (ReflectionHelpers.IsAssignableFromType(typeof(Quaternion), itemType)) {
parameter.SetValue((Quaternion) item.Value);
}
else {
throw new NotSupportedException ("Parameter type is not supported");
}
} else {
Debug.WriteLine ("No parameter " + item.Key);
}
}
return effectMaterial;
}
}
}
@@ -0,0 +1,25 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using Microsoft.Xna.Framework.Graphics;
namespace Microsoft.Xna.Framework.Content
{
internal class EffectReader : ContentTypeReader<Effect>
{
public EffectReader()
{
}
protected internal override Effect Read(ContentReader input, Effect existingInstance)
{
int dataSize = input.ReadInt32();
byte[] data = input.ContentManager.GetScratchBuffer(dataSize);
input.Read(data, 0, dataSize);
var effect = new Effect(input.GraphicsDevice, data, 0, dataSize);
effect.Name = input.AssetName;
return effect;
}
}
}
@@ -0,0 +1,29 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
namespace Microsoft.Xna.Framework.Content
{
internal class EnumReader<T> : ContentTypeReader<T>
{
ContentTypeReader elementReader;
public EnumReader()
{
}
protected internal override void Initialize(ContentTypeReaderManager manager)
{
Type readerType = Enum.GetUnderlyingType(typeof(T));
elementReader = manager.GetTypeReader(readerType);
}
protected internal override T Read(ContentReader input, T existingInstance)
{
return input.ReadRawObject<T>(elementReader);
}
}
}
@@ -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 Microsoft.Xna.Framework.Graphics;
namespace Microsoft.Xna.Framework.Content
{
class EnvironmentMapEffectReader : ContentTypeReader<EnvironmentMapEffect>
{
protected internal override EnvironmentMapEffect Read(ContentReader input, EnvironmentMapEffect existingInstance)
{
var effect = new EnvironmentMapEffect(input.GraphicsDevice);
effect.Texture = input.ReadExternalReference<Texture>() as Texture2D;
effect.EnvironmentMap = input.ReadExternalReference<TextureCube>() as TextureCube;
effect.EnvironmentMapAmount = input.ReadSingle ();
effect.EnvironmentMapSpecular = input.ReadVector3 ();
effect.FresnelFactor = input.ReadSingle ();
effect.DiffuseColor = input.ReadVector3 ();
effect.EmissiveColor = input.ReadVector3 ();
effect.Alpha = input.ReadSingle ();
return effect;
}
}
}
@@ -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.
namespace Microsoft.Xna.Framework.Content
{
/// <summary>
/// External reference reader, provided for compatibility with XNA Framework built content
/// </summary>
internal class ExternalReferenceReader : ContentTypeReader
{
public ExternalReferenceReader()
: base(null)
{
}
protected internal override object Read(ContentReader input, object existingInstance)
{
return input.ReadExternalReference<object>();
}
}
}
@@ -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 Microsoft.Xna.Framework.Graphics;
namespace Microsoft.Xna.Framework.Content
{
class IndexBufferReader : ContentTypeReader<IndexBuffer>
{
protected internal override IndexBuffer Read(ContentReader input, IndexBuffer existingInstance)
{
IndexBuffer indexBuffer = existingInstance;
bool sixteenBits = input.ReadBoolean();
int dataSize = input.ReadInt32();
byte[] data = input.ContentManager.GetScratchBuffer(dataSize);
input.Read(data, 0, dataSize);
if (indexBuffer == null)
{
indexBuffer = new IndexBuffer(input.GraphicsDevice,
sixteenBits ? IndexElementSize.SixteenBits : IndexElementSize.ThirtyTwoBits,
dataSize / (sixteenBits ? 2 : 4), BufferUsage.None);
}
indexBuffer.SetData(data, 0, dataSize);
return indexBuffer;
}
}
}
@@ -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;
using Microsoft.Xna.Framework.Content;
namespace Microsoft.Xna.Framework.Content
{
internal class Int16Reader : ContentTypeReader<short>
{
public Int16Reader ()
{
}
protected internal override short Read (ContentReader input, short existingInstance)
{
return input.ReadInt16 ();
}
}
}
@@ -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 System;
namespace Microsoft.Xna.Framework.Content
{
internal class Int32Reader : ContentTypeReader<int>
{
public Int32Reader()
{
}
protected internal override int Read(ContentReader input, int existingInstance)
{
return input.ReadInt32();
}
}
}
@@ -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;
using Microsoft.Xna.Framework.Content;
namespace Microsoft.Xna.Framework.Content
{
internal class Int64Reader : ContentTypeReader<long>
{
public Int64Reader ()
{
}
protected internal override long Read (ContentReader input, long existingInstance)
{
return input.ReadInt64 ();
}
}
}
@@ -0,0 +1,51 @@
// 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 Microsoft.Xna.Framework.Content;
using MonoGame.Utilities;
namespace Microsoft.Xna.Framework.Content
{
internal class ListReader<T> : ContentTypeReader<List<T>>
{
ContentTypeReader elementReader;
public ListReader()
{
}
protected internal override void Initialize(ContentTypeReaderManager manager)
{
Type readerType = typeof(T);
elementReader = manager.GetTypeReader(readerType);
}
public override bool CanDeserializeIntoExistingObject
{
get { return true; }
}
protected internal override List<T> Read(ContentReader input, List<T> existingInstance)
{
int count = input.ReadInt32();
List<T> list = existingInstance;
if (list == null) list = new List<T>(count);
for (int i = 0; i < count; i++)
{
if (ReflectionHelpers.IsValueType(typeof(T)))
{
list.Add(input.ReadObject<T>(elementReader));
}
else
{
var readerType = input.Read7BitEncodedInt();
list.Add(readerType > 0 ? input.ReadObject<T>(input.TypeReaders[readerType - 1]) : default(T));
}
}
return list;
}
}
}
@@ -0,0 +1,30 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
namespace Microsoft.Xna.Framework.Content
{
class MatrixReader : ContentTypeReader<Matrix>
{
protected internal override Matrix Read(ContentReader input, Matrix existingInstance)
{
var m11 = input.ReadSingle();
var m12 = input.ReadSingle();
var m13 = input.ReadSingle();
var m14 = input.ReadSingle();
var m21 = input.ReadSingle();
var m22 = input.ReadSingle();
var m23 = input.ReadSingle();
var m24 = input.ReadSingle();
var m31 = input.ReadSingle();
var m32 = input.ReadSingle();
var m33 = input.ReadSingle();
var m34 = input.ReadSingle();
var m41 = input.ReadSingle();
var m42 = input.ReadSingle();
var m43 = input.ReadSingle();
var m44 = input.ReadSingle();
return new Matrix(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44);
}
}
}
@@ -0,0 +1,199 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
using System.Diagnostics;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using System.Collections.Generic;
namespace Microsoft.Xna.Framework.Content
{
internal class ModelReader : ContentTypeReader<Model>
{
// List<VertexBuffer> vertexBuffers = new List<VertexBuffer>();
// List<IndexBuffer> indexBuffers = new List<IndexBuffer>();
// List<Effect> effects = new List<Effect>();
// List<GraphicsResource> sharedResources = new List<GraphicsResource>();
public ModelReader ()
{
}
static int ReadBoneReference(ContentReader reader, uint boneCount)
{
uint boneId;
// Read the bone ID, which may be encoded as either an 8 or 32 bit value.
if (boneCount < 255)
{
boneId = reader.ReadByte();
}
else
{
boneId = reader.ReadUInt32();
}
// Print out the bone ID.
if (boneId != 0)
{
//Debug.WriteLine("bone #{0}", boneId - 1);
return (int)(boneId - 1);
}
else
{
//Debug.WriteLine("null");
}
return -1;
}
protected internal override Model Read(ContentReader reader, Model existingInstance)
{
// Read the bone names and transforms.
uint boneCount = reader.ReadUInt32();
//Debug.WriteLine("Bone count: {0}", boneCount);
List<ModelBone> bones = new List<ModelBone>((int)boneCount);
for (uint i = 0; i < boneCount; i++)
{
string name = reader.ReadObject<string>();
var matrix = reader.ReadMatrix();
var bone = new ModelBone { Transform = matrix, Index = (int)i, Name = name };
bones.Add(bone);
}
// Read the bone hierarchy.
for (int i = 0; i < boneCount; i++)
{
var bone = bones[i];
//Debug.WriteLine("Bone {0} hierarchy:", i);
// Read the parent bone reference.
//Debug.WriteLine("Parent: ");
var parentIndex = ReadBoneReference(reader, boneCount);
if (parentIndex != -1)
{
bone.Parent = bones[parentIndex];
}
// Read the child bone references.
uint childCount = reader.ReadUInt32();
if (childCount != 0)
{
//Debug.WriteLine("Children:");
for (uint j = 0; j < childCount; j++)
{
var childIndex = ReadBoneReference(reader, boneCount);
if (childIndex != -1)
{
bone.AddChild(bones[childIndex]);
}
}
}
}
List<ModelMesh> meshes = new List<ModelMesh>();
//// Read the mesh data.
int meshCount = reader.ReadInt32();
//Debug.WriteLine("Mesh count: {0}", meshCount);
for (int i = 0; i < meshCount; i++)
{
//Debug.WriteLine("Mesh {0}", i);
string name = reader.ReadObject<string>();
var parentBoneIndex = ReadBoneReference(reader, boneCount);
var boundingSphere = reader.ReadBoundingSphere();
// Tag
var meshTag = reader.ReadObject<object>();
// Read the mesh part data.
int partCount = reader.ReadInt32();
//Debug.WriteLine("Mesh part count: {0}", partCount);
List<ModelMeshPart> parts = new List<ModelMeshPart>(partCount);
for (uint j = 0; j < partCount; j++)
{
ModelMeshPart part;
if (existingInstance != null)
part = existingInstance.Meshes[i].MeshParts[(int)j];
else
part = new ModelMeshPart();
part.VertexOffset = reader.ReadInt32();
part.NumVertices = reader.ReadInt32();
part.StartIndex = reader.ReadInt32();
part.PrimitiveCount = reader.ReadInt32();
// tag
part.Tag = reader.ReadObject<object>();
parts.Add(part);
int jj = (int)j;
reader.ReadSharedResource<VertexBuffer>(delegate (VertexBuffer v)
{
parts[jj].VertexBuffer = v;
});
reader.ReadSharedResource<IndexBuffer>(delegate (IndexBuffer v)
{
parts[jj].IndexBuffer = v;
});
reader.ReadSharedResource<Effect>(delegate (Effect v)
{
parts[jj].Effect = v;
});
}
if (existingInstance != null)
continue;
ModelMesh mesh = new ModelMesh(reader.GraphicsDevice, parts);
// Tag reassignment
mesh.Tag = meshTag;
mesh.Name = name;
mesh.ParentBone = bones[parentBoneIndex];
mesh.ParentBone.AddMesh(mesh);
mesh.BoundingSphere = boundingSphere;
meshes.Add(mesh);
}
if (existingInstance != null)
{
// Read past remaining data and return existing instance
ReadBoneReference(reader, boneCount);
reader.ReadObject<object>();
return existingInstance;
}
// Read the final pieces of model data.
var rootBoneIndex = ReadBoneReference(reader, boneCount);
Model model = new Model(reader.GraphicsDevice, bones, meshes);
model.Root = bones[rootBoneIndex];
model.BuildHierarchy();
// Tag?
model.Tag = reader.ReadObject<object>();
return model;
}
}
}
@@ -0,0 +1,83 @@
// 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 MonoGame.Utilities;
namespace Microsoft.Xna.Framework.Content
{
internal class MultiArrayReader<T> : ContentTypeReader<Array>
{
ContentTypeReader elementReader;
public MultiArrayReader() { }
protected internal override void Initialize(ContentTypeReaderManager manager)
{
Type readerType = typeof(T);
elementReader = manager.GetTypeReader(readerType);
}
protected internal override Array Read(ContentReader input, Array existingInstance)
{
var rank = input.ReadInt32();
if (rank < 1)
throw new RankException();
var dimensions = new int[rank];
var count = 1;
for (int d = 0; d < dimensions.Length; d++)
count *= dimensions[d] = input.ReadInt32();
var array = existingInstance;
if (array == null)
array = Array.CreateInstance(typeof(T), dimensions);//new T[count];
else if (dimensions.Length != array.Rank)
throw new RankException("existingInstance");
var indices = new int[rank];
for (int i = 0; i < count; i++)
{
T value;
if (ReflectionHelpers.IsValueType(typeof(T)))
value = input.ReadObject<T>(elementReader);
else
{
var readerType = input.Read7BitEncodedInt();
if (readerType > 0)
value = input.ReadObject<T>(input.TypeReaders[readerType - 1]);
else
value = default(T);
}
CalcIndices(array, i, indices);
array.SetValue(value, indices);
}
return array;
}
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,32 @@
// 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
{
internal class NullableReader<T> : ContentTypeReader<T?> where T : struct
{
ContentTypeReader elementReader;
public NullableReader()
{
}
protected internal override void Initialize(ContentTypeReaderManager manager)
{
Type readerType = typeof(T);
elementReader = manager.GetTypeReader(readerType);
}
protected internal override T? Read(ContentReader input, T? existingInstance)
{
if(input.ReadBoolean())
return input.ReadObject<T>(elementReader);
return null;
}
}
}
@@ -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
{
internal class PlaneReader : ContentTypeReader<Plane>
{
public PlaneReader()
{
}
protected internal override Plane Read(ContentReader input, Plane existingInstance)
{
existingInstance.Normal = input.ReadVector3();
existingInstance.D = input.ReadSingle();
return existingInstance;
}
}
}
@@ -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 System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace Microsoft.Xna.Framework.Content
{
internal class PointReader : ContentTypeReader<Point>
{
public PointReader ()
{
}
protected internal override Point Read (ContentReader input, Point existingInstance)
{
int X = input.ReadInt32 ();
int Y = input.ReadInt32 ();
return new Point ( X, Y);
}
}
}
@@ -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 System;
namespace Microsoft.Xna.Framework.Content
{
internal class QuaternionReader : ContentTypeReader<Quaternion>
{
public QuaternionReader()
{
}
protected internal override Quaternion Read(ContentReader input, Quaternion existingInstance)
{
return input.ReadQuaternion();
}
}
}
@@ -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 System;
using Microsoft.Xna.Framework;
namespace Microsoft.Xna.Framework.Content
{
internal class RayReader : ContentTypeReader<Ray>
{
public RayReader()
{
}
protected internal override Ray Read(ContentReader input, Ray existingInstance)
{
Vector3 position = input.ReadVector3();
Vector3 direction = input.ReadVector3();
return new Ray(position, direction);
}
}
}
@@ -0,0 +1,30 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace Microsoft.Xna.Framework.Content
{
internal class RectangleReader : ContentTypeReader<Rectangle>
{
public RectangleReader()
{
}
protected internal override Rectangle Read(ContentReader input, Rectangle existingInstance)
{
int left = input.ReadInt32();
int top = input.ReadInt32();
int width = input.ReadInt32();
int height = input.ReadInt32();
return new Rectangle(left, top, width, height);
}
}
}
@@ -0,0 +1,191 @@
// 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
{
internal class ReflectiveReader<T> : ContentTypeReader
{
delegate void ReadElement(ContentReader input, object parent);
private List<ReadElement> _readers;
private ConstructorInfo _constructor;
private ContentTypeReader _baseTypeReader;
public ReflectiveReader()
: base(typeof(T))
{
}
public override bool CanDeserializeIntoExistingObject
{
get { return TargetType.IsClass(); }
}
protected internal override void Initialize(ContentTypeReaderManager manager)
{
base.Initialize(manager);
var baseType = ReflectionHelpers.GetBaseType(TargetType);
if (baseType != null && baseType != typeof(object))
_baseTypeReader = manager.GetTypeReader(baseType);
_constructor = TargetType.GetDefaultConstructor();
var properties = TargetType.GetAllProperties();
var fields = TargetType.GetAllFields();
_readers = new List<ReadElement>(fields.Length + properties.Length);
// Gather the properties.
foreach (var property in properties)
{
var read = GetElementReader(manager, property);
if (read != null)
_readers.Add(read);
}
// Gather the fields.
foreach (var field in fields)
{
var read = GetElementReader(manager, field);
if (read != null)
_readers.Add(read);
}
}
private static ReadElement GetElementReader(ContentTypeReaderManager manager, MemberInfo member)
{
var property = member as PropertyInfo;
var field = member as FieldInfo;
Debug.Assert(field != null || property != null);
if (property != null)
{
// Properties must have at least a getter.
if (property.CanRead == false)
return null;
// Skip over indexer properties.
if (property.GetIndexParameters().Any())
return null;
}
// Are we explicitly asked to ignore this item?
if (ReflectionHelpers.GetCustomAttribute<ContentSerializerIgnoreAttribute>(member) != null)
return null;
var contentSerializerAttribute = ReflectionHelpers.GetCustomAttribute<ContentSerializerAttribute>(member);
if (contentSerializerAttribute == null)
{
if (property != null)
{
// There is no ContentSerializerAttribute, so non-public
// properties cannot be deserialized.
if (!ReflectionHelpers.PropertyIsPublic(property))
return null;
// If the read-only property has a type reader,
// and CanDeserializeIntoExistingObject is true,
// then it is safe to deserialize into the existing object.
if (!property.CanWrite)
{
var typeReader = manager.GetTypeReader(property.PropertyType);
if (typeReader == null || !typeReader.CanDeserializeIntoExistingObject)
return null;
}
}
else
{
// There is no ContentSerializerAttribute, so non-public
// fields cannot be deserialized.
if (!field.IsPublic)
return null;
// evolutional: Added check to skip initialise only fields
if (field.IsInitOnly)
return null;
}
}
Action<object, object> setter;
Type elementType;
if (property != null)
{
elementType = property.PropertyType;
if (property.CanWrite)
setter = (o, v) => property.SetValue(o, v, null);
else
setter = (o, v) => { };
}
else
{
elementType = field.FieldType;
setter = field.SetValue;
}
// Shared resources get special treatment.
if (contentSerializerAttribute != null && contentSerializerAttribute.SharedResource)
{
return (input, parent) =>
{
Action<object> action = value => setter(parent, value);
input.ReadSharedResource(action);
};
}
// We need to have a reader at this point.
var reader = manager.GetTypeReader(elementType);
if (reader == null)
if (elementType == typeof(System.Array))
reader = new ArrayReader<Array>();
else
throw new ContentLoadException(string.Format("Content reader could not be found for {0} type.", elementType.FullName));
// We use the construct delegate to pick the correct existing
// object to be the target of deserialization.
Func<object, object> construct = parent => null;
if (property != null && !property.CanWrite)
construct = parent => property.GetValue(parent, null);
return (input, parent) =>
{
var existing = construct(parent);
var obj2 = input.ReadObject(reader, existing);
setter(parent, obj2);
};
}
protected internal override object Read(ContentReader input, object existingInstance)
{
T obj;
if (existingInstance != null)
obj = (T)existingInstance;
else
obj = (_constructor == null ? (T)Activator.CreateInstance(typeof(T)) : (T)_constructor.Invoke(null));
if(_baseTypeReader != null)
_baseTypeReader.Read(input, obj);
// Box the type.
var boxed = (object)obj;
foreach (var reader in _readers)
reader(input, boxed);
// Unbox it... required for value types.
obj = (T)boxed;
return obj;
}
}
}
@@ -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 System;
namespace Microsoft.Xna.Framework.Content
{
internal class SByteReader : ContentTypeReader<sbyte>
{
public SByteReader()
{
}
protected internal override sbyte Read(ContentReader input, sbyte existingInstance)
{
return input.ReadSByte();
}
}
}
@@ -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 System;
namespace Microsoft.Xna.Framework.Content
{
internal class SingleReader : ContentTypeReader<float>
{
public SingleReader()
{
}
protected internal override float Read(ContentReader input, float existingInstance)
{
return input.ReadSingle();
}
}
}
@@ -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 Microsoft.Xna.Framework.Graphics;
namespace Microsoft.Xna.Framework.Content
{
class SkinnedEffectReader : ContentTypeReader<SkinnedEffect>
{
protected internal override SkinnedEffect Read(ContentReader input, SkinnedEffect existingInstance)
{
var effect = new SkinnedEffect(input.GraphicsDevice);
effect.Texture = input.ReadExternalReference<Texture> () as Texture2D;
effect.WeightsPerVertex = input.ReadInt32 ();
effect.DiffuseColor = input.ReadVector3 ();
effect.EmissiveColor = input.ReadVector3 ();
effect.SpecularColor = input.ReadVector3 ();
effect.SpecularPower = input.ReadSingle ();
effect.Alpha = input.ReadSingle ();
return effect;
}
}
}
@@ -0,0 +1,59 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace Microsoft.Xna.Framework.Content
{
internal class SpriteFontReader : ContentTypeReader<SpriteFont>
{
public SpriteFontReader()
{
}
protected internal override SpriteFont Read(ContentReader input, SpriteFont existingInstance)
{
if (existingInstance != null)
{
// Read the texture into the existing texture instance
input.ReadObject<Texture2D>(existingInstance.Texture);
// discard the rest of the SpriteFont data as we are only reloading GPU resources for now
input.ReadObject<List<Rectangle>>();
input.ReadObject<List<Rectangle>>();
input.ReadObject<List<char>>();
input.ReadInt32();
input.ReadSingle();
input.ReadObject<List<Vector3>>();
if (input.ReadBoolean())
{
input.ReadChar();
}
return existingInstance;
}
else
{
// Create a fresh SpriteFont instance
Texture2D texture = input.ReadObject<Texture2D>();
List<Rectangle> glyphs = input.ReadObject<List<Rectangle>>();
List<Rectangle> cropping = input.ReadObject<List<Rectangle>>();
List<char> charMap = input.ReadObject<List<char>>();
int lineSpacing = input.ReadInt32();
float spacing = input.ReadSingle();
List<Vector3> kerning = input.ReadObject<List<Vector3>>();
char? defaultCharacter = null;
if (input.ReadBoolean())
{
defaultCharacter = new char?(input.ReadChar());
}
return new SpriteFont(texture, glyphs, cropping, charMap, lineSpacing, spacing, kerning, defaultCharacter);
}
}
}
}
@@ -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;
using System.Collections.Generic;
using System.Text;
namespace Microsoft.Xna.Framework.Content
{
internal class StringReader : ContentTypeReader<String>
{
public StringReader()
{
}
protected internal override string Read(ContentReader input, string existingInstance)
{
return input.ReadString();
}
}
}
@@ -0,0 +1,181 @@
// 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;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace Microsoft.Xna.Framework.Content
{
internal class Texture2DReader : ContentTypeReader<Texture2D>
{
public Texture2DReader()
{
// Do nothing
}
protected internal override Texture2D Read(ContentReader reader, Texture2D existingInstance)
{
Texture2D texture = null;
var surfaceFormat = (SurfaceFormat)reader.ReadInt32();
int width = reader.ReadInt32();
int height = reader.ReadInt32();
int levelCount = reader.ReadInt32();
int levelCountOutput = levelCount;
// If the system does not fully support Power of Two textures,
// skip any mip maps supplied with any non PoT textures.
if (levelCount > 1 && !reader.GraphicsDevice.GraphicsCapabilities.SupportsNonPowerOfTwo &&
(!MathHelper.IsPowerOfTwo(width) || !MathHelper.IsPowerOfTwo(height)))
{
levelCountOutput = 1;
System.Diagnostics.Debug.WriteLine(
"Device does not support non Power of Two textures. Skipping mipmaps.");
}
SurfaceFormat convertedFormat = surfaceFormat;
switch (surfaceFormat)
{
case SurfaceFormat.Dxt1:
case SurfaceFormat.Dxt1a:
if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsDxt1)
convertedFormat = SurfaceFormat.Color;
break;
case SurfaceFormat.Dxt1SRgb:
if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsDxt1)
convertedFormat = SurfaceFormat.ColorSRgb;
break;
case SurfaceFormat.Dxt3:
case SurfaceFormat.Dxt5:
if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc)
convertedFormat = SurfaceFormat.Color;
break;
case SurfaceFormat.Dxt3SRgb:
case SurfaceFormat.Dxt5SRgb:
if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc)
convertedFormat = SurfaceFormat.ColorSRgb;
break;
case SurfaceFormat.NormalizedByte4:
convertedFormat = SurfaceFormat.Color;
break;
}
texture = existingInstance ?? new Texture2D(reader.GraphicsDevice, width, height, levelCountOutput > 1, convertedFormat);
#if OPENGL
Threading.BlockOnUIThread(() =>
{
#endif
for (int level = 0; level < levelCount; level++)
{
var levelDataSizeInBytes = reader.ReadInt32();
var levelData = reader.ContentManager.GetScratchBuffer(levelDataSizeInBytes);
reader.Read(levelData, 0, levelDataSizeInBytes);
int levelWidth = Math.Max(width >> level, 1);
int levelHeight = Math.Max(height >> level, 1);
if (level >= levelCountOutput)
continue;
//Convert the image data if required
switch (surfaceFormat)
{
case SurfaceFormat.Dxt1:
case SurfaceFormat.Dxt1SRgb:
case SurfaceFormat.Dxt1a:
if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsDxt1 && convertedFormat == SurfaceFormat.Color)
{
levelData = DxtUtil.DecompressDxt1(levelData, levelWidth, levelHeight);
levelDataSizeInBytes = levelData.Length;
}
break;
case SurfaceFormat.Dxt3:
case SurfaceFormat.Dxt3SRgb:
if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc)
if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc &&
convertedFormat == SurfaceFormat.Color)
{
levelData = DxtUtil.DecompressDxt3(levelData, levelWidth, levelHeight);
levelDataSizeInBytes = levelData.Length;
}
break;
case SurfaceFormat.Dxt5:
case SurfaceFormat.Dxt5SRgb:
if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc)
if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc &&
convertedFormat == SurfaceFormat.Color)
{
levelData = DxtUtil.DecompressDxt5(levelData, levelWidth, levelHeight);
levelDataSizeInBytes = levelData.Length;
}
break;
case SurfaceFormat.Bgra5551:
{
#if OPENGL
// Shift the channels to suit OpenGL
int offset = 0;
for (int y = 0; y < levelHeight; y++)
{
for (int x = 0; x < levelWidth; x++)
{
ushort pixel = BitConverter.ToUInt16(levelData, offset);
pixel = (ushort)(((pixel & 0x7FFF) << 1) | ((pixel & 0x8000) >> 15));
levelData[offset] = (byte)(pixel);
levelData[offset + 1] = (byte)(pixel >> 8);
offset += 2;
}
}
#endif
}
break;
case SurfaceFormat.Bgra4444:
{
#if OPENGL
// Shift the channels to suit OpenGL
int offset = 0;
for (int y = 0; y < levelHeight; y++)
{
for (int x = 0; x < levelWidth; x++)
{
ushort pixel = BitConverter.ToUInt16(levelData, offset);
pixel = (ushort)(((pixel & 0x0FFF) << 4) | ((pixel & 0xF000) >> 12));
levelData[offset] = (byte)(pixel);
levelData[offset + 1] = (byte)(pixel >> 8);
offset += 2;
}
}
#endif
}
break;
case SurfaceFormat.NormalizedByte4:
{
int bytesPerPixel = surfaceFormat.GetSize();
int pitch = levelWidth * bytesPerPixel;
for (int y = 0; y < levelHeight; y++)
{
for (int x = 0; x < levelWidth; x++)
{
int color = BitConverter.ToInt32(levelData, y * pitch + x * bytesPerPixel);
levelData[y * pitch + x * 4] = (byte)(((color >> 16) & 0xff)); //R:=W
levelData[y * pitch + x * 4 + 1] = (byte)(((color >> 8) & 0xff)); //G:=V
levelData[y * pitch + x * 4 + 2] = (byte)(((color) & 0xff)); //B:=U
levelData[y * pitch + x * 4 + 3] = (byte)(((color >> 24) & 0xff)); //A:=Q
}
}
}
break;
}
texture.SetData(level, null, levelData, 0, levelDataSizeInBytes);
}
#if OPENGL
});
#endif
return texture;
}
}
}
@@ -0,0 +1,50 @@
// 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.Graphics;
namespace Microsoft.Xna.Framework.Content
{
internal class Texture3DReader : ContentTypeReader<Texture3D>
{
protected internal override Texture3D Read(ContentReader reader, Texture3D existingInstance)
{
Texture3D texture = null;
SurfaceFormat format = (SurfaceFormat)reader.ReadInt32();
int width = reader.ReadInt32();
int height = reader.ReadInt32();
int depth = reader.ReadInt32();
int levelCount = reader.ReadInt32();
if (existingInstance == null)
texture = new Texture3D(reader.GraphicsDevice, width, height, depth, levelCount > 1, format);
else
texture = existingInstance;
#if OPENGL
Threading.BlockOnUIThread(() =>
{
#endif
for (int i = 0; i < levelCount; i++)
{
int dataSize = reader.ReadInt32();
byte[] data = reader.ContentManager.GetScratchBuffer(dataSize);
reader.Read(data, 0, dataSize);
texture.SetData(i, 0, 0, width, height, 0, depth, data, 0, dataSize);
// Calculate dimensions of next mip level.
width = Math.Max(width >> 1, 1);
height = Math.Max(height >> 1, 1);
depth = Math.Max(depth >> 1, 1);
}
#if OPENGL
});
#endif
return texture;
}
}
}
@@ -0,0 +1,47 @@
// 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.Graphics;
namespace Microsoft.Xna.Framework.Content
{
internal class TextureCubeReader : ContentTypeReader<TextureCube>
{
protected internal override TextureCube Read(ContentReader reader, TextureCube existingInstance)
{
TextureCube textureCube = null;
SurfaceFormat surfaceFormat = (SurfaceFormat)reader.ReadInt32();
int size = reader.ReadInt32();
int levels = reader.ReadInt32();
if (existingInstance == null)
textureCube = new TextureCube(reader.GraphicsDevice, size, levels > 1, surfaceFormat);
else
textureCube = existingInstance;
#if OPENGL
Threading.BlockOnUIThread(() =>
{
#endif
for (int face = 0; face < 6; face++)
{
for (int i = 0; i < levels; i++)
{
int faceSize = reader.ReadInt32();
byte[] faceData = reader.ContentManager.GetScratchBuffer(faceSize);
reader.Read(faceData, 0, faceSize);
textureCube.SetData<byte>((CubeMapFace)face, i, null, faceData, 0, faceSize);
}
}
#if OPENGL
});
#endif
return textureCube;
}
}
}
@@ -0,0 +1,17 @@
// 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.Graphics;
namespace Microsoft.Xna.Framework.Content
{
internal class TextureReader : ContentTypeReader<Texture>
{
protected internal override Texture Read(ContentReader reader, Texture existingInstance)
{
return existingInstance;
}
}
}
@@ -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 Microsoft.Xna.Framework.Content;
namespace Microsoft.Xna.Framework.Content
{
internal class TimeSpanReader : ContentTypeReader<TimeSpan>
{
public TimeSpanReader ()
{
}
protected internal override TimeSpan Read (ContentReader input, TimeSpan existingInstance)
{
// Could not find any information on this really but from all the searching it looks
// like the constructor of number of ticks is long so I have placed that here for now
// long is a Int64 so we read with 64
// <Duration>PT2S</Duration>
//
return new TimeSpan(input.ReadInt64 ());
}
}
}
@@ -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 System;
namespace Microsoft.Xna.Framework.Content
{
internal class UInt16Reader : ContentTypeReader<ushort>
{
public UInt16Reader()
{
}
protected internal override ushort Read(ContentReader input, ushort existingInstance)
{
return input.ReadUInt16();
}
}
}
@@ -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 System;
namespace Microsoft.Xna.Framework.Content
{
internal class UInt32Reader : ContentTypeReader<uint>
{
public UInt32Reader()
{
}
protected internal override uint Read(ContentReader input, uint existingInstance)
{
return input.ReadUInt32();
}
}
}
@@ -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 System;
namespace Microsoft.Xna.Framework.Content
{
internal class UInt64Reader : ContentTypeReader<ulong>
{
public UInt64Reader()
{
}
protected internal override ulong Read(ContentReader input, ulong existingInstance)
{
return input.ReadUInt64();
}
}
}
@@ -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;
using Microsoft.Xna.Framework.Content;
namespace Microsoft.Xna.Framework.Content
{
internal class Vector2Reader : ContentTypeReader<Vector2>
{
public Vector2Reader ()
{
}
protected internal override Vector2 Read (ContentReader input, Vector2 existingInstance)
{
return input.ReadVector2 ();
}
}
}
@@ -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;
using System.Collections.Generic;
using System.Text;
namespace Microsoft.Xna.Framework.Content
{
internal class Vector3Reader : ContentTypeReader<Vector3>
{
public Vector3Reader()
{
}
protected internal override Vector3 Read(ContentReader input, Vector3 existingInstance)
{
return input.ReadVector3();
}
}
}
@@ -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 System;
namespace Microsoft.Xna.Framework.Content
{
internal class Vector4Reader : ContentTypeReader<Vector4>
{
public Vector4Reader()
{
}
protected internal override Vector4 Read(ContentReader input, Vector4 existingInstance)
{
return input.ReadVector4();
}
}
}
@@ -0,0 +1,25 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
using Microsoft.Xna.Framework.Graphics;
namespace Microsoft.Xna.Framework.Content
{
class VertexBufferReader : ContentTypeReader<VertexBuffer>
{
protected internal override VertexBuffer Read(ContentReader input, VertexBuffer existingInstance)
{
var declaration = input.ReadRawObject<VertexDeclaration>();
var vertexCount = (int)input.ReadUInt32();
int dataSize = vertexCount * declaration.VertexStride;
byte[] data = input.ContentManager.GetScratchBuffer(dataSize);
input.Read(data, 0, dataSize);
var buffer = new VertexBuffer(input.GraphicsDevice, declaration, vertexCount, BufferUsage.None);
buffer.SetData(data, 0, dataSize);
return buffer;
}
}
}
@@ -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.Graphics;
namespace Microsoft.Xna.Framework.Content
{
internal class VertexDeclarationReader : ContentTypeReader<VertexDeclaration>
{
protected internal override VertexDeclaration Read(ContentReader reader, VertexDeclaration existingInstance)
{
var vertexStride = reader.ReadInt32();
var elementCount = reader.ReadInt32();
VertexElement[] elements = new VertexElement[elementCount];
for (int i = 0; i < elementCount; ++i)
{
var offset = reader.ReadInt32();
var elementFormat = (VertexElementFormat)reader.ReadInt32();
var elementUsage = (VertexElementUsage)reader.ReadInt32();
var usageIndex = reader.ReadInt32();
elements[i] = new VertexElement(offset, elementFormat, elementUsage, usageIndex);
}
return VertexDeclaration.GetOrCreate(vertexStride, elements);
}
}
}
@@ -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;
namespace Microsoft.Xna.Framework.Content
{
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public sealed class ContentSerializerAttribute : Attribute
{
private string _collectionItemName;
/// <summary>
/// Creates an instance of the attribute.
/// </summary>
public ContentSerializerAttribute()
{
AllowNull = true;
}
public bool AllowNull { get; set; }
/// <summary>
/// Returns the overriden XML element name or the default "Item".
/// </summary>
public string CollectionItemName
{
get
{
// Return the defaul if unset.
if (string.IsNullOrEmpty(_collectionItemName))
return "Item";
return _collectionItemName;
}
set
{
_collectionItemName = value;
}
}
public string ElementName { get; set; }
public bool FlattenContent { get; set; }
/// <summary>
/// Returns true if the default CollectionItemName value was overridden.
/// </summary>
public bool HasCollectionItemName
{
get
{
return !string.IsNullOrEmpty(_collectionItemName);
}
}
public bool Optional { get; set; }
public bool SharedResource { get; set; }
public ContentSerializerAttribute Clone()
{
var clone = new ContentSerializerAttribute ();
clone.AllowNull = AllowNull;
clone._collectionItemName = _collectionItemName;
clone.ElementName = ElementName;
clone.FlattenContent = FlattenContent;
clone.Optional = Optional;
clone.SharedResource = SharedResource;
return clone;
}
}
}
@@ -0,0 +1,30 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
namespace Microsoft.Xna.Framework.Content
{
/// <summary>
/// This is used to specify the XML element name to use for each item in a collection.
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public sealed class ContentSerializerCollectionItemNameAttribute : Attribute
{
/// <summary>
/// Creates an instance of the attribute.
/// </summary>
/// <param name="collectionItemName">The XML element name to use for each item in the collection.</param>
public ContentSerializerCollectionItemNameAttribute(string collectionItemName)
{
CollectionItemName = collectionItemName;
}
/// <summary>
/// The XML element name to use for each item in the collection.
/// </summary>
public string CollectionItemName { get; private set;}
}
}
@@ -0,0 +1,57 @@
// #region License
// /*
// Microsoft Public License (Ms-PL)
// MonoGame - Copyright © 2009 The MonoGame Team
//
// All rights reserved.
//
// This license governs use of the accompanying software. If you use the software, you accept this license. If you do not
// accept the license, do not use the software.
//
// 1. Definitions
// The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under
// U.S. copyright law.
//
// A "contribution" is the original software, or any additions or changes to the software.
// A "contributor" is any person that distributes its contribution under this license.
// "Licensed patents" are a contributor's patent claims that read directly on its contribution.
//
// 2. Grant of Rights
// (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3,
// each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
// (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3,
// each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
//
// 3. Conditions and Limitations
// (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
// (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software,
// your patent license from such contributor to the software ends automatically.
// (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution
// notices that are present in the software.
// (D) If you distribute any portion of the software in source code form, you may do so only under this license by including
// a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object
// code form, you may only do so under a license that complies with this license.
// (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees
// or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent
// permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular
// purpose and non-infringement.
// */
// #endregion License
//
// Author: Kenneth James Pouncey
//
using System;
namespace Microsoft.Xna.Framework.Content
{
// http://msdn.microsoft.com/en-us/library/bb195465.aspx
// The class definition on msdn site shows: [AttributeUsageAttribute(384)]
// The following code var ff = (AttributeTargets)384; shows that ff is Field | Property
// so that is what we use.
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public sealed class ContentSerializerIgnoreAttribute : Attribute
{
}
}
@@ -0,0 +1,30 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
namespace Microsoft.Xna.Framework.Content
{
/// <summary>
/// This is used to specify the type to use when deserializing this object at runtime.
/// </summary>
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)]
public sealed class ContentSerializerRuntimeTypeAttribute : Attribute
{
/// <summary>
/// Creates an instance of the attribute.
/// </summary>
/// <param name="runtimeType">The name of the type to use at runtime.</param>
public ContentSerializerRuntimeTypeAttribute(string runtimeType)
{
RuntimeType = runtimeType;
}
/// <summary>
/// The name of the type to use at runtime.
/// </summary>
public string RuntimeType { get; private set;}
}
}
@@ -0,0 +1,30 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
namespace Microsoft.Xna.Framework.Content
{
/// <summary>
/// This is used to specify the version when deserializing this object at runtime.
/// </summary>
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)]
public sealed class ContentSerializerTypeVersionAttribute : Attribute
{
/// <summary>
/// Creates an instance of the attribute.
/// </summary>
/// <param name="typeVersion">The version passed to the type at runtime.</param>
public ContentSerializerTypeVersionAttribute(int typeVersion)
{
TypeVersion = typeVersion;
}
/// <summary>
/// The version passed to the type at runtime.
/// </summary>
public int TypeVersion { get; private set; }
}
}
@@ -0,0 +1,64 @@
// 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;
namespace Microsoft.Xna.Framework.Content
{
public abstract class ContentTypeReader
{
private Type _targetType;
public virtual bool CanDeserializeIntoExistingObject
{
get { return false; }
}
public Type TargetType
{
get { return _targetType; }
}
public virtual int TypeVersion
{
get { return 0; } // The default version (unless overridden) is zero
}
protected ContentTypeReader(Type targetType)
{
_targetType = targetType;
}
protected internal virtual void Initialize(ContentTypeReaderManager manager)
{
// Do nothing. Are we supposed to add ourselves to the manager?
}
protected internal abstract object Read(ContentReader input, object existingInstance);
}
public abstract class ContentTypeReader<T> : ContentTypeReader
{
protected ContentTypeReader()
: base(typeof(T))
{
// Nothing
}
protected internal override object Read(ContentReader input, object existingInstance)
{
// as per the documentation http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.content.contenttypereader.read.aspx
// existingInstance
// The object receiving the data, or null if a new instance of the object should be created.
if (existingInstance == null)
{
return Read(input, default(T));
}
return Read(input, (T)existingInstance);
}
protected internal abstract T Read(ContentReader input, T existingInstance);
}
}
@@ -0,0 +1,247 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
using System.Collections;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using MonoGame.Utilities;
namespace Microsoft.Xna.Framework.Content
{
public sealed class ContentTypeReaderManager
{
private static readonly object _locker;
private static readonly Dictionary<Type, ContentTypeReader> _contentReadersCache;
private Dictionary<Type, ContentTypeReader> _contentReaders;
private static readonly string _assemblyName;
static ContentTypeReaderManager()
{
_locker = new object();
_contentReadersCache = new Dictionary<Type, ContentTypeReader>(255);
_assemblyName = ReflectionHelpers.GetAssembly(typeof(ContentTypeReaderManager)).FullName;
}
public ContentTypeReader GetTypeReader(Type targetType)
{
if (targetType.IsArray && targetType.GetArrayRank() > 1)
targetType = typeof(Array);
ContentTypeReader reader;
if (_contentReaders.TryGetValue(targetType, out reader))
return reader;
return null;
}
// Trick to prevent the linker removing the code, but not actually execute the code
static bool falseflag = false;
internal ContentTypeReader[] LoadAssetReaders(ContentReader reader)
{
#pragma warning disable 0219, 0649
// Trick to prevent the linker removing the code, but not actually execute the code
if (falseflag)
{
// Dummy variables required for it to work on iDevices ** DO NOT DELETE **
// This forces the classes not to be optimized out when deploying to iDevices
var hByteReader = new ByteReader();
var hSByteReader = new SByteReader();
var hDateTimeReader = new DateTimeReader();
var hDecimalReader = new DecimalReader();
var hBoundingSphereReader = new BoundingSphereReader();
var hBoundingFrustumReader = new BoundingFrustumReader();
var hRayReader = new RayReader();
var hCharListReader = new ListReader<Char>();
var hRectangleListReader = new ListReader<Rectangle>();
var hRectangleArrayReader = new ArrayReader<Rectangle>();
var hVector3ListReader = new ListReader<Vector3>();
var hStringListReader = new ListReader<StringReader>();
var hIntListReader = new ListReader<Int32>();
var hSpriteFontReader = new SpriteFontReader();
var hTexture2DReader = new Texture2DReader();
var hCharReader = new CharReader();
var hRectangleReader = new RectangleReader();
var hStringReader = new StringReader();
var hVector2Reader = new Vector2Reader();
var hVector3Reader = new Vector3Reader();
var hVector4Reader = new Vector4Reader();
var hCurveReader = new CurveReader();
var hIndexBufferReader = new IndexBufferReader();
var hBoundingBoxReader = new BoundingBoxReader();
var hMatrixReader = new MatrixReader();
var hBasicEffectReader = new BasicEffectReader();
var hVertexBufferReader = new VertexBufferReader();
var hAlphaTestEffectReader = new AlphaTestEffectReader();
var hEnumSpriteEffectsReader = new EnumReader<Graphics.SpriteEffects>();
var hArrayFloatReader = new ArrayReader<float>();
var hArrayVector2Reader = new ArrayReader<Vector2>();
var hListVector2Reader = new ListReader<Vector2>();
var hArrayMatrixReader = new ArrayReader<Matrix>();
var hEnumBlendReader = new EnumReader<Graphics.Blend>();
var hNullableRectReader = new NullableReader<Rectangle>();
var hEffectMaterialReader = new EffectMaterialReader();
var hExternalReferenceReader = new ExternalReferenceReader();
var hModelReader = new ModelReader();
var hInt32Reader = new Int32Reader();
var hEffectReader = new EffectReader();
var hSingleReader = new SingleReader();
}
#pragma warning restore 0219, 0649
// The first content byte i read tells me the number of content readers in this XNB file
var numberOfReaders = reader.Read7BitEncodedInt();
var contentReaders = new ContentTypeReader[numberOfReaders];
var needsInitialize = new BitArray(numberOfReaders);
_contentReaders = new Dictionary<Type, ContentTypeReader>(numberOfReaders);
// Lock until we're done allocating and initializing any new
// content type readers... this ensures we can load content
// from multiple threads and still cache the readers.
lock (_locker)
{
// For each reader in the file, we read out the length of the string which contains the type of the reader,
// then we read out the string. Finally we instantiate an instance of that reader using reflection
for (var i = 0; i < numberOfReaders; i++)
{
// This string tells us what reader we need to decode the following data
// string readerTypeString = reader.ReadString();
string originalReaderTypeString = reader.ReadString();
Func<ContentTypeReader> readerFunc;
if (typeCreators.TryGetValue(originalReaderTypeString, out readerFunc))
{
contentReaders[i] = readerFunc();
needsInitialize[i] = true;
}
else
{
//System.Diagnostics.Debug.WriteLine(originalReaderTypeString);
// Need to resolve namespace differences
string readerTypeString = originalReaderTypeString;
readerTypeString = PrepareType(readerTypeString);
var l_readerType = Type.GetType(readerTypeString);
if (l_readerType != null)
{
ContentTypeReader typeReader;
if (!_contentReadersCache.TryGetValue(l_readerType, out typeReader))
{
try
{
typeReader = l_readerType.GetDefaultConstructor().Invoke(null) as ContentTypeReader;
}
catch (TargetInvocationException ex)
{
// If you are getting here, the Mono runtime is most likely not able to JIT the type.
// In particular, MonoTouch needs help instantiating types that are only defined in strings in Xnb files.
throw new InvalidOperationException(
"Failed to get default constructor for ContentTypeReader. To work around, add a creation function to ContentTypeReaderManager.AddTypeCreator() " +
"with the following failed type string: " + originalReaderTypeString, ex);
}
needsInitialize[i] = true;
_contentReadersCache.Add(l_readerType, typeReader);
}
contentReaders[i] = typeReader;
}
else
throw new ContentLoadException(
"Could not find ContentTypeReader Type. Please ensure the name of the Assembly that contains the Type matches the assembly in the full type name: " +
originalReaderTypeString + " (" + readerTypeString + ")");
}
var targetType = contentReaders[i].TargetType;
if (targetType != null)
if (!_contentReaders.ContainsKey(targetType))
_contentReaders.Add(targetType, contentReaders[i]);
// I think the next 4 bytes refer to the "Version" of the type reader,
// although it always seems to be zero
reader.ReadInt32();
}
// Initialize any new readers.
for (var i = 0; i < contentReaders.Length; i++)
{
if (needsInitialize.Get(i))
contentReaders[i].Initialize(this);
}
} // lock (_locker)
return contentReaders;
}
/// <summary>
/// Removes Version, Culture and PublicKeyToken from a type string.
/// </summary>
/// <remarks>
/// Supports multiple generic types (e.g. Dictionary&lt;TKey,TValue&gt;) and nested generic types (e.g. List&lt;List&lt;int&gt;&gt;).
/// </remarks>
/// <param name="type">
/// A <see cref="System.String"/>
/// </param>
/// <returns>
/// A <see cref="System.String"/>
/// </returns>
public static string PrepareType(string type)
{
//Needed to support nested types
int count = type.Split(new[] {"[["}, StringSplitOptions.None).Length - 1;
string preparedType = type;
for(int i=0; i<count; i++)
{
preparedType = Regex.Replace(preparedType, @"\[(.+?), Version=.+?\]", "[$1]");
}
//Handle non generic types
if(preparedType.Contains("PublicKeyToken"))
preparedType = Regex.Replace(preparedType, @"(.+?), Version=.+?$", "$1");
// TODO: For WinRT this is most likely broken!
preparedType = preparedType.Replace(", Microsoft.Xna.Framework.Graphics", string.Format(", {0}", _assemblyName));
preparedType = preparedType.Replace(", Microsoft.Xna.Framework.Video", string.Format(", {0}", _assemblyName));
preparedType = preparedType.Replace(", Microsoft.Xna.Framework", string.Format(", {0}", _assemblyName));
return preparedType;
}
// Static map of type names to creation functions. Required as iOS requires all types at compile time
private static Dictionary<string, Func<ContentTypeReader>> typeCreators = new Dictionary<string, Func<ContentTypeReader>>();
/// <summary>
/// Adds the type creator.
/// </summary>
/// <param name='typeString'>
/// Type string.
/// </param>
/// <param name='createFunction'>
/// Create function.
/// </param>
public static void AddTypeCreator(string typeString, Func<ContentTypeReader> createFunction)
{
if (!typeCreators.ContainsKey(typeString))
typeCreators.Add(typeString, createFunction);
}
public static void ClearTypeCreators()
{
typeCreators.Clear();
}
}
}
@@ -0,0 +1,780 @@
#region HEADER
/* This file was derived from libmspack
* (C) 2003-2004 Stuart Caie.
* (C) 2011 Ali Scissons.
*
* The LZX method was created by Jonathan Forbes and Tomi Poutanen, adapted
* by Microsoft Corporation.
*
* This source file is Dual licensed; meaning the end-user of this source file
* may redistribute/modify it under the LGPL 2.1 or MS-PL licenses.
*/
#region LGPL License
/* GNU LESSER GENERAL PUBLIC LICENSE version 2.1
* LzxDecoder is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
*/
#endregion
#region MS-PL License
/*
* MICROSOFT PUBLIC LICENSE
* This source code is subject to the terms of the Microsoft Public License (Ms-PL).
*
* Redistribution and use in source and binary forms, with or without modification,
* is permitted provided that redistributions of the source code retain the above
* copyright notices and this file header.
*
* Additional copyright notices should be appended to the list above.
*
* For details, see <http://www.opensource.org/licenses/ms-pl.html>.
*/
#endregion
/*
* This derived work is recognized by Stuart Caie and is authorized to adapt
* any changes made to lzxd.c in his libmspack library and will still retain
* this dual licensing scheme. Big thanks to Stuart Caie!
*
* DETAILS
* This file is a pure C# port of the lzxd.c file from libmspack, with minor
* changes towards the decompression of XNB files. The original decompression
* software of LZX encoded data was written by Suart Caie in his
* libmspack/cabextract projects, which can be located at
* http://http://www.cabextract.org.uk/
*/
#endregion
using System;
using System.Diagnostics;
namespace Microsoft.Xna.Framework.Content
{
using System.IO;
class LzxDecoder
{
public static uint[] position_base = null;
public static byte[] extra_bits = null;
private LzxState m_state;
public LzxDecoder (int window)
{
uint wndsize = (uint)(1 << window);
int posn_slots;
// setup proper exception
if(window < 15 || window > 21) throw new UnsupportedWindowSizeRange();
// let's initialise our state
m_state = new LzxState();
m_state.actual_size = 0;
m_state.window = new byte[wndsize];
for(int i = 0; i < wndsize; i++) m_state.window[i] = 0xDC;
m_state.actual_size = wndsize;
m_state.window_size = wndsize;
m_state.window_posn = 0;
/* initialize static tables */
if(extra_bits == null)
{
extra_bits = new byte[52];
for(int i = 0, j = 0; i <= 50; i += 2)
{
extra_bits[i] = extra_bits[i+1] = (byte)j;
if ((i != 0) && (j < 17)) j++;
}
}
if(position_base == null)
{
position_base = new uint[51];
for(int i = 0, j = 0; i <= 50; i++)
{
position_base[i] = (uint)j;
j += 1 << extra_bits[i];
}
}
/* calculate required position slots */
if(window == 20) posn_slots = 42;
else if(window == 21) posn_slots = 50;
else posn_slots = window << 1;
m_state.R0 = m_state.R1 = m_state.R2 = 1;
m_state.main_elements = (ushort)(LzxConstants.NUM_CHARS + (posn_slots << 3));
m_state.header_read = 0;
m_state.frames_read = 0;
m_state.block_remaining = 0;
m_state.block_type = LzxConstants.BLOCKTYPE.INVALID;
m_state.intel_curpos = 0;
m_state.intel_started = 0;
// yo dawg i herd u liek arrays so we put arrays in ur arrays so u can array while u array
m_state.PRETREE_table = new ushort[(1 << LzxConstants.PRETREE_TABLEBITS) + (LzxConstants.PRETREE_MAXSYMBOLS << 1)];
m_state.PRETREE_len = new byte[LzxConstants.PRETREE_MAXSYMBOLS + LzxConstants.LENTABLE_SAFETY];
m_state.MAINTREE_table = new ushort[(1 << LzxConstants.MAINTREE_TABLEBITS) + (LzxConstants.MAINTREE_MAXSYMBOLS << 1)];
m_state.MAINTREE_len = new byte[LzxConstants.MAINTREE_MAXSYMBOLS + LzxConstants.LENTABLE_SAFETY];
m_state.LENGTH_table = new ushort[(1 << LzxConstants.LENGTH_TABLEBITS) + (LzxConstants.LENGTH_MAXSYMBOLS << 1)];
m_state.LENGTH_len = new byte[LzxConstants.LENGTH_MAXSYMBOLS + LzxConstants.LENTABLE_SAFETY];
m_state.ALIGNED_table = new ushort[(1 << LzxConstants.ALIGNED_TABLEBITS) + (LzxConstants.ALIGNED_MAXSYMBOLS << 1)];
m_state.ALIGNED_len = new byte[LzxConstants.ALIGNED_MAXSYMBOLS + LzxConstants.LENTABLE_SAFETY];
/* initialise tables to 0 (because deltas will be applied to them) */
for(int i = 0; i < LzxConstants.MAINTREE_MAXSYMBOLS; i++) m_state.MAINTREE_len[i] = 0;
for(int i = 0; i < LzxConstants.LENGTH_MAXSYMBOLS; i++) m_state.LENGTH_len[i] = 0;
}
public int Decompress(Stream inData, int inLen, Stream outData, int outLen)
{
BitBuffer bitbuf = new BitBuffer(inData);
long startpos = inData.Position;
long endpos = inData.Position + inLen;
byte[] window = m_state.window;
uint window_posn = m_state.window_posn;
uint window_size = m_state.window_size;
uint R0 = m_state.R0;
uint R1 = m_state.R1;
uint R2 = m_state.R2;
uint i, j;
int togo = outLen, this_run, main_element, match_length, match_offset, length_footer, extra, verbatim_bits;
int rundest, runsrc, copy_length, aligned_bits;
bitbuf.InitBitStream();
/* read header if necessary */
if(m_state.header_read == 0)
{
uint intel = bitbuf.ReadBits(1);
if(intel != 0)
{
// read the filesize
i = bitbuf.ReadBits(16); j = bitbuf.ReadBits(16);
m_state.intel_filesize = (int)((i << 16) | j);
}
m_state.header_read = 1;
}
/* main decoding loop */
while(togo > 0)
{
/* last block finished, new block expected */
if(m_state.block_remaining == 0)
{
// TODO may screw something up here
if(m_state.block_type == LzxConstants.BLOCKTYPE.UNCOMPRESSED) {
if((m_state.block_length & 1) == 1) inData.ReadByte(); /* realign bitstream to word */
bitbuf.InitBitStream();
}
m_state.block_type = (LzxConstants.BLOCKTYPE)bitbuf.ReadBits(3);;
i = bitbuf.ReadBits(16);
j = bitbuf.ReadBits(8);
m_state.block_remaining = m_state.block_length = (uint)((i << 8) | j);
switch(m_state.block_type)
{
case LzxConstants.BLOCKTYPE.ALIGNED:
for(i = 0, j = 0; i < 8; i++) { j = bitbuf.ReadBits(3); m_state.ALIGNED_len[i] = (byte)j; }
MakeDecodeTable(LzxConstants.ALIGNED_MAXSYMBOLS, LzxConstants.ALIGNED_TABLEBITS,
m_state.ALIGNED_len, m_state.ALIGNED_table);
/* rest of aligned header is same as verbatim */
goto case LzxConstants.BLOCKTYPE.VERBATIM;
case LzxConstants.BLOCKTYPE.VERBATIM:
ReadLengths(m_state.MAINTREE_len, 0, 256, bitbuf);
ReadLengths(m_state.MAINTREE_len, 256, m_state.main_elements, bitbuf);
MakeDecodeTable(LzxConstants.MAINTREE_MAXSYMBOLS, LzxConstants.MAINTREE_TABLEBITS,
m_state.MAINTREE_len, m_state.MAINTREE_table);
if(m_state.MAINTREE_len[0xE8] != 0) m_state.intel_started = 1;
ReadLengths(m_state.LENGTH_len, 0, LzxConstants.NUM_SECONDARY_LENGTHS, bitbuf);
MakeDecodeTable(LzxConstants.LENGTH_MAXSYMBOLS, LzxConstants.LENGTH_TABLEBITS,
m_state.LENGTH_len, m_state.LENGTH_table);
break;
case LzxConstants.BLOCKTYPE.UNCOMPRESSED:
m_state.intel_started = 1; /* because we can't assume otherwise */
bitbuf.EnsureBits(16); /* get up to 16 pad bits into the buffer */
if(bitbuf.GetBitsLeft() > 16) inData.Seek(-2, SeekOrigin.Current); /* and align the bitstream! */
byte hi, mh, ml, lo;
lo = (byte)inData.ReadByte(); ml = (byte)inData.ReadByte(); mh = (byte)inData.ReadByte(); hi = (byte)inData.ReadByte();
R0 = (uint)(lo | ml << 8 | mh << 16 | hi << 24);
lo = (byte)inData.ReadByte(); ml = (byte)inData.ReadByte(); mh = (byte)inData.ReadByte(); hi = (byte)inData.ReadByte();
R1 = (uint)(lo | ml << 8 | mh << 16 | hi << 24);
lo = (byte)inData.ReadByte(); ml = (byte)inData.ReadByte(); mh = (byte)inData.ReadByte(); hi = (byte)inData.ReadByte();
R2 = (uint)(lo | ml << 8 | mh << 16 | hi << 24);
break;
default:
return -1; // TODO throw proper exception
}
}
/* buffer exhaustion check */
if(inData.Position > (startpos + inLen))
{
/* it's possible to have a file where the next run is less than
* 16 bits in size. In this case, the READ_HUFFSYM() macro used
* in building the tables will exhaust the buffer, so we should
* allow for this, but not allow those accidentally read bits to
* be used (so we check that there are at least 16 bits
* remaining - in this boundary case they aren't really part of
* the compressed data)
*/
//Debug.WriteLine("WTF");
if(inData.Position > (startpos+inLen+2) || bitbuf.GetBitsLeft() < 16) return -1; //TODO throw proper exception
}
while((this_run = (int)m_state.block_remaining) > 0 && togo > 0)
{
if(this_run > togo) this_run = togo;
togo -= this_run;
m_state.block_remaining -= (uint)this_run;
/* apply 2^x-1 mask */
window_posn &= window_size - 1;
/* runs can't straddle the window wraparound */
if((window_posn + this_run) > window_size)
return -1; //TODO throw proper exception
switch(m_state.block_type)
{
case LzxConstants.BLOCKTYPE.VERBATIM:
while(this_run > 0)
{
main_element = (int)ReadHuffSym(m_state.MAINTREE_table, m_state.MAINTREE_len,
LzxConstants.MAINTREE_MAXSYMBOLS, LzxConstants.MAINTREE_TABLEBITS,
bitbuf);
if(main_element < LzxConstants.NUM_CHARS)
{
/* literal: 0 to NUM_CHARS-1 */
window[window_posn++] = (byte)main_element;
this_run--;
}
else
{
/* match: NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
main_element -= LzxConstants.NUM_CHARS;
match_length = main_element & LzxConstants.NUM_PRIMARY_LENGTHS;
if(match_length == LzxConstants.NUM_PRIMARY_LENGTHS)
{
length_footer = (int)ReadHuffSym(m_state.LENGTH_table, m_state.LENGTH_len,
LzxConstants.LENGTH_MAXSYMBOLS, LzxConstants.LENGTH_TABLEBITS,
bitbuf);
match_length += length_footer;
}
match_length += LzxConstants.MIN_MATCH;
match_offset = main_element >> 3;
if(match_offset > 2)
{
/* not repeated offset */
if(match_offset != 3)
{
extra = extra_bits[match_offset];
verbatim_bits = (int)bitbuf.ReadBits((byte)extra);
match_offset = (int)position_base[match_offset] - 2 + verbatim_bits;
}
else
{
match_offset = 1;
}
/* update repeated offset LRU queue */
R2 = R1; R1 = R0; R0 = (uint)match_offset;
}
else if(match_offset == 0)
{
match_offset = (int)R0;
}
else if(match_offset == 1)
{
match_offset = (int)R1;
R1 = R0; R0 = (uint)match_offset;
}
else /* match_offset == 2 */
{
match_offset = (int)R2;
R2 = R0; R0 = (uint)match_offset;
}
rundest = (int)window_posn;
this_run -= match_length;
/* copy any wrapped around source data */
if(window_posn >= match_offset)
{
/* no wrap */
runsrc = rundest - match_offset;
}
else
{
runsrc = rundest + ((int)window_size - match_offset);
copy_length = match_offset - (int)window_posn;
if(copy_length < match_length)
{
match_length -= copy_length;
window_posn += (uint)copy_length;
while(copy_length-- > 0) window[rundest++] = window[runsrc++];
runsrc = 0;
}
}
window_posn += (uint)match_length;
/* copy match data - no worries about destination wraps */
while(match_length-- > 0) window[rundest++] = window[runsrc++];
}
}
break;
case LzxConstants.BLOCKTYPE.ALIGNED:
while(this_run > 0)
{
main_element = (int)ReadHuffSym(m_state.MAINTREE_table, m_state.MAINTREE_len,
LzxConstants.MAINTREE_MAXSYMBOLS, LzxConstants.MAINTREE_TABLEBITS,
bitbuf);
if(main_element < LzxConstants.NUM_CHARS)
{
/* literal 0 to NUM_CHARS-1 */
window[window_posn++] = (byte)main_element;
this_run--;
}
else
{
/* match: NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
main_element -= LzxConstants.NUM_CHARS;
match_length = main_element & LzxConstants.NUM_PRIMARY_LENGTHS;
if(match_length == LzxConstants.NUM_PRIMARY_LENGTHS)
{
length_footer = (int)ReadHuffSym(m_state.LENGTH_table, m_state.LENGTH_len,
LzxConstants.LENGTH_MAXSYMBOLS, LzxConstants.LENGTH_TABLEBITS,
bitbuf);
match_length += length_footer;
}
match_length += LzxConstants.MIN_MATCH;
match_offset = main_element >> 3;
if(match_offset > 2)
{
/* not repeated offset */
extra = extra_bits[match_offset];
match_offset = (int)position_base[match_offset] - 2;
if(extra > 3)
{
/* verbatim and aligned bits */
extra -= 3;
verbatim_bits = (int)bitbuf.ReadBits((byte)extra);
match_offset += (verbatim_bits << 3);
aligned_bits = (int)ReadHuffSym(m_state.ALIGNED_table, m_state.ALIGNED_len,
LzxConstants.ALIGNED_MAXSYMBOLS, LzxConstants.ALIGNED_TABLEBITS,
bitbuf);
match_offset += aligned_bits;
}
else if(extra == 3)
{
/* aligned bits only */
aligned_bits = (int)ReadHuffSym(m_state.ALIGNED_table, m_state.ALIGNED_len,
LzxConstants.ALIGNED_MAXSYMBOLS, LzxConstants.ALIGNED_TABLEBITS,
bitbuf);
match_offset += aligned_bits;
}
else if (extra > 0) /* extra==1, extra==2 */
{
/* verbatim bits only */
verbatim_bits = (int)bitbuf.ReadBits((byte)extra);
match_offset += verbatim_bits;
}
else /* extra == 0 */
{
/* ??? */
match_offset = 1;
}
/* update repeated offset LRU queue */
R2 = R1; R1 = R0; R0 = (uint)match_offset;
}
else if( match_offset == 0)
{
match_offset = (int)R0;
}
else if(match_offset == 1)
{
match_offset = (int)R1;
R1 = R0; R0 = (uint)match_offset;
}
else /* match_offset == 2 */
{
match_offset = (int)R2;
R2 = R0; R0 = (uint)match_offset;
}
rundest = (int)window_posn;
this_run -= match_length;
/* copy any wrapped around source data */
if(window_posn >= match_offset)
{
/* no wrap */
runsrc = rundest - match_offset;
}
else
{
runsrc = rundest + ((int)window_size - match_offset);
copy_length = match_offset - (int)window_posn;
if(copy_length < match_length)
{
match_length -= copy_length;
window_posn += (uint)copy_length;
while(copy_length-- > 0) window[rundest++] = window[runsrc++];
runsrc = 0;
}
}
window_posn += (uint)match_length;
/* copy match data - no worries about destination wraps */
while(match_length-- > 0) window[rundest++] = window[runsrc++];
}
}
break;
case LzxConstants.BLOCKTYPE.UNCOMPRESSED:
if((inData.Position + this_run) > endpos) return -1; //TODO throw proper exception
byte[] temp_buffer = new byte[this_run];
inData.Read(temp_buffer, 0, this_run);
temp_buffer.CopyTo(window, (int)window_posn);
window_posn += (uint)this_run;
break;
default:
return -1; //TODO throw proper exception
}
}
}
if(togo != 0) return -1; //TODO throw proper exception
int start_window_pos = (int)window_posn;
if(start_window_pos == 0) start_window_pos = (int)window_size;
start_window_pos -= outLen;
outData.Write(window, start_window_pos, outLen);
m_state.window_posn = window_posn;
m_state.R0 = R0;
m_state.R1 = R1;
m_state.R2 = R2;
// TODO finish intel E8 decoding
/* intel E8 decoding */
if((m_state.frames_read++ < 32768) && m_state.intel_filesize != 0)
{
if(outLen <= 6 || m_state.intel_started == 0)
{
m_state.intel_curpos += outLen;
}
else
{
int dataend = outLen - 10;
uint curpos = (uint)m_state.intel_curpos;
m_state.intel_curpos = (int)curpos + outLen;
while(outData.Position < dataend)
{
if(outData.ReadByte() != 0xE8) { curpos++; continue; }
}
}
return -1;
}
return 0;
}
// READ_LENGTHS(table, first, last)
// if(lzx_read_lens(LENTABLE(table), first, last, bitsleft))
// return ERROR (ILLEGAL_DATA)
//
// TODO make returns throw exceptions
private int MakeDecodeTable(uint nsyms, uint nbits, byte[] length, ushort[] table)
{
ushort sym;
uint leaf;
byte bit_num = 1;
uint fill;
uint pos = 0; /* the current position in the decode table */
uint table_mask = (uint)(1 << (int)nbits);
uint bit_mask = table_mask >> 1; /* don't do 0 length codes */
uint next_symbol = bit_mask; /* base of allocation for long codes */
/* fill entries for codes short enough for a direct mapping */
while (bit_num <= nbits )
{
for(sym = 0; sym < nsyms; sym++)
{
if(length[sym] == bit_num)
{
leaf = pos;
if((pos += bit_mask) > table_mask) return 1; /* table overrun */
/* fill all possible lookups of this symbol with the symbol itself */
fill = bit_mask;
while(fill-- > 0) table[leaf++] = sym;
}
}
bit_mask >>= 1;
bit_num++;
}
/* if there are any codes longer than nbits */
if(pos != table_mask)
{
/* clear the remainder of the table */
for(sym = (ushort)pos; sym < table_mask; sym++) table[sym] = 0;
/* give ourselves room for codes to grow by up to 16 more bits */
pos <<= 16;
table_mask <<= 16;
bit_mask = 1 << 15;
while(bit_num <= 16)
{
for(sym = 0; sym < nsyms; sym++)
{
if(length[sym] == bit_num)
{
leaf = pos >> 16;
for(fill = 0; fill < bit_num - nbits; fill++)
{
/* if this path hasn't been taken yet, 'allocate' two entries */
if(table[leaf] == 0)
{
table[(next_symbol << 1)] = 0;
table[(next_symbol << 1) + 1] = 0;
table[leaf] = (ushort)(next_symbol++);
}
/* follow the path and select either left or right for next bit */
leaf = (uint)(table[leaf] << 1);
if(((pos >> (int)(15-fill)) & 1) == 1) leaf++;
}
table[leaf] = sym;
if((pos += bit_mask) > table_mask) return 1;
}
}
bit_mask >>= 1;
bit_num++;
}
}
/* full talbe? */
if(pos == table_mask) return 0;
/* either erroneous table, or all elements are 0 - let's find out. */
for(sym = 0; sym < nsyms; sym++) if(length[sym] != 0) return 1;
return 0;
}
// TODO throw exceptions instead of returns
private void ReadLengths(byte[] lens, uint first, uint last, BitBuffer bitbuf)
{
uint x, y;
int z;
// hufftbl pointer here?
for(x = 0; x < 20; x++)
{
y = bitbuf.ReadBits(4);
m_state.PRETREE_len[x] = (byte)y;
}
MakeDecodeTable(LzxConstants.PRETREE_MAXSYMBOLS, LzxConstants.PRETREE_TABLEBITS,
m_state.PRETREE_len, m_state.PRETREE_table);
for(x = first; x < last;)
{
z = (int)ReadHuffSym(m_state.PRETREE_table, m_state.PRETREE_len,
LzxConstants.PRETREE_MAXSYMBOLS, LzxConstants.PRETREE_TABLEBITS, bitbuf);
if(z == 17)
{
y = bitbuf.ReadBits(4); y += 4;
while(y-- != 0) lens[x++] = 0;
}
else if(z == 18)
{
y = bitbuf.ReadBits(5); y += 20;
while(y-- != 0) lens[x++] = 0;
}
else if(z == 19)
{
y = bitbuf.ReadBits(1); y += 4;
z = (int)ReadHuffSym(m_state.PRETREE_table, m_state.PRETREE_len,
LzxConstants.PRETREE_MAXSYMBOLS, LzxConstants.PRETREE_TABLEBITS, bitbuf);
z = lens[x] - z; if(z < 0) z += 17;
while(y-- != 0) lens[x++] = (byte)z;
}
else
{
z = lens[x] - z; if(z < 0) z += 17;
lens[x++] = (byte)z;
}
}
}
private uint ReadHuffSym(ushort[] table, byte[] lengths, uint nsyms, uint nbits, BitBuffer bitbuf)
{
uint i, j;
bitbuf.EnsureBits(16);
if((i = table[bitbuf.PeekBits((byte)nbits)]) >= nsyms)
{
j = (uint)(1 << (int)((sizeof(uint)*8) - nbits));
do
{
j >>= 1; i <<= 1; i |= (bitbuf.GetBuffer() & j) != 0 ? (uint)1 : 0;
if(j == 0) return 0; // TODO throw proper exception
} while((i = table[i]) >= nsyms);
}
j = lengths[i];
bitbuf.RemoveBits((byte)j);
return i;
}
#region Our BitBuffer Class
private class BitBuffer
{
uint buffer;
byte bitsleft;
Stream byteStream;
public BitBuffer(Stream stream)
{
byteStream = stream;
InitBitStream();
}
public void InitBitStream()
{
buffer = 0;
bitsleft = 0;
}
public void EnsureBits(byte bits)
{
while(bitsleft < bits) {
int lo = (byte)byteStream.ReadByte();
int hi = (byte)byteStream.ReadByte();
//int amount2shift = sizeof(uint)*8 - 16 - bitsleft;
buffer |= (uint)(((hi << 8) | lo) << (sizeof(uint)*8 - 16 - bitsleft));
bitsleft += 16;
}
}
public uint PeekBits(byte bits)
{
return (buffer >> ((sizeof(uint)*8) - bits));
}
public void RemoveBits(byte bits)
{
buffer <<= bits;
bitsleft -= bits;
}
public uint ReadBits(byte bits)
{
uint ret = 0;
if(bits > 0)
{
EnsureBits(bits);
ret = PeekBits(bits);
RemoveBits(bits);
}
return ret;
}
public uint GetBuffer()
{
return buffer;
}
public byte GetBitsLeft()
{
return bitsleft;
}
}
#endregion
struct LzxState {
public uint R0, R1, R2; /* for the LRU offset system */
public ushort main_elements; /* number of main tree elements */
public int header_read; /* have we started decoding at all yet? */
public LzxConstants.BLOCKTYPE block_type; /* type of this block */
public uint block_length; /* uncompressed length of this block */
public uint block_remaining; /* uncompressed bytes still left to decode */
public uint frames_read; /* the number of CFDATA blocks processed */
public int intel_filesize; /* magic header value used for transform */
public int intel_curpos; /* current offset in transform space */
public int intel_started; /* have we seen any translateable data yet? */
public ushort[] PRETREE_table;
public byte[] PRETREE_len;
public ushort[] MAINTREE_table;
public byte[] MAINTREE_len;
public ushort[] LENGTH_table;
public byte[] LENGTH_len;
public ushort[] ALIGNED_table;
public byte[] ALIGNED_len;
// NEEDED MEMBERS
// CAB actualsize
// CAB window
// CAB window_size
// CAB window_posn
public uint actual_size;
public byte[] window;
public uint window_size;
public uint window_posn;
}
}
/* CONSTANTS */
struct LzxConstants {
public const ushort MIN_MATCH = 2;
public const ushort MAX_MATCH = 257;
public const ushort NUM_CHARS = 256;
public enum BLOCKTYPE {
INVALID = 0,
VERBATIM = 1,
ALIGNED = 2,
UNCOMPRESSED = 3
}
public const ushort PRETREE_NUM_ELEMENTS = 20;
public const ushort ALIGNED_NUM_ELEMENTS = 8;
public const ushort NUM_PRIMARY_LENGTHS = 7;
public const ushort NUM_SECONDARY_LENGTHS = 249;
public const ushort PRETREE_MAXSYMBOLS = PRETREE_NUM_ELEMENTS;
public const ushort PRETREE_TABLEBITS = 6;
public const ushort MAINTREE_MAXSYMBOLS = NUM_CHARS + 50*8;
public const ushort MAINTREE_TABLEBITS = 12;
public const ushort LENGTH_MAXSYMBOLS = NUM_SECONDARY_LENGTHS + 1;
public const ushort LENGTH_TABLEBITS = 12;
public const ushort ALIGNED_MAXSYMBOLS = ALIGNED_NUM_ELEMENTS;
public const ushort ALIGNED_TABLEBITS = 7;
public const ushort LENTABLE_SAFETY = 64;
}
/* EXCEPTIONS */
class UnsupportedWindowSizeRange : Exception
{
}
}
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Resources;
namespace Microsoft.Xna.Framework.Content
{
public class ResourceContentManager : ContentManager
{
private ResourceManager resource;
public ResourceContentManager(IServiceProvider servicesProvider, ResourceManager resource)
: base(servicesProvider)
{
if (resource == null)
{
throw new ArgumentNullException("resource");
}
this.resource = resource;
}
protected override System.IO.Stream OpenStream(string assetName)
{
object obj = this.resource.GetObject(assetName);
if (obj == null)
{
throw new ContentLoadException("Resource not found");
}
if (!(obj is byte[]))
{
throw new ContentLoadException("Resource is not in binary format");
}
return new MemoryStream(obj as byte[]);
}
}
}
@@ -0,0 +1,338 @@
// MIT License - Copyright (C) The Mono.Xna 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.ComponentModel;
using System.Runtime.Serialization;
namespace Microsoft.Xna.Framework
{
/// <summary>
/// Contains a collection of <see cref="CurveKey"/> points in 2D space and provides methods for evaluating features of the curve they define.
/// </summary>
// TODO : [TypeConverter(typeof(ExpandableObjectConverter))]
[DataContract]
public class Curve
{
#region Private Fields
private CurveLoopType _preLoop;
private CurveLoopType _postLoop;
private CurveKeyCollection _keys;
#endregion
#region Public Properties
/// <summary>
/// Returns <c>true</c> if this curve is constant (has zero or one points); <c>false</c> otherwise.
/// </summary>
[DataMember]
public bool IsConstant
{
get { return this._keys.Count <= 1; }
}
/// <summary>
/// Defines how to handle weighting values that are less than the first control point in the curve.
/// </summary>
[DataMember]
public CurveLoopType PreLoop
{
get { return this._preLoop; }
set { this._preLoop = value; }
}
/// <summary>
/// Defines how to handle weighting values that are greater than the last control point in the curve.
/// </summary>
[DataMember]
public CurveLoopType PostLoop
{
get { return this._postLoop; }
set { this._postLoop = value; }
}
/// <summary>
/// The collection of curve keys.
/// </summary>
[DataMember]
public CurveKeyCollection Keys
{
get { return this._keys; }
}
#endregion
#region Public Constructors
/// <summary>
/// Constructs a curve.
/// </summary>
public Curve()
{
this._keys = new CurveKeyCollection();
}
#endregion
#region Public Methods
/// <summary>
/// Creates a copy of this curve.
/// </summary>
/// <returns>A copy of this curve.</returns>
public Curve Clone()
{
Curve curve = new Curve();
curve._keys = this._keys.Clone();
curve._preLoop = this._preLoop;
curve._postLoop = this._postLoop;
return curve;
}
/// <summary>
/// Evaluate the value at a position of this <see cref="Curve"/>.
/// </summary>
/// <param name="position">The position on this <see cref="Curve"/>.</param>
/// <returns>Value at the position on this <see cref="Curve"/>.</returns>
public float Evaluate(float position)
{
if (_keys.Count == 0)
{
return 0f;
}
if (_keys.Count == 1)
{
return _keys[0].Value;
}
CurveKey first = _keys[0];
CurveKey last = _keys[_keys.Count - 1];
if (position < first.Position)
{
switch (this.PreLoop)
{
case CurveLoopType.Constant:
//constant
return first.Value;
case CurveLoopType.Linear:
// linear y = a*x +b with a tangeant of last point
return first.Value - first.TangentIn * (first.Position - position);
case CurveLoopType.Cycle:
//start -> end / start -> end
int cycle = GetNumberOfCycle(position);
float virtualPos = position - (cycle * (last.Position - first.Position));
return GetCurvePosition(virtualPos);
case CurveLoopType.CycleOffset:
//make the curve continue (with no step) so must up the curve each cycle of delta(value)
cycle = GetNumberOfCycle(position);
virtualPos = position - (cycle * (last.Position - first.Position));
return (GetCurvePosition(virtualPos) + cycle * (last.Value - first.Value));
case CurveLoopType.Oscillate:
//go back on curve from end and target start
// start-> end / end -> start
cycle = GetNumberOfCycle(position);
if (0 == cycle % 2f)//if pair
virtualPos = position - (cycle * (last.Position - first.Position));
else
virtualPos = last.Position - position + first.Position + (cycle * (last.Position - first.Position));
return GetCurvePosition(virtualPos);
}
}
else if (position > last.Position)
{
int cycle;
switch (this.PostLoop)
{
case CurveLoopType.Constant:
//constant
return last.Value;
case CurveLoopType.Linear:
// linear y = a*x +b with a tangeant of last point
return last.Value + first.TangentOut * (position - last.Position);
case CurveLoopType.Cycle:
//start -> end / start -> end
cycle = GetNumberOfCycle(position);
float virtualPos = position - (cycle * (last.Position - first.Position));
return GetCurvePosition(virtualPos);
case CurveLoopType.CycleOffset:
//make the curve continue (with no step) so must up the curve each cycle of delta(value)
cycle = GetNumberOfCycle(position);
virtualPos = position - (cycle * (last.Position - first.Position));
return (GetCurvePosition(virtualPos) + cycle * (last.Value - first.Value));
case CurveLoopType.Oscillate:
//go back on curve from end and target start
// start-> end / end -> start
cycle = GetNumberOfCycle(position);
virtualPos = position - (cycle * (last.Position - first.Position));
if (0 == cycle % 2f)//if pair
virtualPos = position - (cycle * (last.Position - first.Position));
else
virtualPos = last.Position - position + first.Position + (cycle * (last.Position - first.Position));
return GetCurvePosition(virtualPos);
}
}
//in curve
return GetCurvePosition(position);
}
/// <summary>
/// Computes tangents for all keys in the collection.
/// </summary>
/// <param name="tangentType">The tangent type for both in and out.</param>
public void ComputeTangents (CurveTangent tangentType)
{
ComputeTangents(tangentType, tangentType);
}
/// <summary>
/// Computes tangents for all keys in the collection.
/// </summary>
/// <param name="tangentInType">The tangent in-type. <see cref="CurveKey.TangentIn"/> for more details.</param>
/// <param name="tangentOutType">The tangent out-type. <see cref="CurveKey.TangentOut"/> for more details.</param>
public void ComputeTangents(CurveTangent tangentInType, CurveTangent tangentOutType)
{
for (var i = 0; i < Keys.Count; ++i)
{
ComputeTangent(i, tangentInType, tangentOutType);
}
}
/// <summary>
/// Computes tangent for the specific key in the collection.
/// </summary>
/// <param name="keyIndex">The index of a key in the collection.</param>
/// <param name="tangentType">The tangent type for both in and out.</param>
public void ComputeTangent(int keyIndex, CurveTangent tangentType)
{
ComputeTangent(keyIndex, tangentType, tangentType);
}
/// <summary>
/// Computes tangent for the specific key in the collection.
/// </summary>
/// <param name="keyIndex">The index of key in the collection.</param>
/// <param name="tangentInType">The tangent in-type. <see cref="CurveKey.TangentIn"/> for more details.</param>
/// <param name="tangentOutType">The tangent out-type. <see cref="CurveKey.TangentOut"/> for more details.</param>
public void ComputeTangent(int keyIndex, CurveTangent tangentInType, CurveTangent tangentOutType)
{
// See http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.curvetangent.aspx
var key = _keys[keyIndex];
float p0, p, p1;
p0 = p = p1 = key.Position;
float v0, v, v1;
v0 = v = v1 = key.Value;
if ( keyIndex > 0 )
{
p0 = _keys[keyIndex - 1].Position;
v0 = _keys[keyIndex - 1].Value;
}
if (keyIndex < _keys.Count-1)
{
p1 = _keys[keyIndex + 1].Position;
v1 = _keys[keyIndex + 1].Value;
}
switch (tangentInType)
{
case CurveTangent.Flat:
key.TangentIn = 0;
break;
case CurveTangent.Linear:
key.TangentIn = v - v0;
break;
case CurveTangent.Smooth:
var pn = p1 - p0;
if (Math.Abs(pn) < float.Epsilon)
key.TangentIn = 0;
else
key.TangentIn = (v1 - v0) * ((p - p0) / pn);
break;
}
switch (tangentOutType)
{
case CurveTangent.Flat:
key.TangentOut = 0;
break;
case CurveTangent.Linear:
key.TangentOut = v1 - v;
break;
case CurveTangent.Smooth:
var pn = p1 - p0;
if (Math.Abs(pn) < float.Epsilon)
key.TangentOut = 0;
else
key.TangentOut = (v1 - v0) * ((p1 - p) / pn);
break;
}
}
#endregion
#region Private Methods
private int GetNumberOfCycle(float position)
{
float cycle = (position - _keys[0].Position) / (_keys[_keys.Count - 1].Position - _keys[0].Position);
if (cycle < 0f)
cycle--;
return (int)cycle;
}
private float GetCurvePosition(float position)
{
//only for position in curve
CurveKey prev = this._keys[0];
CurveKey next;
for (int i = 1; i < this._keys.Count; ++i)
{
next = this.Keys[i];
if (next.Position >= position)
{
if (prev.Continuity == CurveContinuity.Step)
{
if (position >= 1f)
{
return next.Value;
}
return prev.Value;
}
float t = (position - prev.Position) / (next.Position - prev.Position);//to have t in [0,1]
float ts = t * t;
float tss = ts * t;
//After a lot of search on internet I have found all about spline function
// and bezier (phi'sss ancien) but finaly use hermite curve
//http://en.wikipedia.org/wiki/Cubic_Hermite_spline
//P(t) = (2*t^3 - 3t^2 + 1)*P0 + (t^3 - 2t^2 + t)m0 + (-2t^3 + 3t^2)P1 + (t^3-t^2)m1
//with P0.value = prev.value , m0 = prev.tangentOut, P1= next.value, m1 = next.TangentIn
return (2 * tss - 3 * ts + 1f) * prev.Value + (tss - 2 * ts + t) * prev.TangentOut + (3 * ts - 2 * tss) * next.Value + (tss - ts) * next.TangentIn;
}
prev = next;
}
return 0f;
}
#endregion
}
}
@@ -0,0 +1,21 @@
// MIT License - Copyright (C) The Mono.Xna 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
{
/// <summary>
/// Defines the continuity of keys on a <see cref="Curve"/>.
/// </summary>
public enum CurveContinuity
{
/// <summary>
/// Interpolation can be used between this key and the next.
/// </summary>
Smooth,
/// <summary>
/// Interpolation cannot be used. A position between the two points returns this point.
/// </summary>
Step
}
}
@@ -0,0 +1,201 @@
// MIT License - Copyright (C) The Mono.Xna 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.ComponentModel;
using System.Runtime.Serialization;
namespace Microsoft.Xna.Framework
{
/// <summary>
/// Key point on the <see cref="Curve"/>.
/// </summary>
// TODO : [TypeConverter(typeof(ExpandableObjectConverter))]
[DataContract]
public class CurveKey : IEquatable<CurveKey>, IComparable<CurveKey>
{
#region Private Fields
private CurveContinuity _continuity;
private readonly float _position;
private float _tangentIn;
private float _tangentOut;
private float _value;
#endregion
#region Properties
/// <summary>
/// Gets or sets the indicator whether the segment between this point and the next point on the curve is discrete or continuous.
/// </summary>
[DataMember]
public CurveContinuity Continuity
{
get { return this._continuity; }
set { this._continuity = value; }
}
/// <summary>
/// Gets a position of the key on the curve.
/// </summary>
[DataMember]
public float Position
{
get { return this._position; }
}
/// <summary>
/// Gets or sets a tangent when approaching this point from the previous point on the curve.
/// </summary>
[DataMember]
public float TangentIn
{
get { return this._tangentIn; }
set { this._tangentIn = value; }
}
/// <summary>
/// Gets or sets a tangent when leaving this point to the next point on the curve.
/// </summary>
[DataMember]
public float TangentOut
{
get { return this._tangentOut; }
set { this._tangentOut = value; }
}
/// <summary>
/// Gets a value of this point.
/// </summary>
[DataMember]
public float Value
{
get { return this._value; }
set { this._value = value; }
}
#endregion
#region Constructors
/// <summary>
/// Creates a new instance of <see cref="CurveKey"/> class with position: 0 and value: 0.
/// </summary>
public CurveKey() : this(0, 0)
{
// This parameterless constructor is needed for correct serialization of CurveKeyCollection and CurveKey.
}
/// <summary>
/// Creates a new instance of <see cref="CurveKey"/> class.
/// </summary>
/// <param name="position">Position on the curve.</param>
/// <param name="value">Value of the control point.</param>
public CurveKey(float position, float value)
: this(position, value, 0, 0, CurveContinuity.Smooth)
{
}
/// <summary>
/// Creates a new instance of <see cref="CurveKey"/> class.
/// </summary>
/// <param name="position">Position on the curve.</param>
/// <param name="value">Value of the control point.</param>
/// <param name="tangentIn">Tangent approaching point from the previous point on the curve.</param>
/// <param name="tangentOut">Tangent leaving point toward next point on the curve.</param>
public CurveKey(float position, float value, float tangentIn, float tangentOut)
: this(position, value, tangentIn, tangentOut, CurveContinuity.Smooth)
{
}
/// <summary>
/// Creates a new instance of <see cref="CurveKey"/> class.
/// </summary>
/// <param name="position">Position on the curve.</param>
/// <param name="value">Value of the control point.</param>
/// <param name="tangentIn">Tangent approaching point from the previous point on the curve.</param>
/// <param name="tangentOut">Tangent leaving point toward next point on the curve.</param>
/// <param name="continuity">Indicates whether the curve is discrete or continuous.</param>
public CurveKey(float position, float value, float tangentIn, float tangentOut, CurveContinuity continuity)
{
this._position = position;
this._value = value;
this._tangentIn = tangentIn;
this._tangentOut = tangentOut;
this._continuity = continuity;
}
#endregion
/// <summary>
///
/// Compares whether two <see cref="CurveKey"/> instances are not equal.
/// </summary>
/// <param name="value1"><see cref="CurveKey"/> instance on the left of the not equal sign.</param>
/// <param name="value2"><see cref="CurveKey"/> instance on the right of the not equal sign.</param>
/// <returns><c>true</c> if the instances are not equal; <c>false</c> otherwise.</returns>
public static bool operator !=(CurveKey value1, CurveKey value2)
{
return !(value1 == value2);
}
/// <summary>
/// Compares whether two <see cref="CurveKey"/> instances are equal.
/// </summary>
/// <param name="value1"><see cref="CurveKey"/> instance on the left of the equal sign.</param>
/// <param name="value2"><see cref="CurveKey"/> instance on the right of the equal sign.</param>
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
public static bool operator ==(CurveKey value1, CurveKey value2)
{
if (object.Equals(value1, null))
return object.Equals(value2, null);
if (object.Equals(value2, null))
return object.Equals(value1, null);
return (value1._position == value2._position)
&& (value1._value == value2._value)
&& (value1._tangentIn == value2._tangentIn)
&& (value1._tangentOut == value2._tangentOut)
&& (value1._continuity == value2._continuity);
}
/// <summary>
/// Creates a copy of this key.
/// </summary>
/// <returns>A copy of this key.</returns>
public CurveKey Clone()
{
return new CurveKey(this._position, this._value, this._tangentIn, this._tangentOut, this._continuity);
}
#region Inherited Methods
public int CompareTo(CurveKey other)
{
return this._position.CompareTo(other._position);
}
public bool Equals(CurveKey other)
{
return (this == other);
}
public override bool Equals(object obj)
{
return (obj as CurveKey) != null && Equals((CurveKey)obj);
}
public override int GetHashCode()
{
return this._position.GetHashCode() ^ this._value.GetHashCode() ^ this._tangentIn.GetHashCode() ^
this._tangentOut.GetHashCode() ^ this._continuity.GetHashCode();
}
#endregion
}
}
@@ -0,0 +1,200 @@
// MIT License - Copyright (C) The Mono.Xna Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace Microsoft.Xna.Framework
{
/// <summary>
/// The collection of the <see cref="CurveKey"/> elements and a part of the <see cref="Curve"/> class.
/// </summary>
// TODO : [TypeConverter(typeof(ExpandableObjectConverter))]
[DataContract]
public class CurveKeyCollection : ICollection<CurveKey>
{
#region Private Fields
private readonly List<CurveKey> _keys;
#endregion
#region Properties
/// <summary>
/// Indexer.
/// </summary>
/// <param name="index">The index of key in this collection.</param>
/// <returns><see cref="CurveKey"/> at <paramref name="index"/> position.</returns>
[DataMember(Name = "Items")]
public CurveKey this[int index]
{
get { return _keys[index]; }
set
{
if (value == null)
throw new ArgumentNullException();
if (index >= _keys.Count)
throw new IndexOutOfRangeException();
if (_keys[index].Position == value.Position)
_keys[index] = value;
else
{
_keys.RemoveAt(index);
_keys.Add(value);
}
}
}
/// <summary>
/// Returns the count of keys in this collection.
/// </summary>
[DataMember]
public int Count
{
get { return _keys.Count; }
}
/// <summary>
/// Returns false because it is not a read-only collection.
/// </summary>
[DataMember]
public bool IsReadOnly
{
get { return false; }
}
#endregion
#region Constructors
/// <summary>
/// Creates a new instance of <see cref="CurveKeyCollection"/> class.
/// </summary>
public CurveKeyCollection()
{
_keys = new List<CurveKey>();
}
#endregion
IEnumerator IEnumerable.GetEnumerator()
{
return _keys.GetEnumerator();
}
/// <summary>
/// Adds a key to this collection.
/// </summary>
/// <param name="item">New key for the collection.</param>
/// <exception cref="ArgumentNullException">Throws if <paramref name="item"/> is null.</exception>
/// <remarks>The new key would be added respectively to a position of that key and the position of other keys.</remarks>
public void Add(CurveKey item)
{
if (item == null)
throw new ArgumentNullException("item");
if (_keys.Count == 0)
{
this._keys.Add(item);
return;
}
for (int i = 0; i < this._keys.Count; i++)
{
if (item.Position < this._keys[i].Position)
{
this._keys.Insert(i, item);
return;
}
}
this._keys.Add(item);
}
/// <summary>
/// Removes all keys from this collection.
/// </summary>
public void Clear()
{
_keys.Clear();
}
/// <summary>
/// Creates a copy of this collection.
/// </summary>
/// <returns>A copy of this collection.</returns>
public CurveKeyCollection Clone()
{
CurveKeyCollection ckc = new CurveKeyCollection();
foreach (CurveKey key in this._keys)
ckc.Add(key);
return ckc;
}
/// <summary>
/// Determines whether this collection contains a specific key.
/// </summary>
/// <param name="item">The key to locate in this collection.</param>
/// <returns><c>true</c> if the key is found; <c>false</c> otherwise.</returns>
public bool Contains(CurveKey item)
{
return _keys.Contains(item);
}
/// <summary>
/// Copies the keys of this collection to an array, starting at the array index provided.
/// </summary>
/// <param name="array">Destination array where elements will be copied.</param>
/// <param name="arrayIndex">The zero-based index in the array to start copying from.</param>
public void CopyTo(CurveKey[] array, int arrayIndex)
{
_keys.CopyTo(array, arrayIndex);
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>An enumerator for the <see cref="CurveKeyCollection"/>.</returns>
public IEnumerator<CurveKey> GetEnumerator()
{
return _keys.GetEnumerator();
}
/// <summary>
/// Finds element in the collection and returns its index.
/// </summary>
/// <param name="item">Element for the search.</param>
/// <returns>Index of the element; or -1 if item is not found.</returns>
public int IndexOf(CurveKey item)
{
return _keys.IndexOf(item);
}
/// <summary>
/// Removes element at the specified index.
/// </summary>
/// <param name="index">The index which element will be removed.</param>
public void RemoveAt(int index)
{
_keys.RemoveAt(index);
}
/// <summary>
/// Removes specific element.
/// </summary>
/// <param name="item">The element</param>
/// <returns><c>true</c> if item is successfully removed; <c>false</c> otherwise. This method also returns <c>false</c> if item was not found.</returns>
public bool Remove(CurveKey item)
{
return _keys.Remove(item);
}
}
}
@@ -0,0 +1,35 @@
// MIT License - Copyright (C) The Mono.Xna 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
{
/// <summary>
/// Defines how the <see cref="Curve"/> value is determined for position before first point or after the end point on the <see cref="Curve"/>.
/// </summary>
public enum CurveLoopType
{
/// <summary>
/// The value of <see cref="Curve"/> will be evaluated as first point for positions before the beginning and end point for positions after the end.
/// </summary>
Constant,
/// <summary>
/// The positions will wrap around from the end to beginning of the <see cref="Curve"/> for determined the value.
/// </summary>
Cycle,
/// <summary>
/// The positions will wrap around from the end to beginning of the <see cref="Curve"/>.
/// The value will be offset by the difference between the values of first and end <see cref="CurveKey"/> multiplied by the wrap amount.
/// If the position is before the beginning of the <see cref="Curve"/> the difference will be subtracted from its value; otherwise the difference will be added.
/// </summary>
CycleOffset,
/// <summary>
/// The value at the end of the <see cref="Curve"/> act as an offset from the same side of the <see cref="Curve"/> toward the opposite side.
/// </summary>
Oscillate,
/// <summary>
/// The linear interpolation will be performed for determined the value.
/// </summary>
Linear
}
}
@@ -0,0 +1,25 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
namespace Microsoft.Xna.Framework
{
/// <summary>
/// Defines the different tangent types to be calculated for <see cref="CurveKey"/> points in a <see cref="Curve"/>.
/// </summary>
public enum CurveTangent
{
/// <summary>
/// The tangent which always has a value equal to zero.
/// </summary>
Flat,
/// <summary>
/// The tangent which contains a difference between current tangent value and the tangent value from the previous <see cref="CurveKey"/>.
/// </summary>
Linear,
/// <summary>
/// The smoouth tangent which contains the inflection between <see cref="CurveKey.TangentIn"/> and <see cref="CurveKey.TangentOut"/> by taking into account the values of both neighbors of the <see cref="CurveKey"/>.
/// </summary>
Smooth
}
}
@@ -0,0 +1,72 @@
// 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.ComponentModel;
using System.Globalization;
namespace Microsoft.Xna.Framework.Design
{
public class Vector2TypeConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (VectorConversion.CanConvertTo(context, destinationType))
return true;
if (destinationType == typeof(string))
return true;
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
var vec = (Vector2)value;
if (VectorConversion.CanConvertTo(context, destinationType))
{
var vec4 = new Vector4(vec.X, vec.Y, 0.0f, 0.0f);
return VectorConversion.ConvertToFromVector4(context, culture, vec4, destinationType);
}
if (destinationType == typeof(string))
{
var terms = new string[2];
terms[0] = vec.X.ToString("R", culture);
terms[1] = vec.Y.ToString("R", culture);
return string.Join(culture.TextInfo.ListSeparator + " ", terms);
}
return base.ConvertTo(context, culture, value, destinationType);
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var sourceType = value.GetType();
var vec = Vector2.Zero;
if (sourceType == typeof(string))
{
var str = (string)value;
var words = str.Split(culture.TextInfo.ListSeparator.ToCharArray());
vec.X = float.Parse(words[0], culture);
vec.Y = float.Parse(words[1], culture);
return vec;
}
return base.ConvertFrom(context, culture, value);
}
}
}
@@ -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.ComponentModel;
using System.Globalization;
namespace Microsoft.Xna.Framework.Design
{
public class Vector3TypeConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (VectorConversion.CanConvertTo(context, destinationType))
return true;
if (destinationType == typeof(string))
return true;
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
var vec = (Vector3)value;
if (VectorConversion.CanConvertTo(context, destinationType))
{
var vec4 = new Vector4(vec.X, vec.Y, vec.Z, 0.0f);
return VectorConversion.ConvertToFromVector4(context, culture, vec4, destinationType);
}
if (destinationType == typeof(string))
{
var terms = new string[3];
terms[0] = vec.X.ToString("R", culture);
terms[1] = vec.Y.ToString("R", culture);
terms[2] = vec.Z.ToString("R", culture);
return string.Join(culture.TextInfo.ListSeparator + " ", terms);
}
return base.ConvertTo(context, culture, value, destinationType);
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var sourceType = value.GetType();
var vec = Vector3.Zero;
if (sourceType == typeof(string))
{
var str = (string)value;
var words = str.Split(culture.TextInfo.ListSeparator.ToCharArray());
vec.X = float.Parse(words[0], culture);
vec.Y = float.Parse(words[1], culture);
vec.Z = float.Parse(words[2], culture);
return vec;
}
return base.ConvertFrom(context, culture, value);
}
}
}
@@ -0,0 +1,76 @@
// 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.ComponentModel;
using System.Globalization;
namespace Microsoft.Xna.Framework.Design
{
public class Vector4TypeConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (VectorConversion.CanConvertTo(context, destinationType))
return true;
if (destinationType == typeof(string))
return true;
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
var vec = (Vector4)value;
if (VectorConversion.CanConvertTo(context, destinationType))
{
return VectorConversion.ConvertToFromVector4(context, culture, vec, destinationType);
}
if (destinationType == typeof(string))
{
var terms = new string[4];
terms[0] = vec.X.ToString("R", culture);
terms[1] = vec.Y.ToString("R", culture);
terms[2] = vec.Z.ToString("R", culture);
terms[3] = vec.W.ToString("R", culture);
return string.Join(culture.TextInfo.ListSeparator + " ", terms);
}
return base.ConvertTo(context, culture, value, destinationType);
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var sourceType = value.GetType();
var vec = Vector4.Zero;
if (sourceType == typeof(string))
{
var str = (string)value;
var words = str.Split(culture.TextInfo.ListSeparator.ToCharArray());
vec.X = float.Parse(words[0], culture);
vec.Y = float.Parse(words[1], culture);
vec.Z = float.Parse(words[2], culture);
vec.W = float.Parse(words[3], culture);
return vec;
}
return base.ConvertFrom(context, culture, value);
}
}
}
@@ -0,0 +1,46 @@
using System;
using System.ComponentModel;
using System.Globalization;
using Microsoft.Xna.Framework.Graphics.PackedVector;
namespace Microsoft.Xna.Framework.Design
{
internal static class VectorConversion
{
public static bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(float))
return true;
if (destinationType == typeof(Vector2))
return true;
if (destinationType == typeof(Vector3))
return true;
if (destinationType == typeof(Vector4))
return true;
if (destinationType.GetInterface("IPackedVector") != null)
return true;
return false;
}
public static object ConvertToFromVector4(ITypeDescriptorContext context, CultureInfo culture, Vector4 value, Type destinationType)
{
if (destinationType == typeof(float))
return value.X;
if (destinationType == typeof(Vector2))
return new Vector2(value.X, value.Y);
if (destinationType == typeof(Vector3))
return new Vector3(value.X, value.Y, value.Z);
if (destinationType == typeof(Vector4))
return new Vector4(value.X, value.Y, value.Z, value.W);
if (destinationType.GetInterface("IPackedVector") != null)
{
var packedVec = (IPackedVector)Activator.CreateInstance(destinationType);
packedVec.PackFromVector4(value);
return packedVec;
}
return null;
}
}
}
@@ -0,0 +1,330 @@
#region License
/*
Microsoft Public License (Ms-PL)
MonoGame - Copyright © 2009 The MonoGame Team
All rights reserved.
This license governs use of the accompanying software. If you use the software, you accept this license. If you do not
accept the license, do not use the software.
1. Definitions
The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under
U.S. copyright law.
A "contribution" is the original software, or any additions or changes to the software.
A "contributor" is any person that distributes its contribution under this license.
"Licensed patents" are a contributor's patent claims that read directly on its contribution.
2. Grant of Rights
(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3,
each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3,
each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
3. Conditions and Limitations
(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software,
your patent license from such contributor to the software ends automatically.
(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution
notices that are present in the software.
(D) If you distribute any portion of the software in source code form, you may do so only under this license by including
a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object
code form, you may only do so under a license that complies with this license.
(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees
or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent
permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular
purpose and non-infringement.
*/
#endregion License
#region Using clause
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Runtime.Remoting.Messaging;
using Microsoft.Xna.Framework.Net;
#endregion Using clause
namespace Microsoft.Xna.Framework.GamerServices
{
public static class Guide
{
private static bool isScreenSaverEnabled;
private static bool isTrialMode;
private static bool isVisible;
private static bool simulateTrialMode;
delegate string ShowKeyboardInputDelegate(
PlayerIndex player,
string title,
string description,
string defaultText,
bool usePasswordMode);
public static string ShowKeyboardInput(
PlayerIndex player,
string title,
string description,
string defaultText,
bool usePasswordMode)
{
throw new NotImplementedException();
}
public static IAsyncResult BeginShowKeyboardInput (
PlayerIndex player,
string title,
string description,
string defaultText,
AsyncCallback callback,
Object state)
{
return BeginShowKeyboardInput(player, title, description, defaultText, callback, state, false );
}
public static IAsyncResult BeginShowKeyboardInput (
PlayerIndex player,
string title,
string description,
string defaultText,
AsyncCallback callback,
Object state,
bool usePasswordMode)
{
return BeginShowKeyboardInput(player, title, description, defaultText, callback, state, false );
}
public static string EndShowKeyboardInput (IAsyncResult result)
{
ShowKeyboardInputDelegate ski = (ShowKeyboardInputDelegate)result.AsyncState;
return ski.EndInvoke(result);
}
delegate Nullable<int> ShowMessageBoxDelegate( string title,
string text,
IEnumerable<string> buttons,
int focusButton,
MessageBoxIcon icon);
public static Nullable<int> ShowMessageBox( string title,
string text,
IEnumerable<string> buttons,
int focusButton,
MessageBoxIcon icon)
{
int? result = null;
IsVisible = true;
IsVisible = false;
return result;
}
public static IAsyncResult BeginShowMessageBox(
PlayerIndex player,
string title,
string text,
IEnumerable<string> buttons,
int focusButton,
MessageBoxIcon icon,
AsyncCallback callback,
Object state
)
{
if (IsVisible)
throw new Exception("The function cannot be completed at this time: the Guide UI is already active. Wait until Guide.IsVisible is false before issuing this call.");
if (player != PlayerIndex.One)
throw new ArgumentOutOfRangeException("player", "Specified argument was out of the range of valid values.");
if (title == null)
throw new ArgumentNullException("title", "This string cannot be null or empty, and must be less than 256 characters long.");
if (text == null)
throw new ArgumentNullException("text", "This string cannot be null or empty, and must be less than 256 characters long.");
if (buttons == null)
throw new ArgumentNullException("buttons", "Value can not be null.");
ShowMessageBoxDelegate smb = ShowMessageBox;
return smb.BeginInvoke(title, text, buttons, focusButton, icon, callback, smb);
}
public static IAsyncResult BeginShowMessageBox (
string title,
string text,
IEnumerable<string> buttons,
int focusButton,
MessageBoxIcon icon,
AsyncCallback callback,
Object state
)
{
return BeginShowMessageBox(PlayerIndex.One, title, text, buttons, focusButton, icon, callback, state);
}
public static Nullable<int> EndShowMessageBox (IAsyncResult result)
{
return ((ShowMessageBoxDelegate)result.AsyncState).EndInvoke(result);
}
public static void ShowMarketplace (PlayerIndex player )
{
}
public static void Show ()
{
ShowSignIn(1, false);
}
public static void ShowSignIn (int paneCount, bool onlineOnly)
{
if ( paneCount != 1 && paneCount != 2 && paneCount != 4)
{
new ArgumentException("paneCount Can only be 1, 2 or 4 on Windows");
return;
}
Microsoft.Xna.Framework.GamerServices.MonoGameGamerServicesHelper.ShowSigninSheet();
if (GamerServicesComponent.LocalNetworkGamer == null)
{
GamerServicesComponent.LocalNetworkGamer = new LocalNetworkGamer();
}
else
{
GamerServicesComponent.LocalNetworkGamer.SignedInGamer.BeginAuthentication(null, null);
}
}
public static void ShowLeaderboard()
{
//if ( ( Gamer.SignedInGamers.Count > 0 ) && ( Gamer.SignedInGamers[0].IsSignedInToLive ) )
//{
// // Lazy load it
// if ( leaderboardController == null )
// {
// leaderboardController = new GKLeaderboardViewController();
// }
// if (leaderboardController != null)
// {
// leaderboardController.DidFinish += delegate(object sender, EventArgs e)
// {
// leaderboardController.DismissModalViewControllerAnimated(true);
// isVisible = false;
// };
// if (Window !=null)
// {
// if(viewController == null)
// {
// viewController = new UIViewController();
// Window.Add(viewController.View);
// viewController.View.Hidden = true;
// }
// viewController.PresentModalViewController(leaderboardController, true);
// isVisible = true;
// }
// }
//}
}
public static void ShowAchievements()
{
//if ( ( Gamer.SignedInGamers.Count > 0 ) && ( Gamer.SignedInGamers[0].IsSignedInToLive ) )
//{
// // Lazy load it
// if ( achievementController == null )
// {
// achievementController = new GKAchievementViewController();
// }
// if (achievementController != null)
// {
// achievementController.DidFinish += delegate(object sender, EventArgs e)
// {
// leaderboardController.DismissModalViewControllerAnimated(true);
// isVisible = false;
// };
// if (Window !=null)
// {
// if(viewController == null)
// {
// viewController = new UIViewController();
// Window.Add(viewController.View);
// viewController.View.Hidden = true;
// }
// viewController.PresentModalViewController(achievementController, true);
// isVisible = true;
// }
// }
//}
}
#region Properties
public static bool IsScreenSaverEnabled
{
get
{
return isScreenSaverEnabled;
}
set
{
isScreenSaverEnabled = value;
}
}
public static bool IsTrialMode
{
get
{
return simulateTrialMode || isTrialMode;
}
}
public static bool IsVisible
{
get
{
return isVisible;
}
set
{
isVisible = value;
}
}
public static bool SimulateTrialMode
{
get
{
return simulateTrialMode;
}
set
{
simulateTrialMode = value;
}
}
public static GameWindow Window
{
get;
set;
}
#endregion
internal static void Initialise(Game game)
{
MonoGameGamerServicesHelper.Initialise(game);
}
}
}
@@ -0,0 +1,151 @@
using System;
using Microsoft.Xna.Framework.Graphics;
namespace Microsoft.Xna.Framework.GamerServices
{
internal class MonoGameGamerServicesHelper
{
private static MonoLiveGuide guide = null;
public static void ShowSigninSheet()
{
guide.Enabled = true;
guide.Visible = true;
Guide.IsVisible = true;
}
internal static void Initialise(Game game)
{
if (guide == null)
{
guide = new MonoLiveGuide(game);
game.Components.Add(guide);
}
}}
internal class MonoLiveGuide : DrawableGameComponent
{
SpriteBatch spriteBatch;
Texture2D signInProgress;
Color alphaColor = new Color(128, 128, 128, 0);
byte startalpha = 0;
public MonoLiveGuide(Game game)
: base(game)
{
this.Enabled = false;
this.Visible = false;
//Guide.IsVisible = false;
this.DrawOrder = Int32.MaxValue;
}
public override void Initialize()
{
base.Initialize();
}
Texture2D Circle(GraphicsDevice graphics, int radius)
{
int aDiameter = radius * 2;
Vector2 aCenter = new Vector2(radius, radius);
Texture2D aCircle = new Texture2D(graphics, aDiameter, aDiameter, false, SurfaceFormat.Color);
Color[] aColors = new Color[aDiameter * aDiameter];
for (int i = 0; i < aColors.Length; i++)
{
int x = (i + 1) % aDiameter;
int y = (i + 1) / aDiameter;
Vector2 aDistance = new Vector2(Math.Abs(aCenter.X - x), Math.Abs(aCenter.Y - y));
if (Math.Sqrt((aDistance.X * aDistance.X) + (aDistance.Y * aDistance.Y)) > radius)
{
aColors[i] = Color.Transparent;
}
else
{
aColors[i] = Color.White;
}
}
aCircle.SetData<Color>(aColors);
return aCircle;
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(this.Game.GraphicsDevice);
signInProgress = Circle(this.Game.GraphicsDevice, 10);
base.LoadContent();
}
protected override void UnloadContent()
{
base.UnloadContent();
}
public override void Draw(GameTime gameTime)
{
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
Vector2 center = new Vector2(this.Game.GraphicsDevice.PresentationParameters.BackBufferWidth / 2, this.Game.GraphicsDevice.PresentationParameters.BackBufferHeight - 100);
Vector2 loc = Vector2.Zero;
alphaColor.A = startalpha;
for (int i = 0; i < 12; i++)
{
float angle = (float)(i / 12.0 * Math.PI * 2);
loc = new Vector2(center.X + (float)Math.Cos(angle) * 50, center.Y + (float)Math.Sin(angle) * 50);
spriteBatch.Draw(signInProgress, loc, alphaColor);
alphaColor.A += 255 / 12;
if (alphaColor.A > 255) alphaColor.A = 0;
}
spriteBatch.End();
base.Draw(gameTime);
}
TimeSpan gt = TimeSpan.Zero;
TimeSpan last = TimeSpan.Zero;
public override void Update(GameTime gameTime)
{
if (gt == TimeSpan.Zero) gt = last = gameTime.TotalGameTime;
if ((gameTime.TotalGameTime - last).Milliseconds > 100)
{
last = gameTime.TotalGameTime;
startalpha += 255 / 12;
}
if ((gameTime.TotalGameTime - gt).TotalSeconds > 5) // close after 10 seconds
{
string strUsr = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
if (strUsr.Contains(@"\"))
{
int idx = strUsr.IndexOf(@"\") + 1;
strUsr = strUsr.Substring(idx, strUsr.Length - idx);
}
SignedInGamer sig = new SignedInGamer();
sig.DisplayName = strUsr;
sig.Gamertag = strUsr;
Gamer.SignedInGamers.Add(sig);
this.Visible = false;
this.Enabled = false;
//Guide.IsVisible = false;
gt = TimeSpan.Zero;
}
base.Update(gameTime);
}
}
}
@@ -0,0 +1,327 @@
#region License
/*
Microsoft Public License (Ms-PL)
MonoGame - Copyright © 2009 The MonoGame Team
All rights reserved.
This license governs use of the accompanying software. If you use the software, you accept this license. If you do not
accept the license, do not use the software.
1. Definitions
The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under
U.S. copyright law.
A "contribution" is the original software, or any additions or changes to the software.
A "contributor" is any person that distributes its contribution under this license.
"Licensed patents" are a contributor's patent claims that read directly on its contribution.
2. Grant of Rights
(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3,
each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3,
each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
3. Conditions and Limitations
(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software,
your patent license from such contributor to the software ends automatically.
(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution
notices that are present in the software.
(D) If you distribute any portion of the software in source code form, you may do so only under this license by including
a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object
code form, you may only do so under a license that complies with this license.
(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees
or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent
permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular
purpose and non-infringement.
*/
#endregion License
#region Statement
using System;
#endregion Statement
namespace Microsoft.Xna.Framework.GamerServices
{
public class SignedInGamer : Gamer
{
private AchievementCollection gamerAchievements;
private FriendCollection friendCollection;
delegate void AuthenticationDelegate();
public IAsyncResult BeginAuthentication(AsyncCallback callback, Object asyncState)
{
// Go off authenticate
AuthenticationDelegate ad = DoAuthentication;
return ad.BeginInvoke(callback, ad);
}
public void EndAuthentication( IAsyncResult result )
{
AuthenticationDelegate ad = (AuthenticationDelegate)result.AsyncState;
ad.EndInvoke(result);
}
private void DoAuthentication()
{
}
public SignedInGamer()
{
var result = BeginAuthentication(null, null);
EndAuthentication( result );
}
private void AuthenticationCompletedCallback( IAsyncResult result )
{
EndAuthentication(result);
}
#region Methods
public FriendCollection GetFriends()
{
if(IsSignedInToLive)
{
if ( friendCollection == null )
{
friendCollection = new FriendCollection();
}
}
return friendCollection;
}
public bool IsFriend (Gamer gamer)
{
if ( gamer == null )
throw new ArgumentNullException();
if ( gamer.IsDisposed )
throw new ObjectDisposedException(gamer.ToString());
bool found = false;
foreach(FriendGamer f in friendCollection)
{
if ( f.Gamertag == gamer.Gamertag )
{
found = true;
}
}
return found;
}
delegate AchievementCollection GetAchievementsDelegate();
public IAsyncResult BeginGetAchievements( AsyncCallback callback, Object asyncState)
{
// Go off and grab achievements
GetAchievementsDelegate gad = GetAchievements;
return gad.BeginInvoke(callback, gad);
}
private void GetAchievementCompletedCallback( IAsyncResult result )
{
// get the delegate that was used to call that method
GetAchievementsDelegate gad = (GetAchievementsDelegate)result.AsyncState;
// get the return value from that method call
gamerAchievements = gad.EndInvoke(result);
}
public AchievementCollection EndGetAchievements( IAsyncResult result )
{
GetAchievementsDelegate gad = (GetAchievementsDelegate)result.AsyncState;
gamerAchievements = gad.EndInvoke(result);
return gamerAchievements;
}
public AchievementCollection GetAchievements()
{
if ( IsSignedInToLive )
{
if (gamerAchievements == null)
{
gamerAchievements = new AchievementCollection();
}
}
return gamerAchievements;
}
delegate void AwardAchievementDelegate(string achievementId, double percentageComplete);
public IAsyncResult BeginAwardAchievement(string achievementId, AsyncCallback callback, Object state)
{
return BeginAwardAchievement(achievementId, 100.0, callback, state);
}
public IAsyncResult BeginAwardAchievement(
string achievementId,
double percentageComplete,
AsyncCallback callback,
Object state
)
{
// Go off and award the achievement
AwardAchievementDelegate aad = DoAwardAchievement;
return aad.BeginInvoke(achievementId, percentageComplete, callback, aad);
}
public void EndAwardAchievement(IAsyncResult result)
{
AwardAchievementDelegate aad = (AwardAchievementDelegate)result.AsyncState;
aad.EndInvoke(result);
}
private void AwardAchievementCompletedCallback( IAsyncResult result )
{
EndAwardAchievement(result);
}
public void AwardAchievement( string achievementId )
{
AwardAchievement(achievementId, 100.0f);
}
public void DoAwardAchievement( string achievementId, double percentageComplete )
{
}
public void AwardAchievement( string achievementId, double percentageComplete )
{
if (IsSignedInToLive)
{
BeginAwardAchievement( achievementId, percentageComplete, AwardAchievementCompletedCallback, null );
}
}
public void UpdateScore( string aCategory, long aScore )
{
if (IsSignedInToLive)
{
}
}
public void ResetAchievements()
{
if (IsSignedInToLive)
{
}
}
#endregion
#region Properties
public GameDefaults GameDefaults
{
get
{
throw new NotSupportedException();
}
}
public bool IsGuest
{
get
{
throw new NotSupportedException();
}
}
public bool IsSignedInToLive
{
get
{
return false;
}
}
public int PartySize
{
get
{
throw new NotSupportedException();
}
set
{
throw new NotSupportedException();
}
}
public PlayerIndex PlayerIndex
{
get
{
return PlayerIndex.One;
}
}
public GamerPresence Presence
{
get
{
throw new NotSupportedException();
}
}
GamerPrivileges _privileges = new GamerPrivileges();
public GamerPrivileges Privileges
{
get
{
return _privileges;
}
}
#endregion
protected virtual void OnSignedIn(SignedInEventArgs e)
{
EventHelpers.Raise(this, SignedIn, e);
}
protected virtual void OnSignedOut(SignedOutEventArgs e)
{
EventHelpers.Raise(this, SignedOut, e);
}
#region Events
public static event EventHandler<SignedInEventArgs> SignedIn;
public static event EventHandler<SignedOutEventArgs> SignedOut;
#endregion
}
public class SignedInEventArgs : EventArgs
{
public SignedInEventArgs ( SignedInGamer gamer )
{
}
}
public class SignedOutEventArgs : EventArgs
{
public SignedOutEventArgs (SignedInGamer gamer )
{
}
}
}
@@ -0,0 +1,40 @@
// 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
{
/// <summary>
/// Defines the orientation of the display.
/// </summary>
[Flags]
public enum DisplayOrientation
{
/// <summary>
/// The default orientation.
/// </summary>
Default = 0,
/// <summary>
/// The display is rotated counterclockwise into a landscape orientation. Width is greater than height.
/// </summary>
LandscapeLeft = 1,
/// <summary>
/// The display is rotated clockwise into a landscape orientation. Width is greater than height.
/// </summary>
LandscapeRight = 2,
/// <summary>
/// The display is rotated as portrait, where height is greater than width.
/// </summary>
Portrait = 4,
/// <summary>
/// The display is rotated as inverted portrait, where height is greater than width.
/// </summary>
PortraitDown = 8,
/// <summary>
/// Unknown display orientation.
/// </summary>
Unknown = 16
}
}
@@ -0,0 +1,79 @@
// 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
{
public class DrawableGameComponent : GameComponent, IDrawable
{
private bool _initialized;
private int _drawOrder;
private bool _visible = true;
public Graphics.GraphicsDevice GraphicsDevice
{
get { return this.Game.GraphicsDevice; }
}
public int DrawOrder
{
get { return _drawOrder; }
set
{
if (_drawOrder != value)
{
_drawOrder = value;
OnDrawOrderChanged(this, EventArgs.Empty);
}
}
}
public bool Visible
{
get { return _visible; }
set
{
if (_visible != value)
{
_visible = value;
OnVisibleChanged(this, EventArgs.Empty);
}
}
}
public event EventHandler<EventArgs> DrawOrderChanged;
public event EventHandler<EventArgs> VisibleChanged;
public DrawableGameComponent(Game game)
: base(game)
{
}
public override void Initialize()
{
if (!_initialized)
{
_initialized = true;
LoadContent();
}
}
protected virtual void LoadContent() { }
protected virtual void UnloadContent () { }
public virtual void Draw(GameTime gameTime) { }
protected virtual void OnVisibleChanged(object sender, EventArgs args)
{
EventHelpers.Raise(sender, VisibleChanged, args);
}
protected virtual void OnDrawOrderChanged(object sender, EventArgs args)
{
EventHelpers.Raise(sender, DrawOrderChanged, args);
}
}
}
@@ -0,0 +1,45 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
namespace Microsoft.Xna.Framework
{
/// <summary>
/// Provides helper methods to make it easier
/// to safely raise events.
/// </summary>
internal static class EventHelpers
{
/// <summary>
/// Safely raises an event by storing a copy of the event's delegate
/// in the <paramref name="handler"/> parameter and checking it for
/// null before invoking it.
/// </summary>
/// <typeparam name="TEventArgs"></typeparam>
/// <param name="sender">The object raising the event.</param>
/// <param name="handler"><see cref="EventHandler{TEventArgs}"/> to be invoked</param>
/// <param name="e">The <typeparamref name="TEventArgs"/> passed to <see cref="EventHandler{TEventArgs}"/></param>
internal static void Raise<TEventArgs>(object sender, EventHandler<TEventArgs> handler, TEventArgs e)
where TEventArgs : EventArgs
{
if (handler != null)
handler(sender, e);
}
/// <summary>
/// Safely raises an event by storing a copy of the event's delegate
/// in the <paramref name="handler"/> parameter and checking it for
/// null before invoking it.
/// </summary>
/// <param name="sender">The object raising the event.</param>
/// <param name="handler"><see cref="EventHandler"/> to be invoked</param>
/// <param name="e">The <see cref="EventArgs"/> passed to <see cref="EventHandler"/></param>
internal static void Raise(object sender, EventHandler handler, EventArgs e)
{
if (handler != null)
handler(sender, e);
}
}
}
@@ -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;
using Microsoft.Xna.Framework.Audio;
namespace Microsoft.Xna.Framework
{
/// <summary>
/// Helper class for processing internal framework events.
/// </summary>
/// <remarks>
/// If you use <see cref="Game"/> class, <see cref="Update()"/> is called automatically.
/// Otherwise you must call it as part of your game loop.
/// </remarks>
public static class FrameworkDispatcher
{
private static bool _initialized = false;
/// <summary>
/// Processes framework events.
/// </summary>
public static void Update()
{
if (!_initialized)
Initialize();
DoUpdate();
}
private static void DoUpdate()
{
}
private static void Initialize()
{
_initialized = true;
}
}
}
@@ -0,0 +1,15 @@
// 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
{
internal static class FrameworkResources
{
#region Error strings
internal const string ResourceCreationWhenDeviceIsNull = "The GraphicsDevice must not be null when creating new resources.";
#endregion
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,92 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
namespace Microsoft.Xna.Framework
{
public class GameComponent : IGameComponent, IUpdateable, IComparable<GameComponent>, IDisposable
{
bool _enabled = true;
int _updateOrder;
public Game Game { get; private set; }
public bool Enabled
{
get { return _enabled; }
set
{
if (_enabled != value)
{
_enabled = value;
OnEnabledChanged(this, EventArgs.Empty);
}
}
}
public int UpdateOrder
{
get { return _updateOrder; }
set
{
if (_updateOrder != value)
{
_updateOrder = value;
OnUpdateOrderChanged(this, EventArgs.Empty);
}
}
}
public event EventHandler<EventArgs> EnabledChanged;
public event EventHandler<EventArgs> UpdateOrderChanged;
public GameComponent(Game game)
{
this.Game = game;
}
~GameComponent()
{
Dispose(false);
}
public virtual void Initialize() { }
public virtual void Update(GameTime gameTime) { }
protected virtual void OnUpdateOrderChanged(object sender, EventArgs args)
{
EventHelpers.Raise(sender, UpdateOrderChanged, args);
}
protected virtual void OnEnabledChanged(object sender, EventArgs args)
{
EventHelpers.Raise(sender, EnabledChanged, args);
}
/// <summary>
/// Shuts down the component.
/// </summary>
protected virtual void Dispose(bool disposing) { }
/// <summary>
/// Shuts down the component.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#region IComparable<GameComponent> Members
// TODO: Should be removed, as it is not part of XNA 4.0
public int CompareTo(GameComponent other)
{
return other.UpdateOrder - this.UpdateOrder;
}
#endregion
}
}
@@ -0,0 +1,76 @@
// 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.ObjectModel;
namespace Microsoft.Xna.Framework
{
public sealed class GameComponentCollection : Collection<IGameComponent>
{
/// <summary>
/// Event that is triggered when a <see cref="GameComponent"/> is added
/// to this <see cref="GameComponentCollection"/>.
/// </summary>
public event EventHandler<GameComponentCollectionEventArgs> ComponentAdded;
/// <summary>
/// Event that is triggered when a <see cref="GameComponent"/> is removed
/// from this <see cref="GameComponentCollection"/>.
/// </summary>
public event EventHandler<GameComponentCollectionEventArgs> ComponentRemoved;
/// <summary>
/// Removes every <see cref="GameComponent"/> from this <see cref="GameComponentCollection"/>.
/// Triggers <see cref="OnComponentRemoved"/> once for each <see cref="GameComponent"/> removed.
/// </summary>
protected override void ClearItems()
{
for (int i = 0; i < base.Count; i++)
{
this.OnComponentRemoved(new GameComponentCollectionEventArgs(base[i]));
}
base.ClearItems();
}
protected override void InsertItem(int index, IGameComponent item)
{
if (base.IndexOf(item) != -1)
{
throw new ArgumentException("Cannot Add Same Component Multiple Times");
}
base.InsertItem(index, item);
if (item != null)
{
this.OnComponentAdded(new GameComponentCollectionEventArgs(item));
}
}
private void OnComponentAdded(GameComponentCollectionEventArgs eventArgs)
{
EventHelpers.Raise(this, ComponentAdded, eventArgs);
}
private void OnComponentRemoved(GameComponentCollectionEventArgs eventArgs)
{
EventHelpers.Raise(this, ComponentRemoved, eventArgs);
}
protected override void RemoveItem(int index)
{
IGameComponent gameComponent = base[index];
base.RemoveItem(index);
if (gameComponent != null)
{
this.OnComponentRemoved(new GameComponentCollectionEventArgs(gameComponent));
}
}
protected override void SetItem(int index, IGameComponent item)
{
throw new NotSupportedException();
}
}
}
@@ -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;
namespace Microsoft.Xna.Framework
{
public class GameComponentCollectionEventArgs : EventArgs
{
private IGameComponent _gameComponent;
public GameComponentCollectionEventArgs(IGameComponent gameComponent)
{
_gameComponent = gameComponent;
}
public IGameComponent GameComponent
{
get
{
return _gameComponent;
}
}
}
}
@@ -0,0 +1,24 @@
// 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;
#if WINDOWS_UAP
using Windows.UI.ViewManagement;
#endif
namespace Microsoft.Xna.Framework
{
partial class GamePlatform
{
internal static GamePlatform PlatformCreate(Game game)
{
#if DESKTOPGL || ANGLE || WINDOWS
return new SdlGamePlatform(game);
#elif WINDOWS_UAP
return new UAPGamePlatform(game);
#endif
}
}
}
@@ -0,0 +1,24 @@
// 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
{
partial class GamePlatform
{
internal static GamePlatform PlatformCreate(Game game)
{
#if IOS
return new iOSGamePlatform(game);
#elif ANDROID
return new AndroidGamePlatform(game);
#elif WINDOWS_PHONE81
return new MetroGamePlatform(game);
#elif WEB
return new WebGamePlatform(game);
#endif
}
}
}
@@ -0,0 +1,296 @@
// 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.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
namespace Microsoft.Xna.Framework
{
abstract partial class GamePlatform : IDisposable
{
#region Fields
protected TimeSpan _inactiveSleepTime = TimeSpan.FromMilliseconds(20.0);
protected bool _needsToResetElapsedTime = false;
bool disposed;
protected bool InFullScreenMode = false;
protected bool IsDisposed { get { return disposed; } }
#endregion
#region Construction/Destruction
protected GamePlatform(Game game)
{
if (game == null)
throw new ArgumentNullException("game");
Game = game;
}
~GamePlatform()
{
Dispose(false);
}
#endregion Construction/Destruction
#region Public Properties
/// <summary>
/// When implemented in a derived class, reports the default
/// GameRunBehavior for this platform.
/// </summary>
public abstract GameRunBehavior DefaultRunBehavior { get; }
/// <summary>
/// Gets the Game instance that owns this GamePlatform instance.
/// </summary>
public Game Game
{
get; private set;
}
private bool _isActive;
public bool IsActive
{
get { return _isActive; }
internal set
{
if (_isActive != value)
{
_isActive = value;
EventHelpers.Raise(this, _isActive ? Activated : Deactivated, EventArgs.Empty);
}
}
}
private bool _isMouseVisible;
public bool IsMouseVisible
{
get { return _isMouseVisible; }
set
{
if (_isMouseVisible != value)
{
_isMouseVisible = value;
OnIsMouseVisibleChanged();
}
}
}
private GameWindow _window;
public GameWindow Window
{
get { return _window; }
protected set
{
if (_window == null)
{
Mouse.PrimaryWindow = value;
TouchPanel.PrimaryWindow = value;
}
_window = value;
}
}
#endregion
#region Events
public event EventHandler<EventArgs> AsyncRunLoopEnded;
public event EventHandler<EventArgs> Activated;
public event EventHandler<EventArgs> Deactivated;
/// <summary>
/// Raises the AsyncRunLoopEnded event. This method must be called by
/// derived classes when the asynchronous run loop they start has
/// stopped running.
/// </summary>
protected void RaiseAsyncRunLoopEnded()
{
EventHelpers.Raise(this, AsyncRunLoopEnded, EventArgs.Empty);
}
#endregion Events
#region Methods
/// <summary>
/// Gives derived classes an opportunity to do work before any
/// components are initialized. Note that the base implementation sets
/// IsActive to true, so derived classes should either call the base
/// implementation or set IsActive to true by their own means.
/// </summary>
public virtual void BeforeInitialize()
{
IsActive = true;
}
/// <summary>
/// Gives derived classes an opportunity to do work just before the
/// run loop is begun. Implementations may also return false to prevent
/// the run loop from starting.
/// </summary>
/// <returns></returns>
public virtual bool BeforeRun()
{
return true;
}
/// <summary>
/// When implemented in a derived, ends the active run loop.
/// </summary>
public abstract void Exit();
/// <summary>
/// When implemented in a derived, starts the run loop and blocks
/// until it has ended.
/// </summary>
public abstract void RunLoop();
/// <summary>
/// When implemented in a derived, starts the run loop and returns
/// immediately.
/// </summary>
public abstract void StartRunLoop();
/// <summary>
/// Gives derived classes an opportunity to do work just before Update
/// is called for all IUpdatable components. Returning false from this
/// method will result in this round of Update calls being skipped.
/// </summary>
/// <param name="gameTime"></param>
/// <returns></returns>
public abstract bool BeforeUpdate(GameTime gameTime);
/// <summary>
/// Gives derived classes an opportunity to do work just before Draw
/// is called for all IDrawable components. Returning false from this
/// method will result in this round of Draw calls being skipped.
/// </summary>
/// <param name="gameTime"></param>
/// <returns></returns>
public abstract bool BeforeDraw(GameTime gameTime);
/// <summary>
/// When implemented in a derived class, causes the game to enter
/// full-screen mode.
/// </summary>
public abstract void EnterFullScreen();
/// <summary>
/// When implemented in a derived class, causes the game to exit
/// full-screen mode.
/// </summary>
public abstract void ExitFullScreen();
/// <summary>
/// Gives derived classes an opportunity to modify
/// Game.TargetElapsedTime before it is set.
/// </summary>
/// <param name="value">The proposed new value of TargetElapsedTime.</param>
/// <returns>The new value of TargetElapsedTime that will be set.</returns>
public virtual TimeSpan TargetElapsedTimeChanging(TimeSpan value)
{
return value;
}
/// <summary>
/// Starts a device transition (windowed to full screen or vice versa).
/// </summary>
/// <param name='willBeFullScreen'>
/// Specifies whether the device will be in full-screen mode upon completion of the change.
/// </param>
public abstract void BeginScreenDeviceChange (
bool willBeFullScreen
);
/// <summary>
/// Completes a device transition.
/// </summary>
/// <param name='screenDeviceName'>
/// Screen device name.
/// </param>
/// <param name='clientWidth'>
/// The new width of the game's client window.
/// </param>
/// <param name='clientHeight'>
/// The new height of the game's client window.
/// </param>
public abstract void EndScreenDeviceChange (
string screenDeviceName,
int clientWidth,
int clientHeight
);
/// <summary>
/// Gives derived classes an opportunity to take action after
/// Game.TargetElapsedTime has been set.
/// </summary>
public virtual void TargetElapsedTimeChanged() {}
/// <summary>
/// MSDN: Use this method if your game is recovering from a slow-running state, and ElapsedGameTime is too large to be useful.
/// Frame timing is generally handled by the Game class, but some platforms still handle it elsewhere. Once all platforms
/// rely on the Game class's functionality, this method and any overrides should be removed.
/// </summary>
public virtual void ResetElapsedTime() {}
public virtual void Present() { }
protected virtual void OnIsMouseVisibleChanged() {}
/// <summary>
/// Called by the GraphicsDeviceManager to notify the platform
/// that the presentation parameters have changed.
/// </summary>
/// <param name="pp">The new presentation parameters.</param>
internal virtual void OnPresentationChanged(PresentationParameters pp)
{
}
#endregion Methods
#region IDisposable implementation
/// <summary>
/// Performs application-defined tasks associated with freeing,
/// releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
Mouse.PrimaryWindow = null;
TouchPanel.PrimaryWindow = null;
disposed = true;
}
}
/// <summary>
/// Log the specified Message.
/// </summary>
/// <param name='Message'>
///
/// </param>
[System.Diagnostics.Conditional("DEBUG")]
public virtual void Log(string Message) {}
#endregion
}
}
@@ -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.
namespace Microsoft.Xna.Framework
{
/// <summary>
/// Defines how <see cref="Game"/> should be runned.
/// </summary>
public enum GameRunBehavior
{
/// <summary>
/// The game loop will be runned asynchronous.
/// </summary>
Asynchronous,
/// <summary>
/// The game loop will be runned synchronous.
/// </summary>
Synchronous
}
}
@@ -0,0 +1,67 @@
// MIT License - Copyright (C) The Mono.Xna 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 MonoGame.Utilities;
namespace Microsoft.Xna.Framework
{
public class GameServiceContainer : IServiceProvider
{
Dictionary<Type, object> services;
public GameServiceContainer()
{
services = new Dictionary<Type, object>();
}
public void AddService(Type type, object provider)
{
if (type == null)
throw new ArgumentNullException("type");
if (provider == null)
throw new ArgumentNullException("provider");
if (!ReflectionHelpers.IsAssignableFrom(type, provider))
throw new ArgumentException("The provider does not match the specified service type!");
services.Add(type, provider);
}
public object GetService(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
object service;
if (services.TryGetValue(type, out service))
return service;
return null;
}
public void RemoveService(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
services.Remove(type);
}
public void AddService<T>(T provider)
{
AddService(typeof(T), provider);
}
public T GetService<T>() where T : class
{
var service = GetService(typeof(T));
if (service == null)
return null;
return (T)service;
}
}
}

Some files were not shown because too many files have changed in this diff Show More