Async added for skin manager.
This commit is contained in:
		@@ -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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user