refactoring; removed configuration setup; added consistent sprite batch; got rid of sprite batch settings; implemented newer setup;

This commit is contained in:
Harrison Deng 2019-03-23 19:04:43 -05:00
parent e3535f5662
commit b045033b25
28 changed files with 342 additions and 329 deletions

View File

@ -1,32 +0,0 @@
using Microsoft.Xna.Framework;
using RecrownedAthenaeum.Camera;
using RecrownedAthenaeum.Render;
using System;
namespace RecrownedAthenaeum
{
/// <summary>
/// All variables here should be for RecrownedAthenaeum to use when needed and thus eliminates unessecary passing.
/// </summary>
public static class Configuration
{
private static GraphicsDeviceManager graphicsDeviceManager;
/// <summary>
/// The graphics device that will be used by default.
/// </summary>
public static GraphicsDeviceManager GraphicsDeviceManager { set { graphicsDeviceManager = value; } get { if (graphicsDeviceManager == null) throw new InvalidOperationException("Graphics device manager property requested as substitute but configuration does not have one."); return graphicsDeviceManager; } }
private static Camera2D camera2D;
/// <summary>
/// 2D camera to be used by default.
/// </summary>
public static Camera2D Camera2D { set { camera2D = value; } get { if (camera2D == null) throw new InvalidOperationException("2D camera property requested as substitute but configuration does not have one."); return camera2D; } }
private static SpriteBatchSettings? spriteBatchSettings;
/// <summary>
/// The begin sprite batch to use for custom begins and consistency.
/// </summary>
public static SpriteBatchSettings? SpriteBatchSettings { set { spriteBatchSettings = value.Value; } get { if (!spriteBatchSettings.HasValue) throw new InvalidOperationException("No default begin batch has been set yet has been requested."); return spriteBatchSettings; } }
}
}

View File

@ -51,14 +51,13 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Render\BasicCamera.cs" />
<Compile Include="Render\ConsistentSpriteBatch.cs" />
<Compile Include="Render\ScissorBox.cs" />
<Compile Include="Render\SpriteBatchSettings.cs" />
<Compile Include="Render\Camera3D.cs" />
<Compile Include="Render\Camera2D.cs" />
<Compile Include="ContentSystem\ContentData.cs" />
<Compile Include="ContentSystem\ContentManagerController.cs" />
<Compile Include="ContentSystem\IContentPathResolver.cs" />
<Compile Include="Configuration.cs" />
<Compile Include="ContentSystem\NormalContentResolver.cs" />
<Compile Include="SpecialTypes\ISpecialDrawable.cs" />
<Compile Include="SpecialTypes\NinePatch.cs" />

View File

@ -1,12 +1,13 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
namespace RecrownedAthenaeum.Camera
{
/// <summary>
/// A generic 3D camera.
/// A generic camera. Functions in 3D.
/// </summary>
public class Camera3D
public class BasicCamera
{
/// <summary>
/// The scale for the world.
@ -24,7 +25,7 @@ namespace RecrownedAthenaeum.Camera
public Vector3 lookAt;
/// <summary>
/// The direction up is for the 3D camera.
/// The direction up is for the camera.
/// </summary>
public Vector3 upDirection;
@ -44,32 +45,22 @@ namespace RecrownedAthenaeum.Camera
public Matrix projectionMatrix;
/// <summary>
/// The graphics device used
/// A basic effect that will be updated with the correct matrice information everytime <see cref="Apply"/> is called. Can be null and thus will not be used.
/// </summary>
protected GraphicsDevice graphicsDevice;
/// <summary>
/// The basic effect that contains the transformations.
/// </summary>
public BasicEffect BasicEffect { get; protected set; }
public BasicEffect basicEffect;
/// <summary>
/// Constructs 3D camera with an orthographic projection matrix with dimensions of graphics devices viewport. All changes to matrices should have apply called after changes.
/// </summary>
/// <param name="graphicsDevice">The graphics device to use. Will use graphics device from <see cref="Configuration"/>'s graphics device manager if this is null which it is by default.</param>
public Camera3D(GraphicsDevice graphicsDevice = null)
/// <param name="basicEffect">A basic effect that will be updated with the correct matrice information everytime <see cref="Apply"/> is called. Can be null and thus will not be used.</param>
public BasicCamera(BasicEffect basicEffect = null)
{
graphicsDevice = graphicsDevice ?? (Configuration.GraphicsDeviceManager.GraphicsDevice);
this.graphicsDevice = graphicsDevice;
worldMatrix = Matrix.Identity;
lookAt = Vector3.Forward;
upDirection = Vector3.Up;
projectionMatrix = Matrix.Identity;
BasicEffect = new BasicEffect(graphicsDevice);
BasicEffect.TextureEnabled = true;
BasicEffect.VertexColorEnabled = true;
this.basicEffect = basicEffect;
Apply();
}
@ -81,9 +72,12 @@ namespace RecrownedAthenaeum.Camera
ViewMatrix = Matrix.CreateLookAt(position, lookAt, upDirection);
worldMatrix *= Matrix.CreateScale(worldScale);
BasicEffect.World = worldMatrix;
BasicEffect.View = ViewMatrix;
BasicEffect.Projection = projectionMatrix;
if (basicEffect != null)
{
basicEffect.World = worldMatrix;
basicEffect.Projection = projectionMatrix;
basicEffect.View = ViewMatrix;
}
}
/// <summary>

View File

@ -5,10 +5,20 @@ using System;
namespace RecrownedAthenaeum.Camera
{
/// <summary>
/// A virtual 2D camera that wraps the normal <see cref="Camera3D"/>. Default projection is orthographic.
/// A virtual 2D camera that wraps the normal <see cref="BasicCamera"/>. Default projection is orthographic.
/// </summary>
public class Camera2D : Camera3D
public class Camera2D : BasicCamera
{
/// <summary>
/// The width of the view of the camera.
/// </summary>
public int viewWidth;
/// <summary>
/// The height of the view of the camera.
/// </summary>
public int viewHeight;
/// <summary>
/// The 2D position.
/// </summary>
@ -17,18 +27,21 @@ namespace RecrownedAthenaeum.Camera
/// <summary>
/// Places camera in the center given the corner position.
/// </summary>
public Vector2 CenterPosition { set { position.X = value.X + graphicsDevice.Viewport.Width / 2f; position.Y = value.Y + graphicsDevice.Viewport.Height / 2f; } }
public Vector2 ConrnerPosition { set { position.X = value.X + viewWidth / 2f; position.Y = value.Y + viewHeight / 2f; } }
/// <summary>
/// A 2D camera from the generic <see cref="Camera3D"/>.
/// A 2D camera from the generic <see cref="BasicCamera"/>.
/// </summary>
/// <param name="graphicsDevice">The graphics device to use if not using the one in <see cref="Configuration"/>.</param>
public Camera2D(GraphicsDevice graphicsDevice = null) : base(graphicsDevice)
/// <param name="height">Width of camera view.</param>
/// <param name="width">Height of camera view.</param>
/// <param name="basicEffect">A basic effect that will be updated with the correct matrice information everytime <see cref="Apply"/> is called. Can be null and thus will not be used.</param>
public Camera2D(int width, int height, BasicEffect basicEffect = null) : base(basicEffect)
{
projectionMatrix = Matrix.CreateOrthographic(this.graphicsDevice.Viewport.Width, this.graphicsDevice.Viewport.Height, 0, 1);
CenterPosition = new Vector2(0, 0);
this.viewWidth = width;
this.viewHeight = height;
upDirection = Vector3.Down;
Apply();
ConrnerPosition = new Vector2(0, 0);
}
/// <summary>
@ -37,6 +50,7 @@ namespace RecrownedAthenaeum.Camera
/// </summary>
public override void Apply()
{
projectionMatrix = Matrix.CreateOrthographic(viewWidth, viewHeight, 0, 1);
position.Z = 0;
lookAt = new Vector3(Position, 1f);
base.Apply();

View File

@ -0,0 +1,89 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RecrownedAthenaeum.Render
{
/// <summary>
/// A <see cref="SpriteBatch"/> that keeps it's settings through begin and end unless manually changed either by the <see cref="Begin(SpriteSortMode, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect, Matrix?)"/> or through changing the fields. Note that changing the fields while the batch has begun will not take effect until the next time the batch is started.
/// </summary>
public class ConsistentSpriteBatch : SpriteBatch
{
/// <summary>
/// How to blend the colors. Uses <see cref="SpriteBatch"/>'s default if not set before or during <see cref="Begin(SpriteSortMode, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect, Matrix?)"/> call.
/// Changes will only take effect on <see cref="Begin(SpriteSortMode, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect, Matrix?)"/> call.
/// </summary>
public BlendState BlendState;
/// <summary>
/// The state of sampler to use for the spritebatch. Uses <see cref="SpriteBatch"/>'s default if not set before or during <see cref="Begin(SpriteSortMode, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect, Matrix?)"/> call.
/// Changes will only take effect on <see cref="Begin(SpriteSortMode, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect, Matrix?)"/> call.
/// </summary>
public SamplerState SamplerState;
/// <summary>
/// The state of the depth-stencil buffer. Uses <see cref="SpriteBatch"/>'s defaultdefault if not set before or during <see cref="Begin(SpriteSortMode, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect, Matrix?)"/> call.
/// Changes will only take effect on <see cref="Begin(SpriteSortMode, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect, Matrix?)"/> call.
/// </summary>
public DepthStencilState DepthStencilState;
/// <summary>
/// The state of rasterizer to use. Uses <see cref="SpriteBatch"/>'s default if not set before or during <see cref="Begin(SpriteSortMode, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect, Matrix?)"/> call.
/// Changes will only take effect on <see cref="Begin(SpriteSortMode, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect, Matrix?)"/> call.
/// </summary>
public RasterizerState RasterizerState;
/// <summary>
/// An effect to apply to the batch. Uses <see cref="SpriteBatch"/>'s default if not set before or during <see cref="Begin(SpriteSortMode, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect, Matrix?)"/> call.
/// Changes will only take effect on <see cref="Begin(SpriteSortMode, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect, Matrix?)"/> call.
/// </summary>
public Effect Effect;
/// <summary>
/// A matrix to be applied to transform the sprites geometry. An identity matrix is used if not provided before or during <see cref="Begin(SpriteSortMode, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect, Matrix?)"/> call.
/// Changes will only take effect on <see cref="Begin(SpriteSortMode, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect, Matrix?)"/> call.
/// </summary>
public Matrix? TransformMatrix;
/// <summary>
/// Creates a consistent sprite batch with default values.
/// </summary>
/// <param name="graphicsDevice">The graphics device to use to create a <see cref="SpriteBatch"/>.</param>
public ConsistentSpriteBatch(GraphicsDevice graphicsDevice) : base(graphicsDevice)
{
}
/// <summary>
/// Begins the consistent sprite batch.
/// </summary>
/// <param name="sortMode">Defines the spritebatch's method of sorting the items in each batch. Uses <see cref="SpriteBatch"/>'s default.</param>
/// <param name="blendState">How to blend the colors. Uses <see cref="SpriteBatch"/>'s default if not set and field is also not set.</param>
/// <param name="samplerState">The state of sampler to use for the spritebatch. Uses <see cref="SpriteBatch"/>'s default if not set and field is also not set.</param>
/// <param name="depthStencilState">What type of rasterization to use. Uses <see cref="SpriteBatch"/>'s default if not set and field is also not set.</param>
/// <param name="rasterizerState">What type of rasterization to use. Uses <see cref="SpriteBatch"/>'s default if not set and field is also not set.</param>
/// <param name="effect">An effect to apply to the batch. Uses <see cref="SpriteBatch"/>'s default if not set and field is also not set.</param>
/// <param name="transformMatrix">A matrix to be applied to transform the sprites geometry. An identity is used if not provided.</param>
public new void Begin(SpriteSortMode sortMode = SpriteSortMode.Deferred, BlendState blendState = null, SamplerState samplerState = null, DepthStencilState depthStencilState = null, RasterizerState rasterizerState = null, Effect effect = null, Matrix? transformMatrix = null)
{
if (blendState != null) this.BlendState = blendState;
if (samplerState != null) this.SamplerState = samplerState;
if (depthStencilState != null) this.DepthStencilState = depthStencilState;
if (rasterizerState != null) this.RasterizerState = rasterizerState;
if (effect != null) this.Effect = effect;
if (transformMatrix != null) this.TransformMatrix = transformMatrix;
base.Begin(
sortMode: sortMode,
blendState: blendState,
samplerState: samplerState,
depthStencilState: depthStencilState,
rasterizerState: rasterizerState,
effect: effect,
transformMatrix: transformMatrix);
}
}
}

View File

@ -12,7 +12,7 @@ namespace RecrownedAthenaeum.Render
{
VertexPositionColor[] vertices;
int bufferPosition;
BasicEffect basicEffect;
Effect effect;
PrimitiveType primitiveType;
private int verticesPerPrimitive;
@ -24,28 +24,26 @@ namespace RecrownedAthenaeum.Render
GraphicsDevice graphicsDevice;
bool began;
bool disposed;
Camera3D camera;
BasicEffect basicEffect;
/// <summary>
/// Creates a batch used to draw primitives.
/// </summary>
/// <param name="camera">The current camera being used. Will use default set in <see cref="Configuration"/> if left null.</param>
/// <param name="graphicsDevice">The graphics device used to draw the primitives. Will be using <see cref="Configuration"/>'s graphics device from graphics device manager if null. Default is null.</param>
/// <param name="graphicsDevice">The graphics device used to draw the primitives.</param>
/// <param name="verticesPerBatch">The amount of vertices every batch can hold before flushing. Default is 450. Should be changed to be the most optimal number if possible to prevent unnecessary resizing. Especially if using strip primitive types.</param>
public PrimitiveBatch(Camera2D camera = null, GraphicsDevice graphicsDevice = null, int verticesPerBatch = 500)
public PrimitiveBatch(GraphicsDevice graphicsDevice, int verticesPerBatch = 500)
{
this.graphicsDevice = graphicsDevice ?? (Configuration.GraphicsDeviceManager.GraphicsDevice);
this.camera = camera ?? (Configuration.Camera2D);
basicEffect = new BasicEffect(this.graphicsDevice);
basicEffect.VertexColorEnabled = true;
vertices = new VertexPositionColor[verticesPerBatch + 1];
this.graphicsDevice = graphicsDevice;
basicEffect = new BasicEffect(graphicsDevice);
}
/// <summary>
/// Starts the batch. Batch cannot be started twice.
/// </summary>
/// <param name="primitiveType">The type of primitive this batch would be drawing.</param>
public void Begin(PrimitiveType primitiveType)
/// <param name="effect">Effect to use to render the primitives. Default will use a <see cref="BasicEffect"/>.</param>
public void Begin(PrimitiveType primitiveType, Effect effect = null)
{
if (began) throw new InvalidOperationException("Begin is being called twice before being ended.");
if (disposed) throw new ObjectDisposedException(this.GetType().Name);
@ -57,9 +55,7 @@ namespace RecrownedAthenaeum.Render
case PrimitiveType.LineStrip: verticesPerPrimitive = 1; break;
case PrimitiveType.TriangleStrip: verticesPerPrimitive = 3; break;
}
basicEffect.World = camera.worldMatrix;
basicEffect.View = camera.ViewMatrix;
basicEffect.Projection = camera.projectionMatrix;
this.effect = effect ?? basicEffect;
began = true;
}
@ -116,7 +112,7 @@ namespace RecrownedAthenaeum.Render
if (disposed) throw new ObjectDisposedException(this.GetType().Name);
if (bufferPosition == 0) return;
if (primitiveCount == 0) primitiveCount = bufferPosition / verticesPerPrimitive;
foreach (EffectPass effectPass in basicEffect.CurrentTechnique.Passes)
foreach (EffectPass effectPass in effect.CurrentTechnique.Passes)
{
effectPass.Apply();
graphicsDevice.DrawUserPrimitives(primitiveType, vertices, 0, primitiveCount);

View File

@ -20,11 +20,10 @@ namespace RecrownedAthenaeum.Render
/// <summary>
/// Creates a rectangle renderer with the given <see cref="PrimitiveBatch"/>.
/// </summary>
/// <param name="camera">Camera to use for <see cref="PrimitiveBatch"/>. Default will use <see cref="Configuration"/>.</param>
/// <param name="graphicsDevice">Graphics device to use. Default will use <see cref="Configuration"/>.</param>
public RectangleRenderer(Camera2D camera = null, GraphicsDevice graphicsDevice = null)
/// <param name="graphicsDevice">Graphics device to use.</param>
public RectangleRenderer(GraphicsDevice graphicsDevice)
{
primitiveBatch = new PrimitiveBatch(camera, graphicsDevice);
primitiveBatch = new PrimitiveBatch(graphicsDevice);
}
/// <summary>

View File

@ -9,23 +9,33 @@ namespace RecrownedAthenaeum.Render
public class ScissorBox
{
SpriteBatch spriteBatch;
Rectangle currentScissorRect;
ConsistentSpriteBatch spriteBatch;
Rectangle originalScissor;
RasterizerState originalRasterizerState;
RasterizerState scissorRasterizerState;
/// <summary>
/// Used to crop off anything that doesn't fit into the defined space.
/// </summary>
public ScissorBox()
{
scissorRasterizerState = new RasterizerState();
scissorRasterizerState.ScissorTestEnable = true;
}
/// <summary>
/// Starts spritebatch with scissoring enabled.
/// </summary>
/// <param name="rectangle"></param>
/// <param name="spriteBatch"></param>
/// <param name="spriteBatchSettings">The settings for using the <see cref="SpriteBatch"/> to perform the scissor.</param>
public void Begin(Rectangle rectangle, SpriteBatch spriteBatch, SpriteBatchSettings? spriteBatchSettings = null)
public void Begin(Rectangle rectangle, ConsistentSpriteBatch spriteBatch)
{
if (spriteBatchSettings == null) spriteBatchSettings = Configuration.SpriteBatchSettings;
this.spriteBatch = spriteBatch;
spriteBatchSettings.Value.rasterizerState.ScissorTestEnable = true;
spriteBatchSettings.Value.BeginSpriteBatch(spriteBatch);
currentScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
originalRasterizerState = spriteBatch.RasterizerState;
spriteBatch.Begin(rasterizerState: scissorRasterizerState);
originalScissor = spriteBatch.GraphicsDevice.ScissorRectangle;
spriteBatch.GraphicsDevice.ScissorRectangle = rectangle;
}
@ -34,7 +44,8 @@ namespace RecrownedAthenaeum.Render
/// </summary>
public void End()
{
spriteBatch.GraphicsDevice.ScissorRectangle = currentScissorRect;
spriteBatch.GraphicsDevice.ScissorRectangle = originalScissor;
spriteBatch.RasterizerState = originalRasterizerState;
spriteBatch.End();
}
}

View File

@ -1,76 +0,0 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace RecrownedAthenaeum.Render
{
/// <summary>
/// The settings the sprite batch should use.
/// </summary>
public struct SpriteBatchSettings
{
/// <summary>
/// Defines sprites sort mode.
/// </summary>
public SpriteSortMode spriteSortMode;
/// <summary>
/// The blend state to use.
/// </summary>
public BlendState blendState;
/// <summary>
/// Sampler state to use.
/// </summary>
public SamplerState samplerState;
/// <summary>
/// The depth stencil state to use.
/// </summary>
public DepthStencilState depthStencilState;
/// <summary>
/// The rasterizer state to use.
/// </summary>
public RasterizerState rasterizerState;
/// <summary>
/// The effect to use.
/// </summary>
public Effect effect;
/// <summary>
/// The transformation matrix to use.
/// </summary>
public Matrix? transformMatrix;
/// <summary>
/// See <see cref="SpriteBatch.Begin(SpriteSortMode, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect, Matrix?)"/> for uses and defaults.
/// </summary>
/// <param name="spriteSortMode"></param>
/// <param name="blendState"></param>
/// <param name="samplerState"></param>
/// <param name="depthStencilState"></param>
/// <param name="rasterizerState"></param>
/// <param name="effect"></param>
/// <param name="transformMatrix"></param>
public SpriteBatchSettings(SpriteSortMode spriteSortMode = SpriteSortMode.Deferred, BlendState blendState = null, SamplerState samplerState = null, DepthStencilState depthStencilState = null, RasterizerState rasterizerState = null, Effect effect = null, Matrix? transformMatrix = null)
{
this.spriteSortMode = spriteSortMode;
this.blendState = blendState;
this.samplerState = samplerState;
this.depthStencilState = depthStencilState;
this.rasterizerState = rasterizerState;
this.effect = effect;
this.transformMatrix = transformMatrix;
}
/// <summary>
/// Begins the given sprite batch with the current set of settings.
/// </summary>
/// <param name="spriteBatch">Begins the spritebatch with the given settings.</param>
public void BeginSpriteBatch(SpriteBatch spriteBatch)
{
spriteBatch.Begin(spriteSortMode, blendState, samplerState, depthStencilState, rasterizerState, effect, transformMatrix);
}
}
}

View File

@ -1,5 +1,6 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RecrownedAthenaeum.Render;
namespace RecrownedAthenaeum.ScreenSystem
{
@ -34,7 +35,7 @@ namespace RecrownedAthenaeum.ScreenSystem
/// Called once every frame while transition is active. Meant to draw transition.
/// </summary>
/// <param name="spriteBatch"></param>
void DrawTransition(SpriteBatch spriteBatch);
void DrawTransition(ConsistentSpriteBatch spriteBatch);
/// <summary>
/// Updates if the previous screen uses a render target for exit transition.

View File

@ -1,6 +1,7 @@

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RecrownedAthenaeum.Render;
using System;
namespace RecrownedAthenaeum.ScreenSystem
@ -62,10 +63,10 @@ namespace RecrownedAthenaeum.ScreenSystem
public void InitiateTransition(Rectangle dimensions)
{
color = Color.White;
textureBounds.Width = (int)(ScreenSize.Height * proportion);
textureBounds.Height = (int)(ScreenSize.Height * proportion);
textureBounds.X = (ScreenSize.Width) / 2;
textureBounds.Y = (ScreenSize.Height) / 2;
textureBounds.Width = (int)(height * proportion);
textureBounds.Height = (int)(height * proportion);
textureBounds.X = (width) / 2;
textureBounds.Y = (height) / 2;
origin.X = texture.Width / 2;
origin.Y = texture.Height / 2;
}
@ -83,7 +84,7 @@ namespace RecrownedAthenaeum.ScreenSystem
/// Draws the transition.
/// </summary>
/// <param name="spriteBatch">Batch to use.</param>
public void DrawTransition(SpriteBatch spriteBatch)
public void DrawTransition(ConsistentSpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, textureBounds, null, color, rotation, origin, SpriteEffects.None, 0f);
}

View File

@ -1,6 +1,7 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RecrownedAthenaeum.Camera;
using RecrownedAthenaeum.Render;
using System.Collections.Generic;
namespace RecrownedAthenaeum.ScreenSystem
@ -34,7 +35,7 @@ namespace RecrownedAthenaeum.ScreenSystem
public readonly List<ITransition> Transitions;
/// <summary>
/// Whether or not to continue rendering this screen onto a buffer for the benifit of the next screen to use as a transition.
/// Whether or not to continue rendering this screen onto a buffer for the benefit of the next screen to use as a transition.
/// </summary>
public bool UseRenderTargetForExitTransition { get; private set; }
@ -49,19 +50,9 @@ namespace RecrownedAthenaeum.ScreenSystem
public Screen NextScreen { get; set; }
/// <summary>
/// The current window size.
/// The current window dimensions.
/// </summary>
public Rectangle ScreenSize { get; private set; }
/// <summary>
/// Whether or not screen have been initiated.
/// </summary>
public bool Initiated { get; private set; }
/// <summary>
/// The 2D camera to be used for the screen.
/// </summary>
public Camera2D Camera { get; private set; }
public int width, height;
/// <summary>
/// Current state of the screen.
@ -79,13 +70,14 @@ namespace RecrownedAthenaeum.ScreenSystem
}
/// <summary>
/// Called only once after initialization to give required parameters.
/// Called when screen size is set.
/// </summary>
public virtual void Initiate(Rectangle screenSize, Camera2D camera)
/// <param name="width">The width of the screen.</param>
/// <param name="height">The height of the screen.</param>
public virtual void ApplySize(int width, int height)
{
this.Camera = camera;
this.ScreenSize = screenSize;
Initiated = true;
this.width = width;
this.height = height;
}
/// <summary>
@ -101,7 +93,7 @@ namespace RecrownedAthenaeum.ScreenSystem
/// Called to draw this screen.
/// </summary>
/// <param name="spriteBatch">SpriteBatch to use.</param>
public virtual void Draw(SpriteBatch spriteBatch)
public virtual void Draw(ConsistentSpriteBatch spriteBatch)
{
foreach (ITransition transition in Transitions)
{
@ -167,7 +159,7 @@ namespace RecrownedAthenaeum.ScreenSystem
{
foreach (ITransition transition in Transitions)
{
transition.InitiateTransition(ScreenSize);
transition.InitiateTransition(new Rectangle(0, 0, width, height));
}
}

View File

@ -11,7 +11,7 @@ namespace RecrownedAthenaeum.ScreenSystem
/// Called when the first screen is being shown.
/// </summary>
/// <param name="screen">The screen to show after the loading screen.</param>
public delegate void ShowFirstScreen(Screen screen);
public delegate void NeedNextScreen(Screen screen);
/// <summary>
/// A manager for screens. Helps with transitions and updating screens as well as resizes.
@ -23,18 +23,15 @@ namespace RecrownedAthenaeum.ScreenSystem
/// <summary>
/// Called when the first loading screen is done, and needs to show the landing screen.
/// </summary>
public event ShowFirstScreen ShowFirstScreenEvent;
public event NeedNextScreen NeedNextScreen;
/// <summary>
/// The settings this manager will use to begin a sprite batch.
/// </summary>
public SpriteBatchSettings batchSettings;
private GraphicsDeviceManager graphics;
private Screen previousScreen;
private RenderTarget2D previousScreenRenderTarget;
private Screen currentScreen;
private Camera2D camera;
private bool firstScreenChangeComplete;
private bool resizing;
/// <summary>
@ -50,9 +47,9 @@ namespace RecrownedAthenaeum.ScreenSystem
{
previousScreen = currentScreen;
currentScreen = value;
if (!Screen.Initiated)
if (Screen.width != graphics.PreferredBackBufferWidth || Screen.height != graphics.PreferredBackBufferHeight)
{
Screen.Initiate(new Rectangle(0, 0, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight), camera);
Screen.ApplySize(graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight);
}
if (previousScreen != null && previousScreenRenderTarget == null && previousScreen.UseRenderTargetForExitTransition)
{
@ -68,27 +65,12 @@ namespace RecrownedAthenaeum.ScreenSystem
}
/// <summary>
/// Creates a screen manager that helps manage multiple screens and their transitions.
/// Creates a screen manager that helps update, draw, and manage multiple screens and their transitions. Uses its own <see cref="SpriteBatch"/>.
/// </summary>
/// <param name="camera">The camera to be used to perform the correct translations and transformations. Will use default set in <see cref="Configuration"/> if left null.</param>
/// <param name="graphicsDeviceManager">The graphics device manager to be used. Will use default set in <see cref="Configuration"/> if left null.</param>
/// <param name="spriteBatchSettings">The settings to begin spritebatch with. Will use the built-in one in screen manager if not provided.</param>
public ScreenManager(Camera2D camera = null, GraphicsDeviceManager graphicsDeviceManager = null, SpriteBatchSettings? spriteBatchSettings = null)
/// <param name="graphicsDeviceManager">The graphics device manager to be used.</param>
public ScreenManager(GraphicsDeviceManager graphicsDeviceManager)
{
if (camera == null) camera = Configuration.Camera2D;
if (!spriteBatchSettings.HasValue)
{
SpriteBatchSettings basicSettings = new SpriteBatchSettings();
basicSettings.effect = camera.BasicEffect;
basicSettings.samplerState = null;
spriteBatchSettings = basicSettings;
}
if (graphicsDeviceManager == null) graphicsDeviceManager = Configuration.GraphicsDeviceManager;
graphics = graphicsDeviceManager ?? throw new ArgumentNullException("Graphics device manager argument cannot be null if setup's graphics device manager is also null.");
this.camera = camera ?? throw new ArgumentNullException("2d camera argument cannot be null if setup's 2d camera is also null.");
batchSettings = spriteBatchSettings.Value;
graphics = graphicsDeviceManager ?? throw new ArgumentNullException("Graphics device manager argument cannot be null.");
}
/// <summary>
@ -98,6 +80,7 @@ namespace RecrownedAthenaeum.ScreenSystem
/// <param name="waiting">Whether or not there is something a transition should be waiting for. Usually used to wait for assets to complete loading.</param>
public void UpdateCurrentScreen(GameTime gameTime, bool waiting)
{
waiting = !waiting;
switch (Screen.State)
{
case ScreenState.EnterTransition:
@ -113,7 +96,7 @@ namespace RecrownedAthenaeum.ScreenSystem
if (!firstScreenChangeComplete)
{
firstScreenChangeComplete = true;
OnFirstScreenChange(Screen);
OnNeedNextScreen(Screen);
}
if (Screen.NextScreen != null)
{
@ -137,24 +120,34 @@ namespace RecrownedAthenaeum.ScreenSystem
/// <summary>
/// Renders screen into window.
/// Starts and ends the given <paramref name="consistentSpriteBatch"/>.
/// </summary>
/// <param name="spriteBatch">Uses this batch to render.</param>
public void DrawCurrentScreen(SpriteBatch spriteBatch)
/// <param name="consistentSpriteBatch">The consistent sprite batch to use. Needs to be consistent as changing render targets requires ending and beginning the sprite batch.</param>
public void DrawScreen(ConsistentSpriteBatch consistentSpriteBatch)
{
if (consistentSpriteBatch == null)
{
throw new ArgumentNullException(nameof(consistentSpriteBatch));
}
if (Screen == null) return;
graphics.GraphicsDevice.Clear(Screen.BackgroundColor);
if (Screen.State == ScreenState.EnterTransition && previousScreen != null && previousScreen.UseRenderTargetForExitTransition)
{
graphics.GraphicsDevice.SetRenderTarget(previousScreenRenderTarget);
graphics.GraphicsDevice.Clear(previousScreen.BackgroundColor);
batchSettings.BeginSpriteBatch(spriteBatch);
previousScreen.Draw(spriteBatch);
spriteBatch.End();
consistentSpriteBatch.Begin();
previousScreen.Draw(consistentSpriteBatch);
consistentSpriteBatch.End();
graphics.GraphicsDevice.SetRenderTarget(null);
Screen.UpdatePreviousScreenFrame(previousScreenRenderTarget);
}
batchSettings.BeginSpriteBatch(spriteBatch);
Screen.Draw(spriteBatch);
spriteBatch.End();
consistentSpriteBatch.Begin();
Screen.Draw(consistentSpriteBatch);
consistentSpriteBatch.End();
}
/// <summary>
@ -181,9 +174,9 @@ namespace RecrownedAthenaeum.ScreenSystem
Screen.AssetLoadStateChange(true);
}
private void OnFirstScreenChange(Screen screen)
private void OnNeedNextScreen(Screen screen)
{
ShowFirstScreenEvent?.Invoke(screen);
NeedNextScreen?.Invoke(screen);
}
/// <summary>
@ -201,12 +194,12 @@ namespace RecrownedAthenaeum.ScreenSystem
/// <param name="disposing">True of user invoked dispose called.</param>
public virtual void Dispose(bool disposing)
{
if (disposed) return;
if (disposed) throw new ObjectDisposedException(GetType().Name);
if (disposing)
{
previousScreenRenderTarget?.Dispose();
}
disposing = true;
disposed = true;
}
/// <summary>

View File

@ -1,5 +1,6 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RecrownedAthenaeum.Render;
namespace RecrownedAthenaeum.SpecialTypes
{
@ -16,6 +17,6 @@ namespace RecrownedAthenaeum.SpecialTypes
/// <param name="color">The color tint to draw with.</param>
/// <param name="rotation">The rotation to be used.</param>
/// <param name="origin">The origin for the rotation.</param>
void Draw(SpriteBatch spriteBatch, Rectangle destination, Color color, float rotation = 0f, Vector2 origin = default(Vector2));
void Draw(ConsistentSpriteBatch spriteBatch, Rectangle destination, Color color, float rotation = 0f, Vector2 origin = default(Vector2));
}
}

View File

@ -86,20 +86,21 @@ namespace RecrownedAthenaeum.SpecialTypes
/// Draws the ninepatch.
/// </summary>
/// <param name="spriteBatch">Batch to use.</param>
/// <param name="destination">Where to the patch.</param>
/// <param name="color">The color of the patch.</param>
/// <param name="spriteBatchSettings">The sprite batch settings to use to begin the batch in after drawing the ninepatch.</param>
public void Draw(SpriteBatch spriteBatch, Color color, Rectangle destination, SpriteBatchSettings? spriteBatchSettings = null)
/// <param name="destination">Where to the patch.</param>
public void Draw(ConsistentSpriteBatch spriteBatch, Color color, Rectangle destination)
{
if (spriteBatchSettings == null) spriteBatchSettings = Configuration.SpriteBatchSettings;
spriteBatch.End();
try
{
spriteBatch.End();
} catch (InvalidOperationException)
{
throw new InvalidOperationException("Begin must be called to draw a nine patch!");
}
SpriteBatchSettings ss = spriteBatchSettings.Value;
SamplerState nSS = ss.samplerState;
ss.samplerState = SamplerState.PointClamp;
ss.BeginSpriteBatch(spriteBatch);
SamplerState originalSamplerState = spriteBatch.SamplerState;
GraphicsDevice graphics = spriteBatch.GraphicsDevice;
spriteBatch.Begin(samplerState: SamplerState.PointClamp);
Rectangle[] destinations = GenenerateDestinationRectangles(destination.Width, destination.Height);
for (int i = 0; i < destinations.Length; i++)
@ -110,20 +111,17 @@ namespace RecrownedAthenaeum.SpecialTypes
}
spriteBatch.End();
ss.samplerState = nSS;
ss.BeginSpriteBatch(spriteBatch);
spriteBatch.Begin(samplerState: originalSamplerState);
}
/// <summary>
/// Draw with more options.
/// Uses the default <see cref="Configuration"/> for the spritebatch settings.
/// </summary>
/// <param name="spriteBatch">Spritebatch to use.</param>
/// <param name="destination">The destination to draw the patch.</param>
/// <param name="color">The tint for each patch.</param>
/// <param name="rotation">Not considered for 9patches.</param>
/// <param name="origin">Not considered for 9patches.</param>
public void Draw(SpriteBatch spriteBatch, Rectangle destination, Color color, float rotation = 0, Vector2 origin = default(Vector2))
public void Draw(ConsistentSpriteBatch spriteBatch, Rectangle destination, Color color, float rotation = 0, Vector2 origin = default(Vector2))
{
if (rotation != 0) throw new NotImplementedException("Ninepatches can't be rotated.");
if (origin != default(Vector2)) throw new NotImplementedException("Ninepatches can't have origin changed (hint: use the destination rectangle to shift and position).");

View File

@ -1,5 +1,6 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RecrownedAthenaeum.Render;
using System;
using System.Collections.Generic;
using System.Linq;
@ -56,7 +57,7 @@ namespace RecrownedAthenaeum.SpecialTypes
/// <param name="color">Color to use.</param>
/// <param name="rotation">Rotation of texture drawn.</param>
/// <param name="origin">Origin used by rotation.</param>
public void Draw(string name, SpriteBatch batch, Rectangle destination, Color color = default(Color), float rotation = 0, Vector2 origin = new Vector2())
public void Draw(string name, ConsistentSpriteBatch batch, Rectangle destination, Color color = default(Color), float rotation = 0, Vector2 origin = new Vector2())
{
dictionaryOfRegions[name].Draw(batch, destination, color, rotation, origin);
}
@ -65,11 +66,10 @@ namespace RecrownedAthenaeum.SpecialTypes
/// Creates or obtains a previously created texture of a region.
/// </summary>
/// <param name="name">Name of region.</param>
/// <param name="graphicsDevice">graphics device to be used. Default is null and will resort to using graphics device from <see cref="Configuration"/>'s graphics device manager.</param>
/// <param name="graphicsDevice">graphics device to be used to generate the texture.</param>
/// <returns>The texture from the region.</returns>
public Texture2D ObtainRegionAsTexture(string name, GraphicsDevice graphicsDevice = null)
public Texture2D ObtainRegionAsTexture(string name, GraphicsDevice graphicsDevice)
{
if (graphicsDevice == null) graphicsDevice = Configuration.GraphicsDeviceManager.GraphicsDevice;
return dictionaryOfRegions[name].AsTexture2D(graphicsDevice);
}
@ -125,7 +125,7 @@ namespace RecrownedAthenaeum.SpecialTypes
/// <summary>
/// A region of a <see cref="TextureAtlas"/>.
/// </summary>
public class Region : IComparable<Region>, ISpecialDrawable, IDisposable
public class Region : ISpecialDrawable, IDisposable
{
/// <summary>
/// The name of the region. Mostly used to be refered to within the context of a <see cref="TextureAtlas"/>.
@ -156,8 +156,8 @@ namespace RecrownedAthenaeum.SpecialTypes
{
this.atlasTexture = atlasTexture ?? throw new ArgumentNullException("Name parameters can be null.");
this.name = name ?? throw new ArgumentNullException("Name parameters can be null.");
this.sourceRectangle = sourceRegion;
this.ninepatch = ninePatch;
sourceRectangle = sourceRegion;
ninepatch = ninePatch;
}
/// <summary>
@ -168,7 +168,7 @@ namespace RecrownedAthenaeum.SpecialTypes
/// <param name="color">The color to use.</param>
/// <param name="rotation">Rotation of the final drawing. Ignored if is a 9patch.</param>
/// <param name="origin">The origin of the drawing. Ignored if is a 9patch.</param>
public void Draw(SpriteBatch batch, Rectangle destination, Color color, float rotation = 0, Vector2 origin = default(Vector2))
public void Draw(ConsistentSpriteBatch batch, Rectangle destination, Color color, float rotation = 0, Vector2 origin = default(Vector2))
{
if (Disposed) throw new ObjectDisposedException(GetType().Name);
@ -185,16 +185,15 @@ namespace RecrownedAthenaeum.SpecialTypes
/// <summary>
/// Create or obtains a previously created texture of this region.
/// </summary>
/// <param name="graphicsDevice">The graphics device to use to create the texture. Will use graphics device from <see cref="Configuration"/>'s graphics device manager if left to null.</param>
/// <param name="graphicsDevice">The graphics device to use to create the texture.</param>
/// <returns>The texture of the region.</returns>
public Texture2D AsTexture2D(GraphicsDevice graphicsDevice = null)
public Texture2D AsTexture2D(GraphicsDevice graphicsDevice)
{
if (Disposed) throw new ObjectDisposedException(GetType().Name);
if (regionTexture == null)
{
Color[] data = new Color[sourceRectangle.Width * sourceRectangle.Height];
if (graphicsDevice == null) graphicsDevice = Configuration.GraphicsDeviceManager.GraphicsDevice;
regionTexture = new Texture2D(graphicsDevice, sourceRectangle.Width, sourceRectangle.Height);
atlasTexture.GetData(0, sourceRectangle, data, 0, sourceRectangle.Width * sourceRectangle.Height);
regionTexture.SetData(data);
@ -202,16 +201,6 @@ namespace RecrownedAthenaeum.SpecialTypes
return regionTexture;
}
/// <summary>
/// Compares this region to another in terms of name.
/// </summary>
/// <param name="other">The other region to compare to in terms of name.</param>
/// <returns>Less than one if precedes, greater than one if after, 0 if same.</returns>
public int CompareTo(Region other)
{
return name.CompareTo(other);
}
/// <summary>
/// Call this to dispose.
/// </summary>

View File

@ -4,7 +4,9 @@ using Microsoft.Xna.Framework.Input;
using RecrownedAthenaeum.Camera;
using RecrownedAthenaeum.ContentSystem;
using RecrownedAthenaeum.Input;
using RecrownedAthenaeum.Render;
using RecrownedAthenaeum.UI.SkinSystem;
using System;
using System.Collections.Generic;
using System.Linq;
@ -17,46 +19,80 @@ namespace RecrownedAthenaeum.UI.BookSystem
{
readonly ContentManagerController assets;
readonly ISkin skin;
Camera2D camera;
Page targetPage;
Rectangle dimensions;
int width, height;
Dictionary<string, Page> pages = new Dictionary<string, Page>();
List<Page> orderedPages = new List<Page>();
/// <summary>
/// The camera to use to change between pages.
/// </summary>
public Camera2D camera;
/// <summary>
/// The scissorbox used to crop things.
/// </summary>
public ScissorBox scissorBox;
/// <summary>
/// Creates a book.
/// </summary>
/// <param name="assets"><see cref="ContentManagerController"/> that holds the assets that are to be used in the pages for this book during initialization.</param>
/// <param name="skin">The skin that will be passed to pages during their initialization.</param>
public Book(ContentManagerController assets, ISkin skin)
/// <param name="camera">Camera to move to change pages.</param>
/// <param name="scissorBox">The scissor box to use to crop the pages to the given dimensions. Default is null, and will not crop anything.</param>
public Book(ContentManagerController assets, ISkin skin, Camera2D camera, ScissorBox scissorBox = null)
{
this.assets = assets;
this.skin = skin;
this.camera = camera ?? throw new ArgumentNullException("Camera can't be null since book needs a camera to move to change between the slides (pages).");
this.scissorBox = scissorBox;
}
/// <summary>
/// Should be called whenever a valid camera and dimensions for the book exist.
/// Initializes book with given parameters.
/// Generally used with a <see cref="ScreenSystem.Screen"/> and called in the <see cref="ScreenSystem.Screen.Initiate(Rectangle, Camera2D)"/> function.
/// Generally used with a <see cref="ScreenSystem.Screen"/> and called in the <see cref="ScreenSystem.Screen.ApplySize(int, int)"/> function.
/// </summary>
/// <param name="camera">Camera game is currently using.</param>
/// <param name="camera">Camera to move to change pages.</param>
/// <param name="dimensions">Dimensions of the book and the dimensions the pages will use.</param>
public void Initiate(Camera2D camera, Rectangle dimensions)
/// <param name="scissorBox">The scissor box to use to crop the pages to the given dimensions. Default is null, and will not crop anything.</param>
public void Initiate(Camera2D camera, Rectangle dimensions, ScissorBox scissorBox = null)
{
this.camera = camera;
this.dimensions = dimensions;
}
/// <summary>
/// Applies the size if the book's pages.
/// </summary>
/// <param name="width">The width of one page.</param>
/// <param name="height">The height of one page.</param>
public void ApplySize(int width, int height)
{
if (this.width == width && this.height == height) return;
this.width = width;
this.height = height;
for (int pageIndex = 0; pageIndex < pages.Count; pageIndex++)
{
Page page = orderedPages[pageIndex];
if (page.Boundaries.Width != width || page.Boundaries.Height != height)
{
page.requiresSizeUpdate = true;
}
}
}
/// <summary>
/// Draws the pages.
/// </summary>
/// <param name="batch">Batch used to draw.</param>
public void Draw(SpriteBatch batch)
public void Draw(ConsistentSpriteBatch batch)
{
for (int pageIndex = 0; pageIndex < pages.Count; pageIndex++)
{
Page page = orderedPages[pageIndex];
page.Draw(batch);
orderedPages[pageIndex].Draw(batch);
}
}
@ -82,7 +118,7 @@ namespace RecrownedAthenaeum.UI.BookSystem
for (int pageIndex = 0; pageIndex < pages.Count; pageIndex++)
{
Page page = pages.ElementAt(pageIndex).Value;
if (page.requiresSizeUpdate) page.ApplySize(dimensions.Width, dimensions.Height);
if (page.requiresSizeUpdate) page.ApplySize(width, height);
page.Update(gameTime);
}
}
@ -97,6 +133,7 @@ namespace RecrownedAthenaeum.UI.BookSystem
{
orderedPages.Add(page);
this.pages.Add(page.name, page);
page.Initialize(assets, skin, scissorBox);
}
}

View File

@ -1,4 +1,5 @@
using RecrownedAthenaeum.ContentSystem;
using RecrownedAthenaeum.Render;
using RecrownedAthenaeum.UI.Modular;
using RecrownedAthenaeum.UI.SkinSystem;
@ -20,7 +21,7 @@ namespace RecrownedAthenaeum.UI.BookSystem
/// </summary>
/// <param name="pageX">The X position in the book.</param>
/// <param name="pageY">The Y position in the book.</param>
public Page(int pageX, int pageY) : base(false)
public Page(int pageX, int pageY) : base()
{
this.pageX = pageX;
this.pageY = pageY;
@ -47,9 +48,10 @@ namespace RecrownedAthenaeum.UI.BookSystem
/// </summary>
/// <param name="assets">The assets to be used during initialization passed by the book this page belongs to.</param>
/// <param name="skin">The skin the book containing this page is given that can be used by this page.</param>
protected internal virtual void Initialize(ContentManagerController assets, ISkin skin)
/// <param name="scissorBox">The scissor box to use for cropping.</param>
protected internal virtual void Initialize(ContentManagerController assets, ISkin skin, ScissorBox scissorBox)
{
this.scissorBox = scissorBox;
}
}
}

View File

@ -1,5 +1,6 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RecrownedAthenaeum.Render;
using RecrownedAthenaeum.SpecialTypes;
using System;
@ -49,7 +50,7 @@ namespace RecrownedAthenaeum.UI.Modular.Modules
/// Draws the image with default values.
/// </summary>
/// <param name="batch">The batch to use.</param>
public override void Draw(SpriteBatch batch)
public override void Draw(ConsistentSpriteBatch batch)
{
batch.Draw(texture, situation, null, color, rotation, origin, SpriteEffects.None, 0f);
base.Draw(batch);
@ -63,7 +64,7 @@ namespace RecrownedAthenaeum.UI.Modular.Modules
/// <param name="color">The color tint to use.</param>
/// <param name="rotation">Rotation of image.</param>
/// <param name="origin">Origin for the rotation.</param>
public void Draw(SpriteBatch spriteBatch, Rectangle destination, Color color, float rotation = 0, Vector2 origin = default(Vector2))
public void Draw(ConsistentSpriteBatch spriteBatch, Rectangle destination, Color color, float rotation = 0, Vector2 origin = default(Vector2))
{
this.color = color;
this.rotation = rotation;

View File

@ -4,6 +4,7 @@ using RecrownedAthenaeum.SpecialTypes;
using RecrownedAthenaeum.Input;
using RecrownedAthenaeum.UI.SkinSystem.Definitions;
using RecrownedAthenaeum.UI.SkinSystem;
using RecrownedAthenaeum.Render;
namespace RecrownedAthenaeum.UI.Modular.Modules.Interactive
{
@ -80,7 +81,7 @@ namespace RecrownedAthenaeum.UI.Modular.Modules.Interactive
/// Draws the button.
/// </summary>
/// <param name="batch">Batch used to draw the button.</param>
public override void Draw(SpriteBatch batch)
public override void Draw(ConsistentSpriteBatch batch)
{
if (disabled)
{

View File

@ -1,5 +1,6 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RecrownedAthenaeum.Render;
using RecrownedAthenaeum.SpecialTypes;
using RecrownedAthenaeum.UI.SkinSystem;
using RecrownedAthenaeum.UI.SkinSystem.Definitions;
@ -84,7 +85,7 @@ namespace RecrownedAthenaeum.UI.Modular.Modules.Interactive
/// Called whenever game wants to render this button.
/// </summary>
/// <param name="batch">Batch to use. Batch should already be started.</param>
public override void Draw(SpriteBatch batch)
public override void Draw(ConsistentSpriteBatch batch)
{
base.Draw(batch);
text.Draw(batch);

View File

@ -1,5 +1,6 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RecrownedAthenaeum.Render;
using System;
using System.Text;
@ -80,7 +81,7 @@ namespace RecrownedAthenaeum.UI.Modular.Modules
/// Draws the text.
/// </summary>
/// <param name="batch">Batch to use.</param>
public override void Draw(SpriteBatch batch)
public override void Draw(ConsistentSpriteBatch batch)
{
batch.DrawString(font, Content, position, color, 0f, default(Vector2), scale, SpriteEffects.None, 0f);
base.Draw(batch);

View File

@ -2,6 +2,7 @@
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using RecrownedAthenaeum.Input;
using RecrownedAthenaeum.Render;
using System;
namespace RecrownedAthenaeum.UI.Modular
@ -61,7 +62,7 @@ namespace RecrownedAthenaeum.UI.Modular
/// Called every frame to draw this module. Anything that needs to be drawn should go here.
/// </summary>
/// <param name="batch">Batch used to draw.</param>
public virtual void Draw(SpriteBatch batch)
public virtual void Draw(ConsistentSpriteBatch batch)
{
}

View File

@ -14,36 +14,22 @@ namespace RecrownedAthenaeum.UI.Modular
public class UIModuleGroup : UIModule
{
List<UIModule> modules = new List<UIModule>();
ScissorBox scissorBox;
/// <summary>
/// Configuration for starting sprite batch after scissoring. Only used if cropping.
/// Set this to crop anything that flows out of the boundaries of this group. Will not crop if this is null.
/// </summary>
public SpriteBatchSettings spriteBatchSettings;
public ScissorBox scissorBox;
/// <summary>
/// Creates a module group.
/// Draws this group of modules. If scissoring, will use the matrix and effect designated in the <see cref="ScissorBox"/> to begin the batch normally again.
/// </summary>
/// <param name="crop">Whether or not to crop out of bounds. Default is false.</param>
public UIModuleGroup(bool crop = false)
{
this.spriteBatchSettings = Configuration.SpriteBatchSettings.Value;
if (crop)
{
scissorBox = new ScissorBox();
}
}
/// <summary>
/// Draws this group of modules.
/// </summary>
/// <param name="batch">Batch used to draw the group.</param>
public override void Draw(SpriteBatch batch)
/// <param name="spriteBatch">Batch used to draw the group.</param>
public override void Draw(ConsistentSpriteBatch spriteBatch)
{
if (scissorBox != null)
{
batch.End();
scissorBox.Begin(Boundaries, batch, spriteBatchSettings);
spriteBatch.End();
scissorBox.Begin(Boundaries, spriteBatch);
}
foreach (UIModule module in modules)
@ -52,7 +38,7 @@ namespace RecrownedAthenaeum.UI.Modular
int offsetY = module.situation.Y;
module.situation.X = situation.X + offsetX;
module.situation.Y = situation.Y + offsetY;
module.Draw(batch);
module.Draw(spriteBatch);
module.situation.X = offsetX;
module.situation.Y = offsetY;
}
@ -61,6 +47,8 @@ namespace RecrownedAthenaeum.UI.Modular
{
scissorBox.End();
GraphicsDevice graphics = spriteBatch.GraphicsDevice;
spriteBatch.Begin();
}
}

View File

@ -1,5 +1,6 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RecrownedAthenaeum.Render;
using RecrownedAthenaeum.SpecialTypes;
using RecrownedAthenaeum.UI.SkinSystem.Definitions;
@ -24,7 +25,7 @@ namespace RecrownedAthenaeum.UI.SkinSystem
/// <param name="destination">The destination to draw to.</param>
/// <param name="rotation">The rotation to use in radians.</param>
/// <param name="origin">The origin for the rotation.</param>
void Draw(string regionName, string color, SpriteBatch batch, Rectangle destination, float rotation = 0, Vector2 origin = default(Vector2));
void Draw(string regionName, string color, ConsistentSpriteBatch batch, Rectangle destination, float rotation = 0, Vector2 origin = default(Vector2));
/// <summary>
/// Returns a <see cref="Color"/> with given name of defined color;

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RecrownedAthenaeum.Render;
using RecrownedAthenaeum.SpecialTypes;
using RecrownedAthenaeum.UI.SkinSystem.Definitions;
@ -33,7 +34,7 @@ namespace RecrownedAthenaeum.UI.SkinSystem
}
}
public void Draw(string regionName, string color, SpriteBatch batch, Rectangle destination, float rotation = 0, Vector2 origin = default(Vector2))
public void Draw(string regionName, string color, ConsistentSpriteBatch batch, Rectangle destination, float rotation = 0, Vector2 origin = default(Vector2))
{
try
{

View File

@ -1,5 +1,6 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RecrownedAthenaeum.Render;
using RecrownedAthenaeum.SpecialTypes;
using RecrownedAthenaeum.UI.SkinSystem.Definitions;
using System;
@ -80,7 +81,7 @@ namespace RecrownedAthenaeum.UI.SkinSystem
/// <param name="destination">The destination to draw to.</param>
/// <param name="rotation">The rotation to use in radians.</param>
/// <param name="origin">The origin for the rotation.</param>
public void Draw(string regionName, string color, SpriteBatch batch, Rectangle destination, float rotation = 0, Vector2 origin = default(Vector2))
public void Draw(string regionName, string color, ConsistentSpriteBatch batch, Rectangle destination, float rotation = 0, Vector2 origin = default(Vector2))
{
if (disposed) throw new ObjectDisposedException(GetType().Name);
textureAtlas.Draw(regionName, batch, destination, colors[color], rotation, origin);

View File

@ -71,7 +71,7 @@ namespace RecrownedAthenaeum.UI.SkinSystem
public ISkin Skin { get { return mergedSkin; } }
/// <summary>
/// The user loaded skin. Set by the skin loaded by calling <see cref="LoadSkin(SkinData, string, GraphicsDevice)"/>.
/// The user loaded skin resulted from asynchronous <see cref="LoadSkin(string, GraphicsDevice)"/>.
/// </summary>
public ISkin loadedSkin { get { return mergedSkin.mainSkin; } private set { mergedSkin.mainSkin = value; } }
@ -111,16 +111,14 @@ namespace RecrownedAthenaeum.UI.SkinSystem
/// <summary>
/// loads a skin asynchronously to the <see cref="loadedSkin"/>.
/// </summary>
/// <param name="graphicsDevice">Graphics device to use for texture creation. Uses graphics device from <see cref="Configuration"/>by default.</param>
/// <param name="skinData">The data to generate from.</param>
/// <param name="path">The path pointing to the file with the extension "<see cref="EXTENSION"/>".</param>
public void LoadSkin(SkinData skinData, string path, GraphicsDevice graphicsDevice = null)
/// <param name="graphicsDevice">Graphics device to use for texture creation.</param>
public void LoadSkin(string path, GraphicsDevice graphicsDevice)
{
if (graphicsDevice == null) graphicsDevice = Configuration.GraphicsDeviceManager.GraphicsDevice;
action = Action.LOAD;
this.graphicsDevice = graphicsDevice;
this.selectedSkinPath = path;
this.skinDataToUse = skinData;
this.graphicsDevice = graphicsDevice ?? throw new ArgumentNullException("Requires graphics device to create textures.");
selectedSkinPath = path ?? throw new ArgumentNullException("Requires path to find textures.");
skinDataToUse = ReadSkinData(path);
AttemptAsync();
}
@ -163,14 +161,18 @@ namespace RecrownedAthenaeum.UI.SkinSystem
}
TextureAtlasDataReader tatlasDataReader = new TextureAtlasDataReader();
TextureAtlasData atlasData;
using (FileStream fileStream = new FileStream(filePath[skinData.nameOfTextureAtlas], FileMode.Open))
{
atlasData = tatlasDataReader.ReadTextureAtlasData(new BinaryReader(fileStream));
}
atlasData = JsonConvert.DeserializeObject<TextureAtlasData>(File.ReadAllText(filePath[skinData.nameOfTextureAtlas]));
Texture2D atlasTexture;
using (FileStream stream = new FileStream(filePath[atlasData.textureName], FileMode.Open))
{
atlasTexture = Texture2D.FromStream(graphicsDevice, stream);
Vector4[] data = new Vector4[atlasTexture.Width * atlasTexture.Height];
atlasTexture.GetData(data);
for (int i = 0; i < data.Length; i++)
{
Color.FromNonPremultiplied(data[i]);
}
atlasTexture.SetData(data);
}
TextureAtlas.Region[] regions = textureAtlasDataReader.GenerateAtlasRegionsFromData(atlasData, atlasTexture);
TextureAtlas textureAtlas = new TextureAtlas(atlasTexture, regions);
@ -180,6 +182,13 @@ namespace RecrownedAthenaeum.UI.SkinSystem
using (FileStream stream = new FileStream(filePath[skinData.cursorTextureName], FileMode.Open))
{
cursorTexture = Texture2D.FromStream(graphicsDevice, stream);
Vector4[] data = new Vector4[cursorTexture.Width * cursorTexture.Height];
atlasTexture.GetData(data);
for (int i = 0; i < data.Length; i++)
{
Color.FromNonPremultiplied(data[i]);
}
cursorTexture.SetData(data);
}
}
else