2018-11-30 02:41:06 +00:00
using Microsoft.Xna.Framework ;
using Microsoft.Xna.Framework.Graphics ;
2019-03-09 06:55:44 +00:00
using Microsoft.Xna.Framework.Input ;
2018-12-04 13:45:09 +00:00
using RecrownedAthenaeum.Camera ;
2019-01-27 21:24:31 +00:00
using RecrownedAthenaeum.ContentSystem ;
2019-03-09 06:55:44 +00:00
using RecrownedAthenaeum.Input ;
2019-03-24 00:04:43 +00:00
using RecrownedAthenaeum.Render ;
2019-01-27 23:43:17 +00:00
using RecrownedAthenaeum.UI.SkinSystem ;
2019-03-24 00:04:43 +00:00
using System ;
2018-11-30 02:41:06 +00:00
using System.Collections.Generic ;
using System.Linq ;
2019-01-27 23:39:18 +00:00
namespace RecrownedAthenaeum.UI.BookSystem
2018-11-30 02:41:06 +00:00
{
2019-01-14 06:34:35 +00:00
/// <summary>
/// Contains the pages.
/// </summary>
2019-03-09 06:55:44 +00:00
public class Book : IInputListener
2018-11-30 02:41:06 +00:00
{
2019-01-27 21:24:31 +00:00
readonly ContentManagerController assets ;
2019-01-28 00:11:45 +00:00
readonly ISkin skin ;
2018-11-30 02:41:06 +00:00
Page targetPage ;
2019-03-24 00:04:43 +00:00
int width , height ;
2018-11-30 02:41:06 +00:00
Dictionary < string , Page > pages = new Dictionary < string , Page > ( ) ;
2019-03-09 06:55:44 +00:00
List < Page > orderedPages = new List < Page > ( ) ;
2018-11-30 02:41:06 +00:00
2019-03-24 00:04:43 +00:00
/// <summary>
/// The camera to use to change between pages.
/// </summary>
public Camera2D camera ;
/// <summary>
/// The scissorbox used to crop things.
/// </summary>
public ScissorBox scissorBox ;
2019-01-27 21:24:31 +00:00
/// <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>
2019-01-27 23:43:17 +00:00
/// <param name="skin">The skin that will be passed to pages during their initialization.</param>
2019-03-24 00:04:43 +00:00
/// <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 )
2019-01-27 21:24:31 +00:00
{
this . assets = assets ;
2019-01-28 00:31:19 +00:00
this . skin = skin ;
2019-03-24 00:04:43 +00:00
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 ;
2019-01-27 21:24:31 +00:00
}
2018-11-30 02:41:06 +00:00
/// <summary>
/// Should be called whenever a valid camera and dimensions for the book exist.
/// Initializes book with given parameters.
2019-03-24 00:04:43 +00:00
/// Generally used with a <see cref="ScreenSystem.Screen"/> and called in the <see cref="ScreenSystem.Screen.ApplySize(int, int)"/> function.
2018-11-30 02:41:06 +00:00
/// </summary>
2019-03-24 00:04:43 +00:00
/// <param name="camera">Camera to move to change pages.</param>
2018-11-30 02:41:06 +00:00
/// <param name="dimensions">Dimensions of the book and the dimensions the pages will use.</param>
2019-03-24 00:04:43 +00:00
/// <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 )
2018-11-30 02:41:06 +00:00
{
this . camera = camera ;
2019-03-24 00:04:43 +00:00
}
/// <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 ;
}
}
2018-11-30 02:41:06 +00:00
}
2019-01-14 06:34:35 +00:00
/// <summary>
/// Draws the pages.
/// </summary>
/// <param name="batch">Batch used to draw.</param>
2019-03-24 00:04:43 +00:00
public void Draw ( ConsistentSpriteBatch batch )
2018-11-30 02:41:06 +00:00
{
for ( int pageIndex = 0 ; pageIndex < pages . Count ; pageIndex + + )
{
2019-03-24 00:04:43 +00:00
orderedPages [ pageIndex ] . Draw ( batch ) ;
2018-11-30 02:41:06 +00:00
}
}
2019-01-14 06:34:35 +00:00
/// <summary>
/// Updates the book.
/// </summary>
/// <param name="gameTime">Snapshot of information of the game time.</param>
2018-11-30 02:41:06 +00:00
public void Update ( GameTime gameTime )
{
if ( targetPage ! = null )
{
Vector2 position ;
2019-03-09 06:55:44 +00:00
Rectangle targetBounds = targetPage . situation ;
2018-11-30 02:41:06 +00:00
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 ;
2019-03-24 00:04:43 +00:00
if ( page . requiresSizeUpdate ) page . ApplySize ( width , height ) ;
2018-11-30 02:41:06 +00:00
page . Update ( gameTime ) ;
}
}
2019-01-14 06:34:35 +00:00
/// <summary>
/// Adds the page(s).
/// </summary>
/// <param name="pages">The page(s) to add.</param>
2018-11-30 02:41:06 +00:00
public void AddPages ( params Page [ ] pages )
{
foreach ( Page page in pages )
{
2019-03-09 06:55:44 +00:00
orderedPages . Add ( page ) ;
2019-03-10 06:49:25 +00:00
this . pages . Add ( page . name , page ) ;
2019-03-24 00:04:43 +00:00
page . Initialize ( assets , skin , scissorBox ) ;
2018-11-30 02:41:06 +00:00
}
}
2019-01-14 06:34:35 +00:00
/// <summary>
/// Removes the page.
/// </summary>
/// <param name="page">Page to remove.</param>
2018-11-30 02:41:06 +00:00
public void RemovePage ( Page page )
{
2019-03-10 06:49:25 +00:00
RemovePage ( page . name ) ;
2018-11-30 02:41:06 +00:00
}
2019-01-14 06:34:35 +00:00
/// <summary>
/// Removes the page.
/// </summary>
/// <param name="name">Name of page to remove.</param>
2018-11-30 02:41:06 +00:00
public void RemovePage ( string name )
{
2019-03-09 06:55:44 +00:00
orderedPages . Remove ( pages [ name ] ) ;
2018-11-30 02:41:06 +00:00
pages . Remove ( name ) ;
}
2019-03-09 06:55:44 +00:00
/// <summary>
/// Removes all pages.
/// </summary>
public void ClearPages ( )
{
orderedPages . Clear ( ) ;
pages . Clear ( ) ;
}
2019-01-14 06:34:35 +00:00
/// <summary>
/// Perform a step of linear interpolation to the given page.
/// </summary>
/// <param name="page">The page to lerp to.</param>
2018-11-30 02:41:06 +00:00
public void LerpToPage ( Page page )
{
targetPage = page ;
}
2019-01-14 06:34:35 +00:00
/// <summary>
/// Goes to page instantly.
/// </summary>
/// <param name="page">Page to go to.</param>
2018-11-30 02:41:06 +00:00
public void GoToPage ( Page page )
{
2019-03-09 06:55:44 +00:00
Rectangle targetBounds = page . situation ;
2019-02-06 06:12:08 +00:00
camera . position . X = targetBounds . X + ( targetBounds . Width * 0.5f ) ;
camera . position . Y = targetBounds . Y + ( targetBounds . Height * 0.5f ) ;
2018-11-30 02:41:06 +00:00
}
2019-03-09 06:55:44 +00:00
/// <summary>
/// Passes the new keyboard state down to each page in order of when it was added.
/// </summary>
/// <param name="state"></param>
/// <returns>True if the state change should to trigger further input listeners.</returns>
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 ;
}
/// <summary>
/// Passes the new mouse state down to each page in order of when it was added.
/// </summary>
/// <param name="state"></param>
/// <returns>True if the state change should to trigger further input listeners.</returns>
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 ;
}
2018-11-30 02:41:06 +00:00
}
}