2019-12-28 21:41:06 +00:00
using RecrownedAthenaeum.Graphics.Render ;
2019-11-24 20:49:53 +00:00
using RecrownedAthenaeum.Types ;
2019-12-28 21:41:06 +00:00
using RecrownedAthenaeum.Graphics.UI.SkinSystem.Definitions ;
2018-12-11 07:12:34 +00:00
using System ;
using System.Collections.Generic ;
2019-12-28 21:41:06 +00:00
using OpenTK.Graphics ;
using OpenTK ;
2018-12-11 07:12:34 +00:00
2019-12-28 21:41:06 +00:00
namespace RecrownedAthenaeum.Graphics.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 ;
2019-12-28 21:41:06 +00:00
Dictionary < string , Color4 > colors ;
2019-04-09 04:58:27 +00:00
readonly Dictionary < string , string > definitionOfType ;
2019-01-29 22:22:14 +00:00
readonly Dictionary < string , Dictionary < string , SkinDefinitionData > > 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 ;
2019-12-28 21:41:06 +00:00
colors = new Dictionary < string , Color4 > ( ) ;
2019-04-09 04:58:27 +00:00
definitionOfType = new Dictionary < string , string > ( ) ;
2019-01-29 22:22:14 +00:00
definitions = new Dictionary < string , Dictionary < string , SkinDefinitionData > > ( ) ;
2018-12-11 07:12:34 +00:00
}
2019-01-20 07:08:38 +00:00
/// <summary>
2019-01-29 21:59:35 +00:00
/// Returns a <see cref="TextureAtlas.Region"/> with given name of region. Null values acceptable. Will return null if parameter is null.
2019-01-20 07:08:38 +00:00
/// </summary>
/// <param name="name">Name of region.</param>
2019-03-08 05:43:25 +00:00
/// <param name="required">Whether or not this texture is mandatory for the module to work. If true, will throw error on failing to retrieve.</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-03-08 05:43:25 +00:00
public TextureAtlas . Region GetTextureAtlasRegion ( string name , bool required = false )
2019-01-20 07:08:38 +00:00
{
2019-03-08 05:43:25 +00:00
if ( ! required & & ( name = = null | | ! textureAtlas . ContainsRegion ( name ) ) )
{
return null ;
} else
{
return textureAtlas [ name ] ;
}
2019-01-20 07:08:38 +00:00
}
/// <summary>
/// Returns a <see cref="Color"/> with given name of defined color;
/// </summary>
2019-01-29 22:54:24 +00:00
/// <param name="name">Name of defined color. Will use "default" if null. Default value is null.</param>
2019-01-20 07:08:38 +00:00
/// <returns>The defined color based on the name given.</returns>
2019-12-28 21:41:06 +00:00
public Color4 GetColor ( string name = null )
2019-01-20 07:08:38 +00:00
{
2019-01-29 22:54:24 +00:00
if ( name = = null ) name = "default" ;
2019-01-20 07:08:38 +00:00
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-03-24 00:04:43 +00:00
public void Draw ( string regionName , string color , ConsistentSpriteBatch 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 22:22:14 +00:00
private SkinDefinitionData ObtainDefinition ( string typeFullName , 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 22:22:14 +00:00
if ( ! definitions . ContainsKey ( typeFullName ) ) throw new KeyNotFoundException ( "Could not find any skin definition defining type \"" + typeFullName + "\"" ) ;
if ( ! definitions [ typeFullName ] . ContainsKey ( definitionName ) ) throw new KeyNotFoundException ( "Could not find skin definition defining type \"" + typeFullName + "\" with name \"" + definitionName + "\"" ) ;
return definitions [ typeFullName ] [ definitionName ] ;
2018-12-12 02:03:35 +00:00
}
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 22:54:24 +00:00
public T ObtainDefinition < T > ( string definitionName = null ) where T : SkinDefinitionData
2018-12-14 06:43:38 +00:00
{
2019-04-09 04:58:27 +00:00
return ( T ) ObtainDefinition ( definitionOfType [ 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 22:54:24 +00:00
public void AddDefinition ( SkinDefinitionData 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" ;
2019-01-29 22:22:14 +00:00
if ( ! definitions . ContainsKey ( skinDefinition . uiModuleTypeFullName ) )
2018-12-11 07:12:34 +00:00
{
2019-04-09 04:58:27 +00:00
definitionOfType . Add ( skinDefinition . GetType ( ) . FullName , skinDefinition . uiModuleTypeFullName ) ;
2019-01-29 22:22:14 +00:00
definitions . Add ( skinDefinition . uiModuleTypeFullName , new Dictionary < string , SkinDefinitionData > ( ) ) ;
2019-03-08 05:43:25 +00:00
}
else if ( definitions [ skinDefinition . uiModuleTypeFullName ] . ContainsKey ( definitionName ) ) throw new ArgumentException ( "Type of definition with that name already exists!" ) ;
2018-12-11 07:12:34 +00:00
2019-01-29 22:22:14 +00:00
definitions [ skinDefinition . uiModuleTypeFullName ] . 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>
2019-12-28 21:41:06 +00:00
public void AddColor ( string name , Color4 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
}
}