using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using RecrownedAthenaeum.Graphics.Render; using System.Collections.Generic; namespace RecrownedAthenaeum.UI.ScreenSystem { /// /// Represents one of the poosible states a screen can be in. /// public enum ScreenState { /// /// Screen is transitioning in. /// EnterTransition, /// /// Screen is transitioning out. /// ExitTransition, /// /// Screen is currently displayed normally without transition. /// Normal } /// /// A screen represents a virtual system of management that controls an system of items to be displayed. /// public class Screen { /// /// Transitions to apply. /// public readonly List Transitions; /// /// Whether or not to continue rendering this screen onto a buffer for the benefit of the next screen to use as a transition. /// public bool UseRenderTargetForExitTransition { get; private set; } /// /// The background color to be used to clear the screen. /// public Color BackgroundColor; /// /// The next screen to be displayed after exit transition finishes. May be null, leading to transition to previous screen or loading screen. /// public Screen NextScreen { get; set; } /// /// The current window dimensions. /// public int width, height; /// /// Current state of the screen. /// public ScreenState State { get; private set; } /// /// Creates a new screen. /// /// True to start in entering transition state. public Screen(bool useEnterTransition = false) { State = useEnterTransition ? ScreenState.EnterTransition : ScreenState.Normal; Transitions = new List(); } /// /// Called when screen size is set. /// /// The width of the screen. /// The height of the screen. public virtual void ApplySize(int width, int height) { this.width = width; this.height = height; } /// /// Called to update the screen. /// /// Game time information. public virtual void Update(GameTime gameTime) { } /// /// Called to draw this screen. /// /// SpriteBatch to use. public virtual void Draw(ConsistentSpriteBatch spriteBatch) { foreach (ITransition transition in Transitions) { transition.DrawTransition(spriteBatch); } } /// /// Updates the transition based on the current state of the screen. /// /// Time passed since last frame in seconds. /// If the this transition should wait. /// Only returns true if exit transition is complete. Returns false otherwise. public bool UpdateTransition(double delta, bool waiting) { switch (State) { case ScreenState.EnterTransition: EnteringTransition(delta, waiting); break; case ScreenState.ExitTransition: return ExitingTransition(delta, waiting); } return false; } private void EnteringTransition(double delta, bool waiting) { bool complete = true; for (int transitionID = 0; transitionID < Transitions.Count; transitionID++) { ITransition transition = Transitions[transitionID]; if (!transition.UpdateEnteringTransition(delta, waiting)) { complete = false; } } if (complete && State != ScreenState.ExitTransition) { State = ScreenState.Normal; } } private bool ExitingTransition(double delta, bool waiting) { bool complete = true; foreach (ITransition transition in Transitions) { if (!transition.UpdateExitingTransition(delta, waiting)) { complete = false; } } return complete; } /// /// Called when the screen is shown. /// public virtual void Show() { foreach (ITransition transition in Transitions) { transition.InitiateTransition(new Rectangle(0, 0, width, height)); } } /// /// Called when this screen is no longer the displayed screen. /// public virtual void Hide() { } /// /// Called whenever the status of assets changes from being loaded to unloaded or unloaded to loaded. /// /// True for loaded, false for unloaded. public virtual void AssetLoadStateChange(bool state) { } /// /// Call this to begin exit transition. /// /// Whether or not to use a render target for the next screen to use. public void StartExitTransition(bool UseRenderTargetForExitTransition = false) { this.UseRenderTargetForExitTransition = UseRenderTargetForExitTransition; State = ScreenState.ExitTransition; } /// /// Called everytime the previous screen frame buffer updates. Used for transition purposes. /// /// The previous screen's render buffer. public virtual void UpdatePreviousScreenFrame(RenderTarget2D previousScreenFrame) { foreach (ITransition transition in Transitions) { transition.UpdatePreviousScreenFrame(previousScreenFrame); } } } }