using System; using System.Collections.Generic; using System.Linq; using Artemis.Core.DataModelExpansions; using Artemis.Storage.Entities.Module; using SkiaSharp; namespace Artemis.Core.Modules { /// /// Allows you to add support for new games/applications while utilizing your own data model /// public abstract class Module : Module where T : DataModel { /// /// The data model driving this module /// Note: This default data model is automatically registered upon plugin enable /// public T DataModel { get => (T) InternalDataModel; internal set => InternalDataModel = value; } /// /// Gets or sets whether this module must also expand the main data model /// /// Note: If expanding the main data model is all you want your plugin to do, create a /// plugin instead. /// /// public bool ExpandsDataModel { get => InternalExpandsMainDataModel; set => InternalExpandsMainDataModel = value; } /// /// Override to provide your own data model description. By default this returns a description matching your plugin /// name and description /// /// public virtual DataModelPropertyAttribute GetDataModelDescription() { return new DataModelPropertyAttribute {Name = PluginInfo.Name, Description = PluginInfo.Description}; } internal override void InternalEnablePlugin() { DataModel = Activator.CreateInstance(); DataModel.PluginInfo = PluginInfo; DataModel.DataModelDescription = GetDataModelDescription(); base.InternalEnablePlugin(); } internal override void InternalDisablePlugin() { DataModel = null; base.InternalDisablePlugin(); } } /// /// Allows you to add support for new games/applications /// public abstract class Module : Plugin { /// /// The modules display name that's shown in the menu /// public string DisplayName { get; protected set; } /// /// The modules display icon that's shown in the menu see for available /// icons /// public string DisplayIcon { get; set; } /// /// A path to an image to use as the modules display icon that's shown in the menu. /// If set, takes precedence over /// public string DisplayIconPath { get; set; } /// /// Gets whether this module is activated. A module can only be active while its /// are met /// public bool IsActivated { get; internal set; } /// /// Gets whether this module's activation was due to an override, can only be true if is /// true /// public bool IsActivatedOverride { get; set; } /// /// A list of activation requirements /// Note: if empty the module is always activated /// public List ActivationRequirements { get; } = new List(); /// /// Gets or sets the activation requirement mode, defaults to /// public ActivationRequirementType ActivationRequirementMode { get; set; } = ActivationRequirementType.Any; /// /// Gets or sets the default priority category for this module, defaults to /// /// public ModulePriorityCategory DefaultPriorityCategory { get; set; } = ModulePriorityCategory.Normal; /// /// Gets the current priority category of this module /// public ModulePriorityCategory PriorityCategory { get; internal set; } /// /// Gets the current priority of this module within its priority category /// public int Priority { get; internal set; } internal DataModel InternalDataModel { get; set; } internal bool InternalExpandsMainDataModel { get; set; } internal ModuleSettingsEntity Entity { get; set; } /// /// A list of custom module tabs that show in the UI /// public IEnumerable ModuleTabs { get; protected set; } /// /// Called each frame when the module must update /// /// Time in seconds since the last update public abstract void Update(double deltaTime); /// /// Called each frame when the module must render /// /// Time since the last render /// The RGB Surface to render to /// /// public abstract void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas, SKImageInfo canvasInfo); /// /// Called when the are met or during an override /// /// /// If true, the activation was due to an override. This usually means the module was activated /// by the profile editor /// public abstract void ModuleActivated(bool isOverride); /// /// Called when the are no longer met or during an override /// /// /// If true, the deactivation was due to an override. This usually means the module was deactivated /// by the profile editor /// public abstract void ModuleDeactivated(bool isOverride); internal virtual void InternalUpdate(double deltaTime) { Update(deltaTime); } internal virtual void InternalRender(double deltaTime, ArtemisSurface surface, SKCanvas canvas, SKImageInfo canvasInfo) { Render(deltaTime, surface, canvas, canvasInfo); } /// /// Evaluates the activation requirements following the and returns the result /// /// The evaluated result of the activation requirements public bool EvaluateActivationRequirements() { if (!ActivationRequirements.Any()) return true; if (ActivationRequirementMode == ActivationRequirementType.All) return ActivationRequirements.All(r => r.Evaluate()); if (ActivationRequirementMode == ActivationRequirementType.Any) return ActivationRequirements.Any(r => r.Evaluate()); return false; } internal virtual void Activate(bool isOverride) { if (IsActivated) return; IsActivatedOverride = isOverride; ModuleActivated(isOverride); IsActivated = true; } internal virtual void Deactivate(bool isOverride) { if (!IsActivated) return; IsActivatedOverride = false; IsActivated = false; ModuleDeactivated(isOverride); } internal void ApplyToEntity() { if (Entity == null) Entity = new ModuleSettingsEntity(); Entity.PluginGuid = PluginInfo.Guid; Entity.PriorityCategory = (int) PriorityCategory; Entity.Priority = Priority; } } /// /// Describes in what way the activation requirements of a module must be met /// public enum ActivationRequirementType { /// /// Any activation requirement must be met for the module to activate /// Any, /// /// All activation requirements must be met for the module to activate /// All } /// /// Describes the priority category of a module /// public enum ModulePriorityCategory { /// /// Indicates a normal render priority /// Normal, /// /// Indicates that the module renders for a specific application/game, rendering on top of normal modules /// Application, /// /// Indicates that the module renders an overlay, always rendering on top /// Overlay } }