using RecrownedAthenaeum.Input;
using RecrownedAthenaeum.Assets;
using RecrownedAthenaeum.Render;
using RecrownedAthenaeum.UI.SkinSystem;
using System;
using System.Collections.Generic;
using System.Linq;
using RecrownedAthenaeum.Types;
namespace RecrownedAthenaeum.UI.BookSystem
{
///
/// Contains the pages.
///
public class Book : IInputListener
{
readonly AssetManager assets;
readonly ISkin skin;
Page targetPage;
int width, height;
Dictionary pages = new Dictionary();
List orderedPages = new List();
///
/// The camera to use to change between pages.
///
public Camera2D camera;
private BasicScissor basicScissor;
///
/// Creates a book.
///
/// that holds the assets that are to be used in the pages for this book during initialization.
/// The skin that will be passed to pages during their initialization.
/// Camera to move to change pages.
public Book(AssetManager assets, ISkin skin, Camera2D camera)
{
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.basicScissor = new BasicScissor();
}
///
/// Should be called whenever a valid camera and dimensions for the book exist.
/// Initializes book with given parameters.
/// Generally used with a and called in the function.
///
/// Camera to move to change pages.
/// Dimensions of the book and the dimensions the pages will use.
public void Initiate(Camera2D camera, Rectangle dimensions)
{
this.camera = camera;
}
///
/// Applies the size if the book's pages.
///
/// The width of one page.
/// The height of one page.
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;
}
}
}
///
/// Draws the pages.
///
/// Batch used to draw.
public void Draw(ConsistentSpriteBatch batch)
{
for (int pageIndex = 0; pageIndex < pages.Count; pageIndex++)
{
orderedPages[pageIndex].Draw(batch);
}
}
///
/// Updates the book.
///
/// Snapshot of information of the game time.
public void Update(GameTime gameTime)
{
if (targetPage != null)
{
Vector2 position;
Rectangle targetBounds = targetPage.Boundaries;
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.requiresSizeUpdate) page.ApplySize(width, height);
page.Update(gameTime);
}
}
///
/// Adds the page(s).
///
/// The page(s) to add.
public void AddPages(params Page[] pages)
{
foreach (Page page in pages)
{
orderedPages.Add(page);
this.pages.Add(page.name, page);
page.Initialize(assets, skin, basicScissor);
}
}
///
/// Removes the page.
///
/// Page to remove.
public void RemovePage(Page page)
{
RemovePage(page.name);
}
///
/// Removes the page.
///
/// Name of page to remove.
public void RemovePage(string name)
{
orderedPages.Remove(pages[name]);
pages.Remove(name);
}
///
/// Removes all pages.
///
public void ClearPages()
{
orderedPages.Clear();
pages.Clear();
}
///
/// Perform a step of linear interpolation to the given page.
///
/// The page to lerp to.
public void LerpToPage(Page page)
{
targetPage = page;
}
///
/// Goes to page instantly.
///
/// Page to go to.
public void GoToPage(Page page)
{
Rectangle targetBounds = page.Boundaries;
camera.position.X = targetBounds.X + (targetBounds.Width * 0.5f);
camera.position.Y = targetBounds.Y + (targetBounds.Height * 0.5f);
}
///
/// Passes the new keyboard state down to each page in order of when it was added.
///
///
/// True if the state change should to trigger further input listeners.
public bool KeyboardStateChanged(KeyboardState state)
{
for (int pageIndex = 0; pageIndex < pages.Count; pageIndex++)
{
Page page = orderedPages[pageIndex];
if (!page.KeyboardStateChanged(state)) return false;
}
return true;
}
///
/// Passes the new mouse state down to each page in order of when it was added.
///
///
/// True if the state change should to trigger further input listeners.
public bool MouseStateChanged(MouseState state)
{
for (int pageIndex = 0; pageIndex < pages.Count; pageIndex++)
{
Page page = orderedPages[pageIndex];
if (!page.MouseStateChanged(state)) return false;
}
return true;
}
}
}