mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Modules - Added activation mechanism and conditions
This commit is contained in:
parent
12456519d5
commit
6a32ecc3a4
33
src/Artemis.Core/Extensions/ProcessExtensions.cs
Normal file
33
src/Artemis.Core/Extensions/ProcessExtensions.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Artemis.Core.Extensions
|
||||||
|
{
|
||||||
|
public static class ProcessExtensions
|
||||||
|
{
|
||||||
|
public static string GetProcessFilename(this Process p)
|
||||||
|
{
|
||||||
|
var capacity = 2000;
|
||||||
|
var builder = new StringBuilder(capacity);
|
||||||
|
var ptr = OpenProcess(ProcessAccessFlags.QueryLimitedInformation, false, p.Id);
|
||||||
|
if (!QueryFullProcessImageName(ptr, 0, builder, ref capacity)) return string.Empty;
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
private static extern bool QueryFullProcessImageName([In] IntPtr hProcess, [In] int dwFlags, [Out] StringBuilder lpExeName, ref int lpdwSize);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
private static extern IntPtr OpenProcess(ProcessAccessFlags processAccess, bool bInheritHandle, int processId);
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
private enum ProcessAccessFlags : uint
|
||||||
|
{
|
||||||
|
QueryLimitedInformation = 0x00001000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Artemis.Core.Models.Surface;
|
using Artemis.Core.Models.Surface;
|
||||||
using Artemis.Core.Plugins.Abstract.DataModels;
|
using Artemis.Core.Plugins.Abstract.DataModels;
|
||||||
using Artemis.Core.Plugins.Abstract.DataModels.Attributes;
|
using Artemis.Core.Plugins.Abstract.DataModels.Attributes;
|
||||||
using Artemis.Core.Plugins.Abstract.ViewModels;
|
using Artemis.Core.Plugins.Abstract.ViewModels;
|
||||||
|
using Artemis.Core.Plugins.ModuleActivationRequirements;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
namespace Artemis.Core.Plugins.Abstract
|
namespace Artemis.Core.Plugins.Abstract
|
||||||
@ -26,7 +28,7 @@ namespace Artemis.Core.Plugins.Abstract
|
|||||||
/// Gets or sets whether this module must also expand the main data model
|
/// Gets or sets whether this module must also expand the main data model
|
||||||
/// <para>
|
/// <para>
|
||||||
/// Note: If expanding the main data model is all you want your plugin to do, create a
|
/// Note: If expanding the main data model is all you want your plugin to do, create a
|
||||||
/// <see cref="BaseDataModelExpansion" /> plugin instead.
|
/// <see cref="BaseDataModelExpansion{T}" /> plugin instead.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ExpandsDataModel
|
public bool ExpandsDataModel
|
||||||
@ -66,9 +68,11 @@ namespace Artemis.Core.Plugins.Abstract
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class Module : Plugin
|
public abstract class Module : Plugin
|
||||||
{
|
{
|
||||||
internal DataModel InternalDataModel { get; set; }
|
protected Module()
|
||||||
|
{
|
||||||
internal bool InternalExpandsMainDataModel { get; set; }
|
ActivationRequirements = new List<IModuleActivationRequirement>();
|
||||||
|
ActivationRequirementMode = ActivationRequirementType.Any;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The modules display name that's shown in the menu
|
/// The modules display name that's shown in the menu
|
||||||
@ -81,6 +85,27 @@ namespace Artemis.Core.Plugins.Abstract
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string DisplayIcon { get; set; }
|
public string DisplayIcon { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether this module is activated. A module can only be active while its <see cref="ActivationRequirements" />
|
||||||
|
/// are met
|
||||||
|
/// </summary>
|
||||||
|
public bool IsActivated { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A list of activation requirements
|
||||||
|
/// <para>Note: if empty the module is always activated</para>
|
||||||
|
/// </summary>
|
||||||
|
public List<IModuleActivationRequirement> ActivationRequirements { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the activation requirement mode, defaults to <see cref="ActivationRequirementType.Any" />
|
||||||
|
/// </summary>
|
||||||
|
public ActivationRequirementType ActivationRequirementMode { get; set; }
|
||||||
|
|
||||||
|
internal DataModel InternalDataModel { get; set; }
|
||||||
|
|
||||||
|
internal bool InternalExpandsMainDataModel { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called each frame when the module must update
|
/// Called each frame when the module must update
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -101,5 +126,62 @@ namespace Artemis.Core.Plugins.Abstract
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public abstract IEnumerable<ModuleViewModel> GetViewModels();
|
public abstract IEnumerable<ModuleViewModel> GetViewModels();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the <see cref="ActivationRequirements" /> are met
|
||||||
|
/// </summary>
|
||||||
|
public abstract void ModuleActivated();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the <see cref="ActivationRequirements" /> are no longer met
|
||||||
|
/// </summary>
|
||||||
|
public abstract void ModuleDeactivated();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Evaluates the activation requirements following the <see cref="ActivationRequirementMode" /> and returns the result
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The evaluated result of the activation requirements</returns>
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
if (IsActivated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ModuleActivated();
|
||||||
|
IsActivated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal virtual void Deactivate()
|
||||||
|
{
|
||||||
|
if (!IsActivated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IsActivated = false;
|
||||||
|
ModuleDeactivated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ActivationRequirementType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Any activation requirement must be met for the module to activate
|
||||||
|
/// </summary>
|
||||||
|
Any,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// All activation requirements must be met for the module to activate
|
||||||
|
/// </summary>
|
||||||
|
All
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,7 +143,8 @@ namespace Artemis.Core.Plugins.Abstract
|
|||||||
{
|
{
|
||||||
if (profile != null && profile.Module != this)
|
if (profile != null && profile.Module != this)
|
||||||
throw new ArtemisCoreException($"Cannot activate a profile of module {profile.Module} on a module of plugin {PluginInfo}.");
|
throw new ArtemisCoreException($"Cannot activate a profile of module {profile.Module} on a module of plugin {PluginInfo}.");
|
||||||
|
if (!IsActivated)
|
||||||
|
throw new ArtemisCoreException("Cannot activate a profile on a deactivated module");
|
||||||
|
|
||||||
if (profile == ActiveProfile || AnimatingProfileChange)
|
if (profile == ActiveProfile || AnimatingProfileChange)
|
||||||
return;
|
return;
|
||||||
@ -164,6 +165,9 @@ namespace Artemis.Core.Plugins.Abstract
|
|||||||
{
|
{
|
||||||
if (profile != null && profile.Module != this)
|
if (profile != null && profile.Module != this)
|
||||||
throw new ArtemisCoreException($"Cannot activate a profile of module {profile.Module} on a module of plugin {PluginInfo}.");
|
throw new ArtemisCoreException($"Cannot activate a profile of module {profile.Module} on a module of plugin {PluginInfo}.");
|
||||||
|
if (!IsActivated)
|
||||||
|
throw new ArtemisCoreException("Cannot activate a profile on a deactivated module");
|
||||||
|
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
if (profile == ActiveProfile)
|
if (profile == ActiveProfile)
|
||||||
@ -188,6 +192,15 @@ namespace Artemis.Core.Plugins.Abstract
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AnimatingProfileChange { get; private set; }
|
public bool AnimatingProfileChange { get; private set; }
|
||||||
|
|
||||||
|
internal override void Deactivate()
|
||||||
|
{
|
||||||
|
base.Deactivate();
|
||||||
|
|
||||||
|
var profile = ActiveProfile;
|
||||||
|
ActiveProfile = null;
|
||||||
|
profile?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
|
|
||||||
public event EventHandler ActiveProfileChanged;
|
public event EventHandler ActiveProfileChanged;
|
||||||
|
|||||||
@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Artemis.Core.Extensions;
|
||||||
|
|
||||||
|
namespace Artemis.Core.Plugins.ModuleActivationRequirements
|
||||||
|
{
|
||||||
|
public class ProcessActivationRequirement : IModuleActivationRequirement
|
||||||
|
{
|
||||||
|
public string ProcessName { get; set; }
|
||||||
|
public string Location { get; set; }
|
||||||
|
|
||||||
|
public ProcessActivationRequirement(string processName, string location = null)
|
||||||
|
{
|
||||||
|
ProcessName = processName;
|
||||||
|
Location = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool Evaluate()
|
||||||
|
{
|
||||||
|
if (ProcessName == null && Location == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var processes = ProcessName != null ? Process.GetProcessesByName(ProcessName).Where(p => !p.HasExited) : Process.GetProcesses().Where(p => !p.HasExited);
|
||||||
|
return Location != null
|
||||||
|
? processes.Any(p => Path.GetDirectoryName(p.GetProcessFilename()) == Location)
|
||||||
|
: processes.Any();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IModuleActivationRequirement
|
||||||
|
{
|
||||||
|
bool Evaluate();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -39,6 +39,7 @@ namespace Artemis.Core.Services
|
|||||||
private List<BaseDataModelExpansion> _dataModelExpansions;
|
private List<BaseDataModelExpansion> _dataModelExpansions;
|
||||||
private List<Module> _modules;
|
private List<Module> _modules;
|
||||||
private IntroAnimation _introAnimation;
|
private IntroAnimation _introAnimation;
|
||||||
|
private DateTime _lastModuleActivationUpdate;
|
||||||
|
|
||||||
// ReSharper disable once UnusedParameter.Local - Storage migration service is injected early to ensure it runs before anything else
|
// ReSharper disable once UnusedParameter.Local - Storage migration service is injected early to ensure it runs before anything else
|
||||||
internal CoreService(ILogger logger, StorageMigrationService _, ISettingsService settingsService, IPluginService pluginService,
|
internal CoreService(ILogger logger, StorageMigrationService _, ISettingsService settingsService, IPluginService pluginService,
|
||||||
@ -95,8 +96,6 @@ namespace Artemis.Core.Services
|
|||||||
_logger.Information("Initialized without an active surface entity");
|
_logger.Information("Initialized without an active surface entity");
|
||||||
|
|
||||||
PlayIntroAnimation();
|
PlayIntroAnimation();
|
||||||
_profileService.ActivateLastActiveProfiles();
|
|
||||||
|
|
||||||
OnInitialized();
|
OnInitialized();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,6 +169,11 @@ namespace Artemis.Core.Services
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_frameStopWatch.Restart();
|
_frameStopWatch.Restart();
|
||||||
|
|
||||||
|
// Only run the module activation update every 2 seconds
|
||||||
|
if (DateTime.Now - _lastModuleActivationUpdate > TimeSpan.FromSeconds(2))
|
||||||
|
ModuleActivationUpdate();
|
||||||
|
|
||||||
lock (_dataModelExpansions)
|
lock (_dataModelExpansions)
|
||||||
{
|
{
|
||||||
// Update all active modules
|
// Update all active modules
|
||||||
@ -177,13 +181,16 @@ namespace Artemis.Core.Services
|
|||||||
dataModelExpansion.Update(args.DeltaTime);
|
dataModelExpansion.Update(args.DeltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Module> modules;
|
||||||
lock (_modules)
|
lock (_modules)
|
||||||
{
|
{
|
||||||
// Update all active modules
|
modules = _modules.Where(m => m.IsActivated).ToList();
|
||||||
foreach (var module in _modules)
|
|
||||||
module.Update(args.DeltaTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update all active modules
|
||||||
|
foreach (var module in modules)
|
||||||
|
module.Update(args.DeltaTime);
|
||||||
|
|
||||||
// If there is no ready bitmap brush, skip the frame
|
// If there is no ready bitmap brush, skip the frame
|
||||||
if (_rgbService.BitmapBrush == null)
|
if (_rgbService.BitmapBrush == null)
|
||||||
return;
|
return;
|
||||||
@ -194,20 +201,15 @@ namespace Artemis.Core.Services
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Render all active modules
|
// Render all active modules
|
||||||
using (var canvas = new SKCanvas(_rgbService.BitmapBrush.Bitmap))
|
using var canvas = new SKCanvas(_rgbService.BitmapBrush.Bitmap);
|
||||||
{
|
|
||||||
canvas.Clear(new SKColor(0, 0, 0));
|
canvas.Clear(new SKColor(0, 0, 0));
|
||||||
if (!ModuleRenderingDisabled)
|
if (!ModuleRenderingDisabled)
|
||||||
{
|
{
|
||||||
lock (_modules)
|
foreach (var module in modules)
|
||||||
{
|
|
||||||
foreach (var module in _modules)
|
|
||||||
module.Render(args.DeltaTime, _surfaceService.ActiveSurface, canvas, _rgbService.BitmapBrush.Bitmap.Info);
|
module.Render(args.DeltaTime, _surfaceService.ActiveSurface, canvas, _rgbService.BitmapBrush.Bitmap.Info);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
OnFrameRendering(new FrameRenderingEventArgs(_modules, canvas, args.DeltaTime, _rgbService.Surface));
|
OnFrameRendering(new FrameRenderingEventArgs(modules, canvas, args.DeltaTime, _rgbService.Surface));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@ -221,6 +223,33 @@ namespace Artemis.Core.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ModuleActivationUpdate()
|
||||||
|
{
|
||||||
|
_lastModuleActivationUpdate = DateTime.Now;
|
||||||
|
var stopwatch = new Stopwatch();
|
||||||
|
stopwatch.Start();
|
||||||
|
lock (_modules)
|
||||||
|
{
|
||||||
|
foreach (var module in _modules)
|
||||||
|
{
|
||||||
|
var shouldBeActivated = module.EvaluateActivationRequirements();
|
||||||
|
if (shouldBeActivated && !module.IsActivated)
|
||||||
|
{
|
||||||
|
module.Activate();
|
||||||
|
// If this is a profile module, activate the last active profile after module activation
|
||||||
|
if (module is ProfileModule profileModule)
|
||||||
|
_profileService.ActivateLastProfile(profileModule);
|
||||||
|
}
|
||||||
|
else if (!shouldBeActivated && module.IsActivated)
|
||||||
|
module.Deactivate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stopwatch.Stop();
|
||||||
|
if (stopwatch.ElapsedMilliseconds > 100)
|
||||||
|
_logger.Warning("Activation requirements evaluation took too long: {moduleCount} module(s) in {elapsed}", _modules.Count, stopwatch.Elapsed);
|
||||||
|
}
|
||||||
|
|
||||||
private void SurfaceOnUpdated(UpdatedEventArgs args)
|
private void SurfaceOnUpdated(UpdatedEventArgs args)
|
||||||
{
|
{
|
||||||
if (_rgbService.IsRenderPaused)
|
if (_rgbService.IsRenderPaused)
|
||||||
|
|||||||
@ -11,11 +11,6 @@ namespace Artemis.Core.Services.Storage.Interfaces
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IProfileService : IArtemisService
|
public interface IProfileService : IArtemisService
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Activates the last profile for each module
|
|
||||||
/// </summary>
|
|
||||||
void ActivateLastActiveProfiles();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new profile for the given module and returns a descriptor pointing to it
|
/// Creates a new profile for the given module and returns a descriptor pointing to it
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -50,6 +45,12 @@ namespace Artemis.Core.Services.Storage.Interfaces
|
|||||||
/// <param name="profileDescriptor">The descriptor pointing to the profile to delete</param>
|
/// <param name="profileDescriptor">The descriptor pointing to the profile to delete</param>
|
||||||
void DeleteProfile(ProfileDescriptor profileDescriptor);
|
void DeleteProfile(ProfileDescriptor profileDescriptor);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Activates the last profile of the given profile module
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="profileModule"></param>
|
||||||
|
void ActivateLastProfile(ProfileModule profileModule);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Activates the profile described in the given <see cref="ProfileDescriptor" /> with the currently active surface
|
/// Activates the profile described in the given <see cref="ProfileDescriptor" /> with the currently active surface
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO.Compression;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core.Events;
|
using Artemis.Core.Events;
|
||||||
@ -11,7 +10,6 @@ using Artemis.Core.Plugins.Abstract;
|
|||||||
using Artemis.Core.Plugins.LayerEffect.Abstract;
|
using Artemis.Core.Plugins.LayerEffect.Abstract;
|
||||||
using Artemis.Core.Services.Interfaces;
|
using Artemis.Core.Services.Interfaces;
|
||||||
using Artemis.Core.Services.Storage.Interfaces;
|
using Artemis.Core.Services.Storage.Interfaces;
|
||||||
using Artemis.Core.Utilities;
|
|
||||||
using Artemis.Storage.Entities.Profile;
|
using Artemis.Storage.Entities.Profile;
|
||||||
using Artemis.Storage.Repositories.Interfaces;
|
using Artemis.Storage.Repositories.Interfaces;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
@ -44,15 +42,6 @@ namespace Artemis.Core.Services.Storage
|
|||||||
public JsonSerializerSettings MementoSettings { get; set; } = new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.All};
|
public JsonSerializerSettings MementoSettings { get; set; } = new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.All};
|
||||||
public JsonSerializerSettings ExportSettings { get; set; } = new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.All, Formatting = Formatting.Indented};
|
public JsonSerializerSettings ExportSettings { get; set; } = new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.All, Formatting = Formatting.Indented};
|
||||||
|
|
||||||
public void ActivateLastActiveProfiles()
|
|
||||||
{
|
|
||||||
foreach (var profileModule in _pluginService.GetPluginsOfType<ProfileModule>())
|
|
||||||
{
|
|
||||||
var activeProfile = GetLastActiveProfile(profileModule);
|
|
||||||
ActivateProfile(activeProfile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ProfileDescriptor> GetProfileDescriptors(ProfileModule module)
|
public List<ProfileDescriptor> GetProfileDescriptors(ProfileModule module)
|
||||||
{
|
{
|
||||||
var profileEntities = _profileRepository.GetByPluginGuid(module.PluginInfo.Guid);
|
var profileEntities = _profileRepository.GetByPluginGuid(module.PluginInfo.Guid);
|
||||||
@ -67,6 +56,12 @@ namespace Artemis.Core.Services.Storage
|
|||||||
return new ProfileDescriptor(module, profileEntity);
|
return new ProfileDescriptor(module, profileEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ActivateLastProfile(ProfileModule profileModule)
|
||||||
|
{
|
||||||
|
var activeProfile = GetLastActiveProfile(profileModule);
|
||||||
|
ActivateProfile(activeProfile);
|
||||||
|
}
|
||||||
|
|
||||||
public Profile ActivateProfile(ProfileDescriptor profileDescriptor)
|
public Profile ActivateProfile(ProfileDescriptor profileDescriptor)
|
||||||
{
|
{
|
||||||
if (profileDescriptor.ProfileModule.ActiveProfile?.EntityId == profileDescriptor.Id)
|
if (profileDescriptor.ProfileModule.ActiveProfile?.EntityId == profileDescriptor.Id)
|
||||||
@ -109,16 +104,6 @@ namespace Artemis.Core.Services.Storage
|
|||||||
SaveActiveProfile(module);
|
SaveActiveProfile(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveActiveProfile(ProfileModule module)
|
|
||||||
{
|
|
||||||
var profileEntities = _profileRepository.GetByPluginGuid(module.PluginInfo.Guid);
|
|
||||||
foreach (var profileEntity in profileEntities)
|
|
||||||
{
|
|
||||||
profileEntity.IsActive = module.ActiveProfile.EntityId == profileEntity.Id;
|
|
||||||
_profileRepository.Save(profileEntity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ClearActiveProfileAnimated(ProfileModule module)
|
public async Task ClearActiveProfileAnimated(ProfileModule module)
|
||||||
{
|
{
|
||||||
await module.ChangeActiveProfileAnimated(null, _surfaceService.ActiveSurface);
|
await module.ChangeActiveProfileAnimated(null, _surfaceService.ActiveSurface);
|
||||||
@ -210,13 +195,6 @@ namespace Artemis.Core.Services.Storage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProfileDescriptor GetLastActiveProfile(ProfileModule module)
|
|
||||||
{
|
|
||||||
var moduleProfiles = _profileRepository.GetByPluginGuid(module.PluginInfo.Guid);
|
|
||||||
var profileEntity = moduleProfiles.FirstOrDefault(p => p.IsActive) ?? moduleProfiles.FirstOrDefault();
|
|
||||||
return profileEntity == null ? null : new ProfileDescriptor(module, profileEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void InstantiateProfile(Profile profile)
|
public void InstantiateProfile(Profile profile)
|
||||||
{
|
{
|
||||||
profile.PopulateLeds(_surfaceService.ActiveSurface);
|
profile.PopulateLeds(_surfaceService.ActiveSurface);
|
||||||
@ -245,6 +223,23 @@ namespace Artemis.Core.Services.Storage
|
|||||||
return new ProfileDescriptor(profileModule, profileEntity);
|
return new ProfileDescriptor(profileModule, profileEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ProfileDescriptor GetLastActiveProfile(ProfileModule module)
|
||||||
|
{
|
||||||
|
var moduleProfiles = _profileRepository.GetByPluginGuid(module.PluginInfo.Guid);
|
||||||
|
var profileEntity = moduleProfiles.FirstOrDefault(p => p.IsActive) ?? moduleProfiles.FirstOrDefault();
|
||||||
|
return profileEntity == null ? null : new ProfileDescriptor(module, profileEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveActiveProfile(ProfileModule module)
|
||||||
|
{
|
||||||
|
var profileEntities = _profileRepository.GetByPluginGuid(module.PluginInfo.Guid);
|
||||||
|
foreach (var profileEntity in profileEntities)
|
||||||
|
{
|
||||||
|
profileEntity.IsActive = module.ActiveProfile.EntityId == profileEntity.Id;
|
||||||
|
_profileRepository.Save(profileEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes the properties on the layers of the given profile
|
/// Initializes the properties on the layers of the given profile
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -347,11 +342,6 @@ namespace Artemis.Core.Services.Storage
|
|||||||
ActiveProfilesInstantiatePlugins();
|
ActiveProfilesInstantiatePlugins();
|
||||||
if (e.PluginInfo.Instance is LayerEffectProvider)
|
if (e.PluginInfo.Instance is LayerEffectProvider)
|
||||||
ActiveProfilesInstantiatePlugins();
|
ActiveProfilesInstantiatePlugins();
|
||||||
else if (e.PluginInfo.Instance is ProfileModule profileModule)
|
|
||||||
{
|
|
||||||
var activeProfile = GetLastActiveProfile(profileModule);
|
|
||||||
ActivateProfile(activeProfile);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -2,18 +2,13 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using Artemis.Core.Extensions;
|
using Artemis.Core.Extensions;
|
||||||
using Artemis.Core.Models.Profile;
|
using Artemis.Core.Models.Profile;
|
||||||
using Artemis.Core.Models.Surface;
|
|
||||||
using Artemis.Core.Plugins.Abstract;
|
using Artemis.Core.Plugins.Abstract;
|
||||||
using Artemis.Core.Plugins.Abstract.ViewModels;
|
using Artemis.Core.Plugins.Abstract.ViewModels;
|
||||||
using Artemis.Core.Plugins.LayerBrush;
|
|
||||||
using Artemis.Core.Services.Interfaces;
|
|
||||||
using Artemis.Core.Services.Storage.Interfaces;
|
using Artemis.Core.Services.Storage.Interfaces;
|
||||||
using Artemis.Storage.Entities.Profile;
|
using Artemis.Storage.Entities.Profile;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
@ -33,6 +28,17 @@ namespace Artemis.Core.Utilities
|
|||||||
CreateIntroProfile();
|
CreateIntroProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Profile AnimationProfile { get; set; }
|
||||||
|
|
||||||
|
public void Render(double deltaTime, SKCanvas canvas, SKImageInfo bitmapInfo)
|
||||||
|
{
|
||||||
|
if (AnimationProfile == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AnimationProfile.Update(deltaTime);
|
||||||
|
AnimationProfile.Render(deltaTime, canvas, bitmapInfo);
|
||||||
|
}
|
||||||
|
|
||||||
private void CreateIntroProfile()
|
private void CreateIntroProfile()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -43,10 +49,10 @@ namespace Artemis.Core.Utilities
|
|||||||
// Inject every LED on the surface into each layer
|
// Inject every LED on the surface into each layer
|
||||||
foreach (var profileEntityLayer in profileEntity.Layers)
|
foreach (var profileEntityLayer in profileEntity.Layers)
|
||||||
{
|
{
|
||||||
profileEntityLayer.Leds.AddRange(_surfaceService.ActiveSurface.Devices.SelectMany(d => d.Leds).Select(l => new LedEntity()
|
profileEntityLayer.Leds.AddRange(_surfaceService.ActiveSurface.Devices.SelectMany(d => d.Leds).Select(l => new LedEntity
|
||||||
{
|
{
|
||||||
DeviceIdentifier = l.Device.RgbDevice.GetDeviceIdentifier(),
|
DeviceIdentifier = l.Device.RgbDevice.GetDeviceIdentifier(),
|
||||||
LedName = l.RgbLed.Id.ToString(),
|
LedName = l.RgbLed.Id.ToString()
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,32 +67,33 @@ namespace Artemis.Core.Utilities
|
|||||||
_logger.Warning(e, "Failed to load intro profile");
|
_logger.Warning(e, "Failed to load intro profile");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Profile AnimationProfile { get; set; }
|
|
||||||
|
|
||||||
public void Render(double deltaTime, SKCanvas canvas, SKImageInfo bitmapInfo)
|
|
||||||
{
|
|
||||||
if (AnimationProfile == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
AnimationProfile.Update(deltaTime);
|
|
||||||
AnimationProfile.Render(deltaTime, canvas, bitmapInfo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class DummyModule : ProfileModule
|
internal class DummyModule : ProfileModule
|
||||||
{
|
{
|
||||||
public override void EnablePlugin()
|
public override void EnablePlugin()
|
||||||
{
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DisablePlugin()
|
public override void DisablePlugin()
|
||||||
{
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ModuleActivated()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ModuleDeactivated()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IEnumerable<ModuleViewModel> GetViewModels()
|
public override IEnumerable<ModuleViewModel> GetViewModels()
|
||||||
{
|
{
|
||||||
return new List<ModuleViewModel>();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,6 +121,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Resource Include="Resources\Cursors\aero_rotate.cur" />
|
<Resource Include="Resources\Cursors\aero_rotate.cur" />
|
||||||
|
<Resource Include="Resources\Images\Sidebar\sidebar-header.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentValidation" Version="8.6.2" />
|
<PackageReference Include="FluentValidation" Version="8.6.2" />
|
||||||
@ -296,6 +297,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="Resources\Fonts\RobotoMono-Regular.ttf" />
|
<None Remove="Resources\Fonts\RobotoMono-Regular.ttf" />
|
||||||
<None Remove="Resources\Images\Logo\logo-512.ico" />
|
<None Remove="Resources\Images\Logo\logo-512.ico" />
|
||||||
|
<None Remove="Resources\Images\Sidebar\sidebar-header.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Update="Properties\Resources.Designer.cs">
|
<Compile Update="Properties\Resources.Designer.cs">
|
||||||
|
|||||||
BIN
src/Artemis.UI/Resources/Images/Sidebar/sidebar-header.png
Normal file
BIN
src/Artemis.UI/Resources/Images/Sidebar/sidebar-header.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.3 KiB |
@ -51,13 +51,13 @@
|
|||||||
</mde:MaterialWindow.Resources>
|
</mde:MaterialWindow.Resources>
|
||||||
<materialDesign:DialogHost Identifier="RootDialog" DialogTheme="Inherit" SnackbarMessageQueue="{Binding MainMessageQueue}">
|
<materialDesign:DialogHost Identifier="RootDialog" DialogTheme="Inherit" SnackbarMessageQueue="{Binding MainMessageQueue}">
|
||||||
<Grid>
|
<Grid>
|
||||||
<materialDesign:DrawerHost IsLeftDrawerOpen="{Binding IsSidebarVisible}">
|
<materialDesign:DrawerHost IsLeftDrawerOpen="{Binding SidebarViewModel.IsSidebarOpen}">
|
||||||
<materialDesign:DrawerHost.LeftDrawerContent>
|
<materialDesign:DrawerHost.LeftDrawerContent>
|
||||||
<ContentControl s:View.Model="{Binding SidebarViewModel}" Width="220" ClipToBounds="False" />
|
<ContentControl s:View.Model="{Binding SidebarViewModel}" Width="220" ClipToBounds="False" />
|
||||||
</materialDesign:DrawerHost.LeftDrawerContent>
|
</materialDesign:DrawerHost.LeftDrawerContent>
|
||||||
<DockPanel>
|
<DockPanel>
|
||||||
<mde:AppBar Type="Dense"
|
<mde:AppBar Type="Dense"
|
||||||
IsNavigationDrawerOpen="{Binding IsSidebarVisible, Mode=TwoWay}"
|
IsNavigationDrawerOpen="{Binding SidebarViewModel.IsSidebarOpen, Mode=TwoWay}"
|
||||||
Title="{Binding ActiveItem.DisplayName}"
|
Title="{Binding ActiveItem.DisplayName}"
|
||||||
ShowNavigationDrawerButton="True"
|
ShowNavigationDrawerButton="True"
|
||||||
DockPanel.Dock="Top">
|
DockPanel.Dock="Top">
|
||||||
|
|||||||
@ -67,12 +67,6 @@ namespace Artemis.UI.Screens
|
|||||||
set => SetAndNotify(ref _mainMessageQueue, value);
|
set => SetAndNotify(ref _mainMessageQueue, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSidebarVisible
|
|
||||||
{
|
|
||||||
get => _isSidebarVisible;
|
|
||||||
set => SetAndNotify(ref _isSidebarVisible, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ActiveItemReady
|
public bool ActiveItemReady
|
||||||
{
|
{
|
||||||
get => _activeItemReady;
|
get => _activeItemReady;
|
||||||
@ -140,7 +134,7 @@ namespace Artemis.UI.Screens
|
|||||||
{
|
{
|
||||||
if (e.PropertyName == nameof(SidebarViewModel.SelectedItem))
|
if (e.PropertyName == nameof(SidebarViewModel.SelectedItem))
|
||||||
{
|
{
|
||||||
IsSidebarVisible = false;
|
SidebarViewModel.IsSidebarOpen = false;
|
||||||
ActiveItemReady = false;
|
ActiveItemReady = false;
|
||||||
|
|
||||||
// Allow the menu to close, it's slower but feels more responsive, funny how that works right
|
// Allow the menu to close, it's slower but feels more responsive, funny how that works right
|
||||||
|
|||||||
@ -10,22 +10,19 @@
|
|||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800"
|
d:DesignHeight="450" d:DesignWidth="800"
|
||||||
d:DataContext="{d:DesignInstance sidebar:SidebarViewModel}">
|
d:DataContext="{d:DesignInstance sidebar:SidebarViewModel}">
|
||||||
<StackPanel>
|
<Grid>
|
||||||
<!-- Placeholder -->
|
<Grid.RowDefinitions>
|
||||||
<StackPanel Margin="15">
|
<!-- no idea why this has to be 0 -->
|
||||||
<materialDesign:PackIcon Kind="QuestionMarkCircle" Width="50" Height="50" />
|
<RowDefinition Height="0" />
|
||||||
<TextBlock Style="{StaticResource MaterialDesignHeadline6TextBlock}" Margin="0 15 0 0">
|
<RowDefinition Height="Auto" />
|
||||||
Active module
|
<RowDefinition Height="Auto"/>
|
||||||
</TextBlock>
|
<RowDefinition Height="*"/>
|
||||||
<ComboBox BorderThickness="0" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" materialDesign:HintAssist.Hint="Active profile">
|
</Grid.RowDefinitions>
|
||||||
<ComboBoxItem>Profile 1</ComboBoxItem>
|
|
||||||
<ComboBoxItem>Profile 2</ComboBoxItem>
|
|
||||||
<ComboBoxItem>Profile 3</ComboBoxItem>
|
|
||||||
<ComboBoxItem>Profile 4</ComboBoxItem>
|
|
||||||
</ComboBox>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<controls:SideNavigation Items="{Binding SidebarItems}" SelectedItem="{Binding SelectedItem}" WillSelectNavigationItemCommand="{s:Action SelectItem}" />
|
<Image Grid.Row="0" Grid.RowSpan="2" Source="/Resources/Images/Sidebar/sidebar-header.png" Stretch="Uniform" VerticalAlignment="Top" />
|
||||||
</StackPanel>
|
<TextBlock Grid.Row="1" Style="{StaticResource MaterialDesignHeadline6TextBlock}" Margin="15" materialDesign:ShadowAssist.ShadowDepth="Depth1" Text="{Binding ActiveModules}"/>
|
||||||
|
|
||||||
|
<controls:SideNavigation Grid.Row="3" Items="{Binding SidebarItems}" SelectedItem="{Binding SelectedItem}" WillSelectNavigationItemCommand="{s:Action SelectItem}" Margin="0 5 0 0"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Timers;
|
||||||
using Artemis.Core.Events;
|
using Artemis.Core.Events;
|
||||||
using Artemis.Core.Services.Interfaces;
|
using Artemis.Core.Services.Interfaces;
|
||||||
using Artemis.UI.Events;
|
using Artemis.UI.Events;
|
||||||
@ -27,6 +28,9 @@ namespace Artemis.UI.Screens.Sidebar
|
|||||||
private BindableCollection<INavigationItem> _sidebarItems;
|
private BindableCollection<INavigationItem> _sidebarItems;
|
||||||
private Dictionary<INavigationItem, Core.Plugins.Abstract.Module> _sidebarModules;
|
private Dictionary<INavigationItem, Core.Plugins.Abstract.Module> _sidebarModules;
|
||||||
private IScreen _selectedItem;
|
private IScreen _selectedItem;
|
||||||
|
private bool _isSidebarOpen;
|
||||||
|
private readonly Timer _activeModulesUpdateTimer;
|
||||||
|
private string _activeModules;
|
||||||
|
|
||||||
public SidebarViewModel(IKernel kernel, IEventAggregator eventAggregator, IModuleVmFactory moduleVmFactory, IPluginService pluginService)
|
public SidebarViewModel(IKernel kernel, IEventAggregator eventAggregator, IModuleVmFactory moduleVmFactory, IPluginService pluginService)
|
||||||
{
|
{
|
||||||
@ -37,6 +41,10 @@ namespace Artemis.UI.Screens.Sidebar
|
|||||||
SidebarModules = new Dictionary<INavigationItem, Core.Plugins.Abstract.Module>();
|
SidebarModules = new Dictionary<INavigationItem, Core.Plugins.Abstract.Module>();
|
||||||
SidebarItems = new BindableCollection<INavigationItem>();
|
SidebarItems = new BindableCollection<INavigationItem>();
|
||||||
|
|
||||||
|
_activeModulesUpdateTimer = new Timer(1000);
|
||||||
|
_activeModulesUpdateTimer.Start();
|
||||||
|
_activeModulesUpdateTimer.Elapsed += ActiveModulesUpdateTimerOnElapsed;
|
||||||
|
|
||||||
_pluginService.PluginEnabled += PluginServiceOnPluginEnabled;
|
_pluginService.PluginEnabled += PluginServiceOnPluginEnabled;
|
||||||
_pluginService.PluginDisabled += PluginServiceOnPluginDisabled;
|
_pluginService.PluginDisabled += PluginServiceOnPluginDisabled;
|
||||||
|
|
||||||
@ -44,6 +52,15 @@ namespace Artemis.UI.Screens.Sidebar
|
|||||||
eventAggregator.Subscribe(this);
|
eventAggregator.Subscribe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ActiveModulesUpdateTimerOnElapsed(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (!IsSidebarOpen)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var activeModules = SidebarModules.Count(m => m.Value.IsActivated);
|
||||||
|
ActiveModules = activeModules == 1 ? "1 active module" : $"{activeModules} active modules";
|
||||||
|
}
|
||||||
|
|
||||||
public BindableCollection<INavigationItem> SidebarItems
|
public BindableCollection<INavigationItem> SidebarItems
|
||||||
{
|
{
|
||||||
get => _sidebarItems;
|
get => _sidebarItems;
|
||||||
@ -56,19 +73,35 @@ namespace Artemis.UI.Screens.Sidebar
|
|||||||
set => SetAndNotify(ref _sidebarModules, value);
|
set => SetAndNotify(ref _sidebarModules, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string ActiveModules
|
||||||
|
{
|
||||||
|
get => _activeModules;
|
||||||
|
set => SetAndNotify(ref _activeModules, value);
|
||||||
|
}
|
||||||
|
|
||||||
public IScreen SelectedItem
|
public IScreen SelectedItem
|
||||||
{
|
{
|
||||||
get => _selectedItem;
|
get => _selectedItem;
|
||||||
set => SetAndNotify(ref _selectedItem, value);
|
set => SetAndNotify(ref _selectedItem, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsSidebarOpen
|
||||||
|
{
|
||||||
|
get => _isSidebarOpen;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetAndNotify(ref _isSidebarOpen, value);
|
||||||
|
if (value)
|
||||||
|
ActiveModulesUpdateTimerOnElapsed(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void SetupSidebar()
|
public void SetupSidebar()
|
||||||
{
|
{
|
||||||
SidebarItems.Clear();
|
SidebarItems.Clear();
|
||||||
SidebarModules.Clear();
|
SidebarModules.Clear();
|
||||||
|
|
||||||
// Add all default sidebar items
|
// Add all default sidebar items
|
||||||
SidebarItems.Add(new DividerNavigationItem());
|
|
||||||
SidebarItems.Add(new FirstLevelNavigationItem {Icon = PackIconKind.Home, Label = "Home"});
|
SidebarItems.Add(new FirstLevelNavigationItem {Icon = PackIconKind.Home, Label = "Home"});
|
||||||
SidebarItems.Add(new FirstLevelNavigationItem {Icon = PackIconKind.Newspaper, Label = "News"});
|
SidebarItems.Add(new FirstLevelNavigationItem {Icon = PackIconKind.Newspaper, Label = "News"});
|
||||||
SidebarItems.Add(new FirstLevelNavigationItem {Icon = PackIconKind.TestTube, Label = "Workshop"});
|
SidebarItems.Add(new FirstLevelNavigationItem {Icon = PackIconKind.TestTube, Label = "Workshop"});
|
||||||
@ -83,7 +116,7 @@ namespace Artemis.UI.Screens.Sidebar
|
|||||||
AddModule(module);
|
AddModule(module);
|
||||||
|
|
||||||
// Select the top item, which will be one of the defaults
|
// Select the top item, which will be one of the defaults
|
||||||
Task.Run(() => SelectSidebarItem(SidebarItems[1]));
|
Task.Run(() => SelectSidebarItem(SidebarItems[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReSharper disable once UnusedMember.Global - Called by view
|
// ReSharper disable once UnusedMember.Global - Called by view
|
||||||
@ -202,6 +235,9 @@ namespace Artemis.UI.Screens.Sidebar
|
|||||||
|
|
||||||
_pluginService.PluginEnabled -= PluginServiceOnPluginEnabled;
|
_pluginService.PluginEnabled -= PluginServiceOnPluginEnabled;
|
||||||
_pluginService.PluginDisabled -= PluginServiceOnPluginDisabled;
|
_pluginService.PluginDisabled -= PluginServiceOnPluginDisabled;
|
||||||
|
|
||||||
|
_activeModulesUpdateTimer.Stop();
|
||||||
|
_activeModulesUpdateTimer.Elapsed -= ActiveModulesUpdateTimerOnElapsed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using Artemis.Core.Extensions;
|
||||||
using Artemis.Core.Plugins.Abstract.DataModels.Attributes;
|
using Artemis.Core.Plugins.Abstract.DataModels.Attributes;
|
||||||
using Artemis.Plugins.Modules.General.Utilities;
|
using Artemis.Plugins.Modules.General.Utilities;
|
||||||
|
|
||||||
@ -16,7 +17,7 @@ namespace Artemis.Plugins.Modules.General.DataModel.Windows
|
|||||||
ProcessName = process.ProcessName;
|
ProcessName = process.ProcessName;
|
||||||
|
|
||||||
// Accessing MainModule requires admin privileges, this way does not
|
// Accessing MainModule requires admin privileges, this way does not
|
||||||
ProgramLocation = WindowUtilities.GetProcessFilename(process);
|
ProgramLocation = process.GetProcessFilename();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string WindowTitle { get; set; }
|
public string WindowTitle { get; set; }
|
||||||
|
|||||||
@ -12,20 +12,6 @@ namespace Artemis.Plugins.Modules.General
|
|||||||
{
|
{
|
||||||
public class GeneralModule : ProfileModule<GeneralDataModel>
|
public class GeneralModule : ProfileModule<GeneralDataModel>
|
||||||
{
|
{
|
||||||
public override IEnumerable<ModuleViewModel> GetViewModels()
|
|
||||||
{
|
|
||||||
return new List<ModuleViewModel> {new GeneralViewModel(this)};
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Update(double deltaTime)
|
|
||||||
{
|
|
||||||
DataModel.TimeDataModel.CurrentTime = DateTime.Now;
|
|
||||||
DataModel.TimeDataModel.CurrentTimeUTC = DateTime.UtcNow;
|
|
||||||
|
|
||||||
UpdateCurrentWindow();
|
|
||||||
base.Update(deltaTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void EnablePlugin()
|
public override void EnablePlugin()
|
||||||
{
|
{
|
||||||
DisplayName = "General";
|
DisplayName = "General";
|
||||||
@ -42,6 +28,28 @@ namespace Artemis.Plugins.Modules.General
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void ModuleActivated()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ModuleDeactivated()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(double deltaTime)
|
||||||
|
{
|
||||||
|
DataModel.TimeDataModel.CurrentTime = DateTime.Now;
|
||||||
|
DataModel.TimeDataModel.CurrentTimeUTC = DateTime.UtcNow;
|
||||||
|
|
||||||
|
UpdateCurrentWindow();
|
||||||
|
base.Update(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<ModuleViewModel> GetViewModels()
|
||||||
|
{
|
||||||
|
return new List<ModuleViewModel> { new GeneralViewModel(this) };
|
||||||
|
}
|
||||||
|
|
||||||
#region Open windows
|
#region Open windows
|
||||||
|
|
||||||
public void UpdateCurrentWindow()
|
public void UpdateCurrentWindow()
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Artemis.Plugins.Modules.General.Utilities
|
namespace Artemis.Plugins.Modules.General.Utilities
|
||||||
{
|
{
|
||||||
@ -14,33 +12,11 @@ namespace Artemis.Plugins.Modules.General.Utilities
|
|||||||
return (int) processId;
|
return (int) processId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetProcessFilename(Process p)
|
|
||||||
{
|
|
||||||
var capacity = 2000;
|
|
||||||
var builder = new StringBuilder(capacity);
|
|
||||||
var ptr = OpenProcess(ProcessAccessFlags.QueryLimitedInformation, false, p.Id);
|
|
||||||
if (!QueryFullProcessImageName(ptr, 0, builder, ref capacity)) return string.Empty;
|
|
||||||
|
|
||||||
return builder.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
private static extern IntPtr GetForegroundWindow();
|
private static extern IntPtr GetForegroundWindow();
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
||||||
|
|
||||||
[DllImport("kernel32.dll")]
|
|
||||||
private static extern bool QueryFullProcessImageName([In] IntPtr hProcess, [In] int dwFlags, [Out] StringBuilder lpExeName, ref int lpdwSize);
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll")]
|
|
||||||
private static extern IntPtr OpenProcess(ProcessAccessFlags processAccess, bool bInheritHandle, int processId);
|
|
||||||
|
|
||||||
|
|
||||||
[Flags]
|
|
||||||
private enum ProcessAccessFlags : uint
|
|
||||||
{
|
|
||||||
QueryLimitedInformation = 0x00001000
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user