2019-01-16 01:34:59 +00:00
using Microsoft.Xna.Framework ;
using Microsoft.Xna.Framework.Graphics ;
using Newtonsoft.Json ;
using RecrownedAthenaeum.Pipeline ;
2019-01-20 07:08:38 +00:00
using RecrownedAthenaeum.Data ;
2019-01-16 01:34:59 +00:00
using RecrownedAthenaeum.SpecialTypes ;
2019-01-20 07:08:38 +00:00
using RecrownedAthenaeum.UI.Skin.Definitions ;
2019-01-16 01:34:59 +00:00
using System ;
using System.Collections.Generic ;
using System.IO ;
namespace RecrownedAthenaeum.UI.Skin
{
/// <summary>
/// Manages reference to default and loading of custom skins.
/// </summary>
public class SkinManager
{
private const string EXTENSION = ".rbskin" ;
2019-01-20 07:08:38 +00:00
private readonly MergedSkin mergedSkin = new MergedSkin ( ) ;
/// <summary>
/// the skin that favors the selected skin, but still has a fallback to the default skin in case anything is missing.
/// </summary>
public ISkin Skin { get { return mergedSkin ; } }
/// <summary>
/// The user selected skin.
/// </summary>
public ISkin SelectedSkin { get { return mergedSkin . mainSkin ; } set { mergedSkin . mainSkin = value ; } }
/// <summary>
/// The fallback skin in case the selected skin doesn't cover a specific definition or color.
/// </summary>
public ISkin BaseSkin { get { return mergedSkin . alternateSkin ; } set { mergedSkin . alternateSkin = value ; } }
2019-01-16 01:34:59 +00:00
/// <summary>
/// The directory that contains the skins.
/// </summary>
public string skinsDirectory ;
2019-01-20 07:08:38 +00:00
2019-01-16 01:34:59 +00:00
List < string > skinPaths = new List < string > ( ) ;
/// <summary>
/// Updates list of skins by searching recursively in the set <see cref="skinsDirectory"/>.
/// </summary>
public void SearchForSkins ( )
{
skinPaths . Clear ( ) ;
skinPaths = RecursiveSkinSearch ( skinsDirectory ) ;
}
/// <summary>
/// Loads skin data if extension is valid.
/// </summary>
/// <param name="path">the path to load from.</param>
/// <returns>A <see cref="SkinData"/> that holds all the information and some metadata for the loaded skin.</returns>
public SkinData LoadSkinData ( string path )
{
if ( path . ToLower ( ) . EndsWith ( EXTENSION ) )
{
return JsonConvert . DeserializeObject < SkinData > ( File . ReadAllText ( path ) ) ;
}
throw new ArgumentException ( "The path given does not point to a file with the required extension \"" + EXTENSION + "\" rather, has \"" + Path . GetExtension ( path ) + "\"." ) ;
}
/// <summary>
/// Generate skin from skin data.
/// </summary>
/// <param name="skinData">The skin data to generate skin from.</param>
2019-01-20 07:08:38 +00:00
/// <param name="path">The path pointing to the file with the extension "<see cref="EXTENSION"/>".</param>
2019-01-16 01:34:59 +00:00
/// <param name="graphicsDevice">The graphics device to generate the texture.</param>
/// <returns>The skin generated from the skin data.</returns>
public Skin GenerateSkinFromData ( SkinData skinData , string path , GraphicsDevice graphicsDevice )
{
TextureAtlasDataReader textureAtlasDataReader = new TextureAtlasDataReader ( ) ;
2019-01-20 07:08:38 +00:00
FileInfo [ ] skinFiles = Directory . GetParent ( path ) . GetFiles ( ) ;
Dictionary < string , string > fileNameWithPath = new Dictionary < string , string > ( ) ;
for ( int i = 0 ; i < skinFiles . Length ; i + + )
{
fileNameWithPath . Add ( skinFiles [ i ] . Name , skinFiles [ i ] . FullName ) ;
}
TextureAtlasData atlasData = JsonConvert . DeserializeObject < TextureAtlasData > ( fileNameWithPath [ skinData . nameOfTextureAtlas ] ) ;
2019-01-16 01:34:59 +00:00
Texture2D atlasTexture ;
2019-01-20 07:08:38 +00:00
using ( FileStream stream = new FileStream ( fileNameWithPath [ atlasData . textureName ] , FileMode . Open ) )
2019-01-16 01:34:59 +00:00
{
atlasTexture = Texture2D . FromStream ( graphicsDevice , stream ) ;
}
TextureAtlas . Region [ ] regions = textureAtlasDataReader . GenerateAtlasRegionsFromData ( atlasData , atlasTexture ) ;
2019-01-20 07:08:38 +00:00
TextureAtlas textureAtlas = new TextureAtlas ( atlasTexture , regions ) ;
Texture2D cursorTexture ;
if ( Path . HasExtension ( skinData . cursorTextureName ) & & fileNameWithPath . ContainsKey ( skinData . cursorTextureName ) )
{
using ( FileStream stream = new FileStream ( fileNameWithPath [ skinData . cursorTextureName ] , FileMode . Open ) )
{
cursorTexture = Texture2D . FromStream ( graphicsDevice , stream ) ;
}
} else
{
cursorTexture = textureAtlas [ skinData . cursorTextureName ] . AsTexture2D ( graphicsDevice ) ;
}
Skin skin = new Skin ( new TextureAtlas ( atlasTexture , regions ) , cursorTexture ) ;
2019-01-16 01:34:59 +00:00
for ( int i = 0 ; i < skinData . colors . Length ; i + + )
{
SkinData . ColorData colorData = skinData . colors [ i ] ;
2019-01-20 07:08:38 +00:00
skin . AddColor ( colorData . name , new Color ( colorData . r , colorData . g , colorData . b , colorData . a ) ) ;
2019-01-16 01:34:59 +00:00
}
for ( int i = 0 ; i < skinData . definitions . Length ; i + + )
{
SkinData . DefinitionData definitionData = skinData . definitions [ i ] ;
skin . AddDefinition ( definitionData . name , definitionData . skin ) ;
}
return skin ;
}
private List < string > RecursiveSkinSearch ( string path )
{
string [ ] files = Directory . GetFiles ( path ) ;
string [ ] folders = Directory . GetDirectories ( path ) ;
List < string > skins = new List < string > ( ) ;
for ( int i = 0 ; i < files . Length ; i + + )
{
if ( files [ i ] . ToLower ( ) . EndsWith ( EXTENSION ) )
{
skins . Add ( files [ i ] ) ;
}
}
for ( int i = 0 ; i < folders . Length ; i + + )
{
skins . AddRange ( RecursiveSkinSearch ( folders [ i ] ) ) ;
}
return skins ;
}
2019-01-20 07:08:38 +00:00
2019-01-16 01:34:59 +00:00
}
}