moved utilities for rhythmbullet to separate project for a better custom content loaders for the monogame pipeline as well as for future projects and of course learning how things work.
This commit is contained in:
parent
b61f390121
commit
698dd9d2f0
45
Recrowned-Athenaeum/Camera/Camera2D.cs
Normal file
45
Recrowned-Athenaeum/Camera/Camera2D.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
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 RhythmBullet.Utilities.Camera
|
||||||
|
{
|
||||||
|
public class Camera2D
|
||||||
|
{
|
||||||
|
public float Zoom;
|
||||||
|
public Vector2 Position;
|
||||||
|
public Matrix TransformMatrix { get; private set; }
|
||||||
|
public GraphicsDevice graphicsDevice;
|
||||||
|
|
||||||
|
public Camera2D(GraphicsDevice graphicsDevice)
|
||||||
|
{
|
||||||
|
this.graphicsDevice = graphicsDevice;
|
||||||
|
Zoom = 1f;
|
||||||
|
Position.X = this.graphicsDevice.Viewport.Width * 0.5f;
|
||||||
|
Position.Y = this.graphicsDevice.Viewport.Height * 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
Rectangle bounds = graphicsDevice.Viewport.Bounds;
|
||||||
|
TransformMatrix =
|
||||||
|
Matrix.CreateTranslation(new Vector3(-Position.X, -Position.Y, 0)) *
|
||||||
|
Matrix.CreateScale(Zoom) *
|
||||||
|
Matrix.CreateTranslation(new Vector3(bounds.Width * 0.5f, bounds.Height * 0.5f, 0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LinearInterpolationToPosition(float alpha, Vector2 targetPosition, float delta)
|
||||||
|
{
|
||||||
|
if (alpha <= 0 && alpha > 1f) throw new ArgumentException("Alpha can't be greater than 1f, less than or equal to 0.");
|
||||||
|
|
||||||
|
Vector2 distance = targetPosition - Position;
|
||||||
|
distance *= (float)(1.0f - Math.Pow(1 - alpha, delta / 0.02f));
|
||||||
|
|
||||||
|
Position += distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
Recrowned-Athenaeum/ContentSystem/ContentLoad.cs
Normal file
22
Recrowned-Athenaeum/ContentSystem/ContentLoad.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RhythmBullet.Utilities.ContentSystem
|
||||||
|
{
|
||||||
|
struct LoadableContent
|
||||||
|
{
|
||||||
|
internal Type type;
|
||||||
|
internal string assetName;
|
||||||
|
internal bool usePathModifier;
|
||||||
|
|
||||||
|
public LoadableContent(string assetName, Type type, bool usePathModifier)
|
||||||
|
{
|
||||||
|
this.type = type;
|
||||||
|
this.assetName = assetName;
|
||||||
|
this.usePathModifier = usePathModifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
157
Recrowned-Athenaeum/ContentSystem/ContentManagerController.cs
Normal file
157
Recrowned-Athenaeum/ContentSystem/ContentManagerController.cs
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
using Microsoft.Xna.Framework.Content;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RhythmBullet.Utilities.ContentSystem
|
||||||
|
{
|
||||||
|
public class ContentManagerController
|
||||||
|
{
|
||||||
|
Thread thread;
|
||||||
|
readonly ContentManager contentManager;
|
||||||
|
readonly Queue<LoadableContent> queue;
|
||||||
|
Dictionary<string, IDisposable> assets;
|
||||||
|
public readonly Dictionary<Type, IContentPathModifier> contentPathModifier;
|
||||||
|
volatile float progress;
|
||||||
|
volatile bool running;
|
||||||
|
|
||||||
|
public ContentManagerController(ContentManager contentManager)
|
||||||
|
{
|
||||||
|
this.contentManager = contentManager;
|
||||||
|
assets = new Dictionary<string, IDisposable>();
|
||||||
|
queue = new Queue<LoadableContent>();
|
||||||
|
contentPathModifier = new Dictionary<Type, IContentPathModifier>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Load(string assetName, Type type, bool usePathModifier)
|
||||||
|
{
|
||||||
|
string path = assetName;
|
||||||
|
if (usePathModifier)
|
||||||
|
{
|
||||||
|
IContentPathModifier handler = contentPathModifier[type];
|
||||||
|
path = handler.Modify(assetName);
|
||||||
|
|
||||||
|
}
|
||||||
|
assets.Add(assetName, contentManager.Load<IDisposable>(path));
|
||||||
|
|
||||||
|
Debug.WriteLine("Loaded asset: " + assetName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Get<T>(string assetName)
|
||||||
|
{
|
||||||
|
lock (queue)
|
||||||
|
{
|
||||||
|
return (T)assets[assetName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Queue<T>(string assetName, bool usePathModifier = true) where T : IDisposable
|
||||||
|
{
|
||||||
|
lock (queue)
|
||||||
|
{
|
||||||
|
if (!assets.ContainsKey(assetName))
|
||||||
|
{
|
||||||
|
queue.Enqueue(new LoadableContent(assetName, typeof(T), usePathModifier));
|
||||||
|
Debug.WriteLine("Queued asset: " + assetName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Did not queue asset due to asset with same name being loaded: " + assetName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called whenever a batch of assets should be loaded from the queue. Safe to call once every frame.
|
||||||
|
/// </summary>
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (queue.Count > 0 && (thread == null || !thread.IsAlive))
|
||||||
|
{
|
||||||
|
thread = new Thread(LoadBatch);
|
||||||
|
thread.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadBatch()
|
||||||
|
{
|
||||||
|
running = true;
|
||||||
|
int totalTasks = queue.Count;
|
||||||
|
int tasksCompleted = 0;
|
||||||
|
while (queue.Count != 0)
|
||||||
|
{
|
||||||
|
lock (queue)
|
||||||
|
{
|
||||||
|
LoadableContent content = queue.Dequeue();
|
||||||
|
Load(content.assetName, content.type, content.usePathModifier);
|
||||||
|
tasksCompleted++;
|
||||||
|
progress = (float)tasksCompleted / totalTasks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the asset from the list of assets in the system.
|
||||||
|
/// Cannot remove from queue.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">the string name used to load the asset</param>
|
||||||
|
public void Remove(string name)
|
||||||
|
{
|
||||||
|
lock (queue)
|
||||||
|
{
|
||||||
|
if (assets.ContainsKey(name))
|
||||||
|
{
|
||||||
|
assets[name].Dispose();
|
||||||
|
assets.Remove(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears the queue.
|
||||||
|
/// </summary>
|
||||||
|
public void ClearQueue()
|
||||||
|
{
|
||||||
|
lock (queue)
|
||||||
|
{
|
||||||
|
queue.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unloads everything from both queue and loaded list while properly disposing of the assets loaded.
|
||||||
|
/// </summary>
|
||||||
|
public void UnloadAll()
|
||||||
|
{
|
||||||
|
lock (queue)
|
||||||
|
{
|
||||||
|
contentManager.Unload();
|
||||||
|
assets.Clear();
|
||||||
|
ClearQueue();
|
||||||
|
Debug.WriteLine("Unloaded all assets.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Done
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return !running && queue.Count == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Progress
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
Recrowned-Athenaeum/ContentSystem/IContentPathModifier.cs
Normal file
18
Recrowned-Athenaeum/ContentSystem/IContentPathModifier.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RhythmBullet.Utilities.ContentSystem
|
||||||
|
{
|
||||||
|
public interface IContentPathModifier
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the complete path with the content folder as root.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="assetName">Is the asset's name</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
string Modify(string assetName);
|
||||||
|
}
|
||||||
|
}
|
16
Recrowned-Athenaeum/ContentSystem/NormalContentResolver.cs
Normal file
16
Recrowned-Athenaeum/ContentSystem/NormalContentResolver.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RhythmBullet.Utilities.ContentSystem
|
||||||
|
{
|
||||||
|
class NormalContentResolver : IContentPathModifier
|
||||||
|
{
|
||||||
|
public string Modify(string assetName)
|
||||||
|
{
|
||||||
|
return assetName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
160
Recrowned-Athenaeum/DataTypes/NinePatch.cs
Normal file
160
Recrowned-Athenaeum/DataTypes/NinePatch.cs
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
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 RhythmBullet.Utilities.DataTypes
|
||||||
|
{
|
||||||
|
public class NinePatch
|
||||||
|
{
|
||||||
|
public Color color;
|
||||||
|
readonly Texture2D texture;
|
||||||
|
readonly int a, b, c, d;
|
||||||
|
private Rectangle sourceRectangle;
|
||||||
|
private Rectangle drawnRectangle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A nine patch object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="texture">Texture used for the nine patch. Dimensions must be greater than their sum border counter parts.</param>
|
||||||
|
/// <param name="a">Left side.</param>
|
||||||
|
/// <param name="b">Right side.</param>
|
||||||
|
/// <param name="c">Bottom side.</param>
|
||||||
|
/// <param name="d">Top side.</param>
|
||||||
|
public NinePatch(Texture2D texture, int a, int b, int c, int d)
|
||||||
|
{
|
||||||
|
this.texture = texture;
|
||||||
|
if (a + b >= texture.Width) throw new ArgumentOutOfRangeException("a and b cannot be greater than or equal to the width of texture.");
|
||||||
|
if (c + d >= texture.Height) throw new ArgumentOutOfRangeException("c and d cannot be greater or equal to the height of the texture.");
|
||||||
|
this.a = a;
|
||||||
|
this.b = b;
|
||||||
|
this.c = c;
|
||||||
|
this.d = d;
|
||||||
|
|
||||||
|
color = Color.White;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(SpriteBatch batch, Rectangle destination)
|
||||||
|
{
|
||||||
|
//1x1
|
||||||
|
drawnRectangle.X = destination.X;
|
||||||
|
drawnRectangle.Y = destination.Y;
|
||||||
|
drawnRectangle.Width = a;
|
||||||
|
drawnRectangle.Height = c;
|
||||||
|
|
||||||
|
sourceRectangle.X = 0;
|
||||||
|
sourceRectangle.Y = 0;
|
||||||
|
sourceRectangle.Width = a;
|
||||||
|
sourceRectangle.Height = c;
|
||||||
|
|
||||||
|
batch.Draw(texture, drawnRectangle, sourceRectangle, color);
|
||||||
|
|
||||||
|
//2x1
|
||||||
|
drawnRectangle.X = destination.X + a;
|
||||||
|
drawnRectangle.Y = destination.Y;
|
||||||
|
drawnRectangle.Width = destination.Width - a - b;
|
||||||
|
drawnRectangle.Height = c;
|
||||||
|
|
||||||
|
sourceRectangle.X = a;
|
||||||
|
sourceRectangle.Y = 0;
|
||||||
|
sourceRectangle.Width = texture.Width - a - b;
|
||||||
|
sourceRectangle.Height = c;
|
||||||
|
|
||||||
|
batch.Draw(texture, drawnRectangle, sourceRectangle, color);
|
||||||
|
|
||||||
|
//3x1
|
||||||
|
drawnRectangle.X = destination.X + destination.Width - b;
|
||||||
|
drawnRectangle.Y = destination.Y;
|
||||||
|
drawnRectangle.Width = b;
|
||||||
|
drawnRectangle.Height = c;
|
||||||
|
|
||||||
|
sourceRectangle.X = texture.Width - b;
|
||||||
|
sourceRectangle.Y = 0;
|
||||||
|
sourceRectangle.Width = b;
|
||||||
|
sourceRectangle.Height = c;
|
||||||
|
|
||||||
|
batch.Draw(texture, drawnRectangle, sourceRectangle, color);
|
||||||
|
|
||||||
|
//1x2
|
||||||
|
drawnRectangle.X = destination.X;
|
||||||
|
drawnRectangle.Y = destination.Y + c;
|
||||||
|
drawnRectangle.Width = a;
|
||||||
|
drawnRectangle.Height = destination.Height - d - c;
|
||||||
|
|
||||||
|
sourceRectangle.X = 0;
|
||||||
|
sourceRectangle.Y = c;
|
||||||
|
sourceRectangle.Width = a;
|
||||||
|
sourceRectangle.Height = texture.Height - c - d;
|
||||||
|
|
||||||
|
batch.Draw(texture, drawnRectangle, sourceRectangle, color);
|
||||||
|
|
||||||
|
//2x2
|
||||||
|
drawnRectangle.X = destination.X + a;
|
||||||
|
drawnRectangle.Y = destination.Y + c;
|
||||||
|
drawnRectangle.Width = destination.Width - a - b;
|
||||||
|
drawnRectangle.Height = destination.Height - c - d;
|
||||||
|
|
||||||
|
sourceRectangle.X = a;
|
||||||
|
sourceRectangle.Y = c;
|
||||||
|
sourceRectangle.Width = texture.Width - a - b;
|
||||||
|
sourceRectangle.Height = texture.Height - c - d;
|
||||||
|
|
||||||
|
batch.Draw(texture, drawnRectangle, sourceRectangle, color);
|
||||||
|
|
||||||
|
//3x2
|
||||||
|
drawnRectangle.X = destination.X + destination.Width - b;
|
||||||
|
drawnRectangle.Y = destination.Y + c;
|
||||||
|
drawnRectangle.Width = b;
|
||||||
|
drawnRectangle.Height = destination.Height - c - d;
|
||||||
|
|
||||||
|
sourceRectangle.X = texture.Width - b;
|
||||||
|
sourceRectangle.Y = c;
|
||||||
|
sourceRectangle.Width = b;
|
||||||
|
sourceRectangle.Height = texture.Height - c - d;
|
||||||
|
|
||||||
|
batch.Draw(texture, drawnRectangle, sourceRectangle, color);
|
||||||
|
|
||||||
|
//1x3
|
||||||
|
drawnRectangle.X = destination.X;
|
||||||
|
drawnRectangle.Y = destination.Height - d;
|
||||||
|
drawnRectangle.Width = a;
|
||||||
|
drawnRectangle.Height = d;
|
||||||
|
|
||||||
|
sourceRectangle.X = a;
|
||||||
|
sourceRectangle.Y = texture.Height - d;
|
||||||
|
sourceRectangle.Width = a;
|
||||||
|
sourceRectangle.Height = d;
|
||||||
|
|
||||||
|
batch.Draw(texture, drawnRectangle, sourceRectangle, color);
|
||||||
|
|
||||||
|
//2x3
|
||||||
|
drawnRectangle.X = destination.X + a;
|
||||||
|
drawnRectangle.Y = destination.Height - d;
|
||||||
|
drawnRectangle.Width = destination.Width - a - b;
|
||||||
|
drawnRectangle.Height = d;
|
||||||
|
|
||||||
|
sourceRectangle.X = a;
|
||||||
|
sourceRectangle.Y = texture.Height - d;
|
||||||
|
sourceRectangle.Width = texture.Width - a - b;
|
||||||
|
sourceRectangle.Height = d;
|
||||||
|
|
||||||
|
batch.Draw(texture, drawnRectangle, sourceRectangle, color);
|
||||||
|
|
||||||
|
//3x3
|
||||||
|
drawnRectangle.X = destination.X + destination.Width - b;
|
||||||
|
drawnRectangle.Y = destination.Height - d;
|
||||||
|
drawnRectangle.Width = b;
|
||||||
|
drawnRectangle.Height = d;
|
||||||
|
|
||||||
|
sourceRectangle.X = texture.Width - b;
|
||||||
|
sourceRectangle.Y = texture.Height - d;
|
||||||
|
sourceRectangle.Width = b;
|
||||||
|
sourceRectangle.Height = d;
|
||||||
|
|
||||||
|
batch.Draw(texture, drawnRectangle, sourceRectangle, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
Recrowned-Athenaeum/DataTypes/Resolution.cs
Normal file
38
Recrowned-Athenaeum/DataTypes/Resolution.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RhythmBullet.Utilities.DataTypes
|
||||||
|
{
|
||||||
|
public class Resolution : IComparable<Resolution>
|
||||||
|
{
|
||||||
|
public int Width, Height;
|
||||||
|
|
||||||
|
public Resolution(int width, int height)
|
||||||
|
{
|
||||||
|
Width = width;
|
||||||
|
Height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Resolution()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public int CompareTo(Resolution other)
|
||||||
|
{
|
||||||
|
return Area() - other.Area();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Width + "x" + Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Area()
|
||||||
|
{
|
||||||
|
return Width * Height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
Recrowned-Athenaeum/Input/IInputListener.cs
Normal file
16
Recrowned-Athenaeum/Input/IInputListener.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RhythmBullet.Utilities.Input
|
||||||
|
{
|
||||||
|
public interface IInputListener
|
||||||
|
{
|
||||||
|
bool KeyboardStateChanged(KeyboardState state);
|
||||||
|
|
||||||
|
bool MouseStateChanged(MouseState state);
|
||||||
|
}
|
||||||
|
}
|
22
Recrowned-Athenaeum/Input/InputListener.cs
Normal file
22
Recrowned-Athenaeum/Input/InputListener.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
|
||||||
|
namespace RhythmBullet.Utilities.Input
|
||||||
|
{
|
||||||
|
class InputListener : IInputListener
|
||||||
|
{
|
||||||
|
public bool KeyboardStateChanged(KeyboardState state)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MouseStateChanged(MouseState state)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
73
Recrowned-Athenaeum/Input/InputUtilities.cs
Normal file
73
Recrowned-Athenaeum/Input/InputUtilities.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
using RhythmBullet.Utilities.Input;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RhythmBullet.Utilities.Input
|
||||||
|
{
|
||||||
|
public static class InputUtilities
|
||||||
|
{
|
||||||
|
public static List<IInputListener> InputListeners;
|
||||||
|
static KeyboardState keyboardState;
|
||||||
|
static MouseState mouseState;
|
||||||
|
|
||||||
|
static InputUtilities()
|
||||||
|
{
|
||||||
|
InputListeners = new List<IInputListener>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Update()
|
||||||
|
{
|
||||||
|
KeyboardState updatedKeyboardState = Keyboard.GetState();
|
||||||
|
MouseState updatedMouseState = Mouse.GetState();
|
||||||
|
bool disableKeyboard = false;
|
||||||
|
bool disableMouse = false;
|
||||||
|
foreach (IInputListener inputListener in InputListeners)
|
||||||
|
{
|
||||||
|
if (!disableKeyboard && keyboardState != updatedKeyboardState)
|
||||||
|
{
|
||||||
|
disableKeyboard = inputListener.KeyboardStateChanged(updatedKeyboardState);
|
||||||
|
}
|
||||||
|
if (!disableMouse && mouseState != updatedMouseState)
|
||||||
|
{
|
||||||
|
disableMouse = inputListener.MouseStateChanged(updatedMouseState);
|
||||||
|
}
|
||||||
|
if (disableKeyboard && disableMouse)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateStates();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool MouseClicked()
|
||||||
|
{
|
||||||
|
if (mouseState.LeftButton == ButtonState.Pressed)
|
||||||
|
{
|
||||||
|
return Mouse.GetState().LeftButton != ButtonState.Pressed;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpdateStates()
|
||||||
|
{
|
||||||
|
keyboardState = Keyboard.GetState();
|
||||||
|
mouseState = Mouse.GetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool MouseWithinBoundries(Rectangle bounds)
|
||||||
|
{
|
||||||
|
MouseState mouseState = Mouse.GetState();
|
||||||
|
if (mouseState.X >= bounds.X && mouseState.X <= (bounds.X + bounds.Width) && mouseState.Y >= bounds.Y && mouseState.Y <= (bounds.Y + bounds.Height))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,9 +4,9 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Recrowned_Athenaeum
|
namespace RhythmBullet.Utilities.ParticleSystem
|
||||||
{
|
{
|
||||||
public class Class1
|
class Particle
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
13
Recrowned-Athenaeum/Persistence/Preferences.cs
Normal file
13
Recrowned-Athenaeum/Persistence/Preferences.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace RhythmBullet.Utilities.Persistence
|
||||||
|
{
|
||||||
|
public class Preferences
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
79
Recrowned-Athenaeum/Persistence/PreferencesManager.cs
Normal file
79
Recrowned-Athenaeum/Persistence/PreferencesManager.cs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
using RhythmBullet.Preferences;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace RhythmBullet.Utilities.Persistence
|
||||||
|
{
|
||||||
|
public class PreferencesManager
|
||||||
|
{
|
||||||
|
private readonly Dictionary<Type, Preferences> preferenceList;
|
||||||
|
string savePath;
|
||||||
|
XmlSerializer xmlSerializer;
|
||||||
|
|
||||||
|
public PreferencesManager(string savePath, params Preferences[] preferences)
|
||||||
|
{
|
||||||
|
this.savePath = savePath;
|
||||||
|
Directory.CreateDirectory(savePath);
|
||||||
|
preferenceList = new Dictionary<Type, Preferences>();
|
||||||
|
Debug.WriteLine("Preference manager setting up...");
|
||||||
|
Type[] preferenceTypes = new Type[preferences.Length];
|
||||||
|
for (int prefID = 0; prefID < preferences.Length; prefID++)
|
||||||
|
{
|
||||||
|
preferenceList.Add(preferences[prefID].GetType(), preferences[prefID]);
|
||||||
|
preferenceTypes[prefID] = preferences[prefID].GetType();
|
||||||
|
Debug.WriteLine(preferences[prefID] + " added to list of preferences");
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlSerializer = new XmlSerializer(typeof(Preferences), preferenceTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetPreferences<T>() where T : Preferences
|
||||||
|
{
|
||||||
|
return (T)preferenceList[typeof(T)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Load()
|
||||||
|
{
|
||||||
|
List<Type> keys = new List<Type>(preferenceList.Keys);
|
||||||
|
|
||||||
|
foreach (Type key in keys)
|
||||||
|
{
|
||||||
|
if (!LoadSpecific(key))
|
||||||
|
{
|
||||||
|
SaveSpecific(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<Type, Preferences> prefs in preferenceList)
|
||||||
|
{
|
||||||
|
SaveSpecific(prefs.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool LoadSpecific(Type preference)
|
||||||
|
{
|
||||||
|
string path = savePath + "/" + preference.Name + ".xml";
|
||||||
|
if (File.Exists(path))
|
||||||
|
{
|
||||||
|
Stream stream = new FileStream(path, FileMode.Open);
|
||||||
|
preferenceList[preference] = (Preferences)xmlSerializer.Deserialize(stream);
|
||||||
|
stream.Close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveSpecific(Type preference)
|
||||||
|
{
|
||||||
|
Stream stream = new FileStream(savePath + "/" + preference.Name + ".xml", FileMode.Create);
|
||||||
|
xmlSerializer.Serialize(stream, preferenceList[preference]);
|
||||||
|
stream.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -31,6 +31,7 @@
|
|||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="MonoGame.Framework, Version=3.6.0.1625, Culture=neutral, processorArchitecture=MSIL" />
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
@ -41,8 +42,46 @@
|
|||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Class1.cs" />
|
<Compile Include="Camera\Camera2D.cs" />
|
||||||
|
<Compile Include="ContentSystem\ContentLoad.cs" />
|
||||||
|
<Compile Include="ContentSystem\ContentManagerController.cs" />
|
||||||
|
<Compile Include="ContentSystem\IContentPathModifier.cs" />
|
||||||
|
<Compile Include="ContentSystem\NormalContentResolver.cs" />
|
||||||
|
<Compile Include="DataTypes\NinePatch.cs" />
|
||||||
|
<Compile Include="DataTypes\Resolution.cs" />
|
||||||
|
<Compile Include="Input\IInputListener.cs" />
|
||||||
|
<Compile Include="Input\InputListener.cs" />
|
||||||
|
<Compile Include="Input\InputUtilities.cs" />
|
||||||
|
<Compile Include="obj\Debug\TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs" />
|
||||||
|
<Compile Include="obj\Debug\TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs" />
|
||||||
|
<Compile Include="obj\Debug\TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs" />
|
||||||
|
<Compile Include="ParticleSystem\Particle.cs" />
|
||||||
|
<Compile Include="Persistence\Preferences.cs" />
|
||||||
|
<Compile Include="Persistence\PreferencesManager.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="ScreenSystem\ITransition.cs" />
|
||||||
|
<Compile Include="ScreenSystem\LoadingScreen.cs" />
|
||||||
|
<Compile Include="ScreenSystem\Screen.cs" />
|
||||||
|
<Compile Include="ScreenSystem\ScreenManager.cs" />
|
||||||
|
<Compile Include="UI\Book\Book.cs" />
|
||||||
|
<Compile Include="UI\Book\Page.cs" />
|
||||||
|
<Compile Include="UI\Modular\Modules\Image.cs" />
|
||||||
|
<Compile Include="UI\Modular\Modules\Interactive\Button.cs" />
|
||||||
|
<Compile Include="UI\Modular\Modules\Interactive\TextButton.cs" />
|
||||||
|
<Compile Include="UI\Modular\Modules\TextLabel.cs" />
|
||||||
|
<Compile Include="UI\Modular\UIModule.cs" />
|
||||||
|
<Compile Include="UI\Modular\UIModuleGroup.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="obj\Debug\DesignTimeResolveAssemblyReferencesInput.cache" />
|
||||||
|
<None Include="obj\Debug\Recrowned-Athenaeum.csproj.CoreCompileInputs.cache" />
|
||||||
|
<None Include="obj\Debug\Recrowned-Athenaeum.csprojAssemblyReference.cache" />
|
||||||
|
<None Include="obj\Release\Recrowned-Athenaeum.csproj.CoreCompileInputs.cache" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="bin\Debug\" />
|
||||||
|
<Folder Include="bin\Release\" />
|
||||||
|
<Folder Include="obj\Debug\TempPE\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
48
Recrowned-Athenaeum/ScreenSystem/ITransition.cs
Normal file
48
Recrowned-Athenaeum/ScreenSystem/ITransition.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
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 RhythmBullet.Utilities.ScreenSystem
|
||||||
|
{
|
||||||
|
public interface ITransition
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Called once when the transition is needed.
|
||||||
|
/// <param name="Dimensions">The dimensions of the screen.</param>
|
||||||
|
/// </summary>
|
||||||
|
void InitiateTransition(Rectangle dimensions);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called every frame if the state of the screen this transition is placed upon is in the enter transition phase.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="delta">The time passed in seconds since the last frame.</param>
|
||||||
|
/// <param name="assetsLoaded">Whether or not if all assets have been loaded by the <see cref="ContentSystem"/>.</param>
|
||||||
|
/// <param name="previousScreenExitFrame">The frame being rendered by the screen as it exits. This can be null.</param>
|
||||||
|
/// <returns>If this returns true, then it is considered that this transition is complete.</returns>
|
||||||
|
bool EnteringTransition(double delta, bool assetsLoaded);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called every frame if the state of the screen this transition is placed upon is in the exit phase.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="delta">The time passed in seconds since the last frame.</param>
|
||||||
|
/// <param name="assetsLoaded">Whether or not if all assets have been loaded by the <see cref="ContentSystem"/>.</param>
|
||||||
|
/// <returns>If this returns true, then it is considered that this transition is complete.</returns>
|
||||||
|
bool ExitingTransition(double delta, bool assetsLoaded);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called once every frame while transition is active. Meant to draw transition.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="spriteBatch"></param>
|
||||||
|
void DrawTransition(SpriteBatch spriteBatch);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates if the previous screen uses a render target for exit transition.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="previousScreenFrame">The frame of the previous screen.</param>
|
||||||
|
void UpdatePreviousScreenFrame(RenderTarget2D previousScreenFrame);
|
||||||
|
}
|
||||||
|
}
|
136
Recrowned-Athenaeum/ScreenSystem/LoadingScreen.cs
Normal file
136
Recrowned-Athenaeum/ScreenSystem/LoadingScreen.cs
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Content;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace RhythmBullet.Utilities.ScreenSystem
|
||||||
|
{
|
||||||
|
public class LoadingScreen : Screen, ITransition
|
||||||
|
{
|
||||||
|
private const float ENTER_TIME = 2f;
|
||||||
|
private const float EXIT_TIME = 1f;
|
||||||
|
Game game;
|
||||||
|
readonly Texture2D texture;
|
||||||
|
Color color;
|
||||||
|
Rectangle textureBounds;
|
||||||
|
readonly float proportion;
|
||||||
|
bool recorded;
|
||||||
|
float rR, rG, rB;
|
||||||
|
float progR, progG, progB;
|
||||||
|
float progC = 254;
|
||||||
|
float rotation;
|
||||||
|
readonly bool rotate;
|
||||||
|
Vector2 origin;
|
||||||
|
|
||||||
|
public LoadingScreen(Game game, Texture2D screenImage, float proportion, bool rotate = false) : base(true)
|
||||||
|
{
|
||||||
|
this.game = game;
|
||||||
|
this.texture = screenImage;
|
||||||
|
this.proportion = proportion;
|
||||||
|
this.rotate = rotate;
|
||||||
|
Transitions.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Show()
|
||||||
|
{
|
||||||
|
game.IsMouseVisible = false;
|
||||||
|
base.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Hide()
|
||||||
|
{
|
||||||
|
game.IsMouseVisible = true;
|
||||||
|
base.Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
origin.X = texture.Width / 2;
|
||||||
|
origin.Y = texture.Height / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoRotate(float deltaf)
|
||||||
|
{
|
||||||
|
rotation += (2f / 3f) * (float)Math.PI * deltaf;
|
||||||
|
if (rotation >= 2 * Math.PI)
|
||||||
|
{
|
||||||
|
rotation = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawTransition(SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
spriteBatch.Draw(texture, textureBounds, null, color, rotation, origin, SpriteEffects.None, 0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool EnteringTransition(double delta, bool assetsLoaded)
|
||||||
|
{
|
||||||
|
float deltaf = (float)delta;
|
||||||
|
if (rotate)
|
||||||
|
{
|
||||||
|
DoRotate(deltaf);
|
||||||
|
}
|
||||||
|
if (assetsLoaded)
|
||||||
|
{
|
||||||
|
if (progR < 254 || progG < 254 || progB < 254)
|
||||||
|
{
|
||||||
|
if (!recorded)
|
||||||
|
{
|
||||||
|
rR = (Color.White.R - BackgroundColor.R) / ENTER_TIME;
|
||||||
|
rG = (Color.White.G - BackgroundColor.G) / ENTER_TIME;
|
||||||
|
rB = (Color.White.B - BackgroundColor.B) / ENTER_TIME;
|
||||||
|
recorded = true;
|
||||||
|
}
|
||||||
|
progR += rR * deltaf;
|
||||||
|
progR = Math.Min(progR, 254);
|
||||||
|
progG += rG * deltaf;
|
||||||
|
progG = Math.Min(progG, 254);
|
||||||
|
progB += rB * deltaf;
|
||||||
|
progB = Math.Min(progB, 254);
|
||||||
|
BackgroundColor.R = (byte)progR;
|
||||||
|
BackgroundColor.G = (byte)progG;
|
||||||
|
BackgroundColor.B = (byte)progB;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StartExitTransition(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ExitingTransition(double delta, bool assetsLoaded)
|
||||||
|
{
|
||||||
|
float deltaf = (float)delta;
|
||||||
|
if (rotate)
|
||||||
|
{
|
||||||
|
DoRotate(deltaf);
|
||||||
|
}
|
||||||
|
if (progC > 0)
|
||||||
|
{
|
||||||
|
float rate = deltaf * 255 / EXIT_TIME;
|
||||||
|
progC -= rate;
|
||||||
|
progC = Math.Max(progC, 0);
|
||||||
|
color.R = (byte)progC;
|
||||||
|
color.G = (byte)progC;
|
||||||
|
color.B = (byte)progC;
|
||||||
|
color.A = (byte)progC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
146
Recrowned-Athenaeum/ScreenSystem/Screen.cs
Normal file
146
Recrowned-Athenaeum/ScreenSystem/Screen.cs
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using RhythmBullet.Utilities.Camera;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RhythmBullet.Utilities.ScreenSystem
|
||||||
|
{
|
||||||
|
public enum ScreenState { EnterTransition, ExitTransition, Normal }
|
||||||
|
|
||||||
|
public class Screen
|
||||||
|
{
|
||||||
|
public List<ITransition> Transitions;
|
||||||
|
public bool UseRenderTargetForExitTransition;
|
||||||
|
public Color BackgroundColor;
|
||||||
|
public GraphicsDevice GraphicsDevice { get; private set; }
|
||||||
|
public Screen NextScreen { get; set; }
|
||||||
|
public Rectangle ScreenSize { get; private set; }
|
||||||
|
public bool Initiated { get; private set; }
|
||||||
|
public Camera2D Camera { get; private set; }
|
||||||
|
public Screen(bool useEnterTransition = false)
|
||||||
|
{
|
||||||
|
State = useEnterTransition ? ScreenState.EnterTransition : ScreenState.Normal;
|
||||||
|
Transitions = new List<ITransition>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called only once after initialization to give required parameters.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="graphicsDevice"></param>
|
||||||
|
/// <param name="screenSize"></param>
|
||||||
|
/// <param name="camera"></param>
|
||||||
|
public virtual void Initiate(GraphicsDevice graphicsDevice, Rectangle screenSize, Camera2D camera)
|
||||||
|
{
|
||||||
|
this.Camera = camera;
|
||||||
|
this.ScreenSize = screenSize;
|
||||||
|
GraphicsDevice = graphicsDevice;
|
||||||
|
Initiated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Update(GameTime gameTime)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Draw(SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
foreach (ITransition transition in Transitions)
|
||||||
|
{
|
||||||
|
transition.DrawTransition(spriteBatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the transition.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="delta">Time passed since last frame in seconds.</param>
|
||||||
|
/// <param name="assetsLoaded">If waiting on assets.</param>
|
||||||
|
/// <param name="previousScreenExitFrame">The previous screen's frame. May be null.</param>
|
||||||
|
/// <returns>Only returns true if exit transition is complete. Returns false otherwise.</returns>
|
||||||
|
public bool UpdateTransition(double delta, bool assetsLoaded)
|
||||||
|
{
|
||||||
|
switch (State)
|
||||||
|
{
|
||||||
|
case ScreenState.EnterTransition:
|
||||||
|
EnteringTransition(delta, assetsLoaded);
|
||||||
|
break;
|
||||||
|
case ScreenState.ExitTransition:
|
||||||
|
return ExitingTransition(delta, assetsLoaded);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnteringTransition(double delta, bool assetsLoaded)
|
||||||
|
{
|
||||||
|
bool complete = true;
|
||||||
|
for (int transitionID = 0; transitionID < Transitions.Count; transitionID++)
|
||||||
|
{
|
||||||
|
ITransition transition = Transitions[transitionID];
|
||||||
|
if (!transition.EnteringTransition(delta, assetsLoaded))
|
||||||
|
{
|
||||||
|
complete = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (complete && State != ScreenState.ExitTransition)
|
||||||
|
{
|
||||||
|
State = ScreenState.Normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ExitingTransition(double delta, bool assetsLoaded)
|
||||||
|
{
|
||||||
|
bool complete = true;
|
||||||
|
foreach (ITransition transition in Transitions)
|
||||||
|
{
|
||||||
|
if (!transition.ExitingTransition(delta, assetsLoaded))
|
||||||
|
{
|
||||||
|
complete = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return complete;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the screen is shown.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void Show()
|
||||||
|
{
|
||||||
|
foreach (ITransition transition in Transitions)
|
||||||
|
{
|
||||||
|
transition.InitiateTransition(ScreenSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Hide()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void AssetLoadStateChange(bool state)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScreenState State { get; private set; }
|
||||||
|
|
||||||
|
public void StartExitTransition(bool UseRenderTargetForExitTransition = false)
|
||||||
|
{
|
||||||
|
this.UseRenderTargetForExitTransition = UseRenderTargetForExitTransition;
|
||||||
|
State = ScreenState.ExitTransition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void UpdatePreviousScreenFrame(RenderTarget2D previousScreenFrame)
|
||||||
|
{
|
||||||
|
foreach (ITransition transition in Transitions)
|
||||||
|
{
|
||||||
|
transition.UpdatePreviousScreenFrame(previousScreenFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
137
Recrowned-Athenaeum/ScreenSystem/ScreenManager.cs
Normal file
137
Recrowned-Athenaeum/ScreenSystem/ScreenManager.cs
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using RhythmBullet.Utilities.Camera;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RhythmBullet.Utilities.ScreenSystem
|
||||||
|
{
|
||||||
|
public delegate void FirstScreenChange(Screen screen);
|
||||||
|
|
||||||
|
public class ScreenManager : IDisposable
|
||||||
|
{
|
||||||
|
public event FirstScreenChange RequireNextScreenEvent;
|
||||||
|
private GraphicsDeviceManager graphics;
|
||||||
|
private Screen previousScreen;
|
||||||
|
private RenderTarget2D previousScreenRenderTarget;
|
||||||
|
private Screen currentScreen;
|
||||||
|
private Camera2D camera;
|
||||||
|
private bool firstScreenChangeComplete;
|
||||||
|
public Screen Screen
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return currentScreen;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
previousScreen = currentScreen;
|
||||||
|
currentScreen = value;
|
||||||
|
if (!Screen.Initiated)
|
||||||
|
{
|
||||||
|
Screen.Initiate(graphics.GraphicsDevice, new Rectangle(0, 0, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight), camera);
|
||||||
|
}
|
||||||
|
if (previousScreen != null && previousScreenRenderTarget == null && previousScreen.UseRenderTargetForExitTransition)
|
||||||
|
{
|
||||||
|
previousScreenRenderTarget = new RenderTarget2D(graphics.GraphicsDevice, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight);
|
||||||
|
}
|
||||||
|
graphics.GraphicsDevice.SetRenderTarget(previousScreenRenderTarget);
|
||||||
|
graphics.GraphicsDevice.Clear(Color.Black);
|
||||||
|
|
||||||
|
Debug.WriteLine("Showing " + value.GetType().Name);
|
||||||
|
Screen.Show();
|
||||||
|
previousScreen?.Hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScreenManager(GraphicsDeviceManager graphicsDeviceManager, Camera2D camera)
|
||||||
|
{
|
||||||
|
this.graphics = graphicsDeviceManager;
|
||||||
|
this.camera = camera;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateCurrentScreen(GameTime gameTime, bool assetsDone)
|
||||||
|
{
|
||||||
|
switch (Screen.State)
|
||||||
|
{
|
||||||
|
case ScreenState.EnterTransition:
|
||||||
|
if (previousScreen != null && previousScreen.UseRenderTargetForExitTransition)
|
||||||
|
{
|
||||||
|
previousScreen.UpdateTransition(gameTime.ElapsedGameTime.TotalSeconds, assetsDone);
|
||||||
|
}
|
||||||
|
Screen.UpdateTransition(gameTime.ElapsedGameTime.TotalSeconds, assetsDone);
|
||||||
|
break;
|
||||||
|
case ScreenState.ExitTransition:
|
||||||
|
if (Screen.UseRenderTargetForExitTransition || Screen.UpdateTransition(gameTime.ElapsedGameTime.TotalSeconds, assetsDone))
|
||||||
|
{
|
||||||
|
if (!firstScreenChangeComplete)
|
||||||
|
{
|
||||||
|
firstScreenChangeComplete = true;
|
||||||
|
OnFirstScreenChange(Screen);
|
||||||
|
}
|
||||||
|
if (Screen.NextScreen != null)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Changing to the next given screen.");
|
||||||
|
Screen = Screen.NextScreen;
|
||||||
|
}
|
||||||
|
else if (previousScreen != null)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Changing to previous screen.");
|
||||||
|
Screen = previousScreen;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("No next screen provided and no previous screen to return to.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Screen.Update(gameTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawCurrentScreen(SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
graphics.GraphicsDevice.Clear(Screen.BackgroundColor);
|
||||||
|
if (Screen.State == ScreenState.EnterTransition && previousScreen != null && previousScreen.UseRenderTargetForExitTransition)
|
||||||
|
{
|
||||||
|
graphics.GraphicsDevice.SetRenderTarget(previousScreenRenderTarget);
|
||||||
|
graphics.GraphicsDevice.Clear(previousScreen.BackgroundColor);
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, camera.TransformMatrix);
|
||||||
|
previousScreen.Draw(spriteBatch);
|
||||||
|
spriteBatch.End();
|
||||||
|
graphics.GraphicsDevice.SetRenderTarget(null);
|
||||||
|
Screen.UpdatePreviousScreenFrame(previousScreenRenderTarget);
|
||||||
|
}
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, camera.TransformMatrix);
|
||||||
|
Screen.Draw(spriteBatch);
|
||||||
|
spriteBatch.End();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Resize(LoadingScreen loadingScreen)
|
||||||
|
{
|
||||||
|
Screen.AssetLoadStateChange(true);
|
||||||
|
Screen = loadingScreen;
|
||||||
|
previousScreenRenderTarget.Dispose();
|
||||||
|
previousScreenRenderTarget = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostResize()
|
||||||
|
{
|
||||||
|
Screen.AssetLoadStateChange(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnFirstScreenChange(Screen screen)
|
||||||
|
{
|
||||||
|
RequireNextScreenEvent?.Invoke(screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
previousScreenRenderTarget?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
93
Recrowned-Athenaeum/UI/Book/Book.cs
Normal file
93
Recrowned-Athenaeum/UI/Book/Book.cs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using RhythmBullet.Utilities.Camera;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RhythmBullet.UI.Book
|
||||||
|
{
|
||||||
|
class Book
|
||||||
|
{
|
||||||
|
Camera2D camera;
|
||||||
|
Page targetPage;
|
||||||
|
Rectangle dimensions;
|
||||||
|
Dictionary<string, Page> pages = new Dictionary<string, Page>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should be called whenever a valid camera and dimensions for the book exist.
|
||||||
|
/// Initializes book with given parameters.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="camera">Camera game is currently using.</param>
|
||||||
|
/// <param name="dimensions">Dimensions of the book and the dimensions the pages will use.</param>
|
||||||
|
public void Initiate(Camera2D camera, Rectangle dimensions)
|
||||||
|
{
|
||||||
|
this.camera = camera;
|
||||||
|
this.dimensions = dimensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(SpriteBatch batch)
|
||||||
|
{
|
||||||
|
for (int pageIndex = 0; pageIndex < pages.Count; pageIndex++)
|
||||||
|
{
|
||||||
|
Page page = pages.ElementAt(pageIndex).Value;
|
||||||
|
page.Draw(batch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(GameTime gameTime)
|
||||||
|
{
|
||||||
|
if (targetPage != null)
|
||||||
|
{
|
||||||
|
Vector2 position;
|
||||||
|
Rectangle targetBounds = targetPage.bounds;
|
||||||
|
position.X = targetBounds.X + (targetBounds.Width * 0.5f);
|
||||||
|
position.Y = targetBounds.Y + (targetBounds.Height * 0.5f);
|
||||||
|
camera.LinearInterpolationToPosition(0.4f, position, (float)gameTime.ElapsedGameTime.TotalSeconds);
|
||||||
|
if (camera.Position == position)
|
||||||
|
{
|
||||||
|
targetPage = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int pageIndex = 0; pageIndex < pages.Count; pageIndex++)
|
||||||
|
{
|
||||||
|
Page page = pages.ElementAt(pageIndex).Value;
|
||||||
|
if (page.NeedsSizeUpdate) page.ApplySize(dimensions.Width, dimensions.Height);
|
||||||
|
page.Update(gameTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddPages(params Page[] pages)
|
||||||
|
{
|
||||||
|
foreach (Page page in pages)
|
||||||
|
{
|
||||||
|
this.pages.Add(page.Name, page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemovePage(Page page)
|
||||||
|
{
|
||||||
|
RemovePage(page.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemovePage(string name)
|
||||||
|
{
|
||||||
|
pages.Remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LerpToPage(Page page)
|
||||||
|
{
|
||||||
|
targetPage = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GoToPage(Page page)
|
||||||
|
{
|
||||||
|
Rectangle targetBounds = page.bounds;
|
||||||
|
camera.Position.X = targetBounds.X + (targetBounds.Width * 0.5f);
|
||||||
|
camera.Position.Y = targetBounds.Y + (targetBounds.Height * 0.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
Recrowned-Athenaeum/UI/Book/Page.cs
Normal file
35
Recrowned-Athenaeum/UI/Book/Page.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using RhythmBullet.UI.Modular;
|
||||||
|
using RhythmBullet.Utilities.Camera;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RhythmBullet.UI.Book
|
||||||
|
{
|
||||||
|
class Page : UIModuleGroup
|
||||||
|
{
|
||||||
|
private readonly int pageX, pageY;
|
||||||
|
public bool NeedsSizeUpdate;
|
||||||
|
|
||||||
|
public Page(int pageX, int pageY) : base(false)
|
||||||
|
{
|
||||||
|
this.pageX = pageX;
|
||||||
|
this.pageY = pageY;
|
||||||
|
NeedsSizeUpdate = true;
|
||||||
|
Name = ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void ApplySize(int width, int height)
|
||||||
|
{
|
||||||
|
bounds.X = pageX * width;
|
||||||
|
bounds.Y = pageY * height;
|
||||||
|
bounds.Width = width;
|
||||||
|
bounds.Height = height;
|
||||||
|
NeedsSizeUpdate = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
63
Recrowned-Athenaeum/UI/Modular/Modules/Image.cs
Normal file
63
Recrowned-Athenaeum/UI/Modular/Modules/Image.cs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using RhythmBullet.UI.Modular;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RhythmBullet.Utilities.UI.Modular.Modules
|
||||||
|
{
|
||||||
|
class Image : UIModule
|
||||||
|
{
|
||||||
|
public float rotation = 0f;
|
||||||
|
public Texture2D Texture { get; set; }
|
||||||
|
public float ScaleX
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (float)bounds.Width / Texture.Width;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
bounds.Width = (int)(Texture.Width * value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float ScaleY
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (float)bounds.Height / Texture.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
bounds.Height = (int)(Texture.Height * value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Scale
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
bounds.Height = (int)(Texture.Height * value);
|
||||||
|
bounds.Width = (int)(Texture.Width * value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image(Texture2D texture)
|
||||||
|
{
|
||||||
|
Texture = texture ?? throw new ArgumentException("Image requires a texture.");
|
||||||
|
bounds = texture.Bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(SpriteBatch batch)
|
||||||
|
{
|
||||||
|
batch.Draw(Texture, bounds, null, color, rotation, origin, SpriteEffects.None, 0f);
|
||||||
|
base.Draw(batch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
Recrowned-Athenaeum/UI/Modular/Modules/Interactive/Button.cs
Normal file
62
Recrowned-Athenaeum/UI/Modular/Modules/Interactive/Button.cs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
using RhythmBullet.UI.Modular;
|
||||||
|
using RhythmBullet.Utilities.DataTypes;
|
||||||
|
using RhythmBullet.Utilities.Input;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RhythmBullet.Utilities.UI.Modular.Modules.Interactive
|
||||||
|
{
|
||||||
|
public delegate bool Clicked();
|
||||||
|
|
||||||
|
public class Button : UIModule
|
||||||
|
{
|
||||||
|
private NinePatch background;
|
||||||
|
public event Clicked Listeners;
|
||||||
|
|
||||||
|
public Button(NinePatch background = null)
|
||||||
|
{
|
||||||
|
this.background = background;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(SpriteBatch batch)
|
||||||
|
{
|
||||||
|
background?.Draw(batch, bounds);
|
||||||
|
base.Draw(batch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed override bool MouseStateChanged(MouseState state)
|
||||||
|
{
|
||||||
|
if (InputUtilities.MouseWithinBoundries(bounds))
|
||||||
|
{
|
||||||
|
if (InputUtilities.MouseClicked())
|
||||||
|
{
|
||||||
|
OnClick();
|
||||||
|
}
|
||||||
|
Highlighted = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Highlighted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.MouseStateChanged(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed override bool KeyboardStateChanged(KeyboardState state)
|
||||||
|
{
|
||||||
|
return base.KeyboardStateChanged(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void OnClick()
|
||||||
|
{
|
||||||
|
Listeners?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Highlighted { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using RhythmBullet.UI.Modular.Modules;
|
||||||
|
using RhythmBullet.Utilities.DataTypes;
|
||||||
|
using RhythmBullet.Utilities.UI.Modular.Modules.Interactive;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RhythmBullet.Utilities.UI.Modular.Modules.Interactive
|
||||||
|
{
|
||||||
|
internal class TextButton : Button
|
||||||
|
{
|
||||||
|
private TextLabel label;
|
||||||
|
|
||||||
|
internal TextButton(string text, SpriteFont font, NinePatch background) : base(background)
|
||||||
|
{
|
||||||
|
label = new TextLabel(font, text);
|
||||||
|
label.autoScale = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(GameTime gameTime)
|
||||||
|
{
|
||||||
|
label.bounds = bounds;
|
||||||
|
label.Update(gameTime);
|
||||||
|
base.Update(gameTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(SpriteBatch batch)
|
||||||
|
{
|
||||||
|
label.Draw(batch);
|
||||||
|
base.Draw(batch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
146
Recrowned-Athenaeum/UI/Modular/Modules/TextLabel.cs
Normal file
146
Recrowned-Athenaeum/UI/Modular/Modules/TextLabel.cs
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using RhythmBullet.Utilities.Camera;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RhythmBullet.UI.Modular.Modules
|
||||||
|
{
|
||||||
|
public class TextLabel : UIModule
|
||||||
|
{
|
||||||
|
private SpriteFont font;
|
||||||
|
private float scale;
|
||||||
|
private Vector2 position;
|
||||||
|
private string originalText;
|
||||||
|
private string displayedText;
|
||||||
|
private Vector2 modifiedTextSize;
|
||||||
|
public bool autoWrap;
|
||||||
|
public bool autoScale;
|
||||||
|
public bool useEllipses;
|
||||||
|
public string ellipsis = "...";
|
||||||
|
private string ModifiedText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return displayedText;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
displayedText = value;
|
||||||
|
modifiedTextSize = font.MeasureString(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string Text
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return originalText;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == null) value = "...";
|
||||||
|
modifiedTextSize = font.MeasureString(value);
|
||||||
|
originalText = value;
|
||||||
|
displayedText = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextLabel(SpriteFont font, string text = null)
|
||||||
|
{
|
||||||
|
Text = text;
|
||||||
|
this.font = font;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(GameTime gameTime)
|
||||||
|
{
|
||||||
|
position.X = bounds.X;
|
||||||
|
position.Y = bounds.Y;
|
||||||
|
|
||||||
|
if (useEllipses) AttemptToApplyEllipsis();
|
||||||
|
if (autoWrap) AttemptToWrapText();
|
||||||
|
if (autoScale) AttemptToScaleFont();
|
||||||
|
|
||||||
|
base.Update(gameTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(SpriteBatch batch)
|
||||||
|
{
|
||||||
|
batch.DrawString(font, Text, position, color, 0f, origin, scale, SpriteEffects.None, 0f);
|
||||||
|
base.Draw(batch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AttemptToApplyEllipsis()
|
||||||
|
{
|
||||||
|
if (modifiedTextSize.X * scale > bounds.Width && ModifiedText.Length > ellipsis.Length + 1)
|
||||||
|
{
|
||||||
|
RemoveLineBreaks();
|
||||||
|
StringBuilder stringBuilder = new StringBuilder(ModifiedText);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
stringBuilder.Remove(stringBuilder.Length, ellipsis.Length - 1);
|
||||||
|
stringBuilder.Insert(stringBuilder.Length, ellipsis);
|
||||||
|
}
|
||||||
|
while (font.MeasureString(stringBuilder).X * scale > bounds.Width);
|
||||||
|
|
||||||
|
ModifiedText = stringBuilder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AttemptToScaleFont()
|
||||||
|
{
|
||||||
|
if (modifiedTextSize.X * scale > bounds.Width || modifiedTextSize.X * scale < bounds.Width - 5)
|
||||||
|
{
|
||||||
|
scale = bounds.Width / modifiedTextSize.X;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modifiedTextSize.Y * scale > bounds.Height || modifiedTextSize.Y * scale < bounds.Height - 5)
|
||||||
|
{
|
||||||
|
scale = bounds.Height / modifiedTextSize.Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveLineBreaks()
|
||||||
|
{
|
||||||
|
ModifiedText = ModifiedText.Replace("\n", " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetToOriginalText()
|
||||||
|
{
|
||||||
|
ModifiedText = originalText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AttemptToWrapText(bool unwrap = false)
|
||||||
|
{
|
||||||
|
if (unwrap) RemoveLineBreaks();
|
||||||
|
if (modifiedTextSize.X * scale > bounds.Width)
|
||||||
|
{
|
||||||
|
ModifiedText = ModifiedText.Replace("\n", " ");
|
||||||
|
string[] words = ModifiedText.Split(' ');
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
float currentScaledLineWidth = 0f;
|
||||||
|
|
||||||
|
for (int w = 0; w < words.Length; w++)
|
||||||
|
{
|
||||||
|
string word = words[w];
|
||||||
|
float scaledWidth = font.MeasureString(word).X * scale;
|
||||||
|
|
||||||
|
if (currentScaledLineWidth + scaledWidth <= bounds.Width)
|
||||||
|
{
|
||||||
|
stringBuilder.Append(word);
|
||||||
|
currentScaledLineWidth += scaledWidth;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stringBuilder.AppendLine();
|
||||||
|
currentScaledLineWidth = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ModifiedText = stringBuilder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
74
Recrowned-Athenaeum/UI/Modular/UIModule.cs
Normal file
74
Recrowned-Athenaeum/UI/Modular/UIModule.cs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
using RhythmBullet.Utilities.Camera;
|
||||||
|
using RhythmBullet.Utilities.Input;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RhythmBullet.UI.Modular
|
||||||
|
{
|
||||||
|
public class UIModule : IInputListener
|
||||||
|
{
|
||||||
|
public Rectangle bounds;
|
||||||
|
public Vector2 origin;
|
||||||
|
public UIModuleGroup Parent;
|
||||||
|
public string Name;
|
||||||
|
public Color color = Color.White;
|
||||||
|
|
||||||
|
public virtual void Update(GameTime gameTime)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Draw(SpriteBatch batch)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rectangle ConvertToParentCoordinates(Rectangle bounds)
|
||||||
|
{
|
||||||
|
if (Parent != null)
|
||||||
|
{
|
||||||
|
Rectangle parentHitbox = Parent.ConvertToParentCoordinates(bounds);
|
||||||
|
int tX = bounds.X + parentHitbox.X;
|
||||||
|
int tY = bounds.Y + parentHitbox.Y;
|
||||||
|
return new Rectangle(tX, tY, bounds.Width, bounds.Height);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveFromParent()
|
||||||
|
{
|
||||||
|
if (Parent == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Parent is null.");
|
||||||
|
}
|
||||||
|
Parent.RemoveModule(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called whenever the keyboard state is changed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">The current keyboard state.</param>
|
||||||
|
/// <returns>Returning whether or not to continue to call the next listener.</returns>
|
||||||
|
public virtual bool KeyboardStateChanged(KeyboardState state)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called whenever the state of the mouse changes. This includes movement.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">The current state of the mouse.</param>
|
||||||
|
/// <returns>Returning whether or not to continue to call the next listener.</returns>
|
||||||
|
public virtual bool MouseStateChanged(MouseState state)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
109
Recrowned-Athenaeum/UI/Modular/UIModuleGroup.cs
Normal file
109
Recrowned-Athenaeum/UI/Modular/UIModuleGroup.cs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
using RhythmBullet.Utilities.Camera;
|
||||||
|
using RhythmBullet.Utilities.Input;
|
||||||
|
|
||||||
|
namespace RhythmBullet.UI.Modular
|
||||||
|
{
|
||||||
|
public class UIModuleGroup : UIModule
|
||||||
|
{
|
||||||
|
List<UIModule> modules = new List<UIModule>();
|
||||||
|
Rectangle scissorBounds;
|
||||||
|
RasterizerState scissorRasterizer = new RasterizerState();
|
||||||
|
public Camera2D Camera { get; set; }
|
||||||
|
|
||||||
|
public UIModuleGroup(bool crop = false, Camera2D camera = null)
|
||||||
|
{
|
||||||
|
Camera = camera;
|
||||||
|
if (crop)
|
||||||
|
{
|
||||||
|
scissorRasterizer.ScissorTestEnable = true;
|
||||||
|
scissorBounds = new Rectangle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(SpriteBatch batch)
|
||||||
|
{
|
||||||
|
if (scissorBounds != null)
|
||||||
|
{
|
||||||
|
batch.End();
|
||||||
|
batch.Begin(SpriteSortMode.Deferred, null, null, null, scissorRasterizer, null, Camera?.TransformMatrix);
|
||||||
|
scissorBounds.Width = bounds.Width;
|
||||||
|
scissorBounds.Height = bounds.Height;
|
||||||
|
scissorBounds.X = bounds.X;
|
||||||
|
scissorBounds.Y = bounds.Y;
|
||||||
|
Rectangle scissor = scissorBounds;
|
||||||
|
scissorBounds = batch.GraphicsDevice.ScissorRectangle;
|
||||||
|
batch.GraphicsDevice.ScissorRectangle = scissor;
|
||||||
|
}
|
||||||
|
foreach (UIModule module in modules)
|
||||||
|
{
|
||||||
|
int offsetX = module.bounds.X;
|
||||||
|
int offsetY = module.bounds.Y;
|
||||||
|
module.bounds.X = bounds.X + offsetX - (int)module.origin.X;
|
||||||
|
module.bounds.Y = bounds.Y + offsetY - (int)module.origin.Y;
|
||||||
|
module.Draw(batch);
|
||||||
|
module.bounds.X = offsetX;
|
||||||
|
module.bounds.Y = offsetY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scissorBounds != null)
|
||||||
|
{
|
||||||
|
batch.GraphicsDevice.ScissorRectangle = scissorBounds;
|
||||||
|
batch.End();
|
||||||
|
batch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, Camera?.TransformMatrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(GameTime gameTime)
|
||||||
|
{
|
||||||
|
foreach (UIModule module in modules)
|
||||||
|
{
|
||||||
|
module.Update(gameTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddModule(params UIModule[] addModules)
|
||||||
|
{
|
||||||
|
foreach (UIModule module in addModules)
|
||||||
|
{
|
||||||
|
if (modules.Contains(module))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(module.ToString() + " already exists in " + this.ToString());
|
||||||
|
}
|
||||||
|
module.Parent = this;
|
||||||
|
modules.Add(module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveModule(UIModule module)
|
||||||
|
{
|
||||||
|
module.Parent = null;
|
||||||
|
modules.Remove(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool KeyboardStateChanged(KeyboardState state)
|
||||||
|
{
|
||||||
|
foreach (UIModule module in modules)
|
||||||
|
{
|
||||||
|
module.KeyboardStateChanged(state);
|
||||||
|
}
|
||||||
|
return base.KeyboardStateChanged(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool MouseStateChanged(MouseState state)
|
||||||
|
{
|
||||||
|
foreach (UIModule module in modules)
|
||||||
|
{
|
||||||
|
module.MouseStateChanged(state);
|
||||||
|
}
|
||||||
|
return base.MouseStateChanged(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user