Async added for skin manager.

This commit is contained in:
Harrison Deng 2019-01-20 18:05:40 -06:00
parent 019b955577
commit 1ae2b0cf8d

View File

@ -4,21 +4,56 @@ 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;
using System.Threading;
namespace RecrownedAthenaeum.UI.Skin
{
/// <summary>
/// Called when the skin manager has completed a async action.
/// </summary>
/// <param name="actionCompleted">The completed action.</param>
public delegate void AsyncComplete(SkinManager.Action actionCompleted);
/// <summary>
/// Manages reference to default and loading of custom skins.
/// </summary>
public class SkinManager
{
private const string EXTENSION = ".rbskin";
private readonly MergedSkin mergedSkin = new MergedSkin();
private Thread thread;
private Action action;
private GraphicsDevice graphicsDevice;
private string selectedSkinPath;
private SkinData skinDataToUse;
/// <summary>
/// The list of paths for all found skins by <see cref="SearchSkinDirectory"/>. May be null.
/// </summary>
public volatile List<string> skinPaths;
/// <summary>
/// The event that is called when a state changes.
/// </summary>
public event AsyncComplete AsyncCompleteEvent;
/// <summary>
/// The various possible states a skin manager could be in.
/// </summary>
public enum Action
{
/// <summary>
/// After a search has completed.
/// </summary>
SEARCH,
/// <summary>
/// Having the skin generated to be in a useable state.
/// </summary>
GENERATE
}
/// <summary>
/// the skin that favors the selected skin, but still has a fallback to the default skin in case anything is missing.
@ -40,15 +75,13 @@ namespace RecrownedAthenaeum.UI.Skin
/// </summary>
public string skinsDirectory;
List<string> skinPaths = new List<string>();
/// <summary>
/// Updates list of skins by searching recursively in the set <see cref="skinsDirectory"/>.
/// Performs a recursive asynchronous search of the directory given in a path set by <see cref="skinsDirectory"/>.
/// </summary>
public void SearchForSkins()
public void SearchSkinDirectory()
{
skinPaths.Clear();
skinPaths = RecursiveSkinSearch(skinsDirectory);
action = Action.SEARCH;
AttemptAsync();
}
/// <summary>
@ -66,13 +99,49 @@ namespace RecrownedAthenaeum.UI.Skin
}
/// <summary>
/// Generate skin from skin data.
/// Generates a skin asynchronously.
/// </summary>
/// <param name="skinData">The skin data to generate skin from.</param>
/// <param name="graphicsDevice">Graphics device to use for texture creation.</param>
/// <param name="skinData">The data to generate from.</param>
/// <param name="path">The path pointing to the file with the extension "<see cref="EXTENSION"/>".</param>
/// <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)
public void GenerateSkin(GraphicsDevice graphicsDevice, SkinData skinData, string path)
{
action = Action.GENERATE;
this.graphicsDevice = graphicsDevice;
this.selectedSkinPath = path;
this.skinDataToUse = skinData;
AttemptAsync();
}
private void AttemptAsync()
{
if (thread != null && thread.IsAlive) throw new InvalidOperationException("Already performing task: " + action);
thread = new Thread(ThreadStart);
}
private void ThreadStart()
{
switch (action)
{
case Action.SEARCH:
SearchForSkins();
OnAsyncComplete(action);
break;
case Action.GENERATE:
SelectedSkin = GenerateSkinFromData(skinDataToUse, selectedSkinPath, graphicsDevice);
OnAsyncComplete(action);
break;
}
}
private void SearchForSkins()
{
skinPaths.Clear();
skinPaths = RecursiveSkinSearch(skinsDirectory);
}
private Skin GenerateSkinFromData(SkinData skinData, string path, GraphicsDevice graphicsDevice)
{
TextureAtlasDataReader textureAtlasDataReader = new TextureAtlasDataReader();
FileInfo[] skinFiles = Directory.GetParent(path).GetFiles();
@ -96,7 +165,8 @@ namespace RecrownedAthenaeum.UI.Skin
{
cursorTexture = Texture2D.FromStream(graphicsDevice, stream);
}
} else
}
else
{
cursorTexture = textureAtlas[skinData.cursorTextureName].AsTexture2D(graphicsDevice);
}
@ -137,5 +207,9 @@ namespace RecrownedAthenaeum.UI.Skin
return skins;
}
private void OnAsyncComplete(Action newState)
{
AsyncCompleteEvent?.Invoke(newState);
}
}
}