1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Profiles - Added toggle to enable/disable folders, layers and effects

Profiles - Fixed folders not saving they children properly
UI - Show version and frame time in window title
This commit is contained in:
SpoinkyNL 2020-06-18 19:08:46 +02:00
parent 7921a4f932
commit 0903865c7d
27 changed files with 315 additions and 97 deletions

View File

@ -62,7 +62,7 @@ namespace Artemis.Core.Models.Profile
if (Parent is EffectProfileElement effectParent)
shapeClip = shapeClip.Op(effectParent.CreateShapeClip(), SKPathOp.Union);
foreach (var baseLayerEffect in LayerEffects)
foreach (var baseLayerEffect in LayerEffects.Where(e => e.Enabled))
{
var effectClip = baseLayerEffect.InternalCreateShapeClip(Path);
shapeClip = shapeClip.Op(effectClip, SKPathOp.Difference);
@ -82,6 +82,7 @@ namespace Artemis.Core.Models.Profile
PluginGuid = layerEffect.PluginInfo.Guid,
EffectType = layerEffect.GetType().Name,
Name = layerEffect.Name,
Enabled = layerEffect.Enabled,
HasBeenRenamed = layerEffect.HasBeenRenamed,
Order = layerEffect.Order
};

View File

@ -17,6 +17,7 @@ namespace Artemis.Core.Models.Profile
Profile = profile;
Parent = parent;
Name = name;
Enabled = true;
_layerEffects = new List<BaseLayerEffect>();
_expandedPropertyGroups = new List<string>();
@ -31,6 +32,7 @@ namespace Artemis.Core.Models.Profile
Profile = profile;
Parent = parent;
Name = folderEntity.Name;
Enabled = folderEntity.Enabled;
Order = folderEntity.Order;
_layerEffects = new List<BaseLayerEffect>();
@ -58,7 +60,10 @@ namespace Artemis.Core.Models.Profile
public override void Update(double deltaTime)
{
foreach (var baseLayerEffect in LayerEffects)
if (!Enabled)
return;
foreach (var baseLayerEffect in LayerEffects.Where(e => e.Enabled))
baseLayerEffect.Update(deltaTime);
// Iterate the children in reverse because that's how they must be rendered too
@ -71,6 +76,12 @@ namespace Artemis.Core.Models.Profile
public override void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint)
{
if (!Enabled)
return;
if (Path == null)
return;
canvas.Save();
canvas.ClipPath(Path);
@ -79,7 +90,7 @@ namespace Artemis.Core.Models.Profile
// Pre-processing only affects other pre-processors and the brushes
canvas.Save();
foreach (var baseLayerEffect in LayerEffects)
foreach (var baseLayerEffect in LayerEffects.Where(e => e.Enabled))
baseLayerEffect.InternalPreProcess(canvas, canvasInfo, new SKPath(Path), groupPaint);
// Iterate the children in reverse because the first layer must be rendered last to end up on top
@ -91,12 +102,17 @@ namespace Artemis.Core.Models.Profile
// Restore the canvas as to not be affected by pre-processors
canvas.Restore();
foreach (var baseLayerEffect in LayerEffects)
foreach (var baseLayerEffect in LayerEffects.Where(e => e.Enabled))
baseLayerEffect.InternalPostProcess(canvas, canvasInfo, new SKPath(Path), groupPaint);
canvas.Restore();
}
/// <summary>
/// Adds a new folder to the bottom of this folder
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public Folder AddFolder(string name)
{
var folder = new Folder(Profile, this, name) {Order = Children.LastOrDefault()?.Order ?? 1};
@ -104,6 +120,20 @@ namespace Artemis.Core.Models.Profile
return folder;
}
/// <inheritdoc />
public override void AddChild(ProfileElement child, int? order = null)
{
base.AddChild(child, order);
CalculateRenderProperties();
}
/// <inheritdoc />
public override void RemoveChild(ProfileElement child)
{
base.RemoveChild(child);
CalculateRenderProperties();
}
public override string ToString()
{
return $"[Folder] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}";
@ -134,6 +164,7 @@ namespace Artemis.Core.Models.Profile
FolderEntity.Order = Order;
FolderEntity.Name = Name;
FolderEntity.Enabled = Enabled;
FolderEntity.ProfileId = Profile.EntityId;
@ -152,5 +183,12 @@ namespace Artemis.Core.Models.Profile
}
#endregion
internal void Deactivate()
{
var layerEffects = new List<BaseLayerEffect>(LayerEffects);
foreach (var baseLayerEffect in layerEffects)
DeactivateLayerEffect(baseLayerEffect);
}
}
}

View File

@ -34,6 +34,7 @@ namespace Artemis.Core.Models.Profile
Profile = profile;
Parent = parent;
Name = name;
Enabled = true;
General = new LayerGeneralProperties {IsCorePropertyGroup = true};
Transform = new LayerTransformProperties {IsCorePropertyGroup = true};
@ -52,6 +53,7 @@ namespace Artemis.Core.Models.Profile
Profile = profile;
Parent = parent;
Name = layerEntity.Name;
Enabled = layerEntity.Enabled;
Order = layerEntity.Order;
General = new LayerGeneralProperties {IsCorePropertyGroup = true};
Transform = new LayerTransformProperties {IsCorePropertyGroup = true};
@ -111,6 +113,7 @@ namespace Artemis.Core.Models.Profile
LayerEntity.Id = EntityId;
LayerEntity.ParentId = Parent?.EntityId ?? new Guid();
LayerEntity.Order = Order;
LayerEntity.Enabled = Enabled;
LayerEntity.Name = Name;
LayerEntity.ProfileId = Profile.EntityId;
LayerEntity.ExpandedPropertyGroups.Clear();
@ -177,6 +180,9 @@ namespace Artemis.Core.Models.Profile
/// <inheritdoc />
public override void Update(double deltaTime)
{
if (!Enabled)
return;
if (LayerBrush?.BaseProperties == null || !LayerBrush.BaseProperties.PropertiesInitialized)
return;
@ -192,7 +198,7 @@ namespace Artemis.Core.Models.Profile
General.Override(TimeSpan.Zero);
Transform.Override(TimeSpan.Zero);
LayerBrush.BaseProperties.Override(TimeSpan.Zero);
foreach (var baseLayerEffect in LayerEffects)
foreach (var baseLayerEffect in LayerEffects.Where(e => e.Enabled))
baseLayerEffect.BaseProperties?.Override(TimeSpan.Zero);
}
else
@ -200,12 +206,12 @@ namespace Artemis.Core.Models.Profile
General.Update(deltaTime);
Transform.Update(deltaTime);
LayerBrush.BaseProperties.Update(deltaTime);
foreach (var baseLayerEffect in LayerEffects)
foreach (var baseLayerEffect in LayerEffects.Where(e => e.Enabled))
baseLayerEffect.BaseProperties?.Update(deltaTime);
}
LayerBrush.Update(deltaTime);
foreach (var baseLayerEffect in LayerEffects)
foreach (var baseLayerEffect in LayerEffects.Where(e => e.Enabled))
baseLayerEffect.Update(deltaTime);
}
@ -221,6 +227,9 @@ namespace Artemis.Core.Models.Profile
/// <inheritdoc />
public override void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint)
{
if (!Enabled)
return;
// Ensure the layer is ready
if (Path == null || LayerShape?.Path == null || !General.PropertiesInitialized || !Transform.PropertiesInitialized)
return;
@ -230,13 +239,13 @@ namespace Artemis.Core.Models.Profile
canvas.Save();
canvas.ClipPath(Path);
paint.BlendMode = General.BlendMode.CurrentValue;
paint.Color = new SKColor(0, 0, 0, (byte) (Transform.Opacity.CurrentValue * 2.55f));
// Pre-processing only affects other pre-processors and the brushes
canvas.Save();
foreach (var baseLayerEffect in LayerEffects)
foreach (var baseLayerEffect in LayerEffects.Where(e => e.Enabled))
baseLayerEffect.InternalPreProcess(canvas, canvasInfo, new SKPath(Path), paint);
// Shape clip must be determined before commiting to any rendering
@ -253,9 +262,9 @@ namespace Artemis.Core.Models.Profile
// Restore the canvas as to not be affected by pre-processors
canvas.Restore();
foreach (var baseLayerEffect in LayerEffects)
foreach (var baseLayerEffect in LayerEffects.Where(e => e.Enabled))
baseLayerEffect.InternalPostProcess(canvas, canvasInfo, new SKPath(Path), paint);
canvas.Restore();
}

View File

@ -21,7 +21,7 @@ namespace Artemis.Core.Models.Profile
UndoStack = new Stack<string>();
RedoStack = new Stack<string>();
AddChild(new Folder(this, null, "Root folder"));
AddChild(new Folder(this, this, "Root folder"));
ApplyToEntity();
}
@ -80,13 +80,18 @@ namespace Artemis.Core.Models.Profile
lock (_children)
{
foreach (var folder in GetAllFolders())
folder.Deactivate();
foreach (var layer in GetAllLayers())
layer.Deactivate();
_children.Clear();
// Populate the profile starting at the root, the rest is populated recursively
var rootFolder = ProfileEntity.Folders.FirstOrDefault(f => f.ParentId == new Guid());
var rootFolder = ProfileEntity.Folders.FirstOrDefault(f => f.ParentId == EntityId);
if (rootFolder == null)
AddChild(new Folder(this, null, "Root folder"));
AddChild(new Folder(this, this, "Root folder"));
else
AddChild(new Folder(this, null, rootFolder));
AddChild(new Folder(this, this, rootFolder));
}
}
@ -132,6 +137,8 @@ namespace Artemis.Core.Models.Profile
if (!IsActivated)
return;
foreach (var folder in GetAllFolders())
folder.Deactivate();
foreach (var layer in GetAllLayers())
layer.Deactivate();

View File

@ -35,6 +35,11 @@ namespace Artemis.Core.Models.Profile
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets or sets the enabled state, if not enabled the element is skipped in render and update
/// </summary>
public bool Enabled { get; set; }
/// <summary>
/// Updates the element
/// </summary>
@ -79,7 +84,7 @@ namespace Artemis.Core.Models.Profile
/// </summary>
/// <param name="child">The profile element to add</param>
/// <param name="order">The order where to place the child (1-based), defaults to the end of the collection</param>
public void AddChild(ProfileElement child, int? order = null)
public virtual void AddChild(ProfileElement child, int? order = null)
{
lock (_children)
{
@ -88,23 +93,25 @@ namespace Artemis.Core.Models.Profile
{
_children.Add(child);
child.Order = _children.Count;
return;
}
// Shift everything after the given order
else
{
foreach (var profileElement in _children.Where(c => c.Order >= order).ToList())
profileElement.Order++;
int targetIndex;
if (order == 0)
targetIndex = 0;
else if (order > _children.Count)
targetIndex = _children.Count;
else
targetIndex = _children.FindIndex(c => c.Order == order + 1);
_children.Insert(targetIndex, child);
child.Order = order.Value;
}
// Shift everything after the given order
foreach (var profileElement in _children.Where(c => c.Order >= order).ToList())
profileElement.Order++;
int targetIndex;
if (order == 0)
targetIndex = 0;
else if (order > _children.Count)
targetIndex = _children.Count;
else
targetIndex = _children.FindIndex(c => c.Order == order + 1);
_children.Insert(targetIndex, child);
child.Order = order.Value;
child.Parent = this;
}
}
@ -113,7 +120,7 @@ namespace Artemis.Core.Models.Profile
/// Removes a profile element from the <see cref="Children" /> collection
/// </summary>
/// <param name="child">The profile element to remove</param>
public void RemoveChild(ProfileElement child)
public virtual void RemoveChild(ProfileElement child)
{
lock (_children)
{

View File

@ -27,6 +27,11 @@ namespace Artemis.Core.Plugins.LayerEffect.Abstract
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets or sets the enabled state, if not enabled the effect is skipped in render and update
/// </summary>
public bool Enabled { get; set; }
/// <summary>
/// Gets or sets whether the effect has been renamed by the user, if true consider refraining from changing the name
/// programatically

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Artemis.Core.Events;
using Artemis.Core.Exceptions;
using Artemis.Core.JsonConverters;
@ -23,11 +24,12 @@ namespace Artemis.Core.Services
public class CoreService : ICoreService
{
private readonly ILogger _logger;
private readonly PluginSetting<LogEventLevel> _loggingLevel;
private readonly IPluginService _pluginService;
private readonly IProfileService _profileService;
private readonly IRgbService _rgbService;
private readonly ISurfaceService _surfaceService;
private readonly PluginSetting<LogEventLevel> _loggingLevel;
private readonly Stopwatch _frameStopWatch;
private List<Module> _modules;
// ReSharper disable once UnusedParameter.Local - Storage migration service is injected early to ensure it runs before anything else
@ -48,10 +50,13 @@ namespace Artemis.Core.Services
_modules = _pluginService.GetPluginsOfType<Module>();
_pluginService.PluginEnabled += (sender, args) => _modules = _pluginService.GetPluginsOfType<Module>();
_pluginService.PluginDisabled += (sender, args) => _modules = _pluginService.GetPluginsOfType<Module>();
_frameStopWatch = new Stopwatch();
ConfigureJsonConvert();
}
public TimeSpan FrameTime { get; private set; }
public bool ModuleUpdatingDisabled { get; set; }
public bool ModuleRenderingDisabled { get; set; }
@ -117,6 +122,7 @@ namespace Artemis.Core.Services
try
{
_frameStopWatch.Restart();
if (!ModuleUpdatingDisabled && _modules != null)
{
lock (_modules)
@ -157,6 +163,11 @@ namespace Artemis.Core.Services
{
throw new ArtemisCoreException("Exception during update", e);
}
finally
{
_frameStopWatch.Stop();
FrameTime = _frameStopWatch.Elapsed;
}
}
private void SurfaceOnUpdated(UpdatedEventArgs args)

View File

@ -10,6 +10,11 @@ namespace Artemis.Core.Services.Interfaces
/// </summary>
bool IsInitialized { get; }
/// <summary>
/// The time the last frame took to render
/// </summary>
TimeSpan FrameTime { get; }
/// <summary>
/// Gets or sets whether modules are updated each frame by calling their Update method
/// </summary>

View File

@ -86,6 +86,7 @@ namespace Artemis.Core.Services
effect.ProfileElement = effectElement;
effect.EntityId = Guid.NewGuid();
effect.Enabled = true;
effect.Order = effectElement.LayerEffects.Count + 1;
effect.Descriptor = layerEffectDescriptor;
@ -109,15 +110,8 @@ namespace Artemis.Core.Services
var layerEffectProviders = _pluginService.GetPluginsOfType<LayerEffectProvider>();
var descriptors = layerEffectProviders.SelectMany(l => l.LayerEffectDescriptors).ToList();
List<LayerEffectEntity> entities;
if (effectElement is Layer layer)
entities = layer.LayerEntity.LayerEffects.OrderByDescending(e => e.Order).ToList();
else if (effectElement is Folder folder)
entities = folder.FolderEntity.LayerEffects.OrderByDescending(e => e.Order).ToList();
else
throw new ArtemisCoreException("Provided effect element is of an unsupported type, must be Layer of Folder");
var entities = effectElement.EffectsEntity.LayerEffects.OrderByDescending(e => e.Order).ToList();
foreach (var layerEffectEntity in entities)
{
// Get a matching descriptor
@ -133,6 +127,7 @@ namespace Artemis.Core.Services
effect.EntityId = layerEffectEntity.Id;
effect.Order = layerEffectEntity.Order;
effect.Name = layerEffectEntity.Name;
effect.Enabled = layerEffectEntity.Enabled;
effect.Descriptor = descriptor;
effect.Initialize(this);

View File

@ -19,6 +19,7 @@ namespace Artemis.Storage.Entities.Profile
public int Order { get; set; }
public string Name { get; set; }
public bool Enabled { get; set; }
[BsonRef("ProfileEntity")]
public ProfileEntity Profile { get; set; }

View File

@ -8,6 +8,7 @@ namespace Artemis.Storage.Entities.Profile
public Guid PluginGuid { get; set; }
public string EffectType { get; set; }
public string Name { get; set; }
public bool Enabled { get; set; }
public bool HasBeenRenamed { get; set; }
public int Order { get; set; }
}

View File

@ -20,6 +20,7 @@ namespace Artemis.Storage.Entities.Profile
public int Order { get; set; }
public string Name { get; set; }
public bool Enabled { get; set; }
public List<LedEntity> Leds { get; set; }

View File

@ -0,0 +1,34 @@
using Artemis.Storage.Entities.Profile;
using Artemis.Storage.Migrations.Interfaces;
using LiteDB;
namespace Artemis.Storage.Migrations
{
public class ProfileEntitiesEnabledMigration : IStorageMigration
{
public int UserVersion => 2;
public void Apply(LiteRepository repository)
{
var profiles = repository.Query<ProfileEntity>().ToList();
foreach (var profileEntity in profiles)
{
foreach (var profileEntityFolder in profileEntity.Folders)
{
profileEntityFolder.Enabled = true;
foreach (var layerEffectEntity in profileEntityFolder.LayerEffects)
layerEffectEntity.Enabled = true;
}
foreach (var profileEntityLayer in profileEntity.Layers)
{
profileEntityLayer.Enabled = true;
foreach (var layerEffectEntity in profileEntityLayer.LayerEffects)
layerEffectEntity.Enabled = true;
}
repository.Upsert(profileEntity);
}
}
}
}

View File

@ -19,7 +19,7 @@ namespace Artemis.UI.Shared.Services.Interfaces
IKernel Kernel { get; }
void ChangeSelectedProfile(Profile profile);
void UpdateSelectedProfile(bool includeChildren);
void UpdateSelectedProfile();
void ChangeSelectedProfileElement(ProfileElement profileElement);
void UpdateSelectedProfileElement();
void UpdateProfilePreview();

View File

@ -71,9 +71,9 @@ namespace Artemis.UI.Shared.Services
OnSelectedProfileChanged(profileElementEvent);
}
public void UpdateSelectedProfile(bool includeChildren)
public void UpdateSelectedProfile()
{
_profileService.UpdateProfile(SelectedProfile, includeChildren);
_profileService.UpdateProfile(SelectedProfile, true);
UpdateProfilePreview();
OnSelectedProfileElementUpdated(new ProfileElementEventArgs(SelectedProfile));
}

View File

@ -9,7 +9,6 @@
<NeutralLanguage>en-US</NeutralLanguage>
<Description>Adds third-party support for RGB keyboards to games.</Description>
<Copyright>Copyright © Robert Beekman - 2020</Copyright>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<FileVersion>2.0.0.0</FileVersion>
<Prefer32Bit>true</Prefer32Bit>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
@ -27,6 +26,18 @@
</PropertyGroup>
<PropertyGroup>
<PostBuildEvent />
<AssemblyVersion>2.0.0.0</AssemblyVersion>
<Version>2.0.0</Version>
</PropertyGroup>
<PropertyGroup>
<NrtRevisionFormat>2.0-{chash:6}</NrtRevisionFormat>
<NrtResolveSimpleAttributes>true</NrtResolveSimpleAttributes>
<NrtResolveInformationalAttribute>true</NrtResolveInformationalAttribute>
<NrtResolveCopyright>true</NrtResolveCopyright>
<NrtTagMatch>v[0-9]*</NrtTagMatch>
<NrtRemoveTagV>true</NrtRemoveTagV>
<NrtRequiredVcs>git</NrtRequiredVcs>
<NrtShowRevision>true</NrtShowRevision>
</PropertyGroup>
<Target Name="SkiaCleanUpAfterBuild" AfterTargets="AfterBuild">
<Delete Files="$(OutputPath)\libSkiaSharp.dylib" />
@ -141,6 +152,10 @@
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.7.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Compile Remove="obj\x64\Debug\App.g.cs" />

View File

@ -5,6 +5,7 @@ using Artemis.Core.Models.Profile;
using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Plugins.LayerEffect;
using Artemis.Core.Services.Interfaces;
using Artemis.UI.Shared.Services.Interfaces;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.LayerEffects
@ -12,12 +13,14 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.LayerEffects
public class EffectsViewModel : PropertyChangedBase
{
private readonly ILayerService _layerService;
private readonly IProfileEditorService _profileEditorService;
private readonly IPluginService _pluginService;
public EffectsViewModel(LayerPropertiesViewModel layerPropertiesViewModel, IPluginService pluginService, ILayerService layerService)
public EffectsViewModel(LayerPropertiesViewModel layerPropertiesViewModel, IPluginService pluginService, ILayerService layerService, IProfileEditorService profileEditorService)
{
_pluginService = pluginService;
_layerService = layerService;
_profileEditorService = profileEditorService;
LayerPropertiesViewModel = layerPropertiesViewModel;
LayerEffectDescriptors = new BindableCollection<LayerEffectDescriptor>();
PropertyChanged += HandleSelectedLayerEffectChanged;
@ -58,6 +61,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.LayerEffects
{
await Task.Delay(500);
_layerService.AddLayerEffect(effectElement, SelectedLayerEffectDescriptor);
_profileEditorService.UpdateSelectedProfileElement();
});
}
}

View File

@ -310,7 +310,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
MoveAfter(source, target);
ApplyCurrentEffectsOrder();
ProfileEditorService.UpdateSelectedProfile(true);
ProfileEditorService.UpdateSelectedProfile();
}
private void MoveBefore(LayerPropertyGroupViewModel source, LayerPropertyGroupViewModel target)

View File

@ -93,7 +93,6 @@
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
@ -105,12 +104,12 @@
</Style.Triggers>
</Style>
</Grid.Style>
<materialDesign:PackIcon
Grid.Column="0"
<materialDesign:PackIcon
Grid.Column="0"
Cursor="SizeNS"
Kind="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.Icon}"
Margin="0 5 5 0"
Background="Transparent"/>
Kind="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.Icon}"
Margin="0 5 5 0"
Background="Transparent" />
<TextBlock Grid.Column="1" ToolTip="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.Description}" Margin="0 5 0 0">
Effect
</TextBlock>
@ -132,25 +131,36 @@
Margin="0 5"
Visibility="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Name, Converter={StaticResource NullToVisibilityConverter}}" />
<Button Grid.Column="5"
Style="{StaticResource MaterialDesignIconButton}"
ToolTip="Rename"
Width="24"
Height="24"
VerticalAlignment="Center"
Command="{s:Action RenameEffect}">
<materialDesign:PackIcon Kind="RenameBox" Height="16" Width="16" />
</Button>
<StackPanel Grid.Column="5" Orientation="Horizontal">
<ToggleButton
Style="{StaticResource MaterialDesignFlatToggleButton}"
ToolTip="Toggle enabled state"
Width="18"
Height="18"
IsChecked="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Enabled}"
VerticalAlignment="Center" Padding="-25"
Margin="5 0"
Command="{s:Action EnableToggled}">
<materialDesign:PackIcon Kind="Eye" Height="13" Width="13" />
</ToggleButton>
<Button Style="{StaticResource MaterialDesignIconButton}"
ToolTip="Rename"
Width="24"
Height="24"
VerticalAlignment="Center"
Command="{s:Action RenameEffect}">
<materialDesign:PackIcon Kind="RenameBox" Height="16" Width="16" />
</Button>
<Button Style="{StaticResource MaterialDesignIconButton}"
ToolTip="Remove"
Width="24"
Height="24"
VerticalAlignment="Center"
Command="{s:Action DeleteEffect}">
<materialDesign:PackIcon Kind="TrashCan" Height="16" Width="16" />
</Button>
</StackPanel>
<Button Grid.Column="6"
Style="{StaticResource MaterialDesignIconButton}"
ToolTip="Remove"
Width="24"
Height="24"
VerticalAlignment="Center"
Command="{s:Action DeleteEffect}">
<materialDesign:PackIcon Kind="TrashCan" Height="16" Width="16" />
</Button>
</Grid>
</StackPanel>

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Diagnostics;
using Artemis.Core.Services.Interfaces;
using Artemis.UI.Screens.Module.ProfileEditor.Dialogs;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract;
@ -37,14 +38,19 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree
{
LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Name = newName;
LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.HasBeenRenamed = true;
_profileEditorService.UpdateSelectedProfile(true);
_profileEditorService.UpdateSelectedProfile();
}
}
public void DeleteEffect()
{
_layerService.RemoveLayerEffect(LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect);
_profileEditorService.UpdateSelectedProfile(true);
_profileEditorService.UpdateSelectedProfile();
}
public void EnableToggled()
{
_profileEditorService.UpdateSelectedProfile();
}
}
}

View File

@ -77,7 +77,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
break;
}
_profileEditorService.UpdateSelectedProfile(true);
_profileEditorService.UpdateSelectedProfile();
}
// ReSharper disable once UnusedMember.Global - Called from view

View File

@ -36,13 +36,28 @@
</MenuItem>
</ContextMenu>
</StackPanel.ContextMenu>
<StackPanel Orientation="Horizontal" Margin="10">
<materialDesign:PackIcon Kind="Folder"
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<materialDesign:PackIcon Grid.Column="0"
Kind="Folder"
Visibility="{Binding IsExpanded, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}}" />
<materialDesign:PackIcon Kind="FolderOpen"
<materialDesign:PackIcon Grid.Column="0"
Kind="FolderOpen"
Visibility="{Binding IsExpanded, Converter={x:Static s:BoolToVisibilityConverter.Instance}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}}" />
<TextBlock Text="{Binding ProfileElement.Name}" Margin="10 0 0 0" />
</StackPanel>
<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"
Width="18"
Height="18"
IsChecked="{Binding ProfileElement.Enabled}"
VerticalAlignment="Center" Padding="-25">
<materialDesign:PackIcon Kind="Eye" Height="13" Width="13" />
</ToggleButton>
</Grid>
</StackPanel>
</UserControl>

View File

@ -25,15 +25,32 @@
</MenuItem>
</ContextMenu>
</StackPanel.ContextMenu>
<StackPanel Orientation="Horizontal" Margin="10">
<materialDesign:PackIcon Kind="Layers" Width="16" />
<materialDesign:PackIcon Kind="{Binding Layer.LayerBrush.Descriptor.Icon}"
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<materialDesign:PackIcon Grid.Column="0" Kind="Layers" Width="16" VerticalAlignment="Center"/>
<materialDesign:PackIcon Grid.Column="1"
VerticalAlignment="Center"
Kind="{Binding Layer.LayerBrush.Descriptor.Icon}"
Width="16"
Margin="5 0 0 0"
ToolTip="{Binding Layer.LayerBrush.Descriptor.DisplayName, Mode=OneWay}"
Visibility="{Binding ShowIcons, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}"
Background="Transparent" />
<TextBlock Text="{Binding Layer.Name}" Margin="5 0 0 0" />
</StackPanel>
<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"
Width="18"
Height="18"
IsChecked="{Binding ProfileElement.Enabled}"
VerticalAlignment="Center" Padding="-25">
<materialDesign:PackIcon Kind="Eye" Height="13" Width="13" />
</ToggleButton>
</Grid>
</StackPanel>
</UserControl>

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using Artemis.Core.Models.Profile;
@ -37,9 +38,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
ProfileElement = profileElement;
Children = new BindableCollection<TreeItemViewModel>();
ProfileElement.PropertyChanged += HandleProfileElementEnabledChanged;
UpdateProfileElements();
}
private void HandleProfileElementEnabledChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(ProfileElement.Enabled))
_profileEditorService.UpdateSelectedProfile();
}
public TreeItemViewModel Parent { get; set; }
public ProfileElement ProfileElement { get; set; }
@ -113,7 +121,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
ProfileElement.AddChild(new Folder(ProfileElement.Profile, ProfileElement, "New folder"));
UpdateProfileElements();
_profileEditorService.UpdateSelectedProfile(true);
_profileEditorService.UpdateSelectedProfile();
}
public void AddLayer()
@ -123,7 +131,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
_layerService.CreateLayer(ProfileElement.Profile, ProfileElement, "New layer");
UpdateProfileElements();
_profileEditorService.UpdateSelectedProfile(true);
_profileEditorService.UpdateSelectedProfile();
}
// ReSharper disable once UnusedMember.Global - Called from view
@ -139,7 +147,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
if (result is string newName)
{
ProfileElement.Name = newName;
_profileEditorService.UpdateSelectedProfile(true);
_profileEditorService.UpdateSelectedProfile();
}
}
@ -160,7 +168,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
parent.RemoveExistingElement(this);
parent.UpdateProfileElements();
_profileEditorService.UpdateSelectedProfile(true);
_profileEditorService.UpdateSelectedProfile();
}
public void UpdateProfileElements()

View File

@ -56,7 +56,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
newLayer.AddLeds(selectedLeds);
ProfileEditorService.ChangeSelectedProfileElement(newLayer);
ProfileEditorService.UpdateSelectedProfileElement();
ProfileEditorService.UpdateSelectedProfile(false);
}
// If no folder selected, apply it to a new layer in the root folder
else
@ -66,7 +65,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
newLayer.AddLeds(selectedLeds);
ProfileEditorService.ChangeSelectedProfileElement(newLayer);
ProfileEditorService.UpdateSelectedProfileElement();
ProfileEditorService.UpdateSelectedProfile(false);
}
}

View File

@ -11,7 +11,7 @@
mc:Ignorable="d"
FadeContentIfInactive="False"
Icon="/Resources/Images/Logo/logo-512.png"
Title="Artemis"
Title="{Binding WindowTitle}"
TitleBarIcon="{StaticResource BowIcon}"
Foreground="{DynamicResource MaterialDesignBody}"
Background="{DynamicResource MaterialDesignPaper}"

View File

@ -1,9 +1,12 @@
using System.ComponentModel;
using System.Reflection;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Input;
using Artemis.Core.Plugins.Models;
using Artemis.Core.Services;
using Artemis.Core.Services.Interfaces;
using Artemis.UI.Events;
using Artemis.UI.Screens.Settings;
using Artemis.UI.Screens.Sidebar;
@ -15,16 +18,21 @@ namespace Artemis.UI.Screens
{
public class RootViewModel : Conductor<IScreen>
{
private readonly IEventAggregator _eventAggregator;
private readonly PluginSetting<ApplicationColorScheme> _colorScheme;
private bool _lostFocus;
private readonly ICoreService _coreService;
private readonly IEventAggregator _eventAggregator;
private readonly ThemeWatcher _themeWatcher;
private bool _lostFocus;
private readonly Timer _titleUpdateTimer;
public RootViewModel(IEventAggregator eventAggregator, SidebarViewModel sidebarViewModel, ISettingsService settingsService)
public RootViewModel(IEventAggregator eventAggregator, SidebarViewModel sidebarViewModel, ISettingsService settingsService, ICoreService coreService)
{
SidebarViewModel = sidebarViewModel;
_eventAggregator = eventAggregator;
_coreService = coreService;
_titleUpdateTimer = new Timer(500);
_titleUpdateTimer.Elapsed += (sender, args) => UpdateWindowTitle();
_colorScheme = settingsService.GetSetting("UI.ColorScheme", ApplicationColorScheme.Automatic);
_colorScheme.SettingChanged += (sender, args) => ApplyColorSchemeSetting();
_themeWatcher = new ThemeWatcher();
@ -40,6 +48,8 @@ namespace Artemis.UI.Screens
public bool IsSidebarVisible { get; set; }
public bool ActiveItemReady { get; set; }
public string WindowTitle { get; set; }
public void WindowDeactivated()
{
var windowState = ((Window) View).WindowState;
@ -69,6 +79,26 @@ namespace Artemis.UI.Screens
_eventAggregator.Publish(new MainWindowKeyEvent(false, e));
}
protected override void OnActivate()
{
UpdateWindowTitle();
_titleUpdateTimer.Start();
}
protected override void OnDeactivate()
{
_titleUpdateTimer.Stop();
}
private void UpdateWindowTitle()
{
var versionAttribute = typeof(RootViewModel).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
if (versionAttribute != null)
WindowTitle = $"Artemis {versionAttribute.InformationalVersion} - Frame time: {_coreService.FrameTime.TotalMilliseconds:F2} ms";
else
WindowTitle = $"Artemis - Frame time: {_coreService.FrameTime.TotalMilliseconds:F2} ms";
}
private void SidebarViewModelOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(SidebarViewModel.SelectedItem))