using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Newtonsoft.Json; using RecrownedAthenaeum.Pipeline; using RecrownedAthenaeum.Data; using RecrownedAthenaeum.SpecialTypes; using RecrownedAthenaeum.UI.Skin.Definitions; using System; using System.Collections.Generic; using System.IO; namespace RecrownedAthenaeum.UI.Skin { /// /// Manages reference to default and loading of custom skins. /// public class SkinManager { private const string EXTENSION = ".rbskin"; private readonly MergedSkin mergedSkin = new MergedSkin(); /// /// the skin that favors the selected skin, but still has a fallback to the default skin in case anything is missing. /// public ISkin Skin { get { return mergedSkin; } } /// /// The user selected skin. /// public ISkin SelectedSkin { get { return mergedSkin.mainSkin; } set { mergedSkin.mainSkin = value; } } /// /// The fallback skin in case the selected skin doesn't cover a specific definition or color. /// public ISkin BaseSkin { get { return mergedSkin.alternateSkin; } set { mergedSkin.alternateSkin = value; } } /// /// The directory that contains the skins. /// public string skinsDirectory; List skinPaths = new List(); /// /// Updates list of skins by searching recursively in the set . /// public void SearchForSkins() { skinPaths.Clear(); skinPaths = RecursiveSkinSearch(skinsDirectory); } /// /// Loads skin data if extension is valid. /// /// the path to load from. /// A that holds all the information and some metadata for the loaded skin. public SkinData LoadSkinData(string path) { if (path.ToLower().EndsWith(EXTENSION)) { return JsonConvert.DeserializeObject(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) + "\"."); } /// /// Generate skin from skin data. /// /// The skin data to generate skin from. /// The path pointing to the file with the extension "". /// The graphics device to generate the texture. /// The skin generated from the skin data. public Skin GenerateSkinFromData(SkinData skinData, string path, GraphicsDevice graphicsDevice) { TextureAtlasDataReader textureAtlasDataReader = new TextureAtlasDataReader(); FileInfo[] skinFiles = Directory.GetParent(path).GetFiles(); Dictionary fileNameWithPath = new Dictionary(); for (int i = 0; i < skinFiles.Length; i++) { fileNameWithPath.Add(skinFiles[i].Name, skinFiles[i].FullName); } TextureAtlasData atlasData = JsonConvert.DeserializeObject(fileNameWithPath[skinData.nameOfTextureAtlas]); Texture2D atlasTexture; using (FileStream stream = new FileStream(fileNameWithPath[atlasData.textureName], FileMode.Open)) { atlasTexture = Texture2D.FromStream(graphicsDevice, stream); } TextureAtlas.Region[] regions = textureAtlasDataReader.GenerateAtlasRegionsFromData(atlasData, atlasTexture); 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); for (int i = 0; i < skinData.colors.Length; i++) { SkinData.ColorData colorData = skinData.colors[i]; skin.AddColor(colorData.name, new Color(colorData.r, colorData.g, colorData.b, colorData.a)); } 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 RecursiveSkinSearch(string path) { string[] files = Directory.GetFiles(path); string[] folders = Directory.GetDirectories(path); List skins = new List(); 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; } } }