diff --git a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs index a7f4eebbb..f2efc95be 100644 --- a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs +++ b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.ComponentModel; using System.Linq; using Artemis.Core.DeviceProviders; -using Artemis.Core.Services; using Artemis.Storage.Entities.Surface; using RGB.NET.Core; using SkiaSharp; @@ -44,12 +44,16 @@ public class ArtemisDevice : CorePropertyChanged InputIdentifiers = new List(); InputMappings = new Dictionary(); Categories = new HashSet(); - - UpdateLeds(); + + RgbDevice.ColorCorrections.Clear(); + RgbDevice.ColorCorrections.Add(new ScaleColorCorrection(this)); + + UpdateLeds(false); ApplyKeyboardLayout(); - ApplyToEntity(); - ApplyDefaultCategories(); CalculateRenderProperties(); + Save(); + + RgbDevice.PropertyChanged += RgbDeviceOnPropertyChanged; } internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider, DeviceEntity deviceEntity) @@ -71,11 +75,18 @@ public class ArtemisDevice : CorePropertyChanged foreach (DeviceInputIdentifierEntity identifierEntity in DeviceEntity.InputIdentifiers) InputIdentifiers.Add(new ArtemisDeviceInputIdentifier(identifierEntity.InputProvider, identifierEntity.Identifier)); - - UpdateLeds(); + + RgbDevice.ColorCorrections.Clear(); + RgbDevice.ColorCorrections.Add(new ScaleColorCorrection(this)); + + UpdateLeds(false); + Load(); ApplyKeyboardLayout(); + CalculateRenderProperties(); + + RgbDevice.PropertyChanged += RgbDeviceOnPropertyChanged; } - + /// /// Gets the (hopefully unique and persistent) ID of this device /// @@ -149,6 +160,8 @@ public class ArtemisDevice : CorePropertyChanged set { DeviceEntity.X = value; + if (RgbDevice.Surface != null) + ApplyLocation(DeviceEntity.X, DeviceEntity.Y); OnPropertyChanged(nameof(X)); } } @@ -162,6 +175,8 @@ public class ArtemisDevice : CorePropertyChanged set { DeviceEntity.Y = value; + if (RgbDevice.Surface != null) + ApplyLocation(DeviceEntity.X, DeviceEntity.Y); OnPropertyChanged(nameof(Y)); } } @@ -175,6 +190,8 @@ public class ArtemisDevice : CorePropertyChanged set { DeviceEntity.Rotation = value; + if (RgbDevice.Surface != null) + RgbDevice.Rotation = DeviceEntity.Rotation; OnPropertyChanged(nameof(Rotation)); } } @@ -188,6 +205,8 @@ public class ArtemisDevice : CorePropertyChanged set { DeviceEntity.Scale = value; + if (RgbDevice.Surface != null) + RgbDevice.Scale = DeviceEntity.Scale; OnPropertyChanged(nameof(Scale)); } } @@ -412,8 +431,7 @@ public class ArtemisDevice : CorePropertyChanged case RGBDeviceType.Mousepad: case RGBDeviceType.HeadsetStand: case RGBDeviceType.Keypad: - if (!Categories.Contains(DeviceCategory.Peripherals)) - Categories.Add(DeviceCategory.Peripherals); + Categories.Add(DeviceCategory.Peripherals); break; case RGBDeviceType.Mainboard: case RGBDeviceType.GraphicsCard: @@ -421,20 +439,16 @@ public class ArtemisDevice : CorePropertyChanged case RGBDeviceType.Fan: case RGBDeviceType.LedStripe: case RGBDeviceType.Cooler: - if (!Categories.Contains(DeviceCategory.Case)) - Categories.Add(DeviceCategory.Case); + Categories.Add(DeviceCategory.Case); break; case RGBDeviceType.Speaker: - if (!Categories.Contains(DeviceCategory.Desk)) - Categories.Add(DeviceCategory.Desk); + Categories.Add(DeviceCategory.Desk); break; case RGBDeviceType.Monitor: - if (!Categories.Contains(DeviceCategory.Monitor)) - Categories.Add(DeviceCategory.Monitor); + Categories.Add(DeviceCategory.Monitor); break; case RGBDeviceType.LedMatrix: - if (!Categories.Contains(DeviceCategory.Room)) - Categories.Add(DeviceCategory.Room); + Categories.Add(DeviceCategory.Room); break; } } @@ -464,10 +478,9 @@ public class ArtemisDevice : CorePropertyChanged if (layout == null) { ClearLayout(); - UpdateLeds(); + UpdateLeds(true); CalculateRenderProperties(); - OnDeviceUpdated(); return; } @@ -481,13 +494,12 @@ public class ArtemisDevice : CorePropertyChanged ClearLayout(); if (layout.IsValid) layout.ApplyTo(RgbDevice, createMissingLeds, removeExcessiveLeds); - UpdateLeds(); + UpdateLeds(true); Layout = layout; Layout.ApplyDevice(this); CalculateRenderProperties(); - OnDeviceUpdated(); } private void ClearLayout() @@ -505,7 +517,7 @@ public class ArtemisDevice : CorePropertyChanged RgbDevice.AddLed(originalLed.Id, originalLed.Location, originalLed.Size, originalLed.CustomData); } - internal void ApplyToEntity() + internal void Save() { // Other properties are computed DeviceEntity.Id = Identifier; @@ -513,48 +525,30 @@ public class ArtemisDevice : CorePropertyChanged DeviceEntity.InputIdentifiers.Clear(); foreach (ArtemisDeviceInputIdentifier identifier in InputIdentifiers) - { - DeviceEntity.InputIdentifiers.Add(new DeviceInputIdentifierEntity - { - InputProvider = identifier.InputProvider, - Identifier = identifier.Identifier - }); - } + DeviceEntity.InputIdentifiers.Add(new DeviceInputIdentifierEntity {InputProvider = identifier.InputProvider, Identifier = identifier.Identifier}); DeviceEntity.InputMappings.Clear(); foreach ((ArtemisLed? original, ArtemisLed? mapped) in InputMappings) DeviceEntity.InputMappings.Add(new InputMappingEntity {OriginalLedId = (int) original.RgbLed.Id, MappedLedId = (int) mapped.RgbLed.Id}); - + DeviceEntity.Categories.Clear(); foreach (DeviceCategory deviceCategory in Categories) DeviceEntity.Categories.Add((int) deviceCategory); } - internal void ApplyToRgbDevice() + internal void Load() { - RgbDevice.Rotation = DeviceEntity.Rotation; - RgbDevice.Scale = DeviceEntity.Scale; - - // Workaround for device rotation not applying - if (DeviceEntity.X == 0 && DeviceEntity.Y == 0) - RgbDevice.Location = new Point(1, 1); - RgbDevice.Location = new Point(DeviceEntity.X, DeviceEntity.Y); - InputIdentifiers.Clear(); foreach (DeviceInputIdentifierEntity identifierEntity in DeviceEntity.InputIdentifiers) InputIdentifiers.Add(new ArtemisDeviceInputIdentifier(identifierEntity.InputProvider, identifierEntity.Identifier)); - if (!RgbDevice.ColorCorrections.Any()) - RgbDevice.ColorCorrections.Add(new ScaleColorCorrection(this)); - Categories.Clear(); foreach (int deviceEntityCategory in DeviceEntity.Categories) Categories.Add((DeviceCategory) deviceEntityCategory); if (!Categories.Any()) ApplyDefaultCategories(); - - CalculateRenderProperties(); - OnDeviceUpdated(); + + LoadInputMappings(); } internal void CalculateRenderProperties() @@ -571,13 +565,21 @@ public class ArtemisDevice : CorePropertyChanged path.AddRect(artemisLed.AbsoluteRectangle); Path = path; + + OnDeviceUpdated(); } - private void UpdateLeds() + private void UpdateLeds(bool loadInputMappings) { Leds = RgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly(); LedIds = new ReadOnlyDictionary(Leds.ToDictionary(l => l.RgbLed.Id, l => l)); + if (loadInputMappings) + LoadInputMappings(); + } + + private void LoadInputMappings() + { InputMappings.Clear(); foreach (InputMappingEntity deviceEntityInputMapping in DeviceEntity.InputMappings) { @@ -604,6 +606,27 @@ public class ArtemisDevice : CorePropertyChanged else LogicalLayout = DeviceEntity.LogicalLayout; } + + private void RgbDeviceOnPropertyChanged(object? sender, PropertyChangedEventArgs e) + { + if (e.PropertyName != nameof(IRGBDevice.Surface)) + return; + + RgbDevice.Rotation = DeviceEntity.Rotation; + RgbDevice.Scale = DeviceEntity.Scale; + ApplyLocation(DeviceEntity.X, DeviceEntity.Y); + } + + private void ApplyLocation(float x, float y) + { + // Workaround for device rotation not applying + if (x == 0 && y == 0) + RgbDevice.Location = new Point(1, 1); + RgbDevice.Location = new Point(x, y); + + UpdateLeds(false); + CalculateRenderProperties(); + } } /// diff --git a/src/Artemis.Core/Services/CoreRenderer.cs b/src/Artemis.Core/Services/CoreRenderer.cs new file mode 100644 index 000000000..2856d646a --- /dev/null +++ b/src/Artemis.Core/Services/CoreRenderer.cs @@ -0,0 +1,42 @@ +using Artemis.Core.ScriptingProviders; +using Artemis.Core.Services.Core; +using SkiaSharp; + +namespace Artemis.Core.Services; + +internal class CoreRenderer : IRenderer +{ + private readonly IModuleService _moduleService; + private readonly IScriptingService _scriptingService; + private readonly IProfileService _profileService; + + public CoreRenderer(IModuleService moduleService, IScriptingService scriptingService, IProfileService profileService) + { + _moduleService = moduleService; + _scriptingService = scriptingService; + _profileService = profileService; + } + + /// + public void Render(SKCanvas canvas, double delta) + { + foreach (GlobalScript scriptingServiceGlobalScript in _scriptingService.GlobalScripts) + scriptingServiceGlobalScript.OnCoreUpdating(delta); + + _moduleService.UpdateActiveModules(delta); + + if (!_profileService.ProfileRenderingDisabled) + { + _profileService.UpdateProfiles(delta); + _profileService.RenderProfiles(canvas); + } + + foreach (GlobalScript scriptingServiceGlobalScript in _scriptingService.GlobalScripts) + scriptingServiceGlobalScript.OnCoreUpdated(delta); + } + + /// + public void PostRender(SKTexture texture) + { + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Services/DeviceService.cs b/src/Artemis.Core/Services/DeviceService.cs index 2cddc24f4..14e330977 100644 --- a/src/Artemis.Core/Services/DeviceService.cs +++ b/src/Artemis.Core/Services/DeviceService.cs @@ -175,7 +175,7 @@ internal class DeviceService : IDeviceService _enabledDevices.Add(device); device.IsEnabled = true; - device.ApplyToEntity(); + device.Save(); _deviceRepository.Save(device.DeviceEntity); OnDeviceEnabled(new DeviceEventArgs(device)); @@ -190,7 +190,7 @@ internal class DeviceService : IDeviceService _enabledDevices.Remove(device); device.IsEnabled = false; - device.ApplyToEntity(); + device.Save(); _deviceRepository.Save(device.DeviceEntity); OnDeviceDisabled(new DeviceEventArgs(device)); @@ -200,9 +200,7 @@ internal class DeviceService : IDeviceService /// public void SaveDevice(ArtemisDevice artemisDevice) { - artemisDevice.ApplyToEntity(); - artemisDevice.ApplyToRgbDevice(); - + artemisDevice.Save(); _deviceRepository.Save(artemisDevice.DeviceEntity); UpdateLeds(); } @@ -211,11 +209,7 @@ internal class DeviceService : IDeviceService public void SaveDevices() { foreach (ArtemisDevice artemisDevice in _devices) - { - artemisDevice.ApplyToEntity(); - artemisDevice.ApplyToRgbDevice(); - } - + artemisDevice.Save(); _deviceRepository.Save(_devices.Select(d => d.DeviceEntity)); UpdateLeds(); } @@ -236,7 +230,6 @@ internal class DeviceService : IDeviceService device = new ArtemisDevice(rgbDevice, deviceProvider); } - device.ApplyToRgbDevice(); ApplyDeviceLayout(device, device.GetBestDeviceLayout()); return device; } diff --git a/src/Artemis.Core/Services/RenderService.cs b/src/Artemis.Core/Services/RenderService.cs index d9653279a..f9bf44013 100644 --- a/src/Artemis.Core/Services/RenderService.cs +++ b/src/Artemis.Core/Services/RenderService.cs @@ -19,22 +19,24 @@ internal class RenderService : IRenderService, IRenderer, IDisposable private readonly ILogger _logger; private readonly IDeviceService _deviceService; + private readonly CoreRenderer _coreRenderer; private readonly LazyEnumerable _graphicsContextProviders; private readonly PluginSetting _targetFrameRateSetting; private readonly PluginSetting _renderScaleSetting; private readonly PluginSetting _preferredGraphicsContext; + private readonly SurfaceManager _surfaceManager; - private SurfaceManager _surfaceManager; private int _frames; private DateTime _lastExceptionLog; private DateTime _lastFrameRateSample; private bool _initialized; - public RenderService(ILogger logger, ISettingsService settingsService, IDeviceService deviceService, LazyEnumerable graphicsContextProviders) + public RenderService(ILogger logger, ISettingsService settingsService, IDeviceService deviceService, CoreRenderer coreRenderer, LazyEnumerable graphicsContextProviders) { _frameStopWatch = new Stopwatch(); _logger = logger; _deviceService = deviceService; + _coreRenderer = coreRenderer; _graphicsContextProviders = graphicsContextProviders; _targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 30); @@ -77,8 +79,7 @@ internal class RenderService : IRenderService, IRenderer, IDisposable try { OnFrameRendering(new FrameRenderingEventArgs(canvas, delta, _surfaceManager.Surface)); - foreach (IRenderer renderer in Renderers) - renderer.Render(canvas, delta); + _coreRenderer.Render(canvas, delta); } catch (Exception e) { @@ -91,8 +92,7 @@ internal class RenderService : IRenderService, IRenderer, IDisposable { try { - foreach (IRenderer renderer in Renderers) - renderer.PostRender(texture); + _coreRenderer.PostRender(texture); OnFrameRendered(new FrameRenderedEventArgs(texture, _surfaceManager.Surface)); } catch (Exception e) diff --git a/src/Artemis.Core/Services/ScriptingService.cs b/src/Artemis.Core/Services/ScriptingService.cs index baeee28e9..f768c2028 100644 --- a/src/Artemis.Core/Services/ScriptingService.cs +++ b/src/Artemis.Core/Services/ScriptingService.cs @@ -12,7 +12,7 @@ internal class ScriptingService : IScriptingService private readonly IPluginManagementService _pluginManagementService; private readonly IProfileService _profileService; private readonly List _scriptingProviders; - + public ScriptingService(IPluginManagementService pluginManagementService, IProfileService profileService) { _pluginManagementService = pluginManagementService; diff --git a/src/Artemis.Core/Services/Storage/Models/SurfaceArrangement.cs b/src/Artemis.Core/Services/Storage/Models/SurfaceArrangement.cs index 132c623cb..9f4e78fe1 100644 --- a/src/Artemis.Core/Services/Storage/Models/SurfaceArrangement.cs +++ b/src/Artemis.Core/Services/Storage/Models/SurfaceArrangement.cs @@ -27,7 +27,6 @@ internal class SurfaceArrangement { surfaceDevice.X = 0; surfaceDevice.Y = 0; - surfaceDevice.ApplyToRgbDevice(); } foreach (SurfaceArrangementType surfaceArrangementType in Types) @@ -37,18 +36,16 @@ internal class SurfaceArrangement float x = devices.Min(d => d.RgbDevice.Location.X); float y = devices.Min(d => d.RgbDevice.Location.Y); if (x < 0) + { foreach (ArtemisDevice surfaceDevice in devices) - { surfaceDevice.X += x * -1; - surfaceDevice.ApplyToRgbDevice(); - } + } if (y < 0) + { foreach (ArtemisDevice surfaceDevice in devices) - { surfaceDevice.Y += y * -1; - surfaceDevice.ApplyToRgbDevice(); - } + } } internal static SurfaceArrangement GetDefaultArrangement() diff --git a/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementConfiguration.cs b/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementConfiguration.cs index 34decdd69..7f59731f9 100644 --- a/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementConfiguration.cs +++ b/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementConfiguration.cs @@ -80,9 +80,7 @@ internal class SurfaceArrangementConfiguration }; } - artemisDevice.ApplyToRgbDevice(); previous = artemisDevice; - SurfaceArrangement.ArrangedDevices.Add(artemisDevice); } diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs index 485dfd267..f93a4f152 100644 --- a/src/Artemis.Core/Services/Storage/ProfileService.cs +++ b/src/Artemis.Core/Services/Storage/ProfileService.cs @@ -7,7 +7,6 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Artemis.Core.Modules; -using Artemis.Core.Services.Core; using Artemis.Storage.Entities.Profile; using Artemis.Storage.Repositories.Interfaces; using Newtonsoft.Json; @@ -16,7 +15,7 @@ using SkiaSharp; namespace Artemis.Core.Services; -internal class ProfileService : IProfileService, IRenderer +internal class ProfileService : IProfileService { private readonly ILogger _logger; private readonly IProfileCategoryRepository _profileCategoryRepository; @@ -36,7 +35,6 @@ internal class ProfileService : IProfileService, IRenderer IPluginManagementService pluginManagementService, IInputService inputService, IDeviceService deviceService, - IRenderService renderService, IProfileRepository profileRepository) { _logger = logger; @@ -55,8 +53,6 @@ internal class ProfileService : IProfileService, IRenderer if (!_profileCategories.Any()) CreateDefaultProfileCategories(); UpdateModules(); - - renderService.Renderers.Add(this); } public ProfileConfiguration? FocusProfile { get; set; } @@ -187,21 +183,6 @@ internal class ProfileService : IProfileService, IRenderer } } } - - /// - public void Render(SKCanvas canvas, double delta) - { - if (ProfileRenderingDisabled) - return; - - UpdateProfiles(delta); - RenderProfiles(canvas); - } - - /// - public void PostRender(SKTexture texture) - { - } /// public void LoadProfileConfigurationIcon(ProfileConfiguration profileConfiguration) diff --git a/src/Artemis.UI/Screens/SurfaceEditor/SurfaceDeviceViewModel.cs b/src/Artemis.UI/Screens/SurfaceEditor/SurfaceDeviceViewModel.cs index 27bb100d8..e9ee4f9d9 100644 --- a/src/Artemis.UI/Screens/SurfaceEditor/SurfaceDeviceViewModel.cs +++ b/src/Artemis.UI/Screens/SurfaceEditor/SurfaceDeviceViewModel.cs @@ -23,6 +23,8 @@ public class SurfaceDeviceViewModel : ActivatableViewModelBase private double _dragOffsetX; private double _dragOffsetY; private bool _isSelected; + private float _x; + private float _y; public SurfaceDeviceViewModel(ArtemisDevice device, SurfaceEditorViewModel surfaceEditorViewModel, IDeviceService deviceService, ISettingsService settingsService, IWindowService windowService) { @@ -33,6 +35,8 @@ public class SurfaceDeviceViewModel : ActivatableViewModelBase Device = device; SurfaceEditorViewModel = surfaceEditorViewModel; DetectInput = ReactiveCommand.CreateFromTask(ExecuteDetectInput, this.WhenAnyValue(vm => vm.CanDetectInput)); + X = device.X; + Y = device.Y; } public ReactiveCommand DetectInput { get; } @@ -47,6 +51,18 @@ public class SurfaceDeviceViewModel : ActivatableViewModelBase set => RaiseAndSetIfChanged(ref _isSelected, value); } + public float X + { + get => _x; + set => RaiseAndSetIfChanged(ref _x, value); + } + + public float Y + { + get => _y; + set => RaiseAndSetIfChanged(ref _y, value); + } + public void StartMouseDrag(Point mouseStartPosition) { if (!IsSelected) @@ -73,16 +89,16 @@ public class SurfaceDeviceViewModel : ActivatableViewModelBase if (Fits(x, y, ignoreOverlap)) { - Device.X = x; - Device.Y = y; + X = x; + Y = y; } else if (Fits(x, Device.Y, ignoreOverlap)) { - Device.X = x; + X = x; } else if (Fits(Device.X, y, ignoreOverlap)) { - Device.Y = y; + Y = y; } } @@ -100,10 +116,9 @@ public class SurfaceDeviceViewModel : ActivatableViewModelBase IEnumerable own = Device.Leds .Select(l => SKRect.Create(l.Rectangle.Left + x, l.Rectangle.Top + y, l.Rectangle.Width, l.Rectangle.Height)); - IEnumerable others = _deviceService.EnabledDevices - .Where(d => d != Device && d.IsEnabled) - .SelectMany(d => d.Leds) - .Select(l => SKRect.Create(l.Rectangle.Left + l.Device.X, l.Rectangle.Top + l.Device.Y, l.Rectangle.Width, l.Rectangle.Height)); + IEnumerable others = SurfaceEditorViewModel.SurfaceDeviceViewModels + .Where(vm => vm != this && vm.Device.IsEnabled) + .SelectMany(vm => vm.Device.Leds.Select(l => SKRect.Create(l.Rectangle.Left + vm.X, l.Rectangle.Top + vm.Y, l.Rectangle.Width, l.Rectangle.Height))); return !own.Any(o => others.Any(l => l.IntersectsWith(o))); } @@ -122,4 +137,10 @@ public class SurfaceDeviceViewModel : ActivatableViewModelBase if (viewModel.MadeChanges) _deviceService.SaveDevice(Device); } + + public void Apply() + { + Device.X = X; + Device.Y = Y; + } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorView.axaml b/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorView.axaml index 4b6e39d72..05a49c0d6 100644 --- a/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorView.axaml +++ b/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorView.axaml @@ -82,8 +82,8 @@ diff --git a/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorViewModel.cs b/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorViewModel.cs index 980253ea2..aa23a0a90 100644 --- a/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorViewModel.cs +++ b/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorViewModel.cs @@ -135,6 +135,8 @@ public class SurfaceEditorViewModel : RoutableScreen, IMainScreenViewModel try { _saving = true; + foreach (SurfaceDeviceViewModel surfaceDeviceViewModel in SurfaceDeviceViewModels) + surfaceDeviceViewModel.Apply(); _deviceService.SaveDevices(); } catch (Exception e)