Browse Source

Type simplification.

* 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
parent
commit
1cc6a4b4da
  1. 3
      DotSDL.sln.DotSettings
  2. 3
      DotSDL/DotSDL.csproj
  3. 18
      DotSDL/Exceptions/InvalidTypeException.cs
  4. 21
      DotSDL/Graphics/Canvas.cs
  5. 50
      DotSDL/Graphics/Point.cs
  6. 11
      DotSDL/Graphics/Rectangle.cs
  7. 66
      DotSDL/Graphics/SdlWindow.cs
  8. 53
      DotSDL/Graphics/Sprite.cs
  9. 112
      DotSDL/Math/Vector/Vector2.cs
  10. 158
      DotSDL/Math/Vector/VectorSupport.cs
  11. 8
      Samples/Sample.Sprites/Window.cs

3
DotSDL.sln.DotSettings

@ -108,4 +108,5 @@
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsParsFormattingSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsWrapperSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Bezi_00E9r/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Bezi_00E9r/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=SDL_0027s/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

3
DotSDL/DotSDL.csproj

@ -16,7 +16,4 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
</ItemGroup>
</Project>

18
DotSDL/Exceptions/InvalidTypeException.cs

@ -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})" : "") { }
}
}

21
DotSDL/Graphics/Canvas.cs

@ -15,6 +15,12 @@ namespace DotSDL.Graphics {
/// </summary>
protected bool HasTexture { get; set; }
/// <summary>
/// The scaling type that should be used to draw this <see cref="Canvas"/>. This field should not be
/// manipulated directly--use <see cref="ScalingQuality"/> instead.
/// </summary>
protected ScalingQuality ScalingQualityValue;
/// <summary>
/// The SDL_Texture that this <see cref="Canvas"/> maintains.
/// </summary>
@ -62,6 +68,20 @@ namespace DotSDL.Graphics {
}
}
/// <summary>
/// Determines the method that will be used to scale this sprite when it is plotted to the
/// screen.
/// </summary>
public virtual ScalingQuality ScalingQuality {
get => ScalingQualityValue;
set {
ScalingQualityValue = value;
if(HasTexture)
CreateTexture();
}
}
/// <summary>
/// Sets the section of the <see cref="Canvas"/> that should be drawn. If the size values are set to 0, the
/// <see cref="Canvas"/> will fill as much of its containing object as possible.
@ -114,6 +134,7 @@ namespace DotSDL.Graphics {
if(Renderer == IntPtr.Zero) return;
DestroyTexture();
Hints.SetHint(Hints.RenderScaleQuality, ScalingQuality.ToString());
Texture = Render.CreateTexture(Renderer, SdlPixels.PixelFormatArgb8888, textureAccess, Width, Height);
HasTexture = true;

50
DotSDL/Graphics/Point.cs

@ -1,61 +1,67 @@
using DotSDL.Interop.Core;
using DotSDL.Math.Vector;
namespace DotSDL.Graphics {
/// <summary>
/// Represents a point in 2D space.
/// </summary>
public class Point {
public class Point : Vector2<int> {
/// <summary>
/// The base <see cref="SdlPoint"/> structure that this class wraps around.
/// </summary>
internal Rect.SdlPoint SdlPoint;
internal Rect.SdlPoint SdlPoint => new Rect.SdlPoint { X = X, Y = Y };
/// <summary>
/// Returns a <see cref="Point"/> with the coordinates (1, 1).
/// </summary>
public static Point One => new Point(1, 1);
public new static Point One => new Point(1, 1);
/// <summary>
/// Returns a <see cref="Point"/> with the coordinates (1, 0).
/// </summary>
public static Point UnitX => new Point(1, 0);
public new static Point UnitX => new Point(1, 0);
/// <summary>
/// Returns a <see cref="Point"/> with the coordinates (0, 1).
/// </summary>
public static Point UnitY => new Point(0, 1);
public new static Point UnitY => new Point(0, 1);
/// <summary>
/// Returns a <see cref="Point"/> with the coordinates (0, 0).
/// </summary>
public static Point Zero => new Point(0, 0);
public new static Point Zero => new Point(0, 0);
/// <summary>
/// The X coordinate of the point.
/// Creates a new <see cref="Point"/> with the coordinates (0, 0).
/// </summary>
public int X {
get => SdlPoint.X;
set => SdlPoint.X = value;
public Point() : this(Zero) { }
/// <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>
/// The Y coordinate of the point.
/// Creates a new <see cref="Point"/> based on an existing <see cref="Vector2{T}"/>.
/// </summary>
public int Y {
get => SdlPoint.Y;
set => SdlPoint.Y = value;
/// <param name="vec">The <see cref="Vector2{T}"/> to based this new object on.</param>
public Point(Vector2<int> vec) {
X = vec.X;
Y = vec.Y;
}
/// <summary>
/// Creates a new <see cref="Point"/>.
/// Creates a new <see cref="Point"/> based on integer coordinates.
/// </summary>
/// <param name="x">The X value of the new <see cref="Point"/>.</param>
/// <param name="y">The Y value of the new <see cref="Point"/>.</param>
public Point(int x = 0, int y = 0) {
SdlPoint = new Rect.SdlPoint {
X = x,
Y = y
};
/// <param name="x">The X coordinate of the new <see cref="Point"/>.</param>
/// <param name="y">The Y coordinate of the new <see cref="Point"/>.</param>
public Point(int x, int y) {
X = x;
Y = y;
}
}
}

11
DotSDL/Graphics/Rectangle.cs

@ -52,15 +52,8 @@ namespace DotSDL.Graphics {
/// <param name="width">The width of the new <see cref="Rectangle"/>.</param>
/// <param name="height">The height of the new <see cref="Rectangle"/>.</param>
public Rectangle(int x, int y, int width, int height) {
_position = new Point {
X = x,
Y = y,
};
_size = new Point {
X = width,
Y = height
};
_position = new Point(x, y);
_size = new Point(width, height);
}
}
}

66
DotSDL/Graphics/SdlWindow.cs

@ -2,9 +2,7 @@
using DotSDL.Input;
using DotSDL.Interop.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
namespace DotSDL.Graphics {
/// <summary>
@ -16,7 +14,8 @@ namespace DotSDL.Graphics {
private readonly IntPtr _window;
private readonly IntPtr _renderer;
private readonly IntPtr _texture;
private IntPtr _texture;
private bool _hasTexture;
public readonly Canvas Background;
@ -25,6 +24,8 @@ namespace DotSDL.Graphics {
private uint _nextVideoUpdate;
private uint _nextGameUpdate;
private ScalingQuality _scalingQuality = ScalingQuality.Nearest;
/// <summary><c>true</c> if this <see cref="SdlWindow"/> instance has been destroyed, othersize <c>false</c>.</summary>
public bool IsDestroyed { get; set; }
@ -56,7 +57,7 @@ namespace DotSDL.Graphics {
/// <summary>Indicates that the window manager should position the window. To place the window on a specific display, use the <see cref="WindowPosCenteredDisplay"/> function.</summary>
public const int WindowPosUndefined = 0x1FFF0000;
/// <summary>Fired when the window's close button is clicked.</summary>
/// <summary>Fired when tboolhe window's close button is clicked.</summary>
public event EventHandler<WindowEvent> Closed;
/// <summary>Fired when a key is pressed.</summary>
@ -71,6 +72,16 @@ namespace DotSDL.Graphics {
/// <summary>Fired when the window is restored.</summary>
public event EventHandler<WindowEvent> Restored;
public ScalingQuality ScalingQuality {
get => _scalingQuality;
set {
_scalingQuality = value;
if(_hasTexture)
CreateTexture();
}
}
/// <summary>
/// Calculates a value that allows the window to be placed on a specific display, with its exact position determined by the window manager.
/// </summary>
@ -95,7 +106,7 @@ namespace DotSDL.Graphics {
}
/// <summary>
/// Creates a new <see cref="SdlWindow"/>.
/// Creates a new <see cref="SdlWindow"/>.readonly
/// </summary>
/// <param name="title">The text that is displayed on the window's title bar.</param>
/// <param name="position">A <see cref="Point"/> representing the starting position of the window. The X and Y coordinates of the Point can be set to <see cref="WindowPosUndefined"/> or <see cref="WindowPosCentered"/>.</param>
@ -140,20 +151,18 @@ namespace DotSDL.Graphics {
_window = Video.CreateWindow(title, position.X, position.Y, windowWidth, windowHeight, Video.WindowFlags.Hidden);
_renderer = Render.CreateRenderer(_window, -1, Render.RendererFlags.Accelerated);
// Everything should be kept as nearest *except* for the target texture.
SetScalingQuality(scalingQuality);
_texture = Render.CreateTexture(_renderer, Pixels.PixelFormatArgb8888, Render.TextureAccess.Target, textureWidth, textureHeight);
SetScalingQuality(ScalingQuality.Nearest);
Background = new Canvas(textureWidth, textureHeight) { Renderer = _renderer };
Background.CreateTexture();
WindowWidth = windowWidth;
WindowHeight = windowHeight;
TextureWidth = textureWidth;
TextureHeight = textureHeight;
ScalingQuality = scalingQuality;
CreateTexture();
Background = new Canvas(textureWidth, textureHeight) { Renderer = _renderer };
Background.CreateTexture();
Sprites = new SpriteList(_renderer);
IsDestroyed = false;
@ -211,6 +220,16 @@ namespace DotSDL.Graphics {
OnUpdate(); // Call the overridden Update function.
}
/// <summary>
/// Creates the rendering target that all of the layers will be drawn to prior to rendering.
/// </summary>
private void CreateTexture() {
DestroyTexture();
Hints.SetHint(Hints.RenderScaleQuality, ScalingQuality.ToString());
_texture = Render.CreateTexture(_renderer, Pixels.PixelFormatArgb8888, Render.TextureAccess.Target, TextureWidth, TextureHeight);
_hasTexture = true;
}
/// <summary>
/// Destroys this <see cref="SdlWindow"/>.
/// </summary>
@ -219,6 +238,16 @@ namespace DotSDL.Graphics {
IsDestroyed = true;
}
/// <summary>
/// Destroys the render target associated with this <see cref="SdlWindow"/>.
/// </summary>
private void DestroyTexture() {
if(!_hasTexture) return;
Render.DestroyTexture(_texture);
_hasTexture = false;
}
/// <summary>
/// Plots the sprites stored in <see cref="Sprites"/> to the screen. Please note that this method is called by
/// DotSDL's drawing routines and does not need to be called manually. Additionally, this method will not be
@ -227,8 +256,6 @@ namespace DotSDL.Graphics {
public virtual void DrawSprites() {
Render.SetRenderTarget(_renderer, _texture);
foreach(var sprite in Sprites.Where(e => e.Shown).OrderBy(e => e.ZOrder)) {
SetScalingQuality(sprite.ScalingQuality);
var srcRect = sprite.Clipping.SdlRect;
var drawSize = new Point(
(int)(srcRect.W * sprite.Scale.X),
@ -360,15 +387,6 @@ namespace DotSDL.Graphics {
/// </summary>
protected virtual void OnUpdate() { }
/// <summary>
/// Sets the scaling/filter quality. This is set globally within SDL, so
/// for correctness sake it should be called before every texture is created.
/// </summary>
/// <param name="quality"></param>
private void SetScalingQuality(ScalingQuality quality) {
Hints.SetHint(Hints.RenderScaleQuality, quality.ToString());
}
/// <summary>
/// Displays the window and begins executing code that's associated with it.
/// </summary>

53
DotSDL/Graphics/Sprite.cs

@ -1,6 +1,6 @@
using DotSDL.Interop.Core;
using DotSDL.Math.Vector;
using SdlPixels = DotSDL.Interop.Core.Pixels;
using System.Numerics;
namespace DotSDL.Graphics {
/// <summary>
@ -16,7 +16,7 @@ namespace DotSDL.Graphics {
/// The angle that the sprite is drawn, in degrees. Incrementing this will rotate the
/// sprite clockwise.
/// </summary>
public double Rotation { get; set; }
public float Rotation { get; set; }
/// <summary>
/// The point around which the sprite will be rotated. By default, this will be set to
@ -32,13 +32,20 @@ namespace DotSDL.Graphics {
/// <summary>
/// The scale of the <see cref="Sprite"/>. 1.0f is 100%.
/// </summary>
public Vector2 Scale { get; set; }
public Vector2<float> Scale { get; set; }
/// <summary>
/// Determines the method that will be used to scale this sprite when it is plotted to the
/// screen.
/// </summary>
public ScalingQuality ScalingQuality { get; set; }
/// <inheritdoc/>
public override ScalingQuality ScalingQuality {
get => ScalingQualityValue;
set {
ScalingQualityValue = value;
if(HasTexture) {
CreateTexture();
UpdateTexture();
}
}
}
/// <summary>
/// <c>true</c> if the sprite should be drawn to the screen, otherwise <c>false</c>.
@ -56,15 +63,15 @@ namespace DotSDL.Graphics {
/// </summary>
/// <param name="width">The width of the new <see cref="Sprite"/>.</param>
/// <param name="height">The height of the new <see cref="Sprite"/>.</param>
public Sprite(int width, int height) : this(width, height, Point.Zero, Vector2.One, 0) { }
public Sprite(int width, int height) : this(width, height, Point.Zero, Vector2<float>.One, 0) { }
/// <summary>
/// Initializes a new <see cref="Sprite"/>.
/// </summary>
/// <param name="width">The width of the new <see cref="Sprite"/>.</param>
/// <param name="height">The height of the new <see cref="Sprite"/>.</param>
/// <param name="position">A <see cref="Vector2"/> representing the initial position of the new <see cref="Sprite"/>.</param>
public Sprite(int width, int height, Point position) : this(width, height, position, Vector2.One, 0) { }
/// <param name="position">A <see cref="Point"/> representing the initial position of the new <see cref="Sprite"/>.</param>
public Sprite(int width, int height, Point position) : this(width, height, position, Vector2<float>.One, 0) { }
/// <summary>
/// Initializes a new <see cref="Sprite"/>.
@ -73,37 +80,37 @@ namespace DotSDL.Graphics {
/// <param name="height">The height of the new <see cref="Sprite"/>.</param>
/// <param name="zOrder">A value indicating the order in which this <see cref="Sprite"/> is drawn. Higher numbered
/// sprites are drawn on top of other sprites and, thus, will appear above them.</param>
public Sprite(int width, int height, int zOrder) : this(width, height, Point.Zero, Vector2.One, zOrder) { }
public Sprite(int width, int height, int zOrder) : this(width, height, Point.Zero, Vector2<float>.One, zOrder) { }
/// <summary>
/// Initializes a new <see cref="Sprite"/>.
/// </summary>
/// <param name="width">The width of the new <see cref="Sprite"/>.</param>
/// <param name="height">The height of the new <see cref="Sprite"/>.</param>
/// <param name="position">A <see cref="Vector2"/> representing the initial position of the new <see cref="Sprite"/>.</param>
/// <param name="scale">A <see cref="Vector2"/> representing the initial scaling of the new <see cref="Sprite"/>.</param>
public Sprite(int width, int height, Point position, Vector2 scale) : this(width, height, position, scale, 0) { }
/// <param name="position">A <see cref="float"/> representing the initial position of the new <see cref="Sprite"/>.</param>
/// <param name="scale">A <see cref="Vector2{T}"/> representing the initial scaling of the new <see cref="Sprite"/>.</param>
public Sprite(int width, int height, Point position, Vector2<float> scale) : this(width, height, position, scale, 0) { }
/// <summary>
/// Initializes a new <see cref="Sprite"/>.
/// </summary>
/// <param name="width">The width of the new <see cref="Sprite"/>.</param>
/// <param name="height">The height of the new <see cref="Sprite"/>.</param>
/// <param name="position">A <see cref="Vector2"/> representing the initial position of the new <see cref="Sprite"/>.</param>
/// <param name="position">A <see cref="Point"/> representing the initial position of the new <see cref="Sprite"/>.</param>
/// <param name="zOrder">A value indicating the order in which this <see cref="Sprite"/> is drawn. Higher numbered
/// sprites are drawn on top of other sprites and, thus, will appear above them.</param>
public Sprite(int width, int height, Point position, int zOrder) : this(width, height, position, Vector2.One, 0) { }
public Sprite(int width, int height, Point position, int zOrder) : this(width, height, position, Vector2<float>.One, 0) { }
/// <summary>
/// Initializes a new <see cref="Sprite"/>.
/// </summary>
/// <param name="width">The width of the new <see cref="Sprite"/>.</param>
/// <param name="height">The height of the new <see cref="Sprite"/>.</param>
/// <param name="position">A <see cref="Vector2"/> representing the initial position of the new <see cref="Sprite"/>.</param>
/// <param name="scale">A <see cref="Vector2"/> representing the initial scaling of the new <see cref="Sprite"/>.</param>
/// <param name="position">A <see cref="Point"/> representing the initial position of the new <see cref="Sprite"/>.</param>
/// <param name="scale">A <see cref="Vector2{T}"/> representing the initial scaling of the new <see cref="Sprite"/>.</param>
/// <param name="zOrder">A value indicating the order in which this <see cref="Sprite"/> is drawn. Higher numbered
/// sprites are drawn on top of other sprites and, thus, will appear above them.</param>
public Sprite(int width, int height, Point position, Vector2 scale, int zOrder)
public Sprite(int width, int height, Point position, Vector2<float> scale, int zOrder)
: this(width, height, position, new Rectangle(0, 0, width, height), scale, zOrder) { }
/// <summary>
@ -111,12 +118,12 @@ namespace DotSDL.Graphics {
/// </summary>
/// <param name="width">The width of the new <see cref="Sprite"/>.</param>
/// <param name="height">The height of the new <see cref="Sprite"/>.</param>
/// <param name="position">A <see cref="Vector2"/> representing the initial position of the new <see cref="Sprite"/>.</param>
/// <param name="scale">A <see cref="Vector2"/> representing the initial scaling of the new <see cref="Sprite"/>.</param>
/// <param name="position">A <see cref="Point"/> representing the initial position of the new <see cref="Sprite"/>.</param>
/// <param name="scale">A <see cref="Vector2{T}"/> representing the initial scaling of the new <see cref="Sprite"/>.</param>
/// <param name="clipping">A rectangle specifying which part of this <see cref="Sprite"/> should be drawn.</param>
/// <param name="zOrder">A value indicating the order in which this <see cref="Sprite"/> is drawn. Higher numbered
/// sprites are drawn on top of other sprites and, thus, will appear above them.</param>
public Sprite(int width, int height, Point position, Rectangle clipping, Vector2 scale, int zOrder) : base(width, height, clipping) {
public Sprite(int width, int height, Point position, Rectangle clipping, Vector2<float> scale, int zOrder) : base(width, height, clipping) {
Position = position;
Scale = scale;
ZOrder = zOrder;

112
DotSDL/Math/Vector/Vector2.cs

@ -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);
}
}
}
}

158
DotSDL/Math/Vector/VectorSupport.cs

@ -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);
}
}
}

8
Samples/Sample.Sprites/Window.cs

@ -2,6 +2,7 @@
using DotSDL.Graphics;
using DotSDL.Input.Keyboard;
using System;
using System.Numerics;
namespace Sample.Sprites {
public class Window : SdlWindow {
@ -10,7 +11,7 @@ namespace Sample.Sprites {
private Point _player1Delta, _player2Delta;
public Window(int scale) : base("Sprites Test",
new Point { X = WindowPosUndefined, Y = WindowPosUndefined },
new Point(WindowPosUndefined, WindowPosUndefined),
256 * scale, 196 * scale,
256, 196) {
KeyPressed += OnKeyPressed;
@ -87,6 +88,11 @@ namespace Sample.Sprites {
_player2.Position.Y = 24;
_player2Delta = new Point();
_player1.Scale.X = 1.5f;
_player2.ScalingQuality = ScalingQuality.Linear;
_player2.Scale.Y = 2.0f;
Sprites.Add(_player1);
Sprites.Add(_player2);
}

Loading…
Cancel
Save