diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj index 97c51fdc9..e1a2ea576 100644 --- a/src/Artemis.Core/Artemis.Core.csproj +++ b/src/Artemis.Core/Artemis.Core.csproj @@ -181,16 +181,20 @@ + + + + @@ -209,9 +213,7 @@ Artemis.Plugins - - - + diff --git a/src/Artemis.Core/Attributes/DataModelProperty.cs b/src/Artemis.Core/Attributes/DataModelProperty.cs new file mode 100644 index 000000000..34ac933a2 --- /dev/null +++ b/src/Artemis.Core/Attributes/DataModelProperty.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Artemis.Core.Attributes +{ + public class DataModelPropertyAttribute : Attribute + { + public string DisplayName { get; set; } + } +} diff --git a/src/Artemis.Core/Models/DataModelDescription.cs b/src/Artemis.Core/Models/DataModelDescription.cs new file mode 100644 index 000000000..34794fc4f --- /dev/null +++ b/src/Artemis.Core/Models/DataModelDescription.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Artemis.Core.Models +{ + public class DataModelDescription + { + } +} diff --git a/src/Artemis.Core/Services/Interfaces/ICoreService.cs b/src/Artemis.Core/Services/Interfaces/ICoreService.cs index b99f00d75..aba2228cd 100644 --- a/src/Artemis.Core/Services/Interfaces/ICoreService.cs +++ b/src/Artemis.Core/Services/Interfaces/ICoreService.cs @@ -1,10 +1,12 @@ using System; -using Artemis.Core.Events; namespace Artemis.Core.Services.Interfaces { - public interface ICoreService: IArtemisService, IDisposable + public interface ICoreService : IArtemisService, IDisposable { + /// + /// Indicates wether or not the core has been initialized + /// bool IsInitialized { get; set; } /// diff --git a/src/Artemis.Core/Services/Interfaces/IMainDataModelService.cs b/src/Artemis.Core/Services/Interfaces/IMainDataModelService.cs new file mode 100644 index 000000000..4a0de162d --- /dev/null +++ b/src/Artemis.Core/Services/Interfaces/IMainDataModelService.cs @@ -0,0 +1,32 @@ +using Artemis.Core.Models; +using Artemis.Plugins.Interfaces; + +namespace Artemis.Core.Services.Interfaces +{ + public interface IMainDataModelService : IArtemisService + { + /// + /// Called each frame when the main data model must update + /// + /// Time since the last update + void Update(double deltaTime); + + /// + /// Add an expansion to the datamodel to be available for use after the next update + /// + /// + void AddExpansion(IDataModelExpansion dataModelExpansion); + + /// + /// Remove a previously added expansion so that it is no longer available and updated + /// + /// + void RemoveExpansion(IDataModelExpansion dataModelExpansion); + + /// + /// Generates a data model description for the main datamodel including all it's expansions + /// + /// The generated data model description + DataModelDescription GetMainDataModelDescription(); + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Services/MainDataModelService.cs b/src/Artemis.Core/Services/MainDataModelService.cs new file mode 100644 index 000000000..905f2530f --- /dev/null +++ b/src/Artemis.Core/Services/MainDataModelService.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Artemis.Core.Exceptions; +using Artemis.Core.Models; +using Artemis.Core.Services.Interfaces; +using Artemis.Plugins.Interfaces; + +namespace Artemis.Core.Services +{ + public class MainDataModelService : IMainDataModelService + { + private readonly List _dataModelExpansions; + + public MainDataModelService() + { + _dataModelExpansions = new List(); + } + + public ReadOnlyCollection DataModelExpansions + { + get + { + lock (_dataModelExpansions) + { + return _dataModelExpansions.AsReadOnly(); + } + } + } + + public void Update(double deltaTime) + { + lock (_dataModelExpansions) + { + // Update all expansions + foreach (var expansion in _dataModelExpansions) + expansion.Update(deltaTime); + } + } + + public void AddExpansion(IDataModelExpansion dataModelExpansion) + { + lock (_dataModelExpansions) + { + _dataModelExpansions.Add(dataModelExpansion); + // TODO SpoinkyNL 3-3-2018: Initialize the expansion and fire an event + } + } + + public void RemoveExpansion(IDataModelExpansion dataModelExpansion) + { + lock (_dataModelExpansions) + { + if (!_dataModelExpansions.Contains(dataModelExpansion)) + throw new ArtemisCoreException("Cannot remove a data model expansion that wasn't previously added."); + + // TODO SpoinkyNL 3-3-2018: Dispose the expansion and fire an event + _dataModelExpansions.Remove(dataModelExpansion); + } + } + + public DataModelDescription GetMainDataModelDescription() + { + var dataModelDescription = new DataModelDescription(); + + return dataModelDescription; + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Services/PluginService.cs b/src/Artemis.Core/Services/PluginService.cs index 74bcc48de..50ff1e9e6 100644 --- a/src/Artemis.Core/Services/PluginService.cs +++ b/src/Artemis.Core/Services/PluginService.cs @@ -58,7 +58,7 @@ namespace Artemis.Core.Services /// public async Task GetModuleViewModel(PluginInfo pluginInfo) { - return await pluginInfo.GetModuleViewModel(_kernel); + return pluginInfo.GetModuleViewModel(_kernel); } public void Dispose() diff --git a/src/Artemis.Plugins.BuiltIn/Artemis.Plugins.BuiltIn.csproj b/src/Artemis.Plugins.BuiltIn/Artemis.Plugins.BuiltIn.csproj index 7b2827fc9..3d5ab2cbb 100644 --- a/src/Artemis.Plugins.BuiltIn/Artemis.Plugins.BuiltIn.csproj +++ b/src/Artemis.Plugins.BuiltIn/Artemis.Plugins.BuiltIn.csproj @@ -20,6 +20,7 @@ DEBUG;TRACE prompt 4 + 5 pdbonly @@ -47,15 +48,16 @@ - - + + + - + MSBuild:Compile Designer - + diff --git a/src/Artemis.Plugins.BuiltIn/Modules/General/GeneralDataModel.cs b/src/Artemis.Plugins.BuiltIn/Modules/General/GeneralDataModel.cs new file mode 100644 index 000000000..d44ed99af --- /dev/null +++ b/src/Artemis.Plugins.BuiltIn/Modules/General/GeneralDataModel.cs @@ -0,0 +1,12 @@ +using System; +using Artemis.Core.Attributes; +using Artemis.Plugins.Interfaces; + +namespace Artemis.Plugins.BuiltIn.Modules.General +{ + public class GeneralDataModel : IModuleDataModel + { + [DataModelProperty(DisplayName = "Unique boolean")] + public bool PropertyUniqueToThisDm { get; set; } + } +} \ No newline at end of file diff --git a/src/Artemis.Plugins.BuiltIn/Modules/General/GeneralModule.cs b/src/Artemis.Plugins.BuiltIn/Modules/General/GeneralModule.cs index 46cc4619d..4a96c63cf 100644 --- a/src/Artemis.Plugins.BuiltIn/Modules/General/GeneralModule.cs +++ b/src/Artemis.Plugins.BuiltIn/Modules/General/GeneralModule.cs @@ -1,34 +1,22 @@ -using System.Diagnostics; -using Artemis.Core.Services.Interfaces; -using Artemis.Plugins.Interfaces; +//css_inc GeneralViewModel.cs; +//css_inc GeneralDataModel.cs; + +using System; +using Artemis.Plugins.Abstract; namespace Artemis.Plugins.BuiltIn.Modules.General { - public class GeneralModule : IModule + public class GeneralModule : ProfileModule { - private readonly ICoreService _coreService; - - public GeneralModule(ICoreService coreService) + public override Type ViewModelType { - _coreService = coreService; - - Debugger.Break(); + get { return typeof(GeneralViewModel); } } - public void LoadPlugin() - { - } - - public void UnloadPlugin() - { - } - - public void Update(double deltaTime) - { - } - - public void Render(double deltaTime) + // True since the main data model is all this module shows + public override bool ExpandsMainDataModel { + get { return true; } } } } \ No newline at end of file diff --git a/src/Artemis.Plugins.BuiltIn/Modules/General/plugin.json b/src/Artemis.Plugins.BuiltIn/Modules/General/plugin.json index d245a84e2..4e06582d4 100644 --- a/src/Artemis.Plugins.BuiltIn/Modules/General/plugin.json +++ b/src/Artemis.Plugins.BuiltIn/Modules/General/plugin.json @@ -1,6 +1,5 @@ { "Name": "Default", "Version": "1.0.0", - "Main": "GeneralModule.cs", - "ViewModel": "GeneralViewModel.cs" + "Main": "GeneralModule.cs" } \ No newline at end of file diff --git a/src/Artemis.Plugins.BuiltIn/app.config b/src/Artemis.Plugins.BuiltIn/app.config index c22974a6d..6f8378fea 100644 --- a/src/Artemis.Plugins.BuiltIn/app.config +++ b/src/Artemis.Plugins.BuiltIn/app.config @@ -32,7 +32,7 @@ - + @@ -40,6 +40,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Artemis.Plugins/Abstract/ProfileModule.cs b/src/Artemis.Plugins/Abstract/ProfileModule.cs new file mode 100644 index 000000000..115fdc30c --- /dev/null +++ b/src/Artemis.Plugins/Abstract/ProfileModule.cs @@ -0,0 +1,38 @@ +using System; +using Artemis.Plugins.Interfaces; + +namespace Artemis.Plugins.Abstract +{ + public abstract class ProfileModule : IModule + { + /// + public abstract Type ViewModelType { get; } + + /// + public abstract bool ExpandsMainDataModel { get; } + + /// + public void LoadPlugin() + { + // Load and activate the last active profile + } + + /// + public void UnloadPlugin() + { + // Unload the last active profile + } + + /// + public virtual void Update(double deltaTime) + { + // Update the profile + } + + /// + public virtual void Render(double deltaTime) + { + // Render the profile + } + } +} \ No newline at end of file diff --git a/src/Artemis.Plugins/Artemis.Plugins.csproj b/src/Artemis.Plugins/Artemis.Plugins.csproj index 7c4afe364..0ac24fc04 100644 --- a/src/Artemis.Plugins/Artemis.Plugins.csproj +++ b/src/Artemis.Plugins/Artemis.Plugins.csproj @@ -11,6 +11,8 @@ Artemis.Plugins v4.6 512 + + true @@ -33,17 +35,17 @@ ..\packages\CS-Script.bin.3.28.0.1\lib\net46\CSScriptLibrary.dll - - ..\packages\Microsoft.CodeAnalysis.Common.2.0.0\lib\netstandard1.3\Microsoft.CodeAnalysis.dll + + ..\packages\Microsoft.CodeAnalysis.Common.2.6.1\lib\netstandard1.3\Microsoft.CodeAnalysis.dll - - ..\packages\Microsoft.CodeAnalysis.CSharp.2.0.0\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.2.6.1\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.dll - - ..\packages\Microsoft.CodeAnalysis.CSharp.Scripting.2.0.0\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.Scripting.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.Scripting.2.6.1\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.Scripting.dll - - ..\packages\Microsoft.CodeAnalysis.Scripting.Common.2.0.0\lib\netstandard1.3\Microsoft.CodeAnalysis.Scripting.dll + + ..\packages\Microsoft.CodeAnalysis.Scripting.Common.2.6.1\lib\netstandard1.3\Microsoft.CodeAnalysis.Scripting.dll ..\packages\CS-Script.bin.3.28.0.1\lib\net46\Mono.CSharp.dll @@ -135,11 +137,13 @@ + + diff --git a/src/Artemis.Plugins/Interfaces/IDataModelExpansion.cs b/src/Artemis.Plugins/Interfaces/IDataModelExpansion.cs index 9c0f1025a..eac2f63da 100644 --- a/src/Artemis.Plugins/Interfaces/IDataModelExpansion.cs +++ b/src/Artemis.Plugins/Interfaces/IDataModelExpansion.cs @@ -6,5 +6,6 @@ /// public interface IDataModelExpansion : IPlugin { + void Update(double deltaTime); } } \ No newline at end of file diff --git a/src/Artemis.Plugins/Interfaces/IModule.cs b/src/Artemis.Plugins/Interfaces/IModule.cs index d75b99ee7..7b4899ca0 100644 --- a/src/Artemis.Plugins/Interfaces/IModule.cs +++ b/src/Artemis.Plugins/Interfaces/IModule.cs @@ -1,4 +1,7 @@ -namespace Artemis.Plugins.Interfaces +using System; +using Ninject; + +namespace Artemis.Plugins.Interfaces { /// /// @@ -6,6 +9,17 @@ /// public interface IModule : IPlugin { + /// + /// The type of this module's view model + /// + Type ViewModelType { get; } + + /// + /// Wether or not this module expands upon the main data model. If set to true any data in main data model can be + /// accessed by profiles in this module + /// + bool ExpandsMainDataModel { get; } + /// /// Called each frame when the module must update /// diff --git a/src/Artemis.Plugins/Interfaces/IModuleDataModel.cs b/src/Artemis.Plugins/Interfaces/IModuleDataModel.cs new file mode 100644 index 000000000..7f069887e --- /dev/null +++ b/src/Artemis.Plugins/Interfaces/IModuleDataModel.cs @@ -0,0 +1,7 @@ +namespace Artemis.Plugins.Interfaces +{ + public interface IModuleDataModel + { + + } +} \ No newline at end of file diff --git a/src/Artemis.Plugins/Models/PluginInfo.cs b/src/Artemis.Plugins/Models/PluginInfo.cs index 47ae89ccb..000ac8263 100644 --- a/src/Artemis.Plugins/Models/PluginInfo.cs +++ b/src/Artemis.Plugins/Models/PluginInfo.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; @@ -14,6 +13,8 @@ namespace Artemis.Plugins.Models { public class PluginInfo : IDisposable { + private static Assembly _assembly; + /// /// The name of the plugin /// @@ -29,11 +30,6 @@ namespace Artemis.Plugins.Models /// public string Main { get; set; } - /// - /// The file implementing IPluginViewModel, loaded when opened in the UI - /// - public string ViewModel { get; set; } - /// /// The instantiated plugin, available after successful load /// @@ -46,12 +42,6 @@ namespace Artemis.Plugins.Models [JsonIgnore] public string Folder { get; set; } - /// - /// Indicates wether this is a built-in plugin. - /// - [JsonIgnore] - public bool IsBuiltIn { get; private set; } - public void Dispose() { Plugin.UnloadPlugin(); @@ -68,7 +58,7 @@ namespace Artemis.Plugins.Models // Make sure the right engine is used CSScript.EvaluatorConfig.Engine = EvaluatorEngine.CodeDom; CSScript.EvaluatorConfig.DebugBuild = true; - + CSScript.GlobalSettings.SearchDirs = folder; if (!folder.EndsWith("\\")) folder += "\\"; if (!File.Exists(folder + "plugin.json")) @@ -78,8 +68,8 @@ namespace Artemis.Plugins.Models pluginInfo.Folder = folder; // Load the main script and get the type - var assembly = await CSScript.Evaluator.CompileCodeAsync(File.ReadAllText(folder + pluginInfo.Main)); - var pluginType = assembly.GetTypes().Where(t => typeof(IPlugin).IsAssignableFrom(t)).ToList(); + _assembly = await CSScript.Evaluator.CompileCodeAsync(File.ReadAllText(folder + pluginInfo.Main)); + var pluginType = _assembly.GetTypes().Where(t => typeof(IPlugin).IsAssignableFrom(t)).ToList(); if (!pluginType.Any()) throw new ArtemisPluginException(pluginInfo, "Failed to load plugin, no type found that implements IPlugin"); if (pluginType.Count > 1) @@ -91,33 +81,27 @@ namespace Artemis.Plugins.Models return pluginInfo; } - + /// /// Gets the view model of the module accompanying the provided plugin info /// /// The Ninject kernel to use for DI /// - public async Task GetModuleViewModel(IKernel kernel) + public IModuleViewModel GetModuleViewModel(IKernel kernel) { - // Make sure the right engine is used - CSScript.EvaluatorConfig.Engine = EvaluatorEngine.CodeDom; - CSScript.EvaluatorConfig.DebugBuild = true; - // Don't attempt to locave VMs for something other than a module - if (!(Plugin is IModule)) + if (Plugin == null) + throw new ArtemisPluginException(this, "Cannot locate a view model for this plugin because it's not compiled."); + if (!(Plugin is IModule module)) throw new ArtemisPluginException(this, "Cannot locate a view model for this plugin as it's not a module."); - // Use the plugin's assembly as the VM is precompiled if built in, otherwise compile the VM into a new assembly - var assembly = await CSScript.Evaluator.CompileCodeAsync(File.ReadAllText(Folder + ViewModel)); - - var vmType = assembly.GetTypes().Where(t => typeof(IModuleViewModel).IsAssignableFrom(t)).ToList(); - if (!vmType.Any()) - throw new ArtemisPluginException(this, "Failed to load plugin, no type found that implements IModuleViewModel"); - if (vmType.Count > 1) - throw new ArtemisPluginException(this, "Failed to load plugin, more than one type found that implements IModuleViewModel"); + // Get the type from the module + var vmType = module.ViewModelType; + if (!typeof(IModuleViewModel).IsAssignableFrom(vmType)) + throw new ArtemisPluginException(this, "ViewModel must implement IModuleViewModel."); // Instantiate the ViewModel with Ninject - var vm = (IModuleViewModel) kernel.Get(vmType.First()); + var vm = (IModuleViewModel) kernel.Get(vmType); vm.PluginInfo = this; return vm; } diff --git a/src/Artemis.Plugins/app.config b/src/Artemis.Plugins/app.config index c27651ac4..00fa1b520 100644 --- a/src/Artemis.Plugins/app.config +++ b/src/Artemis.Plugins/app.config @@ -34,6 +34,22 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.Plugins/packages.config b/src/Artemis.Plugins/packages.config index 10d6362ad..1be98b369 100644 --- a/src/Artemis.Plugins/packages.config +++ b/src/Artemis.Plugins/packages.config @@ -2,10 +2,11 @@ - - - - + + + + + diff --git a/src/Artemis.UI/Stylet/ArtemisViewManager.cs b/src/Artemis.UI/Stylet/ArtemisViewManager.cs index 859375f00..176231bcb 100644 --- a/src/Artemis.UI/Stylet/ArtemisViewManager.cs +++ b/src/Artemis.UI/Stylet/ArtemisViewManager.cs @@ -22,8 +22,9 @@ namespace Artemis.UI.Stylet private UIElement CreateViewForPlugin(object model) { + var viewName = model.GetType().Name.Replace("Model", ""); var pluginInfo = ((IModuleViewModel) model).PluginInfo; - var viewPath = pluginInfo.Folder + pluginInfo.ViewModel.Replace("ViewModel", "View").Replace(".cs", ".xaml"); + var viewPath = $"{pluginInfo.Folder}{viewName}.xaml"; // There doesn't have to be a view so make sure one exists if (!File.Exists(viewPath)) return null;