2018-12-11 07:12:34 +00:00
using Microsoft.Xna.Framework ;
using Microsoft.Xna.Framework.Graphics ;
2019-01-15 23:33:55 +00:00
using RecrownedAthenaeum.SpecialTypes ;
2019-01-27 23:39:18 +00:00
using RecrownedAthenaeum.UI.SkinSystem.Definitions ;
2018-12-11 07:12:34 +00:00
using System ;
using System.Collections.Generic ;
2019-01-27 23:39:18 +00:00
namespace RecrownedAthenaeum.UI.SkinSystem
2018-12-11 07:12:34 +00:00
{
2019-01-14 06:34:35 +00:00
/// <summary>
/// A skin is used to group a theme which can then be applied to the UI via the use of modules.
/// </summary>
2019-01-20 07:08:38 +00:00
public class Skin : IDisposable , ISkin
2018-12-11 07:12:34 +00:00
{
2019-01-14 06:34:35 +00:00
/// <summary>
2019-01-20 07:08:38 +00:00
/// Whether or not this skin is completed being built and thus ready to use.
2019-01-14 06:34:35 +00:00
/// </summary>
2019-01-20 07:08:38 +00:00
public bool Laminated { get ; private set ; }
private bool disposed ;
private TextureAtlas textureAtlas ;
Dictionary < string , Color > colors ;
2019-01-29 01:43:41 +00:00
readonly Dictionary < string , Type > moduleTypeOfDefinition ;
readonly Dictionary < Type , Dictionary < string , ISkinDefinitionData > > definitions ;
2018-12-11 07:12:34 +00:00
2019-01-20 07:08:38 +00:00
/// <summary>
/// The texture for the cursor.
/// </summary>
public virtual Texture2D CursorTexture { get ; private set ; }
2019-01-14 06:34:35 +00:00
/// <summary>
2019-01-14 07:26:46 +00:00
/// Creates a basic unfilled skin.
2019-01-14 06:34:35 +00:00
/// </summary>
2019-01-14 07:26:46 +00:00
/// <param name="textureAtlas">The texture atlas to use for this skin.</param>
2019-01-20 07:08:38 +00:00
/// <param name="cursorTexture">The texture the cursor will be.</param>
public Skin ( TextureAtlas textureAtlas , Texture2D cursorTexture )
2018-12-11 07:12:34 +00:00
{
this . textureAtlas = textureAtlas ;
2019-01-20 07:08:38 +00:00
this . CursorTexture = cursorTexture ;
2018-12-11 07:12:34 +00:00
colors = new Dictionary < string , Color > ( ) ;
2019-01-29 01:43:41 +00:00
moduleTypeOfDefinition = new Dictionary < string , Type > ( ) ;
2019-01-15 23:03:17 +00:00
definitions = new Dictionary < Type , Dictionary < string , ISkinDefinitionData > > ( ) ;
2018-12-11 07:12:34 +00:00
}
2019-01-20 07:08:38 +00:00
/// <summary>
/// Returns a <see cref="TextureAtlas.Region"/> with given name of region.
/// </summary>
/// <param name="name">Name of region.</param>
2019-01-29 21:58:20 +00:00
/// <returns>The region corresponding to the name or null if the requested region doesn't exist.</returns>
2019-01-20 07:08:38 +00:00
public virtual TextureAtlas . Region GetTextureAtlasRegion ( string name )
{
2019-01-29 21:58:20 +00:00
if ( ! textureAtlas . ContainsRegion ( name ) ) return null ;
2019-01-20 07:08:38 +00:00
return textureAtlas [ name ] ;
}
/// <summary>
/// Returns a <see cref="Color"/> with given name of defined color;
/// </summary>
/// <param name="name">Name of defined color.</param>
/// <returns>The defined color based on the name given.</returns>
public virtual Color GetColor ( string name )
{
return colors [ name ] ;
}
2019-01-14 07:26:46 +00:00
/// <summary>
/// Draws a region from the texture atlas.
/// </summary>
/// <param name="regionName">Region to draw.</param>
/// <param name="color">The color to tint the region.</param>
/// <param name="batch">The batch to use.</param>
/// <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>
2019-01-20 07:08:38 +00:00
public virtual void Draw ( string regionName , string color , SpriteBatch batch , Rectangle destination , float rotation = 0 , Vector2 origin = default ( Vector2 ) )
2018-12-11 07:12:34 +00:00
{
2019-01-20 07:08:38 +00:00
if ( disposed ) throw new ObjectDisposedException ( GetType ( ) . Name ) ;
2018-12-12 02:03:35 +00:00
textureAtlas . Draw ( regionName , batch , destination , colors [ color ] , rotation , origin ) ;
}
2019-01-29 01:43:41 +00:00
private ISkinDefinitionData ObtainDefinition ( Type type , string definitionName )
2018-12-12 02:03:35 +00:00
{
2019-01-20 07:08:38 +00:00
if ( disposed ) throw new ObjectDisposedException ( GetType ( ) . Name ) ;
if ( ! Laminated ) throw new InvalidOperationException ( "Skin has yet to be laminated yet." ) ;
2018-12-14 06:43:38 +00:00
if ( definitionName = = null ) definitionName = "default" ;
2019-01-29 01:43:41 +00:00
if ( ! definitions . ContainsKey ( type ) ) throw new KeyNotFoundException ( "Could not find any skin definition defining type \"" + type . FullName + "\"" ) ;
if ( ! definitions [ type ] . ContainsKey ( definitionName ) ) throw new KeyNotFoundException ( "Could not find skin definition defining type \"" + type . Name + "\" with name \"" + definitionName + "\"" ) ;
2018-12-12 02:03:35 +00:00
return definitions [ type ] [ definitionName ] ;
}
2018-12-14 06:43:38 +00:00
/// <summary>
/// Returns the proper definition for the given parameters or throws exception in the case the requested definition does not exist.
/// </summary>
/// <typeparam name="T">Convenience to cast to the needed definition type.</typeparam>
/// <param name="definitionName">The name of the definition.</param>
/// <returns>The definition cast to T.</returns>
2019-01-29 01:43:41 +00:00
public virtual T ObtainDefinition < T > ( string definitionName = null ) where T : ISkinDefinitionData
2018-12-14 06:43:38 +00:00
{
2019-01-29 01:43:41 +00:00
return ( T ) ObtainDefinition ( moduleTypeOfDefinition [ typeof ( T ) . FullName ] , definitionName ) ;
2018-12-11 07:12:34 +00:00
}
2019-01-14 07:26:46 +00:00
/// <summary>
/// Adds the definition.
/// </summary>
2019-01-29 01:43:41 +00:00
/// <param name="definitionName">The name of the definition. Default (if left blank) name is "default".</param>
2019-01-14 07:26:46 +00:00
/// <param name="skinDefinition">The definition itself.</param>
2019-01-29 01:43:41 +00:00
public virtual void AddDefinition ( ISkinDefinitionData skinDefinition , string definitionName = null )
2018-12-11 07:12:34 +00:00
{
2019-01-20 07:08:38 +00:00
if ( disposed ) throw new ObjectDisposedException ( GetType ( ) . Name ) ;
2019-01-29 01:43:41 +00:00
if ( Laminated ) throw new InvalidOperationException ( "This skin has been laminated and cannot be edited." ) ;
if ( definitionName = = null ) definitionName = "default" ;
if ( ! definitions . ContainsKey ( moduleTypeOfDefinition [ skinDefinition . GetType ( ) . FullName ] ) )
2018-12-11 07:12:34 +00:00
{
2019-01-29 01:43:41 +00:00
moduleTypeOfDefinition . Add ( skinDefinition . GetType ( ) . FullName , skinDefinition . UIModuleType ) ;
2019-01-15 23:03:17 +00:00
definitions . Add ( skinDefinition . UIModuleType , new Dictionary < string , ISkinDefinitionData > ( ) ) ;
2019-01-29 01:43:41 +00:00
} else if ( definitions [ moduleTypeOfDefinition [ skinDefinition . GetType ( ) . FullName ] ] . ContainsKey ( definitionName ) ) throw new ArgumentException ( "Type of definition with that name already exists!" ) ;
2018-12-11 07:12:34 +00:00
2019-01-29 01:43:41 +00:00
definitions [ moduleTypeOfDefinition [ skinDefinition . GetType ( ) . FullName ] ] . Add ( definitionName , skinDefinition ) ;
2018-12-11 07:12:34 +00:00
}
2019-01-14 07:26:46 +00:00
/// <summary>
2019-01-20 07:08:38 +00:00
/// Adds color to skin.
2019-01-14 07:26:46 +00:00
/// </summary>
2019-01-20 07:08:38 +00:00
/// <param name="name"></param>
/// <param name="color"></param>
public virtual void AddColor ( string name , Color color )
2018-12-11 07:12:34 +00:00
{
2019-01-29 01:43:41 +00:00
if ( Laminated ) throw new InvalidOperationException ( "This skin has been laminated and cannot be edited." ) ;
2019-01-20 07:08:38 +00:00
colors . Add ( name , color ) ;
}
/// <summary>
/// Laminates the skin. Making sure no more additions are done and sets the skin to be ready for use.
/// Needs to be called before any use of skin. Building skin needs to be done before lamination.
/// </summary>
public void Laminate ( )
{
Laminated = true ;
}
/// <summary>
/// Disposes <see cref="textureAtlas"/> and the <see cref="Texture2D"/> holding the cursor texture.
/// </summary>
public void Dispose ( )
{
if ( disposed ) throw new ObjectDisposedException ( GetType ( ) . Name ) ;
Dispose ( true ) ;
GC . SuppressFinalize ( this ) ;
}
/// <summary>
/// Overridable dispose function.
/// </summary>
/// <param name="disposing">true when it's a user call to dispose.</param>
public virtual void Dispose ( bool disposing )
{
disposed = true ;
if ( disposing & & ! disposed )
2018-12-11 07:12:34 +00:00
{
2019-01-20 07:08:38 +00:00
textureAtlas . Dispose ( ) ;
CursorTexture . Dispose ( ) ;
2018-12-11 07:12:34 +00:00
}
}
2019-01-20 07:08:38 +00:00
/// <summary>
/// Destructor. Calls the dispose with false.
/// </summary>
~ Skin ( )
{
Dispose ( false ) ;
}
2018-12-11 07:12:34 +00:00
}
}