From ab4bcea61a3511885b31f938300a08a19b2050d0 Mon Sep 17 00:00:00 2001 From: NM <35472796+NM-20@users.noreply.github.com> Date: Wed, 12 Oct 2022 17:58:01 -0400 Subject: [PATCH 1/3] [Editor, Core, & ModManager] Improved Loaded Plugins List UI and improved PluginManager --- FrostyEditor/BuildDate.txt | 2 +- FrostyEditor/Windows/MainWindow.xaml | 69 +- FrostyEditor/Windows/MainWindow.xaml.cs | 14 +- FrostyModManager/BuildDate.txt | 2 +- FrostyModManager/Windows/MainWindow.xaml | 1469 ++++++++++++++----- FrostyModManager/Windows/MainWindow.xaml.cs | 14 +- FrostyPlugin/FrostyCore.csproj | 10 + FrostyPlugin/Images/Cross_White.png | Bin 0 -> 419 bytes FrostyPlugin/Images/Invalid_White.png | Bin 0 -> 270 bytes FrostyPlugin/Images/Tick_White.png | Bin 0 -> 430 bytes FrostyPlugin/Plugin.cs | 108 ++ FrostyPlugin/PluginLoadStatus.cs | 26 + FrostyPlugin/PluginLoadType.cs | 23 + FrostyPlugin/PluginManager.cs | 442 +++--- FrostyPlugin/PluginManagerType.cs | 29 + FrostyPlugin/ShaderDefinition.cs | 47 + Plugins/BlankPlugin/BuildDate.txt | 2 +- Plugins/LaunchPlatformPlugin/BuildDate.txt | 2 +- 18 files changed, 1637 insertions(+), 622 deletions(-) create mode 100644 FrostyPlugin/Images/Cross_White.png create mode 100644 FrostyPlugin/Images/Invalid_White.png create mode 100644 FrostyPlugin/Images/Tick_White.png create mode 100644 FrostyPlugin/Plugin.cs create mode 100644 FrostyPlugin/PluginLoadStatus.cs create mode 100644 FrostyPlugin/PluginLoadType.cs create mode 100644 FrostyPlugin/PluginManagerType.cs create mode 100644 FrostyPlugin/ShaderDefinition.cs diff --git a/FrostyEditor/BuildDate.txt b/FrostyEditor/BuildDate.txt index b5326c725..e79ce8caf 100644 --- a/FrostyEditor/BuildDate.txt +++ b/FrostyEditor/BuildDate.txt @@ -1 +1 @@ -Wed 10/12/2022 15:03:43.07 \ No newline at end of file +Wed 10/12/2022 17:36:47.21 diff --git a/FrostyEditor/Windows/MainWindow.xaml b/FrostyEditor/Windows/MainWindow.xaml index 2ba7b578c..bdc828c55 100644 --- a/FrostyEditor/Windows/MainWindow.xaml +++ b/FrostyEditor/Windows/MainWindow.xaml @@ -6,6 +6,7 @@ xmlns:local="clr-namespace:FrostyEditor" xmlns:ctrl2="clr-namespace:Frosty.Controls;assembly=FrostyControls" xmlns:core="clr-namespace:Frosty.Core.Controls;assembly=FrostyCore" + xmlns:coreroot="clr-namespace:Frosty.Core;assembly=FrostyCore" xmlns:conv="clr-namespace:Frosty.Core.Converters;assembly=FrostyCore" xmlns:cmd="clr-namespace:FrostyEditor.Commands" xmlns:ext="clr-namespace:FrostyEditor.Extensions" @@ -33,6 +34,15 @@ + + + + + + + @@ -661,7 +671,11 @@ - + @@ -702,10 +716,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FrostyEditor/Windows/MainWindow.xaml.cs b/FrostyEditor/Windows/MainWindow.xaml.cs index 95c97fc3a..49b9bee89 100644 --- a/FrostyEditor/Windows/MainWindow.xaml.cs +++ b/FrostyEditor/Windows/MainWindow.xaml.cs @@ -125,7 +125,7 @@ public MainWindow() LoadTabExtensions(); LoadDataExplorerMenuItemExtensions(); - LoadedPluginsList.ItemsSource = App.PluginManager.LoadedPlugins; + LoadedPluginsList.ItemsSource = App.PluginManager.Plugins; if (toolsMenuItem.Items.Count != 0) toolsMenuItem.Items.Add(new Separator()); @@ -1522,5 +1522,17 @@ public void RefreshRecentProjects() recentProjectsMenuItem.Items.Add(m_clearRecentsMenuItem); recentProjectsMenuItem.IsEnabled = true; } + + private void CopyFullExceptionMenuItem_Click(object sender, RoutedEventArgs e) + { + Plugin selectedPlugin = (Plugin)LoadedPluginsList.SelectedItem; + + // retrieve the selected plugin's load exception, execute ToString on it, and add the result to the clipboard + Clipboard.SetText(string.Format("[{0}]\n{1}", new string[] + { + DateTime.Now.ToString(), + selectedPlugin.LoadException.ToString() + })); + } } } diff --git a/FrostyModManager/BuildDate.txt b/FrostyModManager/BuildDate.txt index b5326c725..e79ce8caf 100644 --- a/FrostyModManager/BuildDate.txt +++ b/FrostyModManager/BuildDate.txt @@ -1 +1 @@ -Wed 10/12/2022 15:03:43.07 \ No newline at end of file +Wed 10/12/2022 17:36:47.21 diff --git a/FrostyModManager/Windows/MainWindow.xaml b/FrostyModManager/Windows/MainWindow.xaml index 7a053d9e7..214699021 100644 --- a/FrostyModManager/Windows/MainWindow.xaml +++ b/FrostyModManager/Windows/MainWindow.xaml @@ -1,50 +1,86 @@  - + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:local="clr-namespace:FrostyModManager" + xmlns:ctrl="clr-namespace:Frosty.Controls;assembly=FrostyControls" + xmlns:localctrl="clr-namespace:FrostyModManager.Controls" + xmlns:conv="clr-namespace:Frosty.Core.Converters;assembly=FrostyCore" + xmlns:coreroot="clr-namespace:Frosty.Core;assembly=FrostyCore" + mc:Ignorable="d" + Title="Frosty Mod Manager" + Height="750" + Width="1050" + Icon="/FrostyModManager;component/AppIcon.ico" + FrostyLoaded="FrostyWindow_FrostyLoaded" + Closing="FrostyWindow_Closing" + AllowDrop="True" + Drop="FrostyWindow_Drop"> - - - - - + + + + + + + - - + + - - - - + + + + - + - - + + - - - + + + - + - - + + - + - - + + - + - - + + - + - + - + - - - - - - - + @@ -222,84 +395,133 @@ - - + + - + - - - + + + - + - + - + - - + + - - + + - + - - + + - - + + - + - - + + - + - + @@ -491,31 +856,51 @@ - + - + - - + + - - + + - + - - + + - - + + - + @@ -523,24 +908,37 @@ - - + + - - + + - - + + - + - + @@ -549,141 +947,266 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - + - + - + - - - + + + - + @@ -824,59 +1462,102 @@ - + - + - - + + - + - - - - + + + + - + - + - + - + - + - - - + + + - - + + - - + + - - + + - + @@ -884,26 +1565,40 @@ - + - + - + - - - + + + - + - + diff --git a/FrostyModManager/Windows/MainWindow.xaml.cs b/FrostyModManager/Windows/MainWindow.xaml.cs index c768ab5a0..e22cde6f1 100644 --- a/FrostyModManager/Windows/MainWindow.xaml.cs +++ b/FrostyModManager/Windows/MainWindow.xaml.cs @@ -477,7 +477,7 @@ private void FrostyWindow_FrostyLoaded(object sender, EventArgs e) { } - LoadedPluginsList.ItemsSource = App.PluginManager.LoadedPlugins; + LoadedPluginsList.ItemsSource = App.PluginManager.Plugins; if (Config.Get("ApplyModOrder", "List") == "List") { @@ -1915,5 +1915,17 @@ private void orderComboBox_SelectionChanged(object sender, SelectionChangedEvent updateAppliedModButtons(); } + + private void CopyFullExceptionMenuItem_Click(object sender, RoutedEventArgs e) + { + Plugin selectedPlugin = (Plugin)LoadedPluginsList.SelectedItem; + + // retrieve the selected plugin's load exception, execute ToString on it, and add the result to the clipboard + Clipboard.SetText(string.Format("[{0}]\n{1}", new string[] + { + DateTime.Now.ToString(), + selectedPlugin.LoadException.ToString() + })); + } } } \ No newline at end of file diff --git a/FrostyPlugin/FrostyCore.csproj b/FrostyPlugin/FrostyCore.csproj index 26a912180..037024d96 100644 --- a/FrostyPlugin/FrostyCore.csproj +++ b/FrostyPlugin/FrostyCore.csproj @@ -172,6 +172,11 @@ + + + + + @@ -416,5 +421,10 @@ + + + + + \ No newline at end of file diff --git a/FrostyPlugin/Images/Cross_White.png b/FrostyPlugin/Images/Cross_White.png new file mode 100644 index 0000000000000000000000000000000000000000..1d3a3480364b6fc01bf887aa02db17bca535e928 GIT binary patch literal 419 zcmV;U0bKrxP)p-dDg75v}BX z1y~VPLh{O&e29P)5y9j>0kNyNiNlF}k}EJ(oCp_h?#>_Dg4E;|TZtVcz!2XyabnS^>T%wTTtUk=QEYySGodMnJAu)xSPQwQ!_8OsM=J9(7%+>8zJJLnWx@E4cW)izom(swS1RU~ zD=?}w)G;nG^kKMokLi7T3RjBg@07G~|G526t(X`*B?V4By?Ewa;e=Vaaw?*~R!k77 z3qQtu;_KQwlb^~SF6=eW6i$eL{MN?tUUdS;n#Ri0LGy5AA`Hat!uyJS)%ULnfylfSB&BcpzNb2O81>sIE3(H_-eI7!18TLIL7H z%*MIA;sA(gx1?bNMK+K=cX#}7g*ZeO4wGmwf&Vacj=3an8|4$pF07*qoM6N<$f(5O>o&W#< literal 0 HcmV?d00001 diff --git a/FrostyPlugin/Plugin.cs b/FrostyPlugin/Plugin.cs new file mode 100644 index 000000000..27cdbf45a --- /dev/null +++ b/FrostyPlugin/Plugin.cs @@ -0,0 +1,108 @@ +using Frosty.Core.Attributes; +using System; +using System.IO; +using System.Reflection; + +namespace Frosty.Core +{ + public class Plugin + { + // Entirely refactored this class to simply make it better overall + + /// + /// The author of this . + /// + public string Author + { + get + { + // Create a string for storing the retrieved author of this plugin's associated assembly + string author = Assembly?.GetCustomAttribute()?.Author; + + // If the author is not null or empty, return it; otherwise, return unknown + return !string.IsNullOrEmpty(author) ? author : "Unknown"; + } + } + + /// + /// The assembly associated with this . + /// + public Assembly Assembly + { + get; + set; + } + + /// + /// An exception that may have occurred as a result of loading this . + /// + public Exception LoadException + { + get; + set; + } + + /// + /// The display name of this . + /// + public string Name + { + get + { + // Create a string for storing the retrieved display name of this plugin + string name = Assembly?.GetCustomAttribute()?.DisplayName; + + // Return the display name or the file name without its extension + return !string.IsNullOrEmpty(name) ? name : Path.GetFileNameWithoutExtension(SourcePath); + } + } + + /// + /// The path at which this was located. + /// + public string SourcePath + { + get; + private set; + } + + /// + /// The load status of this . + /// + public PluginLoadStatus Status + { + get; + set; + } + + /// + /// The version of this . + /// + public string Version + { + get + { + // Create a string for storing the version of this plugin + string version = Assembly?.GetCustomAttribute()?.Version; + + // Return the version if it is not null or empty; otherwise, return a default version of 1.0.0.0 + return !string.IsNullOrEmpty(version) ? version : "1.0.0.0"; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// The assembly to be used. + /// The that hosts this plugin. This is essential for the ability to + /// The path to the plugin's assembly. + public Plugin(Assembly assembly, string sourcePath) + { + // Assign to the assembly + Assembly = assembly; + + // Assign to the source path + SourcePath = sourcePath; + } + } +} diff --git a/FrostyPlugin/PluginLoadStatus.cs b/FrostyPlugin/PluginLoadStatus.cs new file mode 100644 index 000000000..0254959cb --- /dev/null +++ b/FrostyPlugin/PluginLoadStatus.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Frosty.Core +{ + public enum PluginLoadStatus + { + /// + /// An enum entry that indicates that the associated plugin has failed to load. + /// + Failed, + + /// + /// An enum entry that indicates that the associated plugin has successfully loaded. + /// + Loaded, + + /// + /// An enum entry that indicates that the associated plugin has successfully loaded, but is invalid for the currently loaded profile. + /// + LoadedInvalid + } +} diff --git a/FrostyPlugin/PluginLoadType.cs b/FrostyPlugin/PluginLoadType.cs new file mode 100644 index 000000000..194d4ff2a --- /dev/null +++ b/FrostyPlugin/PluginLoadType.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Frosty.Core +{ + /// + /// Describes when the plugin should be loaded. + /// + public enum PluginLoadType + { + /// + /// The plugin loads on app startup. + /// + Startup, + /// + /// The plugin loads during the profile loading process. + /// + Initialize + } +} diff --git a/FrostyPlugin/PluginManager.cs b/FrostyPlugin/PluginManager.cs index 4ee26846d..c39c41736 100644 --- a/FrostyPlugin/PluginManager.cs +++ b/FrostyPlugin/PluginManager.cs @@ -13,174 +13,106 @@ namespace Frosty.Core { /// - /// Describes when the plugin should be loaded. + /// Represents the core plugin manager responsible for loading and managing of plugin extensions. /// - public enum PluginLoadType + public sealed class PluginManager { - /// - /// The plugin loads on app startup. - /// - Startup, - /// - /// The plugin loads during the profile loading process. - /// - Initialize - } + private List m_contextMenuItemExtensions = new List(); - /// - /// Describes the context in which the plugin manager is loading. - /// - public enum PluginManagerType - { - /// - /// The plugin is loading into the editor. - /// - Editor, + private Dictionary m_customHandlers = new Dictionary(); - /// - /// The plugin is loading into the mod manager. - /// - ModManager, + private Dictionary m_definitions = new Dictionary(); - /// - /// The plugin is loading for both the editor and mod manager. - /// - Both - } + private List m_executionActions = new List(); - /// - /// Represents a shader loaded from a plugin - /// - public sealed class ShaderDefinition - { - /// - /// Gets the plugin in which the shader is located. - /// - /// The that represents the plugin. - public Assembly Assembly { get; private set; } + private Dictionary m_globalTypeEditors = new Dictionary(); - /// - /// Gets the name of the shader resource file in the format of Namespace.ResourceName. - /// - /// The name of the shader resource file. - public string ResourceName { get; set; } + private List m_loadedPlugins = new List(); - /// - /// Gets the type of shader. - /// - /// The type of shader. - public ShaderType ShaderType { get; set; } + private Type m_localizedStringDatabaseType; - /// - /// Initializes a new instance of the class with the plugin, shader type, and resource name. - /// - /// The plugin in which the shader is located. - /// The type of shader. - /// The resource name of the shader in the format of Namespace.ResourceName. - public ShaderDefinition(Assembly plugin, ShaderType type, string resourceName) - { - Assembly = plugin; - ShaderType = type; - ResourceName = resourceName; - } - } + private PluginManagerType m_managerType; - public class Plugin - { - public string Name { get; private set; } - public string Author { get; private set; } - public string Version { get; private set; } + private List m_menuExtensions = new List(); - public Assembly Assembly { get; private set; } + private List m_optionsExtensions = new List(); - public Plugin(string name, string author, string version, Assembly assembly) - { - Name = name; - Author = author; - Version = version; + private List m_plugins = new List(); - Assembly = assembly; - } - } + private List m_profiles = new List(); + + private Dictionary m_resCustomHandlers = new Dictionary(); + + private Dictionary m_shaders = new Dictionary(); + + private List m_startupActions = new List(); + + private List m_tabExtensions = new List(); + + private List m_thirdPartyDlls = new List(); + + private Dictionary m_typeOverrides = new Dictionary(); + + private List m_userShaders = new List(); - /// - /// Represents the core plugin manager responsible for loading and managing of plugin extensions. - /// - public sealed class PluginManager - { /// - /// Retreives a collection of menu extensions that have been loaded from plugins. + /// Retrieves a collection of data explorer context menu item extensions that have been loaded from plugins. /// /// A collection of menu extensions. - public IEnumerable MenuExtensions => menuExtensions; + public IEnumerable DataExplorerContextMenuExtensions => m_contextMenuItemExtensions; /// - /// Retreives a collection of menu extensions that have been loaded from plugins. + /// Retrieves a collection of execution actions that have been loaded from plugins. /// - /// A collection of menu extensions. - public IEnumerable TabExtensions => tabExtensions; + /// A collection of execution actions. + public IEnumerable ExecutionActions => m_executionActions; /// - /// Retreives a collection of data explorer context menu item extensions that have been loaded from plugins. + /// Retrieves a collection of loaded plugins. /// - /// A collection of menu extensions. - public IEnumerable DataExplorerContextMenuExtensions => contextMenuItemExtensions; + /// A collection of loaded plugins. + public IEnumerable LoadedPlugins => m_loadedPlugins; /// - /// Retrieves a collection of options extensions that have been loaded from plugins. + /// Retrieves an enum defining which manager is being loaded right now. /// - /// A collection of options extensions. - public IEnumerable OptionsExtensions => optionsExtensions; + /// An enum defining which manager is being loaded right now.. + public PluginManagerType ManagerType => m_managerType; /// - /// Retreives a collection of profiles that have been loaded from plugins. + /// Retrieves a collection of menu extensions that have been loaded from plugins. /// - /// A collection of profiles. - public IEnumerable Profiles => profiles; + /// A collection of menu extensions. + public IEnumerable MenuExtensions => m_menuExtensions; /// - /// Retreives a collection of startup actions that have been loaded from plugins. + /// Retrieves a collection of options extensions that have been loaded from plugins. /// - /// A collection of startup actions. - public IEnumerable StartupActions => startupActions; + /// A collection of options extensions. + public IEnumerable OptionsExtensions => m_optionsExtensions; /// - /// Retreives a collection of execution actions that have been loaded from plugins. + /// An of all plugins that have been found. /// - /// A collection of execution actions. - public IEnumerable ExecutionActions => executionActions; + public IEnumerable Plugins => m_plugins; /// - /// Retreives a collection of loaded plugins. + /// Retrieves a collection of profiles that have been loaded from plugins. /// - /// A collection of loaded plugins. - public IEnumerable LoadedPlugins => loadedPlugins; + /// A collection of profiles. + public IEnumerable Profiles => m_profiles; /// - /// Retreives an enum defining which manager is being loaded right now. + /// Retrieves a collection of menu extensions that have been loaded from plugins. /// - /// An enum defining which manager is being loaded right now.. - public PluginManagerType ManagerType => managerType; - - private Dictionary definitions = new Dictionary(); - private List menuExtensions = new List(); - private List tabExtensions = new List(); - private List contextMenuItemExtensions = new List(); - private Dictionary globalTypEditors = new Dictionary(); - private Dictionary typeOverrides = new Dictionary(); - private List optionsExtensions = new List(); - private List thirdPartyDlls = new List(); - private List profiles = new List(); - private List plugins = new List(); - private List loadedPlugins = new List(); - private List executionActions = new List(); - private List startupActions = new List(); - private Dictionary customHandlers = new Dictionary(); - private Dictionary resCustomHandlers = new Dictionary(); - private Dictionary shaders = new Dictionary(); - private List userShaders = new List(); - private Type localizedStringDatabaseType; - private PluginManagerType managerType; + /// A collection of menu extensions. + public IEnumerable TabExtensions => m_tabExtensions; + + /// + /// Retrieves a collection of startup actions that have been loaded from plugins. + /// + /// A collection of startup actions. + public IEnumerable StartupActions => m_startupActions; /// /// Initializes a new instance of the class with the specified logger and context. @@ -189,57 +121,28 @@ public sealed class PluginManager /// The context which this plugin should load for. public PluginManager(ILogger logger, PluginManagerType context) { - managerType = context; + m_managerType = context; + + // Check if the plugins directory doesn't exist + if (!Directory.Exists("Plugins")) + { + // Inform the user of the missing directory + logger.Log("The \"Plugins\" directory could not be located within the executable's associated directory. Due to some plugins being a necessity for functionality, please retrieve a copy of the needed directory from a clean archive of the editor/mod manager."); - logger.Log(""); - logger.Log($"Scanning '{new FileInfo(Assembly.GetEntryAssembly().Location).DirectoryName}\\Plugins' for plugins"); + // Prevent further execution + return; + } - // load from main executable LoadDefinitionsFromAssembly(PluginLoadType.Startup, Assembly.GetEntryAssembly()); LoadDefinitionsFromAssembly(PluginLoadType.Startup, Assembly.GetExecutingAssembly()); - int pluginCount = 0; - // now load from plugins directory - if (Directory.Exists("Plugins")) + foreach (string item in Directory.EnumerateFiles("Plugins", "*.dll", SearchOption.AllDirectories)) { - foreach (string pluginPath in Directory.EnumerateFiles("Plugins", "*.dll", SearchOption.AllDirectories)) - { - FileInfo fi = new FileInfo(pluginPath); - string statusText = "Located plugin "; - - try - { - var assembly = Assembly.LoadFile(fi.FullName); - - LoadDefinitionsFromAssembly(PluginLoadType.Startup, assembly); - - var displayName = assembly.GetCustomAttribute()?.DisplayName; - var author = assembly.GetCustomAttribute()?.Author; - var version = assembly.GetCustomAttribute()?.Version; - - if (string.IsNullOrEmpty(displayName)) - displayName = fi.Name; - if (string.IsNullOrEmpty(author)) - author = "Unknown"; - if (string.IsNullOrEmpty(version)) - version = "1.0.0.0"; - - statusText += displayName + " (v" + version + ") by " + author; - pluginCount++; + FileInfo fileInfo = new FileInfo(item); - plugins.Add(new Plugin(displayName, author, version, assembly)); - logger.Log(statusText); - } - catch (Exception e) - { - statusText += fi.Name + " - Failed (" + e.Message + ")"; - logger.Log(statusText); - } - } + // Add the plugin to the list of located plugins + m_plugins.Add(LoadPlugin(fileInfo.FullName, PluginLoadType.Startup)); } - - logger.Log("Found a total of {0} plugins", pluginCount); - logger.Log(""); } /// @@ -247,13 +150,20 @@ public PluginManager(ILogger logger, PluginManagerType context) /// public void Initialize() { - foreach (Plugin plugin in plugins) + foreach (Plugin plugin in m_plugins) { - if (!IsValidToLoadPlugin(plugin.Assembly)) + if (IsValidToLoadPlugin(plugin.Assembly)) + { + LoadDefinitionsFromAssembly(PluginLoadType.Initialize, plugin.Assembly); + + // since IsValidToLoadPlugin does not block out Startup plugins, we can simply use this method as a means of adding to the loadedPlugins list + // this also filters out plugins invalid for the current profile + m_loadedPlugins.Add(plugin); continue; + } - LoadDefinitionsFromAssembly(PluginLoadType.Initialize, plugin.Assembly); - loadedPlugins.Add(plugin); + // assign to the current plugin's status with an invalid load status if it did not pass the validity checks + plugin.Status = PluginLoadStatus.LoadedInvalid; } } @@ -268,7 +178,7 @@ public AssetDefinition GetAssetDefinition(string type) return null; type = type.ToLower(); - return !definitions.ContainsKey(type) ? null : definitions[type]; + return !m_definitions.ContainsKey(type) ? null : m_definitions[type]; } /// @@ -279,9 +189,9 @@ public AssetDefinition GetAssetDefinition(string type) public Type GetTypeEditor(string lookupName) { lookupName = lookupName.ToLower(); - if (!globalTypEditors.ContainsKey(lookupName)) + if (!m_globalTypeEditors.ContainsKey(lookupName)) return null; - return globalTypEditors[lookupName]; + return m_globalTypeEditors[lookupName]; } /// @@ -292,9 +202,9 @@ public Type GetTypeEditor(string lookupName) public Type GetTypeOverride(string lookupName) { lookupName = lookupName.ToLower(); - if (!typeOverrides.ContainsKey(lookupName)) + if (!m_typeOverrides.ContainsKey(lookupName)) return null; - return typeOverrides[lookupName]; + return m_typeOverrides[lookupName]; } /// @@ -305,14 +215,14 @@ public Type GetTypeOverride(string lookupName) public bool IsThirdPartyDll(string name) { name = name.ToLower(); - return thirdPartyDlls.Contains(name); + return m_thirdPartyDlls.Contains(name); } /// /// Returns true if the loaded manager is the same a the specific manager type. /// /// A boolean if the loaded manager is the specified manager type. - public bool IsManagerType(PluginManagerType type) => type == managerType; + public bool IsManagerType(PluginManagerType type) => type == m_managerType; /// /// Returns the of the specified plugin if it is loaded. Returns null otherwise. @@ -321,7 +231,7 @@ public bool IsThirdPartyDll(string name) /// The of the plugin. public Assembly GetPluginAssembly(string name) { - foreach (var plugin in plugins) + foreach (var plugin in m_plugins) { if (plugin.Assembly.GetName().Name.Equals(name, StringComparison.OrdinalIgnoreCase)) return plugin.Assembly; @@ -337,10 +247,10 @@ public Assembly GetPluginAssembly(string name) public ILocalizedStringDatabase GetLocalizedStringDatabase() { ILocalizedStringDatabase localizedStringDb; - if (localizedStringDatabaseType == null) + if (m_localizedStringDatabaseType == null) localizedStringDb = new DefaultLocalizedStringDatabase(); else - localizedStringDb = (ILocalizedStringDatabase)Activator.CreateInstance(localizedStringDatabaseType); + localizedStringDb = (ILocalizedStringDatabase)Activator.CreateInstance(m_localizedStringDatabaseType); LocalizedStringDatabase.Current = localizedStringDb; return localizedStringDb; @@ -354,16 +264,16 @@ public ICustomActionHandler GetCustomHandler(string ebxType) public ICustomActionHandler GetCustomHandler(uint handlerHash) { - if (!customHandlers.ContainsKey(handlerHash)) + if (!m_customHandlers.ContainsKey(handlerHash)) return null; - return (ICustomActionHandler)Activator.CreateInstance(customHandlers[handlerHash]); + return (ICustomActionHandler)Activator.CreateInstance(m_customHandlers[handlerHash]); } public ICustomActionHandler GetCustomHandler(ResourceType resType) { - if (!resCustomHandlers.ContainsKey(resType)) + if (!m_resCustomHandlers.ContainsKey(resType)) return null; - return (ICustomActionHandler)Activator.CreateInstance(resCustomHandlers[resType]); + return (ICustomActionHandler)Activator.CreateInstance(m_resCustomHandlers[resType]); } /// @@ -374,15 +284,15 @@ public ICustomActionHandler GetCustomHandler(ResourceType resType) /// The bytecode of the shader. public byte[] GetShader(ShaderType type, string name) { - if (!shaders.ContainsKey(name)) + if (!m_shaders.ContainsKey(name)) return null; ShaderDefinition shaderDef = null; switch (type) { - case ShaderType.VertexShader: shaderDef = shaders[name][0]; break; - case ShaderType.ComputeShader: shaderDef = shaders[name][0]; break; - case ShaderType.PixelShader: shaderDef = shaders[name][1]; break; + case ShaderType.VertexShader: shaderDef = m_shaders[name][0]; break; + case ShaderType.ComputeShader: shaderDef = m_shaders[name][0]; break; + case ShaderType.PixelShader: shaderDef = m_shaders[name][1]; break; } if (shaderDef == null) @@ -393,12 +303,77 @@ public byte[] GetShader(ShaderType type, string name) public IEnumerable GetUserShaders() { - return userShaders; + return m_userShaders; } - // returns true if the specified plugin should be loaded (Based on ValidFor and NotValidFor attributes) + /// + /// Attempts to load a plugin located at the specified . + /// + /// The path to the target plugin. + /// Optional. The that determines what should be loaded from the plugin. + /// A instance regardless of whether or not a failure to load the plugin occurred. You may check for the potential of such failures through the property. + public Plugin LoadPlugin(string pluginPath, PluginLoadType? loadType = null) + { + Plugin loadedPlugin = new Plugin(null, pluginPath); + + // create a variable of type Assembly for temporarily storing the loaded assembly until LoadDefinitionsFromAssembly finishes executing, allowing us to tell whether or not the assembly is a valid plugin before storing it with a Plugin instance + Assembly pluginAssembly; + + // utilize a try catch statement to collect plugin load errors + try + { + pluginAssembly = Assembly.LoadFile(loadedPlugin.SourcePath); + + switch (loadType) + { + case null: + // attempt to load everything from the plugin + LoadDefinitionsFromAssembly(PluginLoadType.Startup, pluginAssembly); + + // since initialization plugins may be game-specific, ensure the plugin may be loaded for the active profile before proceeding + if (IsValidToLoadPlugin(pluginAssembly)) + { + LoadDefinitionsFromAssembly(PluginLoadType.Initialize, pluginAssembly); + + loadedPlugin.Status = PluginLoadStatus.Loaded; + break; + } + + loadedPlugin.Status = PluginLoadStatus.LoadedInvalid; + break; + + case PluginLoadType.Startup: + case PluginLoadType.Initialize: + LoadDefinitionsFromAssembly(loadType.Value, pluginAssembly); + + loadedPlugin.Status = PluginLoadStatus.Loaded; + break; + } + + // the assembly may now be stored within the plugin instance's Assembly property + loadedPlugin.Assembly = pluginAssembly; + } + catch (Exception e) + { + loadedPlugin.LoadException = e; + } + + return loadedPlugin; + } + + /// + /// Determines whether or not a plugin is valid for the active profile. + /// + /// The plugin assembly to be checked. + /// A bool determining whether or not the given plugin is valid for the active profile. private bool IsValidToLoadPlugin(Assembly assembly) { + if (assembly == null) + { + // return true to have the plugin "loaded," as if we were to return false, the plugin would be marked invalid + return true; + } + List validAttrs = new List(); List notValidAttrs = new List(); @@ -407,8 +382,10 @@ private bool IsValidToLoadPlugin(Assembly assembly) foreach (var attr in notValidAttrs) { - if (ProfilesLibrary.DataVersion == attr.ProfileVersion) + if (ProfilesLibrary.IsLoaded((ProfileVersion)attr.ProfileVersion)) + { return false; + } } bool retVal = false; @@ -420,7 +397,7 @@ private bool IsValidToLoadPlugin(Assembly assembly) { foreach (var attr in validAttrs) { - if (ProfilesLibrary.DataVersion == attr.ProfileVersion) + if (ProfilesLibrary.IsLoaded((ProfileVersion)attr.ProfileVersion)) { retVal = true; break; @@ -431,31 +408,40 @@ private bool IsValidToLoadPlugin(Assembly assembly) return retVal; } - // loads all the necessary definitions from a plugin based on the exported attributes. + /// + /// Loads all plugin definitions of a specified from a given assembly. + /// + /// The type of plugins to be located and loaded. + /// The assembly to be checked for plugin definitions. private void LoadDefinitionsFromAssembly(PluginLoadType loadType, Assembly assembly) { + if (assembly == null) + { + return; + } + foreach (var tmpAttr in assembly.GetCustomAttributes()) { - if (managerType == PluginManagerType.ModManager && !(tmpAttr is RegisterCustomHandlerAttribute) && !(tmpAttr is RegisterExecutionAction) && !(tmpAttr is RegisterOptionsExtensionAttribute)) + if (m_managerType == PluginManagerType.ModManager && !(tmpAttr is RegisterCustomHandlerAttribute) && !(tmpAttr is RegisterExecutionAction) && !(tmpAttr is RegisterOptionsExtensionAttribute)) continue; if (loadType == PluginLoadType.Startup) { if (tmpAttr is RegisterProfileAttribute attr1) { - profiles.Add(((IProfile)Activator.CreateInstance(attr1.ProfileType)).CreateProfile()); + m_profiles.Add(((IProfile)Activator.CreateInstance(attr1.ProfileType)).CreateProfile()); } else if (tmpAttr is RegisterTypeOverrideAttribute attr4) { - typeOverrides.Add(attr4.LookupName.ToLower(), attr4.EditorType); + m_typeOverrides.Add(attr4.LookupName.ToLower(), attr4.EditorType); } else if (tmpAttr is RegisterGlobalTypeEditorAttribute attr3) { - globalTypEditors.Add(attr3.LookupName.ToLower(), attr3.EditorType); + m_globalTypeEditors.Add(attr3.LookupName.ToLower(), attr3.EditorType); } else if (tmpAttr is RegisterStartupActionAttribute attr2) { - startupActions.Add((StartupAction)Activator.CreateInstance(attr2.StartupActionType)); + m_startupActions.Add((StartupAction)Activator.CreateInstance(attr2.StartupActionType)); } } else if (loadType == PluginLoadType.Initialize) @@ -469,16 +455,16 @@ private void LoadDefinitionsFromAssembly(PluginLoadType loadType, Assembly assem foreach (var subType in TypeLibrary.GetDerivedTypes(assetType)) { string subName = subType.Name.ToLower(); - if (!definitions.ContainsKey(subName)) + if (!m_definitions.ContainsKey(subName)) { - definitions.Add(subName, definition); + m_definitions.Add(subName, definition); } } string name = assetType.Name.ToLower(); - if (!definitions.ContainsKey(name)) + if (!m_definitions.ContainsKey(name)) { - definitions.Add(name, definition); + m_definitions.Add(name, definition); } } else @@ -487,9 +473,9 @@ private void LoadDefinitionsFromAssembly(PluginLoadType loadType, Assembly assem AssetDefinition definition = (AssetDefinition)Activator.CreateInstance(attr1.AssetDefinitionType); string name = attr1.LookupType.ToLower(); - if (!definitions.ContainsKey(name)) + if (!m_definitions.ContainsKey(name)) { - definitions.Add(name, definition); + m_definitions.Add(name, definition); } } } @@ -497,53 +483,53 @@ private void LoadDefinitionsFromAssembly(PluginLoadType loadType, Assembly assem { if (!attr2.MenuExtensionType.IsSubclassOf(typeof(MenuExtension))) throw new Exception("Menu extensions must extend from MenuExtensions base class"); - menuExtensions.Add((MenuExtension)Activator.CreateInstance(attr2.MenuExtensionType)); + m_menuExtensions.Add((MenuExtension)Activator.CreateInstance(attr2.MenuExtensionType)); } else if (tmpAttr is RegisterOptionsExtensionAttribute attr5) { - if (attr5.ManagerType == managerType || attr5.ManagerType == PluginManagerType.Both) + if (attr5.ManagerType == m_managerType || attr5.ManagerType == PluginManagerType.Both) { if (!attr5.OptionsType.IsSubclassOf(typeof(OptionsExtension))) throw new Exception("Option extensions must extend from OptionsExtension base class"); - optionsExtensions.Add(attr5.OptionsType); + m_optionsExtensions.Add(attr5.OptionsType); } } else if (tmpAttr is RegisterThirdPartyDllAttribute attr6) { string dllname = attr6.DllName.ToLower(); - if (!thirdPartyDlls.Contains(dllname)) - thirdPartyDlls.Add(dllname); + if (!m_thirdPartyDlls.Contains(dllname)) + m_thirdPartyDlls.Add(dllname); } else if (tmpAttr is RegisterLocalizedStringDatabaseAttribute attr7) { - if (localizedStringDatabaseType == null && attr7.LocalizedStringDatabaseType.GetInterface("ILocalizedStringDatabase") != null) - localizedStringDatabaseType = attr7.LocalizedStringDatabaseType; + if (m_localizedStringDatabaseType == null && attr7.LocalizedStringDatabaseType.GetInterface("ILocalizedStringDatabase") != null) + m_localizedStringDatabaseType = attr7.LocalizedStringDatabaseType; } else if (tmpAttr is RegisterShaderAttribute attr8) { - if (!shaders.ContainsKey(attr8.KeyName)) - shaders.Add(attr8.KeyName, new ShaderDefinition[2]); + if (!m_shaders.ContainsKey(attr8.KeyName)) + m_shaders.Add(attr8.KeyName, new ShaderDefinition[2]); - if ((attr8.ShaderType == ShaderType.VertexShader || attr8.ShaderType == ShaderType.ComputeShader) && shaders[attr8.KeyName][0] == null) - shaders[attr8.KeyName][0] = new ShaderDefinition(assembly, attr8.ShaderType, attr8.ResourceName); - if (attr8.ShaderType == ShaderType.PixelShader && shaders[attr8.KeyName][1] == null) - shaders[attr8.KeyName][1] = new ShaderDefinition(assembly, attr8.ShaderType, attr8.ResourceName); + if ((attr8.ShaderType == ShaderType.VertexShader || attr8.ShaderType == ShaderType.ComputeShader) && m_shaders[attr8.KeyName][0] == null) + m_shaders[attr8.KeyName][0] = new ShaderDefinition(assembly, attr8.ShaderType, attr8.ResourceName); + if (attr8.ShaderType == ShaderType.PixelShader && m_shaders[attr8.KeyName][1] == null) + m_shaders[attr8.KeyName][1] = new ShaderDefinition(assembly, attr8.ShaderType, attr8.ResourceName); } else if (tmpAttr is RegisterTabExtensionAttribute attr9) { if (!attr9.TabExtensionType.IsSubclassOf(typeof(TabExtension))) throw new Exception("Tab extensions must extend from MenuExtensions base class"); - tabExtensions.Add((TabExtension)Activator.CreateInstance(attr9.TabExtensionType)); + m_tabExtensions.Add((TabExtension)Activator.CreateInstance(attr9.TabExtensionType)); } else if (tmpAttr is RegisterDataExplorerContextMenuAttribute attr10) { if (!attr10.ContextMenuItemExtensionType.IsSubclassOf(typeof(DataExplorerContextMenuExtension))) throw new Exception("Data Explorer context menu item extensions must extend from ContextMenuExtensions base class"); - contextMenuItemExtensions.Add((DataExplorerContextMenuExtension)Activator.CreateInstance(attr10.ContextMenuItemExtensionType)); + m_contextMenuItemExtensions.Add((DataExplorerContextMenuExtension)Activator.CreateInstance(attr10.ContextMenuItemExtensionType)); } else if (tmpAttr is RegisterExecutionAction attr11) { - executionActions.Add((ExecutionAction)Activator.CreateInstance(attr11.ExecutionActionType)); + m_executionActions.Add((ExecutionAction)Activator.CreateInstance(attr11.ExecutionActionType)); } else if (tmpAttr is RegisterCustomHandlerAttribute attr) { @@ -554,21 +540,21 @@ private void LoadDefinitionsFromAssembly(PluginLoadType loadType, Assembly assem { foreach (var subType in TypeLibrary.GetDerivedTypes(assetType)) { - customHandlers.Add((uint)Fnv1.HashString(subType.Name.ToLower()), attr.HandlerClassType); + m_customHandlers.Add((uint)Fnv1.HashString(subType.Name.ToLower()), attr.HandlerClassType); } - customHandlers.Add((uint)Fnv1.HashString(assetType.Name.ToLower()), attr.HandlerClassType); + m_customHandlers.Add((uint)Fnv1.HashString(assetType.Name.ToLower()), attr.HandlerClassType); } } else if (attr.HandlerType == CustomHandlerType.Res) { - resCustomHandlers.Add(attr.ResType, attr.HandlerClassType); + m_resCustomHandlers.Add(attr.ResType, attr.HandlerClassType); } } else if (tmpAttr is RegisterUserShaderAttribute registerUserShaderAttribute) { if (registerUserShaderAttribute != null) { - userShaders.Add(registerUserShaderAttribute.XmlDescriptor + "," + registerUserShaderAttribute.ShaderName); + m_userShaders.Add(registerUserShaderAttribute.XmlDescriptor + "," + registerUserShaderAttribute.ShaderName); continue; } } diff --git a/FrostyPlugin/PluginManagerType.cs b/FrostyPlugin/PluginManagerType.cs new file mode 100644 index 000000000..e58c33c12 --- /dev/null +++ b/FrostyPlugin/PluginManagerType.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Frosty.Core +{ + /// + /// Describes the context in which the plugin manager is loading. + /// + public enum PluginManagerType + { + /// + /// The plugin is loading into the editor. + /// + Editor, + + /// + /// The plugin is loading into the mod manager. + /// + ModManager, + + /// + /// The plugin is loading for both the editor and mod manager. + /// + Both + } +} diff --git a/FrostyPlugin/ShaderDefinition.cs b/FrostyPlugin/ShaderDefinition.cs new file mode 100644 index 000000000..f33889669 --- /dev/null +++ b/FrostyPlugin/ShaderDefinition.cs @@ -0,0 +1,47 @@ +using Frosty.Core.Attributes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Frosty.Core +{ + /// + /// Represents a shader loaded from a plugin + /// + public sealed class ShaderDefinition + { + /// + /// Gets the plugin in which the shader is located. + /// + /// The that represents the plugin. + public Assembly Assembly { get; private set; } + + /// + /// Gets the name of the shader resource file in the format of Namespace.ResourceName. + /// + /// The name of the shader resource file. + public string ResourceName { get; set; } + + /// + /// Gets the type of shader. + /// + /// The type of shader. + public ShaderType ShaderType { get; set; } + + /// + /// Initializes a new instance of the class with the plugin, shader type, and resource name. + /// + /// The plugin in which the shader is located. + /// The type of shader. + /// The resource name of the shader in the format of Namespace.ResourceName. + public ShaderDefinition(Assembly plugin, ShaderType type, string resourceName) + { + Assembly = plugin; + ShaderType = type; + ResourceName = resourceName; + } + } +} diff --git a/Plugins/BlankPlugin/BuildDate.txt b/Plugins/BlankPlugin/BuildDate.txt index c707bf521..19c9a7215 100644 --- a/Plugins/BlankPlugin/BuildDate.txt +++ b/Plugins/BlankPlugin/BuildDate.txt @@ -1 +1 @@ -Wed 10/12/2022 15:03:38.03 \ No newline at end of file +Wed 10/12/2022 16:58:29.14 diff --git a/Plugins/LaunchPlatformPlugin/BuildDate.txt b/Plugins/LaunchPlatformPlugin/BuildDate.txt index 72896968a..407eca98b 100644 --- a/Plugins/LaunchPlatformPlugin/BuildDate.txt +++ b/Plugins/LaunchPlatformPlugin/BuildDate.txt @@ -1 +1 @@ -Wed 10/12/2022 15:03:39.50 \ No newline at end of file +Wed 10/12/2022 16:58:29.84 From d68d820a375cc4b438c4106fde1198ca41819ada Mon Sep 17 00:00:00 2001 From: NM <35472796+NM-20@users.noreply.github.com> Date: Wed, 12 Oct 2022 18:34:56 -0400 Subject: [PATCH 2/3] [Core] Fixed GetPluginAssembly exception with null assemblies --- FrostyEditor/BuildDate.txt | 2 +- FrostyModManager/BuildDate.txt | 2 +- FrostyPlugin/PluginManager.cs | 5 ++++- Plugins/BlankPlugin/BuildDate.txt | 2 +- Plugins/LaunchPlatformPlugin/BuildDate.txt | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/FrostyEditor/BuildDate.txt b/FrostyEditor/BuildDate.txt index e79ce8caf..15abc4b2a 100644 --- a/FrostyEditor/BuildDate.txt +++ b/FrostyEditor/BuildDate.txt @@ -1 +1 @@ -Wed 10/12/2022 17:36:47.21 +Wed 10/12/2022 18:33:23.69 diff --git a/FrostyModManager/BuildDate.txt b/FrostyModManager/BuildDate.txt index e79ce8caf..15abc4b2a 100644 --- a/FrostyModManager/BuildDate.txt +++ b/FrostyModManager/BuildDate.txt @@ -1 +1 @@ -Wed 10/12/2022 17:36:47.21 +Wed 10/12/2022 18:33:23.69 diff --git a/FrostyPlugin/PluginManager.cs b/FrostyPlugin/PluginManager.cs index c39c41736..a6c3a3750 100644 --- a/FrostyPlugin/PluginManager.cs +++ b/FrostyPlugin/PluginManager.cs @@ -233,8 +233,11 @@ public Assembly GetPluginAssembly(string name) { foreach (var plugin in m_plugins) { - if (plugin.Assembly.GetName().Name.Equals(name, StringComparison.OrdinalIgnoreCase)) + // if the plugin does not have an assigned assembly, skip it + if (plugin.Assembly?.GetName().Name.Equals(name, StringComparison.OrdinalIgnoreCase) ?? false) + { return plugin.Assembly; + } } return null; } diff --git a/Plugins/BlankPlugin/BuildDate.txt b/Plugins/BlankPlugin/BuildDate.txt index 19c9a7215..235648959 100644 --- a/Plugins/BlankPlugin/BuildDate.txt +++ b/Plugins/BlankPlugin/BuildDate.txt @@ -1 +1 @@ -Wed 10/12/2022 16:58:29.14 +Wed 10/12/2022 18:33:19.61 diff --git a/Plugins/LaunchPlatformPlugin/BuildDate.txt b/Plugins/LaunchPlatformPlugin/BuildDate.txt index 407eca98b..26b325f51 100644 --- a/Plugins/LaunchPlatformPlugin/BuildDate.txt +++ b/Plugins/LaunchPlatformPlugin/BuildDate.txt @@ -1 +1 @@ -Wed 10/12/2022 16:58:29.84 +Wed 10/12/2022 18:33:20.54 From 8345be8adb972720d9dbfaa80db9d554d1e39d18 Mon Sep 17 00:00:00 2001 From: NM <35472796+NM-20@users.noreply.github.com> Date: Mon, 24 Oct 2022 18:47:55 -0400 Subject: [PATCH 3/3] [Editor & ModManager] Adjusted loaded plugins list to use SVG icons and slightly resized editor MainWindow --- FrostyControls/FrostyControls.csproj | 4 + FrostyControls/Themes/Generic.xaml | 2848 +++++++++++++++----- FrostyControls/Themes/Icons.xaml | 15 + FrostyEditor/BuildDate.txt | 2 +- FrostyEditor/Windows/MainWindow.xaml | 47 +- FrostyModManager/BuildDate.txt | 2 +- FrostyModManager/Windows/MainWindow.xaml | 43 +- FrostyPlugin/FrostyCore.csproj | 5 - FrostyPlugin/Images/Cross_White.png | Bin 419 -> 0 bytes FrostyPlugin/Images/Invalid_White.png | Bin 270 -> 0 bytes FrostyPlugin/Images/Tick_White.png | Bin 430 -> 0 bytes Plugins/BlankPlugin/BuildDate.txt | 2 +- Plugins/LaunchPlatformPlugin/BuildDate.txt | 2 +- 13 files changed, 2176 insertions(+), 794 deletions(-) create mode 100644 FrostyControls/Themes/Icons.xaml delete mode 100644 FrostyPlugin/Images/Cross_White.png delete mode 100644 FrostyPlugin/Images/Invalid_White.png delete mode 100644 FrostyPlugin/Images/Tick_White.png diff --git a/FrostyControls/FrostyControls.csproj b/FrostyControls/FrostyControls.csproj index 0d33e1e5d..65a1384dc 100644 --- a/FrostyControls/FrostyControls.csproj +++ b/FrostyControls/FrostyControls.csproj @@ -88,6 +88,10 @@ MSBuild:Compile Designer + + Designer + MSBuild:Compile + diff --git a/FrostyControls/Themes/Generic.xaml b/FrostyControls/Themes/Generic.xaml index 7d929fc41..34713be43 100644 --- a/FrostyControls/Themes/Generic.xaml +++ b/FrostyControls/Themes/Generic.xaml @@ -1,73 +1,120 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + - + - + - - - + - + - - + + - + - + - + - + @@ -442,8 +713,11 @@ - - + + @@ -453,45 +727,69 @@ - + - + - - - - - - + - - + + - - + + - - + + @@ -1243,10 +2101,13 @@ - + - + @@ -1254,7 +2115,7 @@ - + @@ -1265,7 +2126,11 @@ - + @@ -1273,52 +2138,111 @@ - + - + - - + + - + - - + + - + - - + - - - + + + - - + + @@ -1336,32 +2260,72 @@ - - - + + + - - + + - + - - + + - - - + + + - diff --git a/FrostyControls/Themes/Icons.xaml b/FrostyControls/Themes/Icons.xaml new file mode 100644 index 000000000..e0f9cb347 --- /dev/null +++ b/FrostyControls/Themes/Icons.xaml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/FrostyEditor/BuildDate.txt b/FrostyEditor/BuildDate.txt index 15abc4b2a..4afa8787c 100644 --- a/FrostyEditor/BuildDate.txt +++ b/FrostyEditor/BuildDate.txt @@ -1 +1 @@ -Wed 10/12/2022 18:33:23.69 +Mon 10/24/2022 18:29:27.22 diff --git a/FrostyEditor/Windows/MainWindow.xaml b/FrostyEditor/Windows/MainWindow.xaml index bdc828c55..4a5929f08 100644 --- a/FrostyEditor/Windows/MainWindow.xaml +++ b/FrostyEditor/Windows/MainWindow.xaml @@ -14,8 +14,8 @@ MinWidth="500" MinHeight="250" Icon="/FrostyEditor;component/AppIcon.ico" - Height="720" - Width="1280" + Height="802" + Width="1448" FrostyLoaded="FrostyWindow_Loaded" WindowState="Maximized" Title="Frosty Editor" @@ -720,44 +720,47 @@ - + Height="24" + HorizontalAlignment="Center"> + - - - + - - + - - + diff --git a/FrostyModManager/BuildDate.txt b/FrostyModManager/BuildDate.txt index 15abc4b2a..4afa8787c 100644 --- a/FrostyModManager/BuildDate.txt +++ b/FrostyModManager/BuildDate.txt @@ -1 +1 @@ -Wed 10/12/2022 18:33:23.69 +Mon 10/24/2022 18:29:27.22 diff --git a/FrostyModManager/Windows/MainWindow.xaml b/FrostyModManager/Windows/MainWindow.xaml index 214699021..894402d11 100644 --- a/FrostyModManager/Windows/MainWindow.xaml +++ b/FrostyModManager/Windows/MainWindow.xaml @@ -996,44 +996,47 @@ - + Height="24" + HorizontalAlignment="Center"> + - - - + - - + - - + diff --git a/FrostyPlugin/FrostyCore.csproj b/FrostyPlugin/FrostyCore.csproj index 037024d96..e46cb019c 100644 --- a/FrostyPlugin/FrostyCore.csproj +++ b/FrostyPlugin/FrostyCore.csproj @@ -421,10 +421,5 @@ - - - - - \ No newline at end of file diff --git a/FrostyPlugin/Images/Cross_White.png b/FrostyPlugin/Images/Cross_White.png deleted file mode 100644 index 1d3a3480364b6fc01bf887aa02db17bca535e928..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 419 zcmV;U0bKrxP)p-dDg75v}BX z1y~VPLh{O&e29P)5y9j>0kNyNiNlF}k}EJ(oCp_h?#>_Dg4E;|TZtVcz!2XyabnS^>T%wTTtUk=QEYySGodMnJAu)xSPQwQ!_8OsM=J9(7%+>8zJJLnWx@E4cW)izom(swS1RU~ zD=?}w)G;nG^kKMokLi7T3RjBg@07G~|G526t(X`*B?V4By?Ewa;e=Vaaw?*~R!k77 z3qQtu;_KQwlb^~SF6=eW6i$eL{MN?tUUdS;n#Ri0LGy5AA`Hat!uyJS)%ULnfylfSB&BcpzNb2O81>sIE3(H_-eI7!18TLIL7H z%*MIA;sA(gx1?bNMK+K=cX#}7g*ZeO4wGmwf&Vacj=3an8|4$pF07*qoM6N<$f(5O>o&W#< diff --git a/Plugins/BlankPlugin/BuildDate.txt b/Plugins/BlankPlugin/BuildDate.txt index 235648959..894b7cbf1 100644 --- a/Plugins/BlankPlugin/BuildDate.txt +++ b/Plugins/BlankPlugin/BuildDate.txt @@ -1 +1 @@ -Wed 10/12/2022 18:33:19.61 +Mon 10/24/2022 18:24:24.42 diff --git a/Plugins/LaunchPlatformPlugin/BuildDate.txt b/Plugins/LaunchPlatformPlugin/BuildDate.txt index 26b325f51..972fd6236 100644 --- a/Plugins/LaunchPlatformPlugin/BuildDate.txt +++ b/Plugins/LaunchPlatformPlugin/BuildDate.txt @@ -1 +1 @@ -Wed 10/12/2022 18:33:20.54 +Mon 10/24/2022 18:24:24.86