Browse Source

Unified the drawing routines.

* Moved both the Shown and ZOrder properties to the Canvas class.
    * Sprites and Backgrounds are now both considered when doing z-order
      checks. As such, sprites can now be drawn under backgrounds. This will
      likely need more optimization.
mouse
Ian Burgmyer 5 years ago
parent
commit
1253e3017b
  1. 2
      DotSDL/Graphics/Background.cs
  2. 11
      DotSDL/Graphics/Canvas.cs
  3. 147
      DotSDL/Graphics/SdlWindow.cs

2
DotSDL/Graphics/Background.cs

@ -30,7 +30,7 @@ namespace DotSDL.Graphics {
// TODO: Might be able to make this faster by leveraging memcpy(). Need to benchmark it.
unsafe {
var copySize = Width * Height * 4; // Width x Height at 4 bytes per pixel.
Render.LockTexture(Texture, IntPtr.Zero, out var pixels, out var _);
Render.LockTexture(Texture, IntPtr.Zero, out var pixels, out _);
Buffer.MemoryCopy(GetCanvasPointer().ToPointer(), pixels, copySize, copySize);
Render.UnlockTexture(Texture);
}

11
DotSDL/Graphics/Canvas.cs

@ -153,6 +153,17 @@ namespace DotSDL.Graphics {
}
}
/// <summary>
/// <c>true</c> if the <see cref="Canvas"/> should be drawn to the screen, otherwise <c>false</c>.
/// </summary>
public bool Shown { get; set; } = true;
/// <summary>
/// The order in which the canvas is drawn. Lower numbered <see cref="Canvas"/> instances are drawn first
/// and will appear on the bottom. This number can be negative.
/// </summary>
public int ZOrder { get; set; }
/// <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.

147
DotSDL/Graphics/SdlWindow.cs

@ -31,6 +31,8 @@ namespace DotSDL.Graphics {
private float _nextGameUpdate;
private float _updateDelta;
private List<Canvas> _drawList = new List<Canvas>();
private ScalingQuality _scalingQuality = ScalingQuality.Nearest;
/// <summary>
@ -228,6 +230,7 @@ namespace DotSDL.Graphics {
BlendMode = BlendMode.None
}
};
Background.ZOrder = int.MinValue;
Background.CreateTexture();
CameraView = new Rectangle(
@ -277,20 +280,29 @@ namespace DotSDL.Graphics {
Render.SetRenderTarget(_renderer, _texture);
// Blit the background canvases to the target texture.
foreach(var canvas in Layers) {
canvas.Clipping.Position = CameraView.Position;
canvas.Clipping.Size = CameraView.Size;
canvas.UpdateTexture();
unsafe {
var canvasClippingRect = canvas.Clipping.SdlRect;
Render.RenderCopy(_renderer, canvas.Texture, new IntPtr(&canvasClippingRect), IntPtr.Zero);
// Sort all of the canvases, then draw them.
_drawList.Clear();
_drawList.AddRange(Layers.Where(l => l.Shown).ToArray());
_drawList.AddRange(Sprites.Where(s => s.Shown).ToArray());
foreach(var canvas in _drawList.OrderBy(layer => layer.ZOrder)) {
switch(canvas) {
case Sprite sprite:
DrawSprite(sprite);
break;
default:
canvas.Clipping.Position = CameraView.Position;
canvas.Clipping.Size = CameraView.Size;
canvas.UpdateTexture();
unsafe {
var canvasClippingRect = canvas.Clipping.SdlRect;
Render.RenderCopy(_renderer, canvas.Texture, new IntPtr(&canvasClippingRect), IntPtr.Zero);
}
break;
}
}
// Plot sprites on top of the background layer.
if(Sprites.Count > 0) DrawSprites();
Render.SetRenderTarget(_renderer, IntPtr.Zero);
Render.RenderCopy(_renderer, _texture, IntPtr.Zero, IntPtr.Zero);
@ -343,61 +355,58 @@ namespace DotSDL.Graphics {
}
/// <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
/// called if there are no sprites defined. You usually do not need to override this method.
/// </summary>
public virtual void DrawSprites() {
Render.SetRenderTarget(_renderer, _texture);
foreach(var sprite in Sprites.Where(e => e.Shown).OrderBy(e => e.ZOrder)) {
var srcRect = sprite.Clipping.SdlRect;
var drawSize = sprite.DrawSize;
Rectangle dest;
Point rotationCenter;
if(sprite.CoordinateSystem == CoordinateSystem.ScreenSpace) {
dest = new Rectangle(sprite.Position, drawSize);
rotationCenter = sprite.RotationCenter;
} else {
// Create a set of world coordinates based on the position of the camera
// and this sprite.
var relPosition = new Point(sprite.Position - CameraView.Position);
var screenPosition = new Point(
(int)((float)relPosition.X / CameraView.Size.X * RenderWidth),
(int)((float)relPosition.Y / CameraView.Size.Y * RenderHeight)
);
var scaleFactorX = (float)RenderWidth / CameraView.Size.X;
var scaleFactorY = (float)RenderHeight / CameraView.Size.Y;
var size = new Point(
(int)(drawSize.X * scaleFactorX),
(int)(drawSize.Y * scaleFactorY)
);
dest = new Rectangle(screenPosition, size);
rotationCenter = new Point(
(int)(sprite.RotationCenter.X * scaleFactorX),
(int)(sprite.RotationCenter.Y * scaleFactorY)
);
}
/// Plots a sprite 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 never be
/// called if there are no active sprites. You usually do not need to override this method.
/// </summary>
public virtual void DrawSprite(Sprite sprite) {
var srcRect = sprite.Clipping.SdlRect;
var drawSize = sprite.DrawSize;
Rectangle dest;
Point rotationCenter;
if(sprite.CoordinateSystem == CoordinateSystem.ScreenSpace) {
dest = new Rectangle(sprite.Position, drawSize);
rotationCenter = sprite.RotationCenter;
} else {
// Create a set of world coordinates based on the position of the camera
// and this sprite.
var relPosition = new Point(sprite.Position - CameraView.Position);
var screenPosition = new Point(
(int)((float)relPosition.X / CameraView.Size.X * RenderWidth),
(int)((float)relPosition.Y / CameraView.Size.Y * RenderHeight)
);
var scaleFactorX = (float)RenderWidth / CameraView.Size.X;
var scaleFactorY = (float)RenderHeight / CameraView.Size.Y;
var size = new Point(
(int)(drawSize.X * scaleFactorX),
(int)(drawSize.Y * scaleFactorY)
);
dest = new Rectangle(screenPosition, size);
rotationCenter = new Point(
(int)(sprite.RotationCenter.X * scaleFactorX),
(int)(sprite.RotationCenter.Y * scaleFactorY)
);
}
var destRect = dest.SdlRect;
var rotationCenterPoint = rotationCenter.SdlPoint;
unsafe {
var srcRectPtr = new IntPtr(&srcRect);
var destRectPtr = new IntPtr(&destRect);
var rotationCenterPtr = new IntPtr(&rotationCenterPoint);
Render.RenderCopyEx(
renderer: _renderer,
texture: sprite.Texture,
srcRect: srcRectPtr,
dstRect: destRectPtr,
angle: sprite.Rotation,
center: rotationCenterPtr,
flip: sprite.Flip
);
}
var destRect = dest.SdlRect;
var rotationCenterPoint = rotationCenter.SdlPoint;
unsafe {
var srcRectPtr = new IntPtr(&srcRect);
var destRectPtr = new IntPtr(&destRect);
var rotationCenterPtr = new IntPtr(&rotationCenterPoint);
Render.RenderCopyEx(
renderer: _renderer,
texture: sprite.Texture,
srcRect: srcRectPtr,
dstRect: destRectPtr,
angle: sprite.Rotation,
center: rotationCenterPtr,
flip: sprite.Flip
);
}
}
@ -537,17 +546,13 @@ namespace DotSDL.Graphics {
/// <summary>
/// Displays the window and begins executing code that's associated with it.
/// </summary>
public void Start() {
Start(0, 0);
}
public void Start() => Start(0, 0);
/// <summary>
/// Displays the window and begins executing code that's associated with it.
/// </summary>
/// <param name="updateRate">The desired number of video and game logic updates per second. 0 causes the display and game to be updated as quickly as possible.</param>
public void Start(float updateRate) {
Start(updateRate, updateRate);
}
public void Start(float updateRate) => Start(updateRate, updateRate);
/// <summary>
/// Displays the window and begins executing code that's associated with it.

Loading…
Cancel
Save