Browse Source
* Removed System.Numerics.Vectors dependency. Implemented basic Vector2<T> type to replace it. * ScalingQuality can now be changed for each canvas independently, as well as for the rendering target texture. * Point type is now based on the new Vector2<T> generic.improved_timing
Ian Burgmyer
5 years ago
11 changed files with 420 additions and 83 deletions
@ -0,0 +1,18 @@ |
|||||||
|
using System; |
||||||
|
|
||||||
|
namespace DotSDL.Exceptions { |
||||||
|
/// <summary> |
||||||
|
/// This <see cref="Exception"/> is thrown when an invalid type is used for |
||||||
|
/// a genetic class or method. |
||||||
|
/// </summary> |
||||||
|
public class InvalidTypeException : Exception { |
||||||
|
/// <summary> |
||||||
|
/// Initializes an <see cref="InvalidTypeException"/>. |
||||||
|
/// </summary> |
||||||
|
/// <param name="objectName">The class or method that was called.</param> |
||||||
|
/// <param name="invalidType">The invalid type that was passed.</param> |
||||||
|
/// <param name="message">A message that should be appended to the base message.</param> |
||||||
|
public InvalidTypeException(string objectName, Type invalidType, string message = "") |
||||||
|
: base($"{objectName} cannot accept the type {nameof(invalidType)}" + message != "" ? $" ({message})" : "") { } |
||||||
|
} |
||||||
|
} |
@ -1,61 +1,67 @@ |
|||||||
using DotSDL.Interop.Core; |
using DotSDL.Interop.Core; |
||||||
|
using DotSDL.Math.Vector; |
||||||
|
|
||||||
namespace DotSDL.Graphics { |
namespace DotSDL.Graphics { |
||||||
/// <summary> |
/// <summary> |
||||||
/// Represents a point in 2D space. |
/// Represents a point in 2D space. |
||||||
/// </summary> |
/// </summary> |
||||||
public class Point { |
public class Point : Vector2<int> { |
||||||
/// <summary> |
/// <summary> |
||||||
/// The base <see cref="SdlPoint"/> structure that this class wraps around. |
/// The base <see cref="SdlPoint"/> structure that this class wraps around. |
||||||
/// </summary> |
/// </summary> |
||||||
internal Rect.SdlPoint SdlPoint; |
internal Rect.SdlPoint SdlPoint => new Rect.SdlPoint { X = X, Y = Y }; |
||||||
|
|
||||||
/// <summary> |
/// <summary> |
||||||
/// Returns a <see cref="Point"/> with the coordinates (1, 1). |
/// Returns a <see cref="Point"/> with the coordinates (1, 1). |
||||||
/// </summary> |
/// </summary> |
||||||
public static Point One => new Point(1, 1); |
public new static Point One => new Point(1, 1); |
||||||
|
|
||||||
/// <summary> |
/// <summary> |
||||||
/// Returns a <see cref="Point"/> with the coordinates (1, 0). |
/// Returns a <see cref="Point"/> with the coordinates (1, 0). |
||||||
/// </summary> |
/// </summary> |
||||||
public static Point UnitX => new Point(1, 0); |
public new static Point UnitX => new Point(1, 0); |
||||||
|
|
||||||
/// <summary> |
/// <summary> |
||||||
/// Returns a <see cref="Point"/> with the coordinates (0, 1). |
/// Returns a <see cref="Point"/> with the coordinates (0, 1). |
||||||
/// </summary> |
/// </summary> |
||||||
public static Point UnitY => new Point(0, 1); |
public new static Point UnitY => new Point(0, 1); |
||||||
|
|
||||||
/// <summary> |
/// <summary> |
||||||
/// Returns a <see cref="Point"/> with the coordinates (0, 0). |
/// Returns a <see cref="Point"/> with the coordinates (0, 0). |
||||||
/// </summary> |
/// </summary> |
||||||
public static Point Zero => new Point(0, 0); |
public new static Point Zero => new Point(0, 0); |
||||||
|
|
||||||
/// <summary> |
/// <summary> |
||||||
/// The X coordinate of the point. |
/// Creates a new <see cref="Point"/> with the coordinates (0, 0). |
||||||
/// </summary> |
/// </summary> |
||||||
public int X { |
public Point() : this(Zero) { } |
||||||
get => SdlPoint.X; |
|
||||||
set => SdlPoint.X = value; |
/// <summary> |
||||||
|
/// Creates a new <see cref="Point"/> based on an existing <see cref="Point"/>. |
||||||
|
/// </summary> |
||||||
|
/// <param name="point">The <see cref="Point"/> to base this new object on.</param> |
||||||
|
public Point(Point point) { |
||||||
|
X = point.X; |
||||||
|
Y = point.Y; |
||||||
} |
} |
||||||
|
|
||||||
/// <summary> |
/// <summary> |
||||||
/// The Y coordinate of the point. |
/// Creates a new <see cref="Point"/> based on an existing <see cref="Vector2{T}"/>. |
||||||
/// </summary> |
/// </summary> |
||||||
public int Y { |
/// <param name="vec">The <see cref="Vector2{T}"/> to based this new object on.</param> |
||||||
get => SdlPoint.Y; |
public Point(Vector2<int> vec) { |
||||||
set => SdlPoint.Y = value; |
X = vec.X; |
||||||
|
Y = vec.Y; |
||||||
} |
} |
||||||
|
|
||||||
/// <summary> |
/// <summary> |
||||||
/// Creates a new <see cref="Point"/>. |
/// Creates a new <see cref="Point"/> based on integer coordinates. |
||||||
/// </summary> |
/// </summary> |
||||||
/// <param name="x">The X value of the new <see cref="Point"/>.</param> |
/// <param name="x">The X coordinate of the new <see cref="Point"/>.</param> |
||||||
/// <param name="y">The Y value of the new <see cref="Point"/>.</param> |
/// <param name="y">The Y coordinate of the new <see cref="Point"/>.</param> |
||||||
public Point(int x = 0, int y = 0) { |
public Point(int x, int y) { |
||||||
SdlPoint = new Rect.SdlPoint { |
X = x; |
||||||
X = x, |
Y = y; |
||||||
Y = y |
|
||||||
}; |
|
||||||
} |
} |
||||||
} |
} |
||||||
} |
} |
||||||
|
@ -0,0 +1,112 @@ |
|||||||
|
using DotSDL.Exceptions; |
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
|
||||||
|
namespace DotSDL.Math.Vector { |
||||||
|
/// <summary> |
||||||
|
/// Represents a generic vector type. |
||||||
|
/// </summary> |
||||||
|
public class Vector2<T> : IEquatable<Vector2<T>> { |
||||||
|
public T X { get; set; } |
||||||
|
public T Y { get; set; } |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Initializes a new <see cref="Vector2{T}"/> object. |
||||||
|
/// </summary> |
||||||
|
/// <exception cref="InvalidTypeException">Thrown if this <see cref="Vector2{T}"/> is created with an unsupported type.</exception> |
||||||
|
public Vector2() { |
||||||
|
if(!VectorBase<T>.IsNumericType()) |
||||||
|
throw new InvalidTypeException(GetType().ToString(), typeof(T)); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Initializes a new <see cref="Vector2{T}"/> object using the values from another <see cref="Vector2{T}"/>. |
||||||
|
/// </summary> |
||||||
|
/// <param name="initialValue">The <see cref="Vector2{T}"/> that should be used to initialize the new object.</param> |
||||||
|
/// <exception cref="InvalidTypeException">Thrown if this <see cref="Vector2{T}"/> is created with an unsupported type.</exception> |
||||||
|
public Vector2(Vector2<T> initialValue) : this() { |
||||||
|
X = initialValue.X; |
||||||
|
Y = initialValue.Y; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Initializes a new <see cref="Vector2{T}"/> object with the X and Y values both set to a given value. |
||||||
|
/// </summary> |
||||||
|
/// <param name="initialValue">The value to initialize the X and Y values to.</param> |
||||||
|
/// <exception cref="InvalidTypeException">Thrown if this <see cref="Vector2{T}"/> is created with an unsupported type.</exception> |
||||||
|
public Vector2(T initialValue) : this() { |
||||||
|
X = Y = initialValue; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Initializes a new <see cref="Vector2{T}"/> object with preset X and Y values. |
||||||
|
/// </summary> |
||||||
|
/// <param name="initialX">The initial value to set the X component to.</param> |
||||||
|
/// <param name="initialY">The initial value to set the Y component to.</param> |
||||||
|
/// <exception cref="InvalidTypeException">Thrown if this <see cref="Vector2{T}"/> is created with an unsupported type.</exception> |
||||||
|
public Vector2(T initialX, T initialY) : this() { |
||||||
|
X = initialX; |
||||||
|
Y = initialY; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Checks to see if two <see cref="Vector2{T}"/> objects are equal. |
||||||
|
/// </summary> |
||||||
|
/// <param name="left">The first <see cref="Vector2{T}"/> in the comparison.</param> |
||||||
|
/// <param name="right">The second <see cref="Vector2{T}"/> in the comparison.</param> |
||||||
|
/// <returns><c>true</c> if the two <see cref="Vector2{T}"/> objects are equal, otherwise <c>false</c>.</returns> |
||||||
|
public static bool operator ==(Vector2<T> left, Vector2<T> right) { |
||||||
|
if(left is null && right is null) return true; |
||||||
|
if(left is null || right is null) return false; |
||||||
|
if(left.GetType() != right.GetType()) return false; |
||||||
|
|
||||||
|
return left.X.Equals(right.X) && left.Y.Equals(right.Y); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Checks to see if two <see cref="Vector2{T}"/> objects are different. |
||||||
|
/// </summary> |
||||||
|
/// <param name="left">The first <see cref="Vector2{T}"/> in the comparison.</param> |
||||||
|
/// <param name="right">The second <see cref="Vector2{T}"/> in the comparison.</param> |
||||||
|
/// <returns><c>true</c> if the two <see cref="Vector2{T}"/> objects are different, otherwise <c>false</c>.</returns> |
||||||
|
public static bool operator !=(Vector2<T> left, Vector2<T> right) { |
||||||
|
return !(left == right); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>Returns a new <see cref="Vector2{T}"/> with both X and Y set to 1.</summary> |
||||||
|
public static Vector2<T> One => new Vector2<T>(VectorBase<T>.GetOne()); |
||||||
|
|
||||||
|
/// <summary>Returns a new <see cref="Vector2{T}"/> containing (1, 0).</summary> |
||||||
|
public static Vector2<T> UnitX => new Vector2<T>(VectorBase<T>.GetOne(), VectorBase<T>.GetZero()); |
||||||
|
|
||||||
|
/// <summary>Returns a new <see cref="Vector2{T}"/> containing (0, 1).</summary> |
||||||
|
public static Vector2<T> UnitY => new Vector2<T>(VectorBase<T>.GetZero(), VectorBase<T>.GetOne()); |
||||||
|
|
||||||
|
/// <summary>Returns a new <see cref="Vector2{T}"/> with both X and Y set to 0.</summary> |
||||||
|
public static Vector2<T> Zero => new Vector2<T>(VectorBase<T>.GetZero()); |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public bool Equals(Vector2<T> other) { |
||||||
|
if(ReferenceEquals(null, other)) return false; |
||||||
|
if(ReferenceEquals(this, other)) return true; |
||||||
|
return EqualityComparer<T>.Default.Equals(X, other.X) && EqualityComparer<T>.Default.Equals(Y, other.Y); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Determines whether this <see cref="Vector2{T}"/> is equal to another one. |
||||||
|
/// </summary> |
||||||
|
/// <param name="other">Another <see cref="Vector2{T}"/> to compare this instance to.</param> |
||||||
|
/// <returns><c>true</c> if the two <see cref="Vector2{T}"/> objects are equal, otherwise <c>false</c>.</returns> |
||||||
|
public override bool Equals(object obj) { |
||||||
|
if(!(obj is Vector2<T>)) return false; |
||||||
|
return this == (Vector2<T>)obj; |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public override int GetHashCode() { |
||||||
|
unchecked { |
||||||
|
return (EqualityComparer<T>.Default.GetHashCode(X) * 397) ^ EqualityComparer<T>.Default.GetHashCode(Y); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,158 @@ |
|||||||
|
using DotSDL.Exceptions; |
||||||
|
using System.Runtime.CompilerServices; |
||||||
|
|
||||||
|
namespace DotSDL.Math.Vector { |
||||||
|
/// <summary> |
||||||
|
/// A class containing static functions that support the implemented vector types. |
||||||
|
/// </summary> |
||||||
|
/// <typeparam name="T">The type of the vector that should be supported..</typeparam> |
||||||
|
internal static class VectorBase<T> { |
||||||
|
/// <summary> |
||||||
|
/// Retrieves a one value in one of the supported types. |
||||||
|
/// </summary> |
||||||
|
/// <returns>A one value in one of the supported types.</returns> |
||||||
|
/// <exception cref="InvalidTypeException">Thrown if a non-numeric or unsupported type is passed.</exception> |
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||||
|
internal static T GetOne() { |
||||||
|
if(typeof(T) == typeof(sbyte)) { |
||||||
|
const sbyte val = 1; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(byte)) { |
||||||
|
const byte val = 1; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(short)) { |
||||||
|
const short val = 1; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(ushort)) { |
||||||
|
const ushort val = 1; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(int)) { |
||||||
|
const int val = 1; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(uint)) { |
||||||
|
const uint val = 1; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(long)) { |
||||||
|
const long val = 1; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(ulong)) { |
||||||
|
const ulong val = 1; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(float)) { |
||||||
|
const float val = 1.0f; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(double)) { |
||||||
|
const double val = 1.0d; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(decimal)) { |
||||||
|
const decimal val = 1.0m; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
throw new InvalidTypeException("VectorBase<T>.GetOne()", typeof(T)); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Retrieves a zero value in one of the supported types. |
||||||
|
/// </summary> |
||||||
|
/// <returns>A zero value in one of the supported types.</returns> |
||||||
|
/// <exception cref="InvalidTypeException">Thrown if a non-numeric or unsupported type is passed.</exception> |
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||||
|
internal static T GetZero() { |
||||||
|
if(typeof(T) == typeof(sbyte)) { |
||||||
|
const sbyte val = 0; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(byte)) { |
||||||
|
const byte val = 0; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(short)) { |
||||||
|
const short val = 0; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(ushort)) { |
||||||
|
const ushort val = 0; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(int)) { |
||||||
|
const int val = 0; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(uint)) { |
||||||
|
const uint val = 0; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(long)) { |
||||||
|
const long val = 0; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(ulong)) { |
||||||
|
const ulong val = 0; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(float)) { |
||||||
|
const float val = 0.0f; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(double)) { |
||||||
|
const double val = 0.0d; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
if(typeof(T) == typeof(decimal)) { |
||||||
|
const decimal val = 0.0m; |
||||||
|
return (T)(object)val; |
||||||
|
} |
||||||
|
|
||||||
|
throw new InvalidTypeException("VectorBase<T>.GetZero()", typeof(T)); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Determines whether or not the desired type is a valid and supported numeric type. |
||||||
|
/// </summary> |
||||||
|
/// <returns><c>type</c> if the value is a supported numeric type, otherwise <c>false</c>.</returns> |
||||||
|
internal static bool IsNumericType() { |
||||||
|
return typeof(T) == typeof(sbyte) |
||||||
|
|| typeof(T) == typeof(byte) |
||||||
|
|| typeof(T) == typeof(short) |
||||||
|
|| typeof(T) == typeof(ushort) |
||||||
|
|| typeof(T) == typeof(int) |
||||||
|
|| typeof(T) == typeof(uint) |
||||||
|
|| typeof(T) == typeof(long) |
||||||
|
|| typeof(T) == typeof(ulong) |
||||||
|
|| typeof(T) == typeof(float) |
||||||
|
|| typeof(T) == typeof(double) |
||||||
|
|| typeof(T) == typeof(decimal); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue