mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Merge branch 'development'
This commit is contained in:
commit
dd54a8a54c
@ -0,0 +1,13 @@
|
||||
namespace Artemis.Core
|
||||
{
|
||||
internal class StringNotNullConditionOperator : ConditionOperator<string>
|
||||
{
|
||||
public override string Description => "Is not null";
|
||||
public override string Icon => "CheckboxMarkedCircleOutline";
|
||||
|
||||
public override bool Evaluate(string a)
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
namespace Artemis.Core
|
||||
{
|
||||
internal class StringNullConditionOperator : ConditionOperator<string>
|
||||
{
|
||||
public override string Description => "Is null";
|
||||
public override string Icon => "Null";
|
||||
|
||||
public override bool Evaluate(string a)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Artemis.Core.LayerEffects;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
@ -27,7 +28,6 @@ namespace Artemis.Core
|
||||
Parent = parent ?? throw new ArgumentNullException(nameof(parent));
|
||||
Profile = Parent.Profile;
|
||||
Name = name;
|
||||
Enabled = true;
|
||||
|
||||
Parent.AddChild(this);
|
||||
}
|
||||
@ -46,7 +46,7 @@ namespace Artemis.Core
|
||||
Profile = profile;
|
||||
Parent = parent;
|
||||
Name = folderEntity.Name;
|
||||
Enabled = folderEntity.Enabled;
|
||||
Suspended = folderEntity.Suspended;
|
||||
Order = folderEntity.Order;
|
||||
|
||||
Load();
|
||||
@ -62,6 +62,9 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public FolderEntity FolderEntity { get; internal set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool ShouldBeEnabled => !Suspended && DisplayConditionMet && !Timeline.IsFinished;
|
||||
|
||||
internal override RenderElementEntity RenderElementEntity => FolderEntity;
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -81,12 +84,14 @@ namespace Artemis.Core
|
||||
if (Disposed)
|
||||
throw new ObjectDisposedException("Folder");
|
||||
|
||||
if (!Enabled)
|
||||
return;
|
||||
|
||||
UpdateDisplayCondition();
|
||||
UpdateTimeline(deltaTime);
|
||||
|
||||
if (ShouldBeEnabled)
|
||||
Enable();
|
||||
else if (Timeline.IsFinished)
|
||||
Disable();
|
||||
|
||||
foreach (ProfileElement child in Children)
|
||||
child.Update(deltaTime);
|
||||
}
|
||||
@ -175,16 +180,16 @@ namespace Artemis.Core
|
||||
throw new ObjectDisposedException("Folder");
|
||||
|
||||
// Ensure the folder is ready
|
||||
if (!Enabled || !Children.Any(c => c.Enabled) || Path == null)
|
||||
if (!Enabled || Path == null)
|
||||
return;
|
||||
|
||||
// No point rendering if none of the children are going to render
|
||||
if (!Children.Any(c => c is RenderProfileElement renderElement && !renderElement.Timeline.IsFinished))
|
||||
// No point rendering if all children are disabled
|
||||
if (!Children.Any(c => c is RenderProfileElement {Enabled: true}))
|
||||
return;
|
||||
|
||||
lock (Timeline)
|
||||
{
|
||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => e.Enabled))
|
||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => !e.Suspended))
|
||||
{
|
||||
baseLayerEffect.BaseProperties?.Update(Timeline);
|
||||
baseLayerEffect.Update(Timeline.Delta.TotalSeconds);
|
||||
@ -194,7 +199,7 @@ namespace Artemis.Core
|
||||
try
|
||||
{
|
||||
SKRectI rendererBounds = SKRectI.Create(0, 0, Bounds.Width, Bounds.Height);
|
||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => e.Enabled))
|
||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => !e.Suspended))
|
||||
baseLayerEffect.PreProcess(canvas, rendererBounds, layerPaint);
|
||||
|
||||
canvas.SaveLayer(layerPaint);
|
||||
@ -215,7 +220,7 @@ namespace Artemis.Core
|
||||
for (int index = Children.Count - 1; index > -1; index--)
|
||||
Children[index].Render(canvas, new SKPointI(Bounds.Left, Bounds.Top));
|
||||
|
||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => e.Enabled))
|
||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => !e.Suspended))
|
||||
baseLayerEffect.PostProcess(canvas, rendererBounds, layerPaint);
|
||||
}
|
||||
finally
|
||||
@ -270,7 +275,7 @@ namespace Artemis.Core
|
||||
|
||||
FolderEntity.Order = Order;
|
||||
FolderEntity.Name = Name;
|
||||
FolderEntity.Enabled = Enabled;
|
||||
FolderEntity.Suspended = Suspended;
|
||||
|
||||
FolderEntity.ProfileId = Profile.EntityId;
|
||||
FolderEntity.ExpandedPropertyGroups.Clear();
|
||||
@ -279,6 +284,46 @@ namespace Artemis.Core
|
||||
SaveRenderElement();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Enable()
|
||||
{
|
||||
if (Enabled)
|
||||
return;
|
||||
|
||||
Debug.WriteLine($"Enabling {this}");
|
||||
|
||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects)
|
||||
baseLayerEffect.InternalEnable();
|
||||
|
||||
foreach (ProfileElement profileElement in Children)
|
||||
{
|
||||
if (profileElement is RenderProfileElement renderProfileElement && renderProfileElement.ShouldBeEnabled)
|
||||
renderProfileElement.Enable();
|
||||
}
|
||||
|
||||
Enabled = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Disable()
|
||||
{
|
||||
if (!Enabled)
|
||||
return;
|
||||
|
||||
Debug.WriteLine($"Disabled {this}");
|
||||
|
||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects)
|
||||
baseLayerEffect.InternalDisable();
|
||||
|
||||
foreach (ProfileElement profileElement in Children)
|
||||
{
|
||||
if (profileElement is RenderProfileElement renderProfileElement)
|
||||
renderProfileElement.Disable();
|
||||
}
|
||||
|
||||
Enabled = false;
|
||||
}
|
||||
|
||||
#region Events
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Artemis.Core.LayerBrushes;
|
||||
using Artemis.Core.LayerEffects;
|
||||
@ -35,7 +36,7 @@ namespace Artemis.Core
|
||||
Parent = parent ?? throw new ArgumentNullException(nameof(parent));
|
||||
Profile = Parent.Profile;
|
||||
Name = name;
|
||||
Enabled = true;
|
||||
Suspended = false;
|
||||
_general = new LayerGeneralProperties();
|
||||
_transform = new LayerTransformProperties();
|
||||
|
||||
@ -120,6 +121,9 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public LayerEntity LayerEntity { get; internal set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool ShouldBeEnabled => !Suspended && DisplayConditionMet;
|
||||
|
||||
internal override RenderElementEntity RenderElementEntity => LayerEntity;
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -192,7 +196,7 @@ namespace Artemis.Core
|
||||
{
|
||||
EntityId = LayerEntity.Id;
|
||||
Name = LayerEntity.Name;
|
||||
Enabled = LayerEntity.Enabled;
|
||||
Suspended = LayerEntity.Suspended;
|
||||
Order = LayerEntity.Order;
|
||||
|
||||
ExpandedPropertyGroups.AddRange(LayerEntity.ExpandedPropertyGroups);
|
||||
@ -208,7 +212,7 @@ namespace Artemis.Core
|
||||
LayerEntity.Id = EntityId;
|
||||
LayerEntity.ParentId = Parent?.EntityId ?? new Guid();
|
||||
LayerEntity.Order = Order;
|
||||
LayerEntity.Enabled = Enabled;
|
||||
LayerEntity.Suspended = Suspended;
|
||||
LayerEntity.Name = Name;
|
||||
LayerEntity.ProfileId = Profile.EntityId;
|
||||
LayerEntity.ExpandedPropertyGroups.Clear();
|
||||
@ -262,11 +266,13 @@ namespace Artemis.Core
|
||||
if (Disposed)
|
||||
throw new ObjectDisposedException("Layer");
|
||||
|
||||
if (!Enabled)
|
||||
return;
|
||||
|
||||
UpdateDisplayCondition();
|
||||
UpdateTimeline(deltaTime);
|
||||
|
||||
if (ShouldBeEnabled)
|
||||
Enable();
|
||||
else if (Timeline.IsFinished)
|
||||
Disable();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -295,6 +301,36 @@ namespace Artemis.Core
|
||||
Timeline.ClearDelta();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Enable()
|
||||
{
|
||||
if (Enabled)
|
||||
return;
|
||||
|
||||
Debug.WriteLine($"Enabling {this}");
|
||||
|
||||
LayerBrush?.InternalEnable();
|
||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects)
|
||||
baseLayerEffect.InternalEnable();
|
||||
|
||||
Enabled = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Disable()
|
||||
{
|
||||
if (!Enabled)
|
||||
return;
|
||||
|
||||
Debug.WriteLine($"Disabling {this}");
|
||||
|
||||
LayerBrush?.InternalDisable();
|
||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects)
|
||||
baseLayerEffect.InternalDisable();
|
||||
|
||||
Enabled = false;
|
||||
}
|
||||
|
||||
private void ApplyTimeline(Timeline timeline)
|
||||
{
|
||||
if (timeline.Delta == TimeSpan.Zero)
|
||||
@ -308,7 +344,7 @@ namespace Artemis.Core
|
||||
LayerBrush.Update(timeline.Delta.TotalSeconds);
|
||||
}
|
||||
|
||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => e.Enabled))
|
||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => !e.Suspended))
|
||||
{
|
||||
baseLayerEffect.BaseProperties?.Update(timeline);
|
||||
baseLayerEffect.Update(timeline.Delta.TotalSeconds);
|
||||
@ -387,7 +423,7 @@ namespace Artemis.Core
|
||||
if (LayerBrush == null)
|
||||
throw new ArtemisCoreException("The layer is not yet ready for rendering");
|
||||
|
||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => e.Enabled))
|
||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => !e.Suspended))
|
||||
baseLayerEffect.PreProcess(canvas, bounds, layerPaint);
|
||||
|
||||
try
|
||||
@ -398,7 +434,7 @@ namespace Artemis.Core
|
||||
canvas.ClipPath(renderPath);
|
||||
LayerBrush.InternalRender(canvas, bounds, layerPaint);
|
||||
|
||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => e.Enabled))
|
||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => !e.Suspended))
|
||||
baseLayerEffect.PostProcess(canvas, bounds, layerPaint);
|
||||
}
|
||||
|
||||
|
||||
@ -196,7 +196,7 @@ namespace Artemis.Core
|
||||
ProfileEntity.Layers.Clear();
|
||||
ProfileEntity.Layers.AddRange(GetAllLayers().Select(f => f.LayerEntity));
|
||||
}
|
||||
|
||||
|
||||
internal void Activate(IEnumerable<ArtemisDevice> devices)
|
||||
{
|
||||
lock (_lock)
|
||||
|
||||
@ -11,7 +11,7 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public abstract class ProfileElement : CorePropertyChanged, IDisposable
|
||||
{
|
||||
private bool _enabled;
|
||||
private bool _suspended;
|
||||
private Guid _entityId;
|
||||
private string? _name;
|
||||
private int _order;
|
||||
@ -87,12 +87,12 @@ namespace Artemis.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the enabled state, if not enabled the element is skipped in render and update
|
||||
/// Gets or sets the suspended state, if suspended the element is skipped in render and update
|
||||
/// </summary>
|
||||
public bool Enabled
|
||||
public bool Suspended
|
||||
{
|
||||
get => _enabled;
|
||||
set => SetAndNotify(ref _enabled, value);
|
||||
get => _suspended;
|
||||
set => SetAndNotify(ref _suspended, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -16,9 +16,9 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public abstract class RenderProfileElement : ProfileElement
|
||||
{
|
||||
private SKPath? _path;
|
||||
private SKRectI _bounds;
|
||||
|
||||
private SKPath? _path;
|
||||
|
||||
internal RenderProfileElement(Profile profile) : base(profile)
|
||||
{
|
||||
Timeline = new Timeline();
|
||||
@ -29,13 +29,26 @@ namespace Artemis.Core
|
||||
LayerEffectStore.LayerEffectRemoved += LayerEffectStoreOnLayerEffectRemoved;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether this render element and its layers/brushes are enabled
|
||||
/// </summary>
|
||||
public bool Enabled { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether this render element and its layers/brushes should be enabled
|
||||
/// </summary>
|
||||
public abstract bool ShouldBeEnabled { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a list of all layer properties present on this render element
|
||||
/// </summary>
|
||||
/// <returns>A list of all layer properties present on this render element</returns>
|
||||
public abstract List<ILayerProperty> GetAllLayerProperties();
|
||||
|
||||
#region IDisposable
|
||||
/// <summary>
|
||||
/// Occurs when a layer effect has been added or removed to this render element
|
||||
/// </summary>
|
||||
public event EventHandler? LayerEffectsUpdated;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Dispose(bool disposing)
|
||||
@ -49,8 +62,6 @@ namespace Artemis.Core
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
internal void LoadRenderElement()
|
||||
{
|
||||
DisplayCondition = RenderElementEntity.DisplayCondition != null
|
||||
@ -75,7 +86,7 @@ namespace Artemis.Core
|
||||
ProviderId = layerEffect.Descriptor?.PlaceholderFor ?? layerEffect.ProviderId,
|
||||
EffectType = layerEffect.GetEffectTypeName(),
|
||||
Name = layerEffect.Name,
|
||||
Enabled = layerEffect.Enabled,
|
||||
Suspended = layerEffect.Suspended,
|
||||
HasBeenRenamed = layerEffect.HasBeenRenamed,
|
||||
Order = layerEffect.Order
|
||||
};
|
||||
@ -92,6 +103,11 @@ namespace Artemis.Core
|
||||
Timeline?.Save();
|
||||
}
|
||||
|
||||
internal void OnLayerEffectsUpdated()
|
||||
{
|
||||
LayerEffectsUpdated?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
#region Timeline
|
||||
|
||||
/// <summary>
|
||||
@ -160,7 +176,7 @@ namespace Artemis.Core
|
||||
#region Property group expansion
|
||||
|
||||
internal List<string> ExpandedPropertyGroups;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the provided property group is expanded
|
||||
/// </summary>
|
||||
@ -188,6 +204,20 @@ namespace Artemis.Core
|
||||
|
||||
#endregion
|
||||
|
||||
#region State
|
||||
|
||||
/// <summary>
|
||||
/// Enables the render element and its brushes and effects
|
||||
/// </summary>
|
||||
public abstract void Disable();
|
||||
|
||||
/// <summary>
|
||||
/// Disables the render element and its brushes and effects
|
||||
/// </summary>
|
||||
public abstract void Enable();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Effect management
|
||||
|
||||
internal List<BaseLayerEffect> LayerEffectsList;
|
||||
@ -208,7 +238,7 @@ namespace Artemis.Core
|
||||
LayerEffectEntity entity = new()
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Enabled = true,
|
||||
Suspended = false,
|
||||
Order = LayerEffects.Count + 1
|
||||
};
|
||||
descriptor.CreateInstance(this, entity);
|
||||
@ -338,6 +368,12 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public void UpdateDisplayCondition()
|
||||
{
|
||||
if (Suspended)
|
||||
{
|
||||
DisplayConditionMet = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (DisplayCondition == null)
|
||||
{
|
||||
DisplayConditionMet = true;
|
||||
@ -381,19 +417,5 @@ namespace Artemis.Core
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a layer effect has been added or removed to this render element
|
||||
/// </summary>
|
||||
public event EventHandler? LayerEffectsUpdated;
|
||||
|
||||
internal void OnLayerEffectsUpdated()
|
||||
{
|
||||
LayerEffectsUpdated?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -82,6 +82,11 @@ namespace Artemis.Core.LayerBrushes
|
||||
/// </summary>
|
||||
public virtual ILayerBrushPreset? DefaultPreset => Presets?.FirstOrDefault();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether the layer brush is enabled or not
|
||||
/// </summary>
|
||||
public bool Enabled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the brush supports transformations
|
||||
/// <para>Note: RGB.NET brushes can never be transformed and setting this to true will throw an exception</para>
|
||||
@ -113,14 +118,6 @@ namespace Artemis.Core.LayerBrushes
|
||||
/// <param name="deltaTime">Seconds passed since last update</param>
|
||||
public abstract void Update(double deltaTime);
|
||||
|
||||
// Not only is this needed to initialize properties on the layer brushes, it also prevents implementing anything
|
||||
// but LayerBrush<T> and RgbNetLayerBrush<T> outside the core
|
||||
internal abstract void Initialize();
|
||||
|
||||
internal abstract void InternalRender(SKCanvas canvas, SKRect path, SKPaint paint);
|
||||
|
||||
#region IDisposable
|
||||
|
||||
/// <summary>
|
||||
/// Releases the unmanaged resources used by the object and optionally releases the managed resources.
|
||||
/// </summary>
|
||||
@ -137,14 +134,42 @@ namespace Artemis.Core.LayerBrushes
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables the layer brush if it isn't already enabled
|
||||
/// </summary>
|
||||
internal void InternalEnable()
|
||||
{
|
||||
if (Enabled)
|
||||
return;
|
||||
|
||||
EnableLayerBrush();
|
||||
Enabled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables the layer brush if it isn't already disabled
|
||||
/// </summary>
|
||||
internal void InternalDisable()
|
||||
{
|
||||
if (!Enabled)
|
||||
return;
|
||||
|
||||
DisableLayerBrush();
|
||||
Enabled = false;
|
||||
}
|
||||
|
||||
// Not only is this needed to initialize properties on the layer brushes, it also prevents implementing anything
|
||||
// but LayerBrush<T> and RgbNetLayerBrush<T> outside the core
|
||||
internal abstract void Initialize();
|
||||
|
||||
internal abstract void InternalRender(SKCanvas canvas, SKRect path, SKPaint paint);
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -71,6 +71,9 @@ namespace Artemis.Core.LayerBrushes
|
||||
|
||||
layer.LayerBrush = brush;
|
||||
layer.OnLayerBrushUpdated();
|
||||
|
||||
if (layer.ShouldBeEnabled)
|
||||
brush.InternalEnable();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -11,7 +11,7 @@ namespace Artemis.Core.LayerEffects
|
||||
{
|
||||
private ILayerEffectConfigurationDialog? _configurationDialog;
|
||||
private LayerEffectDescriptor _descriptor;
|
||||
private bool _enabled;
|
||||
private bool _suspended;
|
||||
private Guid _entityId;
|
||||
private bool _hasBeenRenamed;
|
||||
private string _name;
|
||||
@ -55,12 +55,12 @@ namespace Artemis.Core.LayerEffects
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the enabled state, if not enabled the effect is skipped in render and update
|
||||
/// Gets or sets the suspended state, if suspended the effect is skipped in render and update
|
||||
/// </summary>
|
||||
public bool Enabled
|
||||
public bool Suspended
|
||||
{
|
||||
get => _enabled;
|
||||
set => SetAndNotify(ref _enabled, value);
|
||||
get => _suspended;
|
||||
set => SetAndNotify(ref _suspended, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -112,6 +112,11 @@ namespace Artemis.Core.LayerEffects
|
||||
|
||||
internal string PropertyRootPath => $"LayerEffect.{EntityId}.{GetType().Name}.";
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether the layer effect is enabled or not
|
||||
/// </summary>
|
||||
public bool Enabled { get; private set; }
|
||||
|
||||
#region IDisposable
|
||||
|
||||
/// <summary>
|
||||
@ -176,5 +181,29 @@ namespace Artemis.Core.LayerEffects
|
||||
internal abstract void Initialize();
|
||||
|
||||
internal virtual string GetEffectTypeName() => GetType().Name;
|
||||
|
||||
/// <summary>
|
||||
/// Enables the layer effect if it isn't already enabled
|
||||
/// </summary>
|
||||
internal void InternalEnable()
|
||||
{
|
||||
if (Enabled)
|
||||
return;
|
||||
|
||||
EnableLayerEffect();
|
||||
Enabled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables the layer effect if it isn't already disabled
|
||||
/// </summary>
|
||||
internal void InternalDisable()
|
||||
{
|
||||
if (!Enabled)
|
||||
return;
|
||||
|
||||
DisableLayerEffect();
|
||||
Enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -74,7 +74,7 @@ namespace Artemis.Core.LayerEffects
|
||||
effect.EntityId = entity.Id;
|
||||
effect.Order = entity.Order;
|
||||
effect.Name = entity.Name;
|
||||
effect.Enabled = entity.Enabled;
|
||||
effect.Suspended = entity.Suspended;
|
||||
effect.Descriptor = this;
|
||||
|
||||
effect.Initialize();
|
||||
@ -94,6 +94,9 @@ namespace Artemis.Core.LayerEffects
|
||||
};
|
||||
effect.Initialize();
|
||||
renderElement.ActivateLayerEffect(effect);
|
||||
|
||||
if (renderElement.ShouldBeEnabled)
|
||||
effect.InternalEnable();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,7 @@ namespace Artemis.Core.LayerEffects.Placeholder
|
||||
EntityId = OriginalEntity.Id;
|
||||
Order = OriginalEntity.Order;
|
||||
Name = OriginalEntity.Name;
|
||||
Enabled = OriginalEntity.Enabled;
|
||||
Suspended = OriginalEntity.Suspended;
|
||||
HasBeenRenamed = OriginalEntity.HasBeenRenamed;
|
||||
}
|
||||
|
||||
|
||||
@ -98,11 +98,19 @@ namespace Artemis.Core.Services
|
||||
}
|
||||
else
|
||||
{
|
||||
PluginInfo pluginInfo;
|
||||
try
|
||||
{
|
||||
// Compare versions, copy if the same when debugging
|
||||
PluginInfo pluginInfo = CoreJson.DeserializeObject<PluginInfo>(File.ReadAllText(metadataFile))!;
|
||||
pluginInfo = CoreJson.DeserializeObject<PluginInfo>(File.ReadAllText(metadataFile))!;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ArtemisPluginException($"Failed read plugin metadata needed to install built-in plugin: {e.Message}", e);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (builtInPluginInfo.Version > pluginInfo.Version)
|
||||
{
|
||||
_logger.Debug("Copying updated built-in plugin from {pluginInfo} to {builtInPluginInfo}", pluginInfo, builtInPluginInfo);
|
||||
@ -111,7 +119,7 @@ namespace Artemis.Core.Services
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ArtemisPluginException("Failed read plugin metadata needed to install built-in plugin", e);
|
||||
throw new ArtemisPluginException($"Failed to install built-in plugin: {e.Message}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,6 +61,8 @@ namespace Artemis.Core.Services
|
||||
RegisterConditionOperator(Constants.CorePlugin, new StringStartsWithConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new StringEndsWithConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new StringMatchesRegexConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new StringNullConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new StringNotNullConditionOperator());
|
||||
|
||||
// Null checks, at the bottom
|
||||
// TODO: Implement a priority mechanism
|
||||
|
||||
@ -16,7 +16,7 @@ namespace Artemis.Storage.Entities.Profile
|
||||
|
||||
public int Order { get; set; }
|
||||
public string Name { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
public bool Suspended { get; set; }
|
||||
|
||||
[BsonRef("ProfileEntity")]
|
||||
public ProfileEntity Profile { get; set; }
|
||||
|
||||
@ -8,7 +8,7 @@ namespace Artemis.Storage.Entities.Profile
|
||||
public string ProviderId { get; set; }
|
||||
public string EffectType { get; set; }
|
||||
public string Name { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
public bool Suspended { get; set; }
|
||||
public bool HasBeenRenamed { get; set; }
|
||||
public int Order { get; set; }
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ namespace Artemis.Storage.Entities.Profile
|
||||
|
||||
public int Order { get; set; }
|
||||
public string Name { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
public bool Suspended { get; set; }
|
||||
|
||||
public List<LedEntity> Leds { get; set; }
|
||||
|
||||
|
||||
@ -16,16 +16,16 @@ namespace Artemis.Storage.Migrations
|
||||
{
|
||||
foreach (FolderEntity profileEntityFolder in profileEntity.Folders)
|
||||
{
|
||||
profileEntityFolder.Enabled = true;
|
||||
profileEntityFolder.Suspended = false;
|
||||
foreach (LayerEffectEntity layerEffectEntity in profileEntityFolder.LayerEffects)
|
||||
layerEffectEntity.Enabled = true;
|
||||
layerEffectEntity.Suspended = false;
|
||||
}
|
||||
|
||||
foreach (LayerEntity profileEntityLayer in profileEntity.Layers)
|
||||
{
|
||||
profileEntityLayer.Enabled = true;
|
||||
profileEntityLayer.Suspended = false;
|
||||
foreach (LayerEffectEntity layerEffectEntity in profileEntityLayer.LayerEffects)
|
||||
layerEffectEntity.Enabled = true;
|
||||
layerEffectEntity.Suspended = false;
|
||||
}
|
||||
|
||||
repository.Upsert(profileEntity);
|
||||
|
||||
@ -124,15 +124,30 @@ namespace Artemis.UI.Shared.Services
|
||||
if (SelectedProfile == null || _doTick)
|
||||
return;
|
||||
|
||||
// Stick to the main segment for any element that is not currently selected
|
||||
foreach (Folder folder in SelectedProfile.GetAllFolders())
|
||||
folder.Timeline.Override(CurrentTime, folder.Timeline.PlayMode == TimelinePlayMode.Repeat);
|
||||
foreach (Layer layer in SelectedProfile.GetAllLayers())
|
||||
layer.Timeline.Override(CurrentTime, (layer != SelectedProfileElement || layer.Timeline.Length < CurrentTime) && layer.Timeline.PlayMode == TimelinePlayMode.Repeat);
|
||||
|
||||
TickProfileElement(SelectedProfile.GetRootFolder());
|
||||
_doTick = true;
|
||||
}
|
||||
|
||||
private void TickProfileElement(ProfileElement profileElement)
|
||||
{
|
||||
if (profileElement is not RenderProfileElement renderElement)
|
||||
return;
|
||||
|
||||
if (renderElement.Suspended)
|
||||
renderElement.Disable();
|
||||
else
|
||||
{
|
||||
renderElement.Enable();
|
||||
renderElement.Timeline.Override(
|
||||
CurrentTime,
|
||||
(renderElement != SelectedProfileElement || renderElement.Timeline.Length < CurrentTime) && renderElement.Timeline.PlayMode == TimelinePlayMode.Repeat
|
||||
);
|
||||
|
||||
foreach (ProfileElement child in renderElement.Children)
|
||||
TickProfileElement(child);
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectedProfileOnDeactivated(object? sender, EventArgs e)
|
||||
{
|
||||
// Execute.PostToUIThread(() => ChangeSelectedProfile(null));
|
||||
|
||||
@ -4,13 +4,16 @@ using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Security.Principal;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Screens;
|
||||
using Artemis.UI.Utilities;
|
||||
using Ninject;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI
|
||||
@ -127,5 +130,48 @@ namespace Artemis.UI
|
||||
|
||||
Execute.OnUIThread(() => Application.Current.Shutdown());
|
||||
}
|
||||
|
||||
public void DisplayException(Exception e)
|
||||
{
|
||||
using TaskDialog dialog = new();
|
||||
AssemblyInformationalVersionAttribute versionAttribute = typeof(ApplicationStateManager).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
|
||||
dialog.WindowTitle = $"Artemis {versionAttribute?.InformationalVersion} build {Constants.BuildInfo.BuildNumberDisplay}";
|
||||
dialog.MainInstruction = "Unfortunately Artemis ran into an unhandled exception and cannot continue.";
|
||||
dialog.Content = e.Message;
|
||||
dialog.ExpandedInformation = e.StackTrace.Trim();
|
||||
|
||||
dialog.CollapsedControlText = "Show stack trace";
|
||||
dialog.ExpandedControlText = "Hide stack trace";
|
||||
|
||||
dialog.Footer = "If this keeps happening check out the <a href=\"https://wiki.artemis-rgb.com\">wiki</a> or hit us up on <a href=\"https://discord.gg/S3MVaC9\">Discord</a>.";
|
||||
dialog.FooterIcon = TaskDialogIcon.Error;
|
||||
dialog.EnableHyperlinks = true;
|
||||
dialog.HyperlinkClicked += OpenHyperlink;
|
||||
|
||||
TaskDialogButton copyButton = new("Copy stack trace");
|
||||
TaskDialogButton closeButton = new("Close") {Default = true};
|
||||
dialog.Buttons.Add(copyButton);
|
||||
dialog.Buttons.Add(closeButton);
|
||||
dialog.ButtonClicked += (_, args) =>
|
||||
{
|
||||
if (args.Item == copyButton)
|
||||
{
|
||||
Clipboard.SetText(e.ToString());
|
||||
args.Cancel = true;
|
||||
}
|
||||
};
|
||||
|
||||
dialog.ShowDialog(Application.Current.MainWindow);
|
||||
}
|
||||
|
||||
private void OpenHyperlink(object sender, HyperlinkClickedEventArgs e)
|
||||
{
|
||||
ProcessStartInfo processInfo = new()
|
||||
{
|
||||
FileName = e.Href,
|
||||
UseShellExecute = true
|
||||
};
|
||||
Process.Start(processInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -48,7 +48,14 @@ namespace Artemis.UI
|
||||
return;
|
||||
}
|
||||
|
||||
try { DPIAwareness.Initalize(); } catch (Exception ex) { logger.Error($"Failed to set DPI-Awareness: {ex.Message}"); }
|
||||
try
|
||||
{
|
||||
DPIAwareness.Initalize();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error($"Failed to set DPI-Awareness: {ex.Message}");
|
||||
}
|
||||
|
||||
IViewManager viewManager = Kernel.Get<IViewManager>();
|
||||
StartupArguments = Args.ToList();
|
||||
@ -71,7 +78,7 @@ namespace Artemis.UI
|
||||
Execute.OnUIThreadSync(() =>
|
||||
{
|
||||
UIElement view = viewManager.CreateAndBindViewForModelIfNecessary(RootViewModel);
|
||||
((TrayViewModel)RootViewModel).SetTaskbarIcon(view);
|
||||
((TrayViewModel) RootViewModel).SetTaskbarIcon(view);
|
||||
});
|
||||
|
||||
// Initialize the core async so the UI can show the progress
|
||||
@ -136,15 +143,9 @@ namespace Artemis.UI
|
||||
private void HandleFatalException(Exception e, ILogger logger)
|
||||
{
|
||||
logger.Fatal(e, "Fatal exception during initialization, shutting down.");
|
||||
|
||||
// Can't use a pretty exception dialog here since the UI might not even be visible
|
||||
Execute.OnUIThread(() =>
|
||||
{
|
||||
Kernel.Get<IWindowManager>().ShowMessageBox(e.Message + "\n\n Please refer the log file for more details.",
|
||||
"Fatal exception during initialization",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Error
|
||||
);
|
||||
_applicationStateManager.DisplayException(e);
|
||||
Environment.Exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
d:DataContext="{d:DesignInstance local:TreeGroupViewModel}"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<converters:InverseBooleanConverter x:Key="InverseBooleanConverter"/>
|
||||
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
||||
<converters:PropertyTreeMarginConverter Length="20" x:Key="PropertyTreeMarginConverter" />
|
||||
</UserControl.Resources>
|
||||
@ -180,13 +181,13 @@
|
||||
<StackPanel Grid.Column="5" Orientation="Horizontal">
|
||||
<ToggleButton
|
||||
Style="{StaticResource MaterialDesignFlatToggleButton}"
|
||||
ToolTip="Toggle enabled state"
|
||||
ToolTip="Toggle suspended state"
|
||||
Width="18"
|
||||
Height="18"
|
||||
IsChecked="{Binding LayerPropertyGroup.LayerEffect.Enabled}"
|
||||
IsChecked="{Binding LayerPropertyGroup.LayerEffect.Suspended, Converter={StaticResource InverseBooleanConverter}}"
|
||||
VerticalAlignment="Center" Padding="-25"
|
||||
Margin="5 0"
|
||||
Command="{s:Action EnableToggled}">
|
||||
Command="{s:Action SuspendedToggled}">
|
||||
<materialDesign:PackIcon Kind="Eye" Height="13" Width="13" />
|
||||
</ToggleButton>
|
||||
<Button Style="{StaticResource MaterialDesignIconButton}"
|
||||
|
||||
@ -145,7 +145,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
|
||||
_profileEditorService.UpdateSelectedProfile();
|
||||
}
|
||||
|
||||
public void EnableToggled()
|
||||
public void SuspendedToggled()
|
||||
{
|
||||
_profileEditorService.UpdateSelectedProfile();
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem.FolderView"
|
||||
<UserControl
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
@ -6,9 +6,13 @@
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:treeItem1="clr-namespace:Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem"
|
||||
xmlns:Converters="clr-namespace:Artemis.UI.Converters" x:Class="Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem.FolderView"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
d:DataContext="{d:DesignInstance {x:Type treeItem1:FolderViewModel}}">
|
||||
<UserControl.Resources>
|
||||
<Converters:InverseBooleanConverter x:Key="InverseBooleanConverter"/>
|
||||
</UserControl.Resources>
|
||||
<!-- Capture clicks on full tree view item -->
|
||||
<StackPanel Margin="-10" Background="Transparent" ContextMenuOpening="{s:Action ContextMenuOpening}">
|
||||
<StackPanel.ContextMenu>
|
||||
@ -67,11 +71,11 @@
|
||||
<TextBlock Grid.Column="1" Text="{Binding ProfileElement.Name}" Margin="10 0 0 0" VerticalAlignment="Center" />
|
||||
<ToggleButton Grid.Column="2"
|
||||
Style="{StaticResource MaterialDesignFlatToggleButton}"
|
||||
ToolTip="Toggle enabled state"
|
||||
ToolTip="Toggle suspended state"
|
||||
Width="18"
|
||||
Height="18"
|
||||
IsChecked="{Binding ProfileElement.Enabled}"
|
||||
Command="{s:Action EnableToggled}"
|
||||
IsChecked="{Binding ProfileElement.Suspended, Converter={StaticResource InverseBooleanConverter}}"
|
||||
Command="{s:Action SuspendedToggled}"
|
||||
VerticalAlignment="Center" Padding="-25">
|
||||
<materialDesign:PackIcon Kind="Eye" Height="13" Width="13" />
|
||||
</ToggleButton>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem.LayerView"
|
||||
<UserControl
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
@ -6,9 +6,13 @@
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:treeItem1="clr-namespace:Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem"
|
||||
xmlns:Converters="clr-namespace:Artemis.UI.Converters" x:Class="Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem.LayerView"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
d:DataContext="{d:DesignInstance {x:Type treeItem1:LayerViewModel}}">
|
||||
<UserControl.Resources>
|
||||
<Converters:InverseBooleanConverter x:Key="InverseBooleanConverter"/>
|
||||
</UserControl.Resources>
|
||||
<!-- Capture clicks on full tree view item -->
|
||||
<StackPanel Margin="-10" Background="Transparent" ContextMenuOpening="{s:Action ContextMenuOpening}">
|
||||
<StackPanel.ContextMenu>
|
||||
@ -60,11 +64,11 @@
|
||||
<TextBlock Grid.Column="2" Text="{Binding Layer.Name}" VerticalAlignment="Center" Margin="5 0 0 0" />
|
||||
<ToggleButton Grid.Column="3"
|
||||
Style="{StaticResource MaterialDesignFlatToggleButton}"
|
||||
ToolTip="Toggle enabled state"
|
||||
ToolTip="Toggle suspended state"
|
||||
Width="18"
|
||||
Height="18"
|
||||
IsChecked="{Binding ProfileElement.Enabled}"
|
||||
Command="{s:Action EnableToggled}"
|
||||
IsChecked="{Binding ProfileElement.Suspended, Converter={StaticResource InverseBooleanConverter}}"
|
||||
Command="{s:Action SuspendedToggled}"
|
||||
VerticalAlignment="Center" Padding="-25">
|
||||
<materialDesign:PackIcon Kind="Eye" Height="13" Width="13" />
|
||||
</ToggleButton>
|
||||
|
||||
@ -241,7 +241,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
((BindableCollection<TreeItemViewModel>) Items).Sort(i => i.ProfileElement.Order);
|
||||
}
|
||||
|
||||
public void EnableToggled()
|
||||
public void SuspendedToggled()
|
||||
{
|
||||
_profileEditorService.UpdateSelectedProfile();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user