From 9c4bc3d9c6fbccbfda75c2a65801abe823bcd6aa Mon Sep 17 00:00:00 2001 From: Robert Date: Fri, 14 Oct 2022 17:23:36 +0200 Subject: [PATCH 1/7] Plugins - Ignore version when loading shared assemblies Sidebar - Improved category reordering code --- .../Services/PluginManagementService.cs | 10 +++-- .../Sidebar/SidebarCategoryViewModel.cs | 39 +++++++++++++------ 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/Artemis.Core/Services/PluginManagementService.cs b/src/Artemis.Core/Services/PluginManagementService.cs index dc5d1e3b1..1e113ab95 100644 --- a/src/Artemis.Core/Services/PluginManagementService.cs +++ b/src/Artemis.Core/Services/PluginManagementService.cs @@ -5,6 +5,7 @@ using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; +using System.Runtime.Loader; using System.Threading.Tasks; using Artemis.Core.DeviceProviders; using Artemis.Core.Ninject; @@ -334,13 +335,16 @@ internal class PluginManagementService : IPluginManagementService throw new ArtemisPluginException(plugin, "Plugin main entry casing mismatch at " + plugin.Info.Main); // Load the plugin, all types implementing Plugin and register them with DI - plugin.PluginLoader = PluginLoader.CreateFromAssemblyFile(mainFile!, configure => + plugin.PluginLoader = PluginLoader.CreateFromAssemblyFile(mainFile, configure => { configure.IsUnloadable = true; configure.LoadInMemory = true; configure.PreferSharedTypes = true; + + // Resolving failed, try a loaded assembly but ignoring the version + configure.DefaultContext.Resolving += (context, assemblyName) => context.Assemblies.FirstOrDefault(a => a.GetName().Name == assemblyName.Name); }); - + try { plugin.Assembly = plugin.PluginLoader.LoadDefaultAssembly(); @@ -402,7 +406,7 @@ internal class PluginManagementService : IPluginManagementService OnPluginLoaded(new PluginEventArgs(plugin)); return plugin; } - + public void EnablePlugin(Plugin plugin, bool saveState, bool ignorePluginLock) { if (!plugin.Info.IsCompatible) diff --git a/src/Artemis.UI/Screens/Sidebar/SidebarCategoryViewModel.cs b/src/Artemis.UI/Screens/Sidebar/SidebarCategoryViewModel.cs index 8da48b281..224bb4074 100644 --- a/src/Artemis.UI/Screens/Sidebar/SidebarCategoryViewModel.cs +++ b/src/Artemis.UI/Screens/Sidebar/SidebarCategoryViewModel.cs @@ -26,18 +26,20 @@ public class SidebarCategoryViewModel : ActivatableViewModelBase private readonly IProfileService _profileService; private readonly ISidebarVmFactory _vmFactory; private readonly IWindowService _windowService; + private readonly IProfileEditorService _profileEditorService; private ObservableAsPropertyHelper? _isCollapsed; private ObservableAsPropertyHelper? _isSuspended; private SidebarProfileConfigurationViewModel? _selectedProfileConfiguration; - public SidebarCategoryViewModel(ProfileCategory profileCategory, - IProfileService profileService, - IWindowService windowService, + public SidebarCategoryViewModel(ProfileCategory profileCategory, + IProfileService profileService, + IWindowService windowService, IProfileEditorService profileEditorService, ISidebarVmFactory vmFactory) { _profileService = profileService; _windowService = windowService; + _profileEditorService = profileEditorService; _vmFactory = vmFactory; ProfileCategory = profileCategory; @@ -154,7 +156,11 @@ public class SidebarCategoryViewModel : ActivatableViewModelBase private async Task ExecuteDeleteCategory() { if (await _windowService.ShowConfirmContentDialog($"Delete {ProfileCategory.Name}", "Do you want to delete this category and all its profiles?")) + { + if (ProfileCategory.ProfileConfigurations.Any(c => c.IsBeingEdited)) + _profileEditorService.ChangeCurrentProfileConfiguration(null); _profileService.DeleteProfileCategory(ProfileCategory); + } } private async Task ExecuteAddProfile() @@ -171,7 +177,7 @@ public class SidebarCategoryViewModel : ActivatableViewModelBase } private async Task ExecuteImportProfile() - { + { string[]? result = await _windowService.CreateOpenFileDialog() .HavingFilter(f => f.WithExtension("json").WithName("Artemis profile")) .ShowAsync(); @@ -225,10 +231,9 @@ public class SidebarCategoryViewModel : ActivatableViewModelBase if (index <= 0) return; - categories[index - 1].Order++; - ProfileCategory.Order--; - _profileService.SaveProfileCategory(categories[index - 1]); - _profileService.SaveProfileCategory(ProfileCategory); + categories.Remove(ProfileCategory); + categories.Insert(index - 1, ProfileCategory); + ApplyCategoryOrder(categories); } private void ExecuteMoveDown() @@ -238,9 +243,19 @@ public class SidebarCategoryViewModel : ActivatableViewModelBase if (index >= categories.Count - 1) return; - categories[index + 1].Order--; - ProfileCategory.Order++; - _profileService.SaveProfileCategory(categories[index + 1]); - _profileService.SaveProfileCategory(ProfileCategory); + categories.Remove(ProfileCategory); + categories.Insert(index + 1, ProfileCategory); + ApplyCategoryOrder(categories); + } + + private void ApplyCategoryOrder(List categories) + { + for (int i = 0; i < categories.Count; i++) + { + if (categories[i].Order == i + 1) + continue; + categories[i].Order = i + 1; + _profileService.SaveProfileCategory(categories[i]); + } } } \ No newline at end of file From 194780b25c2f51433c9da76c3d69a5cae3eeefb3 Mon Sep 17 00:00:00 2001 From: Diogo Trindade Date: Sun, 27 Nov 2022 01:54:50 +0000 Subject: [PATCH 2/7] Core - Added fading in and out of profiles --- src/Artemis.Core/Models/Profile/Profile.cs | 45 ++++++++++++++++++- .../ProfileConfiguration.cs | 12 +++++ .../Services/Storage/ProfileService.cs | 19 +++++++- .../Profile/ProfileConfigurationEntity.cs | 2 + .../ProfileConfigurationEditView.axaml | 3 ++ .../ProfileConfigurationEditViewModel.cs | 9 ++++ 6 files changed, 87 insertions(+), 3 deletions(-) diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs index 5534e686d..7bbde4bd3 100644 --- a/src/Artemis.Core/Models/Profile/Profile.cs +++ b/src/Artemis.Core/Models/Profile/Profile.cs @@ -8,6 +8,15 @@ using SkiaSharp; namespace Artemis.Core; + +internal enum FadingStatus +{ + Enabled, + FadingIn, + FadingOut, + Disabled +} + /// /// Represents a profile containing folders and layers /// @@ -18,12 +27,15 @@ public sealed class Profile : ProfileElement private readonly ObservableCollection _scripts; private bool _isFreshImport; private ProfileElement? _lastSelectedProfileElement; + private double _opacity; internal Profile(ProfileConfiguration configuration, ProfileEntity profileEntity) : base(null!) { _scripts = new ObservableCollection(); _scriptConfigurations = new ObservableCollection(); - + _opacity = 0d; + + FadingStatus = FadingStatus.FadingIn; Configuration = configuration; Profile = this; ProfileEntity = profileEntity; @@ -81,6 +93,8 @@ public sealed class Profile : ProfileElement internal List Exceptions { get; } + internal FadingStatus FadingStatus { get; private set; } + /// public override void Update(double deltaTime) { @@ -97,6 +111,16 @@ public sealed class Profile : ProfileElement foreach (ProfileScript profileScript in Scripts) profileScript.OnProfileUpdated(deltaTime); + + const double OPACITY_PER_SECOND = 1; + if (FadingStatus == FadingStatus.FadingIn) + _opacity = Math.Clamp(_opacity + OPACITY_PER_SECOND * deltaTime, 0d, 1d); + if (FadingStatus == FadingStatus.FadingOut) + _opacity = Math.Clamp(_opacity - OPACITY_PER_SECOND * deltaTime, 0d, 1d); + if (_opacity == 0d) + FadingStatus = FadingStatus.Disabled; + if (_opacity == 1d) + FadingStatus = FadingStatus.Enabled; } } @@ -111,9 +135,17 @@ public sealed class Profile : ProfileElement foreach (ProfileScript profileScript in Scripts) profileScript.OnProfileRendering(canvas, canvas.LocalClipBounds); + using var opacityPaint = new SKPaint(); + if (Configuration.FadeInAndOut && FadingStatus != FadingStatus.Enabled) + opacityPaint.Color = new SKColor(0, 0, 0, (byte)(255d * Easings.CubicEaseInOut(_opacity))); + + canvas.SaveLayer(opacityPaint); + foreach (ProfileElement profileElement in Children) profileElement.Render(canvas, basePosition, editorFocus); + canvas.Restore(); + foreach (ProfileScript profileScript in Scripts) profileScript.OnProfileRendered(canvas, canvas.LocalClipBounds); @@ -165,6 +197,17 @@ public sealed class Profile : ProfileElement layer.PopulateLeds(devices); } + /// + /// Starts the fade out process. + /// + public void FadeOut() + { + if (Disposed) + throw new ObjectDisposedException("Profile"); + + FadingStatus = FadingStatus.FadingOut; + } + #region Overrides of BreakableModel /// diff --git a/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfiguration.cs b/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfiguration.cs index 3390a2863..b349acfd1 100644 --- a/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfiguration.cs +++ b/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfiguration.cs @@ -21,6 +21,7 @@ public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable private bool _isBeingEdited; private bool _isMissingModule; private bool _isSuspended; + private bool _fadeInAndOut; private Module? _module; private string _name; @@ -160,6 +161,15 @@ public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable internal set => SetAndNotify(ref _profile, value); } + /// + /// Gets or sets a boolean indicating whether this profile should fade in and out when enabling or disabling + /// + public bool FadeInAndOut + { + get => _fadeInAndOut; + set => SetAndNotify(ref _fadeInAndOut, value); + } + /// /// Gets or sets the module this profile uses /// @@ -272,6 +282,7 @@ public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable IsSuspended = Entity.IsSuspended; ActivationBehaviour = (ActivationBehaviour) Entity.ActivationBehaviour; HotkeyMode = (ProfileConfigurationHotkeyMode) Entity.HotkeyMode; + FadeInAndOut = Entity.FadeInAndOut; Order = Entity.Order; Icon.Load(); @@ -294,6 +305,7 @@ public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable Entity.ActivationBehaviour = (int) ActivationBehaviour; Entity.HotkeyMode = (int) HotkeyMode; Entity.ProfileCategoryId = Category.Entity.Id; + Entity.FadeInAndOut = FadeInAndOut; Entity.Order = Order; Icon.Save(); diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs index d5adc7d87..6a0c2ad52 100644 --- a/src/Artemis.Core/Services/Storage/ProfileService.cs +++ b/src/Artemis.Core/Services/Storage/ProfileService.cs @@ -214,7 +214,12 @@ internal class ProfileService : IProfileService if (shouldBeActive && profileConfiguration.Profile == null && profileConfiguration.BrokenState != "Failed to activate profile") profileConfiguration.TryOrBreak(() => ActivateProfile(profileConfiguration), "Failed to activate profile"); else if (!shouldBeActive && profileConfiguration.Profile != null) - DeactivateProfile(profileConfiguration); + { + if (!profileConfiguration.FadeInAndOut || profileConfiguration.Profile.FadingStatus == FadingStatus.Disabled) + DeactivateProfile(profileConfiguration); + else if (profileConfiguration.Profile.FadingStatus == FadingStatus.Enabled) + RequestDeactivation(profileConfiguration); + } profileConfiguration.Profile?.Update(deltaTime); } @@ -254,7 +259,7 @@ internal class ProfileService : IProfileService { ProfileConfiguration profileConfiguration = profileCategory.ProfileConfigurations[j]; // Ensure all criteria are met before rendering - if (!profileConfiguration.IsSuspended && !profileConfiguration.IsMissingModule && profileConfiguration.ActivationConditionMet) + if (!profileConfiguration.IsSuspended && !profileConfiguration.IsMissingModule && (profileConfiguration.ActivationConditionMet || profileConfiguration.Profile?.FadingStatus == FadingStatus.FadingOut)) profileConfiguration.Profile?.Render(canvas, SKPointI.Empty, null); } catch (Exception e) @@ -361,6 +366,16 @@ internal class ProfileService : IProfileService OnProfileDeactivated(new ProfileConfigurationEventArgs(profileConfiguration)); } + public void RequestDeactivation(ProfileConfiguration profileConfiguration) + { + if (profileConfiguration.IsBeingEdited) + throw new ArtemisCoreException("Cannot disable a profile that is being edited, that's rude"); + if (profileConfiguration.Profile == null) + return; + + profileConfiguration.Profile.FadeOut(); + } + public void DeleteProfile(ProfileConfiguration profileConfiguration) { DeactivateProfile(profileConfiguration); diff --git a/src/Artemis.Storage/Entities/Profile/ProfileConfigurationEntity.cs b/src/Artemis.Storage/Entities/Profile/ProfileConfigurationEntity.cs index 377d78ce7..e91ddcc96 100644 --- a/src/Artemis.Storage/Entities/Profile/ProfileConfigurationEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/ProfileConfigurationEntity.cs @@ -25,4 +25,6 @@ public class ProfileConfigurationEntity public Guid ProfileCategoryId { get; set; } public Guid ProfileId { get; set; } + + public bool FadeInAndOut { get; set; } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditView.axaml b/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditView.axaml index fed01edac..a127cdc14 100644 --- a/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditView.axaml +++ b/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditView.axaml @@ -127,6 +127,9 @@ + + Fade when enabling and disabling + diff --git a/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditViewModel.cs b/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditViewModel.cs index ed55d14c3..fe773c4f5 100644 --- a/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditViewModel.cs +++ b/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditViewModel.cs @@ -30,6 +30,7 @@ public class ProfileConfigurationEditViewModel : DialogViewModelBase? _materialIcons; @@ -57,6 +58,7 @@ public class ProfileConfigurationEditViewModel : DialogViewModelBase RaiseAndSetIfChanged(ref _disableHotkey, value); } + public bool FadeInAndOut + { + get => _fadeInAndOut; + set => RaiseAndSetIfChanged(ref _fadeInAndOut, value); + } + public ObservableCollection Modules { get; } public ProfileModuleViewModel? SelectedModule @@ -155,6 +163,7 @@ public class ProfileConfigurationEditViewModel : DialogViewModelBase Date: Sun, 27 Nov 2022 17:07:55 +0000 Subject: [PATCH 3/7] Core - Removed FadingStatus enum --- src/Artemis.Core/Models/Profile/Profile.cs | 37 +++++++------------ .../Services/Storage/ProfileService.cs | 8 ++-- 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs index 7bbde4bd3..213ca0553 100644 --- a/src/Artemis.Core/Models/Profile/Profile.cs +++ b/src/Artemis.Core/Models/Profile/Profile.cs @@ -8,15 +8,6 @@ using SkiaSharp; namespace Artemis.Core; - -internal enum FadingStatus -{ - Enabled, - FadingIn, - FadingOut, - Disabled -} - /// /// Represents a profile containing folders and layers /// @@ -27,15 +18,14 @@ public sealed class Profile : ProfileElement private readonly ObservableCollection _scripts; private bool _isFreshImport; private ProfileElement? _lastSelectedProfileElement; - private double _opacity; internal Profile(ProfileConfiguration configuration, ProfileEntity profileEntity) : base(null!) { _scripts = new ObservableCollection(); _scriptConfigurations = new ObservableCollection(); - _opacity = 0d; - FadingStatus = FadingStatus.FadingIn; + Opacity = 0d; + ShouldBeEnabled = true; Configuration = configuration; Profile = this; ProfileEntity = profileEntity; @@ -93,7 +83,9 @@ public sealed class Profile : ProfileElement internal List Exceptions { get; } - internal FadingStatus FadingStatus { get; private set; } + internal bool ShouldBeEnabled { get; private set; } + + internal double Opacity { get; private set; } /// public override void Update(double deltaTime) @@ -113,14 +105,11 @@ public sealed class Profile : ProfileElement profileScript.OnProfileUpdated(deltaTime); const double OPACITY_PER_SECOND = 1; - if (FadingStatus == FadingStatus.FadingIn) - _opacity = Math.Clamp(_opacity + OPACITY_PER_SECOND * deltaTime, 0d, 1d); - if (FadingStatus == FadingStatus.FadingOut) - _opacity = Math.Clamp(_opacity - OPACITY_PER_SECOND * deltaTime, 0d, 1d); - if (_opacity == 0d) - FadingStatus = FadingStatus.Disabled; - if (_opacity == 1d) - FadingStatus = FadingStatus.Enabled; + + if (ShouldBeEnabled && Opacity < 1) + Opacity = Math.Clamp(Opacity + OPACITY_PER_SECOND * deltaTime, 0d, 1d); + if (!ShouldBeEnabled && Opacity > 0) + Opacity = Math.Clamp(Opacity - OPACITY_PER_SECOND * deltaTime, 0d, 1d); } } @@ -136,8 +125,8 @@ public sealed class Profile : ProfileElement profileScript.OnProfileRendering(canvas, canvas.LocalClipBounds); using var opacityPaint = new SKPaint(); - if (Configuration.FadeInAndOut && FadingStatus != FadingStatus.Enabled) - opacityPaint.Color = new SKColor(0, 0, 0, (byte)(255d * Easings.CubicEaseInOut(_opacity))); + if (Configuration.FadeInAndOut && Opacity != 1) + opacityPaint.Color = new SKColor(0, 0, 0, (byte)(255d * Easings.CubicEaseInOut(Opacity))); canvas.SaveLayer(opacityPaint); @@ -205,7 +194,7 @@ public sealed class Profile : ProfileElement if (Disposed) throw new ObjectDisposedException("Profile"); - FadingStatus = FadingStatus.FadingOut; + ShouldBeEnabled = false; } #region Overrides of BreakableModel diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs index 6a0c2ad52..ae403e05c 100644 --- a/src/Artemis.Core/Services/Storage/ProfileService.cs +++ b/src/Artemis.Core/Services/Storage/ProfileService.cs @@ -215,9 +215,11 @@ internal class ProfileService : IProfileService profileConfiguration.TryOrBreak(() => ActivateProfile(profileConfiguration), "Failed to activate profile"); else if (!shouldBeActive && profileConfiguration.Profile != null) { - if (!profileConfiguration.FadeInAndOut || profileConfiguration.Profile.FadingStatus == FadingStatus.Disabled) + if (!profileConfiguration.FadeInAndOut) DeactivateProfile(profileConfiguration); - else if (profileConfiguration.Profile.FadingStatus == FadingStatus.Enabled) + else if (!profileConfiguration.Profile.ShouldBeEnabled && profileConfiguration.Profile.Opacity <= 0) + DeactivateProfile(profileConfiguration); + else if (profileConfiguration.Profile.ShouldBeEnabled && profileConfiguration.Profile.Opacity >= 1) RequestDeactivation(profileConfiguration); } @@ -259,7 +261,7 @@ internal class ProfileService : IProfileService { ProfileConfiguration profileConfiguration = profileCategory.ProfileConfigurations[j]; // Ensure all criteria are met before rendering - if (!profileConfiguration.IsSuspended && !profileConfiguration.IsMissingModule && (profileConfiguration.ActivationConditionMet || profileConfiguration.Profile?.FadingStatus == FadingStatus.FadingOut)) + if (!profileConfiguration.IsSuspended && !profileConfiguration.IsMissingModule && (profileConfiguration.ActivationConditionMet || (profileConfiguration.Profile?.ShouldBeEnabled == false && profileConfiguration.Profile?.Opacity >= 0))) profileConfiguration.Profile?.Render(canvas, SKPointI.Empty, null); } catch (Exception e) From b39dd14526dc6d4bda354bb99e93a18a182561e1 Mon Sep 17 00:00:00 2001 From: Diogo Trindade Date: Sun, 27 Nov 2022 19:59:09 +0000 Subject: [PATCH 4/7] Core - Fixed when condition stops being true mid-fade --- src/Artemis.Core/Models/Profile/Profile.cs | 19 ++++--------------- .../Services/Storage/ProfileService.cs | 15 ++++++++++----- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs index 213ca0553..4d68dda3e 100644 --- a/src/Artemis.Core/Models/Profile/Profile.cs +++ b/src/Artemis.Core/Models/Profile/Profile.cs @@ -25,7 +25,7 @@ public sealed class Profile : ProfileElement _scriptConfigurations = new ObservableCollection(); Opacity = 0d; - ShouldBeEnabled = true; + ShouldDisplay = true; Configuration = configuration; Profile = this; ProfileEntity = profileEntity; @@ -83,7 +83,7 @@ public sealed class Profile : ProfileElement internal List Exceptions { get; } - internal bool ShouldBeEnabled { get; private set; } + internal bool ShouldDisplay { get; set; } internal double Opacity { get; private set; } @@ -106,9 +106,9 @@ public sealed class Profile : ProfileElement const double OPACITY_PER_SECOND = 1; - if (ShouldBeEnabled && Opacity < 1) + if (ShouldDisplay && Opacity < 1) Opacity = Math.Clamp(Opacity + OPACITY_PER_SECOND * deltaTime, 0d, 1d); - if (!ShouldBeEnabled && Opacity > 0) + if (!ShouldDisplay && Opacity > 0) Opacity = Math.Clamp(Opacity - OPACITY_PER_SECOND * deltaTime, 0d, 1d); } } @@ -186,17 +186,6 @@ public sealed class Profile : ProfileElement layer.PopulateLeds(devices); } - /// - /// Starts the fade out process. - /// - public void FadeOut() - { - if (Disposed) - throw new ObjectDisposedException("Profile"); - - ShouldBeEnabled = false; - } - #region Overrides of BreakableModel /// diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs index ae403e05c..801419d52 100644 --- a/src/Artemis.Core/Services/Storage/ProfileService.cs +++ b/src/Artemis.Core/Services/Storage/ProfileService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; @@ -213,13 +213,15 @@ internal class ProfileService : IProfileService // Make sure the profile is active or inactive according to the parameters above if (shouldBeActive && profileConfiguration.Profile == null && profileConfiguration.BrokenState != "Failed to activate profile") profileConfiguration.TryOrBreak(() => ActivateProfile(profileConfiguration), "Failed to activate profile"); + if (shouldBeActive && profileConfiguration.Profile != null && !profileConfiguration.Profile.ShouldDisplay) + profileConfiguration.Profile.ShouldDisplay = true; else if (!shouldBeActive && profileConfiguration.Profile != null) { if (!profileConfiguration.FadeInAndOut) DeactivateProfile(profileConfiguration); - else if (!profileConfiguration.Profile.ShouldBeEnabled && profileConfiguration.Profile.Opacity <= 0) + else if (!profileConfiguration.Profile.ShouldDisplay && profileConfiguration.Profile.Opacity <= 0) DeactivateProfile(profileConfiguration); - else if (profileConfiguration.Profile.ShouldBeEnabled && profileConfiguration.Profile.Opacity >= 1) + else if (profileConfiguration.Profile.Opacity > 0) RequestDeactivation(profileConfiguration); } @@ -261,7 +263,7 @@ internal class ProfileService : IProfileService { ProfileConfiguration profileConfiguration = profileCategory.ProfileConfigurations[j]; // Ensure all criteria are met before rendering - if (!profileConfiguration.IsSuspended && !profileConfiguration.IsMissingModule && (profileConfiguration.ActivationConditionMet || (profileConfiguration.Profile?.ShouldBeEnabled == false && profileConfiguration.Profile?.Opacity >= 0))) + if (!profileConfiguration.IsSuspended && !profileConfiguration.IsMissingModule && (profileConfiguration.ActivationConditionMet || (profileConfiguration.Profile?.ShouldDisplay == false && profileConfiguration.Profile?.Opacity >= 0))) profileConfiguration.Profile?.Render(canvas, SKPointI.Empty, null); } catch (Exception e) @@ -323,7 +325,10 @@ internal class ProfileService : IProfileService public Profile ActivateProfile(ProfileConfiguration profileConfiguration) { if (profileConfiguration.Profile != null) + { + profileConfiguration.Profile.ShouldDisplay = true; return profileConfiguration.Profile; + } ProfileEntity profileEntity; try @@ -375,7 +380,7 @@ internal class ProfileService : IProfileService if (profileConfiguration.Profile == null) return; - profileConfiguration.Profile.FadeOut(); + profileConfiguration.Profile.ShouldDisplay = false; } public void DeleteProfile(ProfileConfiguration profileConfiguration) From 5877e4dd208e310d40fae1f22645e41f83c83046 Mon Sep 17 00:00:00 2001 From: Diogo Trindade Date: Sun, 27 Nov 2022 20:04:04 +0000 Subject: [PATCH 5/7] Cleaned up ProfileService render condition --- src/Artemis.Core/Models/Profile/Profile.cs | 2 +- src/Artemis.Core/Services/Storage/ProfileService.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs index 4d68dda3e..e5899b6aa 100644 --- a/src/Artemis.Core/Models/Profile/Profile.cs +++ b/src/Artemis.Core/Models/Profile/Profile.cs @@ -125,7 +125,7 @@ public sealed class Profile : ProfileElement profileScript.OnProfileRendering(canvas, canvas.LocalClipBounds); using var opacityPaint = new SKPaint(); - if (Configuration.FadeInAndOut && Opacity != 1) + if (Configuration.FadeInAndOut && Opacity < 1) opacityPaint.Color = new SKColor(0, 0, 0, (byte)(255d * Easings.CubicEaseInOut(Opacity))); canvas.SaveLayer(opacityPaint); diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs index 801419d52..4b86f3d55 100644 --- a/src/Artemis.Core/Services/Storage/ProfileService.cs +++ b/src/Artemis.Core/Services/Storage/ProfileService.cs @@ -263,7 +263,8 @@ internal class ProfileService : IProfileService { ProfileConfiguration profileConfiguration = profileCategory.ProfileConfigurations[j]; // Ensure all criteria are met before rendering - if (!profileConfiguration.IsSuspended && !profileConfiguration.IsMissingModule && (profileConfiguration.ActivationConditionMet || (profileConfiguration.Profile?.ShouldDisplay == false && profileConfiguration.Profile?.Opacity >= 0))) + bool fadingOut = profileConfiguration.Profile?.ShouldDisplay == false && profileConfiguration.Profile?.Opacity > 0; + if (!profileConfiguration.IsSuspended && !profileConfiguration.IsMissingModule && (profileConfiguration.ActivationConditionMet || fadingOut)) profileConfiguration.Profile?.Render(canvas, SKPointI.Empty, null); } catch (Exception e) From c8a31696884ec139256a717e6efd302d2d3117be Mon Sep 17 00:00:00 2001 From: Diogo Trindade Date: Wed, 11 Jan 2023 09:43:47 +0000 Subject: [PATCH 6/7] Core - Apply opacity layer only when fading --- src/Artemis.Core/Models/Profile/Profile.cs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs index e5899b6aa..c511f9ec9 100644 --- a/src/Artemis.Core/Models/Profile/Profile.cs +++ b/src/Artemis.Core/Models/Profile/Profile.cs @@ -123,17 +123,25 @@ public sealed class Profile : ProfileElement foreach (ProfileScript profileScript in Scripts) profileScript.OnProfileRendering(canvas, canvas.LocalClipBounds); - - using var opacityPaint = new SKPaint(); - if (Configuration.FadeInAndOut && Opacity < 1) + + SKPaint? opacityPaint = null; + bool applyOpacityLayer = Configuration.FadeInAndOut && Opacity < 1; + + if (applyOpacityLayer) + { + opacityPaint = new SKPaint(); opacityPaint.Color = new SKColor(0, 0, 0, (byte)(255d * Easings.CubicEaseInOut(Opacity))); - - canvas.SaveLayer(opacityPaint); + canvas.SaveLayer(opacityPaint); + } foreach (ProfileElement profileElement in Children) profileElement.Render(canvas, basePosition, editorFocus); - canvas.Restore(); + if (applyOpacityLayer) + { + canvas.Restore(); + opacityPaint?.Dispose(); + } foreach (ProfileScript profileScript in Scripts) profileScript.OnProfileRendered(canvas, canvas.LocalClipBounds); From 166cb888c16bbc52ff7854880a5bf8839d943116 Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 11 Jan 2023 22:33:47 +0100 Subject: [PATCH 7/7] Meta - Update RGB.NET Meta - Fixed warnings --- src/Artemis.Core/Artemis.Core.csproj | 6 +++--- src/Artemis.Core/Constants.cs | 4 ++-- .../JsonConverters/ForgivingVersionConverter.cs | 4 ++-- src/Artemis.Core/Plugins/PluginFeatureInfo.cs | 1 - src/Artemis.Core/Services/Input/InputProvider.cs | 5 ++++- src/Artemis.Core/VisualScripting/Interfaces/INode.cs | 2 +- src/Artemis.UI.Shared/Artemis.UI.Shared.csproj | 2 +- src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs | 2 +- .../Shared/DataModelVisualizationViewModel.cs | 7 +++++-- src/Artemis.UI.Shared/ReactiveCoreWindow.cs | 3 +++ .../Services/ProfileEditor/Commands/UpdateColorGradient.cs | 2 +- src/Artemis.UI/Artemis.UI.csproj | 4 ++-- src/Artemis.UI/Screens/Root/RootViewModel.cs | 2 +- .../Sidebar/Dialogs/ProfileConfigurationEditViewModel.cs | 1 - .../Nodes/External/LayerPropertyNode.cs | 2 +- .../Nodes/List/ListOperatorPredicateNode.cs | 5 ++--- 16 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj index 9a766c559..0c62553d4 100644 --- a/src/Artemis.Core/Artemis.Core.csproj +++ b/src/Artemis.Core/Artemis.Core.csproj @@ -44,9 +44,9 @@ - - - + + + diff --git a/src/Artemis.Core/Constants.cs b/src/Artemis.Core/Constants.cs index f465f118e..cfb3b0551 100644 --- a/src/Artemis.Core/Constants.cs +++ b/src/Artemis.Core/Constants.cs @@ -62,8 +62,8 @@ public static class Constants /// /// The current API version for plugins /// - public static readonly int PluginApiVersion = int.Parse(CoreAssembly.GetCustomAttributes() - .First(a => a.Key == "PluginApiVersion").Value); + public static readonly int PluginApiVersion = int.Parse(CoreAssembly.GetCustomAttributes().First(a => a.Key == "PluginApiVersion").Value ?? + throw new InvalidOperationException("Cannot find PluginApiVersion metadata in assembly")); /// /// The plugin info used by core components of Artemis diff --git a/src/Artemis.Core/JsonConverters/ForgivingVersionConverter.cs b/src/Artemis.Core/JsonConverters/ForgivingVersionConverter.cs index 8cfe43151..8a325f7e0 100644 --- a/src/Artemis.Core/JsonConverters/ForgivingVersionConverter.cs +++ b/src/Artemis.Core/JsonConverters/ForgivingVersionConverter.cs @@ -10,9 +10,9 @@ namespace Artemis.Core.JsonConverters /// internal class ForgivingVersionConverter : VersionConverter { - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { - object obj = base.ReadJson(reader, objectType, existingValue, serializer); + object? obj = base.ReadJson(reader, objectType, existingValue, serializer); if (obj is not Version v) return obj; diff --git a/src/Artemis.Core/Plugins/PluginFeatureInfo.cs b/src/Artemis.Core/Plugins/PluginFeatureInfo.cs index 32d5775ec..b1dfbdc7b 100644 --- a/src/Artemis.Core/Plugins/PluginFeatureInfo.cs +++ b/src/Artemis.Core/Plugins/PluginFeatureInfo.cs @@ -18,7 +18,6 @@ namespace Artemis.Core; public class PluginFeatureInfo : CorePropertyChanged, IPrerequisitesSubject { private string? _description; - private string? _icon; private PluginFeature? _instance; private Exception? _loadException; private string _name = null!; diff --git a/src/Artemis.Core/Services/Input/InputProvider.cs b/src/Artemis.Core/Services/Input/InputProvider.cs index c51a25d63..8db4dec76 100644 --- a/src/Artemis.Core/Services/Input/InputProvider.cs +++ b/src/Artemis.Core/Services/Input/InputProvider.cs @@ -8,7 +8,10 @@ namespace Artemis.Core.Services; /// public abstract class InputProvider : IDisposable { - public InputProvider() + /// + /// Creates a new instance of the class. + /// + protected InputProvider() { ProviderName = GetType().FullName ?? throw new InvalidOperationException("Input provider must have a type with a name"); } diff --git a/src/Artemis.Core/VisualScripting/Interfaces/INode.cs b/src/Artemis.Core/VisualScripting/Interfaces/INode.cs index dce2df631..3bc2521fb 100644 --- a/src/Artemis.Core/VisualScripting/Interfaces/INode.cs +++ b/src/Artemis.Core/VisualScripting/Interfaces/INode.cs @@ -97,7 +97,7 @@ public interface INode : INotifyPropertyChanged, IBreakableModel void TryEvaluate(); /// - /// Resets the node causing all pins to re-evaluate the next time is called + /// Resets the node causing all pins to re-evaluate the next time is called /// void Reset(); } \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj b/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj index 66fe3e2c7..09c2d5479 100644 --- a/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj +++ b/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj @@ -20,7 +20,7 @@ - + diff --git a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs index c3fd4fc6e..1632f25a7 100644 --- a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs +++ b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs @@ -317,7 +317,7 @@ public class DeviceVisualizer : Control Dispatcher.UIThread.Post(InvalidateMeasure); } - catch (Exception e) + catch (Exception) { // ignored } diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs index a1df2555c..029a6dc18 100644 --- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs +++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs @@ -18,7 +18,7 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared; /// public abstract class DataModelVisualizationViewModel : ReactiveObject, IDisposable { - private const int MaxDepth = 4; + private const int MAX_DEPTH = 4; private ObservableCollection _children; private DataModel? _dataModel; private bool _isMatchingFilteredTypes; @@ -47,6 +47,9 @@ public abstract class DataModelVisualizationViewModel : ReactiveObject, IDisposa PropertyDescription = DataModelPath?.GetPropertyDescription() ?? DataModel?.DataModelDescription; } + /// + /// Copies the path of the data model to the clipboard. + /// public ReactiveCommand CopyPath { get; } /// @@ -337,7 +340,7 @@ public abstract class DataModelVisualizationViewModel : ReactiveObject, IDisposa { if (DataModel == null) throw new ArtemisSharedUIException("Cannot create a data model visualization child VM for a parent without a data model"); - if (depth > MaxDepth) + if (depth > MAX_DEPTH) return null; DataModelPath dataModelPath = new(DataModel, path); diff --git a/src/Artemis.UI.Shared/ReactiveCoreWindow.cs b/src/Artemis.UI.Shared/ReactiveCoreWindow.cs index 60fd8f353..295f4e6bb 100644 --- a/src/Artemis.UI.Shared/ReactiveCoreWindow.cs +++ b/src/Artemis.UI.Shared/ReactiveCoreWindow.cs @@ -19,6 +19,9 @@ namespace Artemis.UI.Shared; /// ViewModel type. public class ReactiveCoreWindow : CoreWindow, IViewFor where TViewModel : class { + /// + /// The ViewModel. + /// public static readonly StyledProperty ViewModelProperty = AvaloniaProperty .Register, TViewModel?>(nameof(ViewModel)); diff --git a/src/Artemis.UI.Shared/Services/ProfileEditor/Commands/UpdateColorGradient.cs b/src/Artemis.UI.Shared/Services/ProfileEditor/Commands/UpdateColorGradient.cs index 5970b652b..58f91f4bd 100644 --- a/src/Artemis.UI.Shared/Services/ProfileEditor/Commands/UpdateColorGradient.cs +++ b/src/Artemis.UI.Shared/Services/ProfileEditor/Commands/UpdateColorGradient.cs @@ -5,7 +5,7 @@ using Artemis.Core; namespace Artemis.UI.Shared.Services.ProfileEditor.Commands; /// -/// Represents a profile editor command that can be used to update a layer property of type . +/// Represents a profile editor command that can be used to update a color gradient. /// public class UpdateColorGradient : IProfileEditorCommand { diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj index c568a677c..04e578c41 100644 --- a/src/Artemis.UI/Artemis.UI.csproj +++ b/src/Artemis.UI/Artemis.UI.csproj @@ -29,8 +29,8 @@ - - + + diff --git a/src/Artemis.UI/Screens/Root/RootViewModel.cs b/src/Artemis.UI/Screens/Root/RootViewModel.cs index 10481f25c..b9175e9ed 100644 --- a/src/Artemis.UI/Screens/Root/RootViewModel.cs +++ b/src/Artemis.UI/Screens/Root/RootViewModel.cs @@ -92,7 +92,7 @@ public class RootViewModel : ActivatableViewModelBase, IScreen, IMainWindowProvi private void CurrentMainWindowOnClosing(object? sender, EventArgs e) { - WindowSizeSetting.Save(); + WindowSizeSetting?.Save(); _lifeTime.MainWindow = null; SidebarViewModel = null; Router.NavigateAndReset.Execute(new EmptyViewModel(this, "blank")).Subscribe(); diff --git a/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditViewModel.cs b/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditViewModel.cs index fe773c4f5..eaaf00480 100644 --- a/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditViewModel.cs +++ b/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditViewModel.cs @@ -139,7 +139,6 @@ public class ProfileConfigurationEditViewModel : DialogViewModelBase OpenConditionEditor { get; } public ReactiveCommand BrowseBitmapFile { get; } public ReactiveCommand Confirm { get; } - public ReactiveCommand Import { get; } public ReactiveCommand Delete { get; } public ReactiveCommand Cancel { get; } diff --git a/src/Artemis.VisualScripting/Nodes/External/LayerPropertyNode.cs b/src/Artemis.VisualScripting/Nodes/External/LayerPropertyNode.cs index 72fff998a..5a2199c05 100644 --- a/src/Artemis.VisualScripting/Nodes/External/LayerPropertyNode.cs +++ b/src/Artemis.VisualScripting/Nodes/External/LayerPropertyNode.cs @@ -117,7 +117,7 @@ public class LayerPropertyNode : Node - private void CreateOrAddOutputPin(Type valueType, string displayName) + private new void CreateOrAddOutputPin(Type valueType, string displayName) { // Grab the first pin from the bucket that isn't on the node yet OutputPin? pin = _pinBucket.FirstOrDefault(p => !Pins.Contains(p)); diff --git a/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateNode.cs b/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateNode.cs index 90f4f83eb..3631e5934 100644 --- a/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateNode.cs +++ b/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateNode.cs @@ -9,7 +9,7 @@ namespace Artemis.VisualScripting.Nodes.List; public class ListOperatorPredicateNode : Node, IDisposable { private readonly object _scriptLock = new(); - private ListOperatorPredicateStartNode _startNode; + private readonly ListOperatorPredicateStartNode _startNode; public ListOperatorPredicateNode() { @@ -65,7 +65,7 @@ public class ListOperatorPredicateNode : Node