1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-31 09:43:46 +00:00

Profile editor - Removed delay in module override

Modules - Streamline update rules and properly honor them in timed updates
This commit is contained in:
Robert 2020-09-16 20:46:45 +02:00
parent 2eb4d615ae
commit 447a497945
7 changed files with 127 additions and 79 deletions

View File

@ -91,13 +91,13 @@ namespace Artemis.Core.Modules
/// <summary> /// <summary>
/// Gets whether this module's activation was due to an override, can only be true if <see cref="IsActivated" /> is /// Gets whether this module's activation was due to an override, can only be true if <see cref="IsActivated" /> is
/// true /// <see langword="true" />
/// </summary> /// </summary>
public bool IsActivatedOverride { get; private set; } public bool IsActivatedOverride { get; private set; }
/// <summary> /// <summary>
/// Gets whether this module should update if <see cref="IsActivatedOverride" /> is true /// Gets whether this module should update if <see cref="IsActivatedOverride" /> is <see langword="true" />
/// <para>Defaults to <c>true</c></para> /// <para>Defaults to <see langword="true" /></para>
/// </summary> /// </summary>
public bool UpdateDuringActivationOverride { get; protected set; } = true; public bool UpdateDuringActivationOverride { get; protected set; } = true;
@ -138,6 +138,11 @@ namespace Artemis.Core.Modules
/// </summary> /// </summary>
public IEnumerable<ModuleTab> ModuleTabs { get; protected set; } public IEnumerable<ModuleTab> ModuleTabs { get; protected set; }
/// <summary>
/// Gets whether updating this module is currently allowed
/// </summary>
public bool IsUpdateAllowed => IsActivated && (UpdateDuringActivationOverride || !IsActivatedOverride);
/// <summary> /// <summary>
/// Called each frame when the module must update /// Called each frame when the module must update
/// </summary> /// </summary>
@ -189,7 +194,7 @@ namespace Artemis.Core.Modules
internal virtual void InternalUpdate(double deltaTime) internal virtual void InternalUpdate(double deltaTime)
{ {
if (!IsActivatedOverride || UpdateDuringActivationOverride) if (IsUpdateAllowed)
Update(deltaTime); Update(deltaTime);
} }

View File

@ -141,7 +141,7 @@ namespace Artemis.Core.Modules
internal override void InternalUpdate(double deltaTime) internal override void InternalUpdate(double deltaTime)
{ {
if (!IsActivatedOverride || UpdateDuringActivationOverride) if (IsUpdateAllowed)
Update(deltaTime); Update(deltaTime);
lock (this) lock (this)

View File

@ -20,7 +20,6 @@ namespace Artemis.Core
PluginInfo.Instance.PluginEnabled += InstanceOnPluginEnabled; PluginInfo.Instance.PluginEnabled += InstanceOnPluginEnabled;
PluginInfo.Instance.PluginDisabled += InstanceOnPluginDisabled; PluginInfo.Instance.PluginDisabled += InstanceOnPluginDisabled;
if (PluginInfo.Instance.Enabled) if (PluginInfo.Instance.Enabled)
Start(); Start();
} }
@ -54,13 +53,6 @@ namespace Artemis.Core
if (_timer != null) if (_timer != null)
return; return;
// Don't update during override if that is disabled on the module
if (PluginInfo.Instance is Module module)
{
if (module.IsActivatedOverride && !module.UpdateDuringActivationOverride)
return;
}
_lastEvent = DateTime.Now; _lastEvent = DateTime.Now;
_timer = new Timer(Interval.TotalMilliseconds); _timer = new Timer(Interval.TotalMilliseconds);
_timer.Elapsed += TimerOnElapsed; _timer.Elapsed += TimerOnElapsed;
@ -94,6 +86,10 @@ namespace Artemis.Core
var interval = DateTime.Now - _lastEvent; var interval = DateTime.Now - _lastEvent;
_lastEvent = DateTime.Now; _lastEvent = DateTime.Now;
// Modules don't always want to update, honor that
if (PluginInfo.Instance is Module module && !module.IsUpdateAllowed)
return;
Action(interval.TotalSeconds); Action(interval.TotalSeconds);
} }

View File

@ -47,38 +47,24 @@ namespace Artemis.Core.Services
if (ActiveModuleOverride == overrideModule) if (ActiveModuleOverride == overrideModule)
return; return;
// If set to null, resume regular activation // Always deactivate all modules whenever override is called
if (overrideModule == null)
{
ActiveModuleOverride = null;
_logger.Information("Cleared active module override");
return;
}
// If a module was provided, activate it and deactivate everything else
var modules = _pluginService.GetPluginsOfType<Module>().ToList(); var modules = _pluginService.GetPluginsOfType<Module>().ToList();
var tasks = new List<Task>();
foreach (var module in modules) foreach (var module in modules)
OverrideDeactivate(module);
if (overrideModule != null)
{ {
if (module != overrideModule) OverrideActivate(overrideModule);
tasks.Add(DeactivateModule(module, true)); _logger.Information($"Setting active module override to {overrideModule.DisplayName}");
} }
else
_logger.Information("Clearing active module override");
if (!overrideModule.IsActivated)
tasks.Add(ActivateModule(overrideModule, true));
await Task.WhenAll(tasks);
ActiveModuleOverride = overrideModule; ActiveModuleOverride = overrideModule;
_logger.Information($"Set active module override to {ActiveModuleOverride.DisplayName}");
} }
finally finally
{ {
ActiveModuleSemaphore.Release(); ActiveModuleSemaphore.Release();
// With the semaphore released, trigger an update with the override was cleared
if (ActiveModuleOverride == null)
await UpdateModuleActivation();
} }
} }
@ -100,9 +86,9 @@ namespace Artemis.Core.Services
{ {
var shouldBeActivated = module.EvaluateActivationRequirements(); var shouldBeActivated = module.EvaluateActivationRequirements();
if (shouldBeActivated && !module.IsActivated) if (shouldBeActivated && !module.IsActivated)
tasks.Add(ActivateModule(module, false)); tasks.Add(ActivateModule(module));
else if (!shouldBeActivated && module.IsActivated) else if (!shouldBeActivated && module.IsActivated)
tasks.Add(DeactivateModule(module, false)); tasks.Add(DeactivateModule(module));
} }
await Task.WhenAll(tasks); await Task.WhenAll(tasks);
@ -149,11 +135,11 @@ namespace Artemis.Core.Services
await UpdateModuleActivation(); await UpdateModuleActivation();
} }
private async Task ActivateModule(Module module, bool isOverride) private async Task ActivateModule(Module module)
{ {
try try
{ {
module.Activate(isOverride); module.Activate(false);
// If this is a profile module, activate the last active profile after module activation // If this is a profile module, activate the last active profile after module activation
if (module is ProfileModule profileModule) if (module is ProfileModule profileModule)
@ -166,7 +152,27 @@ namespace Artemis.Core.Services
} }
} }
private async Task DeactivateModule(Module module, bool isOverride) private void OverrideActivate(Module module)
{
try
{
if (module.IsActivated)
return;
module.Activate(true);
// If this is a profile module, activate the last active profile after module activation
if (module is ProfileModule profileModule)
_profileService.ActivateLastProfile(profileModule);
}
catch (Exception e)
{
_logger.Error(new ArtemisPluginException(module.PluginInfo, "Failed to activate module and last profile.", e), "Failed to activate module and last profile");
throw;
}
}
private async Task DeactivateModule(Module module)
{ {
try try
{ {
@ -174,7 +180,27 @@ namespace Artemis.Core.Services
if (module.IsActivated && module is ProfileModule profileModule) if (module.IsActivated && module is ProfileModule profileModule)
await profileModule.ChangeActiveProfileAnimated(null, null); await profileModule.ChangeActiveProfileAnimated(null, null);
module.Deactivate(isOverride); module.Deactivate(false);
}
catch (Exception e)
{
_logger.Error(new ArtemisPluginException(module.PluginInfo, "Failed to deactivate module and last profile.", e), "Failed to deactivate module and last profile");
throw;
}
}
private void OverrideDeactivate(Module module)
{
try
{
if (!module.IsActivated)
return;
// If this is a profile module, activate the last active profile after module activation
if (module is ProfileModule profileModule)
profileModule.ChangeActiveProfile(null, null);
module.Deactivate(true);
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -58,8 +58,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
ShowDataModelValues = settingsService.GetSetting<bool>("ProfileEditor.ShowDataModelValues"); ShowDataModelValues = settingsService.GetSetting<bool>("ProfileEditor.ShowDataModelValues");
// Initialize async, no need to wait for it Initialize();
Task.Run(Initialize);
} }
public DisplayConditionPredicate DisplayConditionPredicate => (DisplayConditionPredicate) Model; public DisplayConditionPredicate DisplayConditionPredicate => (DisplayConditionPredicate) Model;

View File

@ -10,8 +10,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
public class TimelinePropertyViewModel<T> : Conductor<TimelineKeyframeViewModel<T>>.Collection.AllActive, ITimelinePropertyViewModel public class TimelinePropertyViewModel<T> : Conductor<TimelineKeyframeViewModel<T>>.Collection.AllActive, ITimelinePropertyViewModel
{ {
private readonly IProfileEditorService _profileEditorService; private readonly IProfileEditorService _profileEditorService;
public LayerProperty<T> LayerProperty { get; } private double _width;
public LayerPropertyViewModel LayerPropertyViewModel { get; }
public TimelinePropertyViewModel(LayerProperty<T> layerProperty, LayerPropertyViewModel layerPropertyViewModel, IProfileEditorService profileEditorService) public TimelinePropertyViewModel(LayerProperty<T> layerProperty, LayerPropertyViewModel layerPropertyViewModel, IProfileEditorService profileEditorService)
{ {
@ -23,22 +22,17 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
LayerProperty.KeyframesToggled += LayerPropertyOnKeyframesToggled; LayerProperty.KeyframesToggled += LayerPropertyOnKeyframesToggled;
LayerProperty.KeyframeAdded += LayerPropertyOnKeyframeAdded; LayerProperty.KeyframeAdded += LayerPropertyOnKeyframeAdded;
LayerProperty.KeyframeRemoved += LayerPropertyOnKeyframeRemoved; LayerProperty.KeyframeRemoved += LayerPropertyOnKeyframeRemoved;
_profileEditorService.PixelsPerSecondChanged += ProfileEditorServiceOnPixelsPerSecondChanged;
UpdateKeyframes(); UpdateKeyframes();
} }
private void LayerPropertyOnKeyframesToggled(object sender, LayerPropertyEventArgs<T> e) public LayerProperty<T> LayerProperty { get; }
{ public LayerPropertyViewModel LayerPropertyViewModel { get; }
UpdateKeyframes();
}
private void LayerPropertyOnKeyframeRemoved(object sender, LayerPropertyEventArgs<T> e) public double Width
{ {
UpdateKeyframes(); get => _width;
} set => SetAndNotify(ref _width, value);
private void LayerPropertyOnKeyframeAdded(object sender, LayerPropertyEventArgs<T> e)
{
UpdateKeyframes();
} }
public List<ITimelineKeyframeViewModel> GetAllKeyframeViewModels() public List<ITimelineKeyframeViewModel> GetAllKeyframeViewModels()
@ -46,29 +40,6 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
return Items.Cast<ITimelineKeyframeViewModel>().ToList(); return Items.Cast<ITimelineKeyframeViewModel>().ToList();
} }
private void UpdateKeyframes()
{
// Only show keyframes if they are enabled
if (LayerProperty.KeyframesEnabled)
{
var keyframes = LayerProperty.Keyframes.ToList();
var toRemove = Items.Where(t => !keyframes.Contains(t.LayerPropertyKeyframe)).ToList();
foreach (var timelineKeyframeViewModel in toRemove)
timelineKeyframeViewModel.Dispose();
Items.RemoveRange(toRemove);
Items.AddRange(keyframes
.Where(k => Items.All(t => t.LayerPropertyKeyframe != k))
.Select(k => new TimelineKeyframeViewModel<T>(k, _profileEditorService))
);
}
else
Items.Clear();
foreach (var timelineKeyframeViewModel in Items)
timelineKeyframeViewModel.Update();
}
public void WipeKeyframes(TimeSpan? start, TimeSpan? end) public void WipeKeyframes(TimeSpan? start, TimeSpan? end)
{ {
start ??= TimeSpan.Zero; start ??= TimeSpan.Zero;
@ -98,6 +69,50 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
LayerProperty.KeyframesToggled -= LayerPropertyOnKeyframesToggled; LayerProperty.KeyframesToggled -= LayerPropertyOnKeyframesToggled;
LayerProperty.KeyframeAdded -= LayerPropertyOnKeyframeAdded; LayerProperty.KeyframeAdded -= LayerPropertyOnKeyframeAdded;
LayerProperty.KeyframeRemoved -= LayerPropertyOnKeyframeRemoved; LayerProperty.KeyframeRemoved -= LayerPropertyOnKeyframeRemoved;
_profileEditorService.PixelsPerSecondChanged -= ProfileEditorServiceOnPixelsPerSecondChanged;
}
private void LayerPropertyOnKeyframesToggled(object sender, LayerPropertyEventArgs<T> e)
{
UpdateKeyframes();
}
private void LayerPropertyOnKeyframeRemoved(object sender, LayerPropertyEventArgs<T> e)
{
UpdateKeyframes();
}
private void LayerPropertyOnKeyframeAdded(object sender, LayerPropertyEventArgs<T> e)
{
UpdateKeyframes();
}
private void ProfileEditorServiceOnPixelsPerSecondChanged(object sender, EventArgs e)
{
Width = GetAllKeyframeViewModels().Max(k => k.Position.TotalSeconds * _profileEditorService.PixelsPerSecond + 25);
}
private void UpdateKeyframes()
{
// Only show keyframes if they are enabled
if (LayerProperty.KeyframesEnabled)
{
var keyframes = LayerProperty.Keyframes.ToList();
var toRemove = Items.Where(t => !keyframes.Contains(t.LayerPropertyKeyframe)).ToList();
foreach (var timelineKeyframeViewModel in toRemove)
timelineKeyframeViewModel.Dispose();
Items.RemoveRange(toRemove);
Items.AddRange(keyframes
.Where(k => Items.All(t => t.LayerPropertyKeyframe != k))
.Select(k => new TimelineKeyframeViewModel<T>(k, _profileEditorService))
);
}
else
Items.Clear();
foreach (var timelineKeyframeViewModel in Items)
timelineKeyframeViewModel.Update();
} }
} }

View File

@ -15,6 +15,7 @@ namespace Artemis.Plugins.Modules.Overlay
DisplayName = "Overlay"; DisplayName = "Overlay";
DisplayIcon = "ArrangeBringToFront"; DisplayIcon = "ArrangeBringToFront";
DefaultPriorityCategory = ModulePriorityCategory.Overlay; DefaultPriorityCategory = ModulePriorityCategory.Overlay;
UpdateDuringActivationOverride = false;
ActivationRequirements.Add(new ProcessActivationRequirement("taskmgr")); ActivationRequirements.Add(new ProcessActivationRequirement("taskmgr"));
ActivationRequirements.Add(new ProcessActivationRequirement("calc")); ActivationRequirements.Add(new ProcessActivationRequirement("calc"));
@ -22,6 +23,12 @@ namespace Artemis.Plugins.Modules.Overlay
{ {
Location = Path.Combine(Directory.GetParent(Environment.GetFolderPath(Environment.SpecialFolder.System)).FullName, "System32") Location = Path.Combine(Directory.GetParent(Environment.GetFolderPath(Environment.SpecialFolder.System)).FullName, "System32")
}); });
AddTimedUpdate(TimeSpan.FromSeconds(5), DelayedUpdate);
}
private void DelayedUpdate(double obj)
{
} }
// This is the end of your plugin life cycle. // This is the end of your plugin life cycle.