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

Core - Brought device load/save logic in line with the rest of the code

This commit is contained in:
Robert 2023-10-14 17:20:22 +02:00
parent 46c035851a
commit 76d424012a
11 changed files with 161 additions and 104 deletions

View File

@ -1,9 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq; using System.Linq;
using Artemis.Core.DeviceProviders; using Artemis.Core.DeviceProviders;
using Artemis.Core.Services;
using Artemis.Storage.Entities.Surface; using Artemis.Storage.Entities.Surface;
using RGB.NET.Core; using RGB.NET.Core;
using SkiaSharp; using SkiaSharp;
@ -45,11 +45,15 @@ public class ArtemisDevice : CorePropertyChanged
InputMappings = new Dictionary<ArtemisLed, ArtemisLed>(); InputMappings = new Dictionary<ArtemisLed, ArtemisLed>();
Categories = new HashSet<DeviceCategory>(); Categories = new HashSet<DeviceCategory>();
UpdateLeds(); RgbDevice.ColorCorrections.Clear();
RgbDevice.ColorCorrections.Add(new ScaleColorCorrection(this));
UpdateLeds(false);
ApplyKeyboardLayout(); ApplyKeyboardLayout();
ApplyToEntity();
ApplyDefaultCategories();
CalculateRenderProperties(); CalculateRenderProperties();
Save();
RgbDevice.PropertyChanged += RgbDeviceOnPropertyChanged;
} }
internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider, DeviceEntity deviceEntity) internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider, DeviceEntity deviceEntity)
@ -72,8 +76,15 @@ public class ArtemisDevice : CorePropertyChanged
foreach (DeviceInputIdentifierEntity identifierEntity in DeviceEntity.InputIdentifiers) foreach (DeviceInputIdentifierEntity identifierEntity in DeviceEntity.InputIdentifiers)
InputIdentifiers.Add(new ArtemisDeviceInputIdentifier(identifierEntity.InputProvider, identifierEntity.Identifier)); InputIdentifiers.Add(new ArtemisDeviceInputIdentifier(identifierEntity.InputProvider, identifierEntity.Identifier));
UpdateLeds(); RgbDevice.ColorCorrections.Clear();
RgbDevice.ColorCorrections.Add(new ScaleColorCorrection(this));
UpdateLeds(false);
Load();
ApplyKeyboardLayout(); ApplyKeyboardLayout();
CalculateRenderProperties();
RgbDevice.PropertyChanged += RgbDeviceOnPropertyChanged;
} }
/// <summary> /// <summary>
@ -149,6 +160,8 @@ public class ArtemisDevice : CorePropertyChanged
set set
{ {
DeviceEntity.X = value; DeviceEntity.X = value;
if (RgbDevice.Surface != null)
ApplyLocation(DeviceEntity.X, DeviceEntity.Y);
OnPropertyChanged(nameof(X)); OnPropertyChanged(nameof(X));
} }
} }
@ -162,6 +175,8 @@ public class ArtemisDevice : CorePropertyChanged
set set
{ {
DeviceEntity.Y = value; DeviceEntity.Y = value;
if (RgbDevice.Surface != null)
ApplyLocation(DeviceEntity.X, DeviceEntity.Y);
OnPropertyChanged(nameof(Y)); OnPropertyChanged(nameof(Y));
} }
} }
@ -175,6 +190,8 @@ public class ArtemisDevice : CorePropertyChanged
set set
{ {
DeviceEntity.Rotation = value; DeviceEntity.Rotation = value;
if (RgbDevice.Surface != null)
RgbDevice.Rotation = DeviceEntity.Rotation;
OnPropertyChanged(nameof(Rotation)); OnPropertyChanged(nameof(Rotation));
} }
} }
@ -188,6 +205,8 @@ public class ArtemisDevice : CorePropertyChanged
set set
{ {
DeviceEntity.Scale = value; DeviceEntity.Scale = value;
if (RgbDevice.Surface != null)
RgbDevice.Scale = DeviceEntity.Scale;
OnPropertyChanged(nameof(Scale)); OnPropertyChanged(nameof(Scale));
} }
} }
@ -412,7 +431,6 @@ public class ArtemisDevice : CorePropertyChanged
case RGBDeviceType.Mousepad: case RGBDeviceType.Mousepad:
case RGBDeviceType.HeadsetStand: case RGBDeviceType.HeadsetStand:
case RGBDeviceType.Keypad: case RGBDeviceType.Keypad:
if (!Categories.Contains(DeviceCategory.Peripherals))
Categories.Add(DeviceCategory.Peripherals); Categories.Add(DeviceCategory.Peripherals);
break; break;
case RGBDeviceType.Mainboard: case RGBDeviceType.Mainboard:
@ -421,19 +439,15 @@ public class ArtemisDevice : CorePropertyChanged
case RGBDeviceType.Fan: case RGBDeviceType.Fan:
case RGBDeviceType.LedStripe: case RGBDeviceType.LedStripe:
case RGBDeviceType.Cooler: case RGBDeviceType.Cooler:
if (!Categories.Contains(DeviceCategory.Case))
Categories.Add(DeviceCategory.Case); Categories.Add(DeviceCategory.Case);
break; break;
case RGBDeviceType.Speaker: case RGBDeviceType.Speaker:
if (!Categories.Contains(DeviceCategory.Desk))
Categories.Add(DeviceCategory.Desk); Categories.Add(DeviceCategory.Desk);
break; break;
case RGBDeviceType.Monitor: case RGBDeviceType.Monitor:
if (!Categories.Contains(DeviceCategory.Monitor))
Categories.Add(DeviceCategory.Monitor); Categories.Add(DeviceCategory.Monitor);
break; break;
case RGBDeviceType.LedMatrix: case RGBDeviceType.LedMatrix:
if (!Categories.Contains(DeviceCategory.Room))
Categories.Add(DeviceCategory.Room); Categories.Add(DeviceCategory.Room);
break; break;
} }
@ -464,10 +478,9 @@ public class ArtemisDevice : CorePropertyChanged
if (layout == null) if (layout == null)
{ {
ClearLayout(); ClearLayout();
UpdateLeds(); UpdateLeds(true);
CalculateRenderProperties(); CalculateRenderProperties();
OnDeviceUpdated();
return; return;
} }
@ -481,13 +494,12 @@ public class ArtemisDevice : CorePropertyChanged
ClearLayout(); ClearLayout();
if (layout.IsValid) if (layout.IsValid)
layout.ApplyTo(RgbDevice, createMissingLeds, removeExcessiveLeds); layout.ApplyTo(RgbDevice, createMissingLeds, removeExcessiveLeds);
UpdateLeds(); UpdateLeds(true);
Layout = layout; Layout = layout;
Layout.ApplyDevice(this); Layout.ApplyDevice(this);
CalculateRenderProperties(); CalculateRenderProperties();
OnDeviceUpdated();
} }
private void ClearLayout() private void ClearLayout()
@ -505,7 +517,7 @@ public class ArtemisDevice : CorePropertyChanged
RgbDevice.AddLed(originalLed.Id, originalLed.Location, originalLed.Size, originalLed.CustomData); RgbDevice.AddLed(originalLed.Id, originalLed.Location, originalLed.Size, originalLed.CustomData);
} }
internal void ApplyToEntity() internal void Save()
{ {
// Other properties are computed // Other properties are computed
DeviceEntity.Id = Identifier; DeviceEntity.Id = Identifier;
@ -513,13 +525,7 @@ public class ArtemisDevice : CorePropertyChanged
DeviceEntity.InputIdentifiers.Clear(); DeviceEntity.InputIdentifiers.Clear();
foreach (ArtemisDeviceInputIdentifier identifier in InputIdentifiers) 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(); DeviceEntity.InputMappings.Clear();
foreach ((ArtemisLed? original, ArtemisLed? mapped) in InputMappings) foreach ((ArtemisLed? original, ArtemisLed? mapped) in InputMappings)
@ -530,31 +536,19 @@ public class ArtemisDevice : CorePropertyChanged
DeviceEntity.Categories.Add((int) deviceCategory); 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(); InputIdentifiers.Clear();
foreach (DeviceInputIdentifierEntity identifierEntity in DeviceEntity.InputIdentifiers) foreach (DeviceInputIdentifierEntity identifierEntity in DeviceEntity.InputIdentifiers)
InputIdentifiers.Add(new ArtemisDeviceInputIdentifier(identifierEntity.InputProvider, identifierEntity.Identifier)); InputIdentifiers.Add(new ArtemisDeviceInputIdentifier(identifierEntity.InputProvider, identifierEntity.Identifier));
if (!RgbDevice.ColorCorrections.Any())
RgbDevice.ColorCorrections.Add(new ScaleColorCorrection(this));
Categories.Clear(); Categories.Clear();
foreach (int deviceEntityCategory in DeviceEntity.Categories) foreach (int deviceEntityCategory in DeviceEntity.Categories)
Categories.Add((DeviceCategory) deviceEntityCategory); Categories.Add((DeviceCategory) deviceEntityCategory);
if (!Categories.Any()) if (!Categories.Any())
ApplyDefaultCategories(); ApplyDefaultCategories();
CalculateRenderProperties(); LoadInputMappings();
OnDeviceUpdated();
} }
internal void CalculateRenderProperties() internal void CalculateRenderProperties()
@ -571,13 +565,21 @@ public class ArtemisDevice : CorePropertyChanged
path.AddRect(artemisLed.AbsoluteRectangle); path.AddRect(artemisLed.AbsoluteRectangle);
Path = path; Path = path;
OnDeviceUpdated();
} }
private void UpdateLeds() private void UpdateLeds(bool loadInputMappings)
{ {
Leds = RgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly(); Leds = RgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
LedIds = new ReadOnlyDictionary<LedId, ArtemisLed>(Leds.ToDictionary(l => l.RgbLed.Id, l => l)); LedIds = new ReadOnlyDictionary<LedId, ArtemisLed>(Leds.ToDictionary(l => l.RgbLed.Id, l => l));
if (loadInputMappings)
LoadInputMappings();
}
private void LoadInputMappings()
{
InputMappings.Clear(); InputMappings.Clear();
foreach (InputMappingEntity deviceEntityInputMapping in DeviceEntity.InputMappings) foreach (InputMappingEntity deviceEntityInputMapping in DeviceEntity.InputMappings)
{ {
@ -604,6 +606,27 @@ public class ArtemisDevice : CorePropertyChanged
else else
LogicalLayout = DeviceEntity.LogicalLayout; 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();
}
} }
/// <summary> /// <summary>

View File

@ -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;
}
/// <inheritdoc />
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);
}
/// <inheritdoc />
public void PostRender(SKTexture texture)
{
}
}

View File

@ -175,7 +175,7 @@ internal class DeviceService : IDeviceService
_enabledDevices.Add(device); _enabledDevices.Add(device);
device.IsEnabled = true; device.IsEnabled = true;
device.ApplyToEntity(); device.Save();
_deviceRepository.Save(device.DeviceEntity); _deviceRepository.Save(device.DeviceEntity);
OnDeviceEnabled(new DeviceEventArgs(device)); OnDeviceEnabled(new DeviceEventArgs(device));
@ -190,7 +190,7 @@ internal class DeviceService : IDeviceService
_enabledDevices.Remove(device); _enabledDevices.Remove(device);
device.IsEnabled = false; device.IsEnabled = false;
device.ApplyToEntity(); device.Save();
_deviceRepository.Save(device.DeviceEntity); _deviceRepository.Save(device.DeviceEntity);
OnDeviceDisabled(new DeviceEventArgs(device)); OnDeviceDisabled(new DeviceEventArgs(device));
@ -200,9 +200,7 @@ internal class DeviceService : IDeviceService
/// <inheritdoc /> /// <inheritdoc />
public void SaveDevice(ArtemisDevice artemisDevice) public void SaveDevice(ArtemisDevice artemisDevice)
{ {
artemisDevice.ApplyToEntity(); artemisDevice.Save();
artemisDevice.ApplyToRgbDevice();
_deviceRepository.Save(artemisDevice.DeviceEntity); _deviceRepository.Save(artemisDevice.DeviceEntity);
UpdateLeds(); UpdateLeds();
} }
@ -211,11 +209,7 @@ internal class DeviceService : IDeviceService
public void SaveDevices() public void SaveDevices()
{ {
foreach (ArtemisDevice artemisDevice in _devices) foreach (ArtemisDevice artemisDevice in _devices)
{ artemisDevice.Save();
artemisDevice.ApplyToEntity();
artemisDevice.ApplyToRgbDevice();
}
_deviceRepository.Save(_devices.Select(d => d.DeviceEntity)); _deviceRepository.Save(_devices.Select(d => d.DeviceEntity));
UpdateLeds(); UpdateLeds();
} }
@ -236,7 +230,6 @@ internal class DeviceService : IDeviceService
device = new ArtemisDevice(rgbDevice, deviceProvider); device = new ArtemisDevice(rgbDevice, deviceProvider);
} }
device.ApplyToRgbDevice();
ApplyDeviceLayout(device, device.GetBestDeviceLayout()); ApplyDeviceLayout(device, device.GetBestDeviceLayout());
return device; return device;
} }

View File

@ -19,22 +19,24 @@ internal class RenderService : IRenderService, IRenderer, IDisposable
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IDeviceService _deviceService; private readonly IDeviceService _deviceService;
private readonly CoreRenderer _coreRenderer;
private readonly LazyEnumerable<IGraphicsContextProvider> _graphicsContextProviders; private readonly LazyEnumerable<IGraphicsContextProvider> _graphicsContextProviders;
private readonly PluginSetting<int> _targetFrameRateSetting; private readonly PluginSetting<int> _targetFrameRateSetting;
private readonly PluginSetting<double> _renderScaleSetting; private readonly PluginSetting<double> _renderScaleSetting;
private readonly PluginSetting<string> _preferredGraphicsContext; private readonly PluginSetting<string> _preferredGraphicsContext;
private readonly SurfaceManager _surfaceManager;
private SurfaceManager _surfaceManager;
private int _frames; private int _frames;
private DateTime _lastExceptionLog; private DateTime _lastExceptionLog;
private DateTime _lastFrameRateSample; private DateTime _lastFrameRateSample;
private bool _initialized; private bool _initialized;
public RenderService(ILogger logger, ISettingsService settingsService, IDeviceService deviceService, LazyEnumerable<IGraphicsContextProvider> graphicsContextProviders) public RenderService(ILogger logger, ISettingsService settingsService, IDeviceService deviceService, CoreRenderer coreRenderer, LazyEnumerable<IGraphicsContextProvider> graphicsContextProviders)
{ {
_frameStopWatch = new Stopwatch(); _frameStopWatch = new Stopwatch();
_logger = logger; _logger = logger;
_deviceService = deviceService; _deviceService = deviceService;
_coreRenderer = coreRenderer;
_graphicsContextProviders = graphicsContextProviders; _graphicsContextProviders = graphicsContextProviders;
_targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 30); _targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 30);
@ -77,8 +79,7 @@ internal class RenderService : IRenderService, IRenderer, IDisposable
try try
{ {
OnFrameRendering(new FrameRenderingEventArgs(canvas, delta, _surfaceManager.Surface)); OnFrameRendering(new FrameRenderingEventArgs(canvas, delta, _surfaceManager.Surface));
foreach (IRenderer renderer in Renderers) _coreRenderer.Render(canvas, delta);
renderer.Render(canvas, delta);
} }
catch (Exception e) catch (Exception e)
{ {
@ -91,8 +92,7 @@ internal class RenderService : IRenderService, IRenderer, IDisposable
{ {
try try
{ {
foreach (IRenderer renderer in Renderers) _coreRenderer.PostRender(texture);
renderer.PostRender(texture);
OnFrameRendered(new FrameRenderedEventArgs(texture, _surfaceManager.Surface)); OnFrameRendered(new FrameRenderedEventArgs(texture, _surfaceManager.Surface));
} }
catch (Exception e) catch (Exception e)

View File

@ -27,7 +27,6 @@ internal class SurfaceArrangement
{ {
surfaceDevice.X = 0; surfaceDevice.X = 0;
surfaceDevice.Y = 0; surfaceDevice.Y = 0;
surfaceDevice.ApplyToRgbDevice();
} }
foreach (SurfaceArrangementType surfaceArrangementType in Types) foreach (SurfaceArrangementType surfaceArrangementType in Types)
@ -37,17 +36,15 @@ internal class SurfaceArrangement
float x = devices.Min(d => d.RgbDevice.Location.X); float x = devices.Min(d => d.RgbDevice.Location.X);
float y = devices.Min(d => d.RgbDevice.Location.Y); float y = devices.Min(d => d.RgbDevice.Location.Y);
if (x < 0) if (x < 0)
foreach (ArtemisDevice surfaceDevice in devices)
{ {
foreach (ArtemisDevice surfaceDevice in devices)
surfaceDevice.X += x * -1; surfaceDevice.X += x * -1;
surfaceDevice.ApplyToRgbDevice();
} }
if (y < 0) if (y < 0)
foreach (ArtemisDevice surfaceDevice in devices)
{ {
foreach (ArtemisDevice surfaceDevice in devices)
surfaceDevice.Y += y * -1; surfaceDevice.Y += y * -1;
surfaceDevice.ApplyToRgbDevice();
} }
} }

View File

@ -80,9 +80,7 @@ internal class SurfaceArrangementConfiguration
}; };
} }
artemisDevice.ApplyToRgbDevice();
previous = artemisDevice; previous = artemisDevice;
SurfaceArrangement.ArrangedDevices.Add(artemisDevice); SurfaceArrangement.ArrangedDevices.Add(artemisDevice);
} }

View File

@ -7,7 +7,6 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Artemis.Core.Modules; using Artemis.Core.Modules;
using Artemis.Core.Services.Core;
using Artemis.Storage.Entities.Profile; using Artemis.Storage.Entities.Profile;
using Artemis.Storage.Repositories.Interfaces; using Artemis.Storage.Repositories.Interfaces;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -16,7 +15,7 @@ using SkiaSharp;
namespace Artemis.Core.Services; namespace Artemis.Core.Services;
internal class ProfileService : IProfileService, IRenderer internal class ProfileService : IProfileService
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IProfileCategoryRepository _profileCategoryRepository; private readonly IProfileCategoryRepository _profileCategoryRepository;
@ -36,7 +35,6 @@ internal class ProfileService : IProfileService, IRenderer
IPluginManagementService pluginManagementService, IPluginManagementService pluginManagementService,
IInputService inputService, IInputService inputService,
IDeviceService deviceService, IDeviceService deviceService,
IRenderService renderService,
IProfileRepository profileRepository) IProfileRepository profileRepository)
{ {
_logger = logger; _logger = logger;
@ -55,8 +53,6 @@ internal class ProfileService : IProfileService, IRenderer
if (!_profileCategories.Any()) if (!_profileCategories.Any())
CreateDefaultProfileCategories(); CreateDefaultProfileCategories();
UpdateModules(); UpdateModules();
renderService.Renderers.Add(this);
} }
public ProfileConfiguration? FocusProfile { get; set; } public ProfileConfiguration? FocusProfile { get; set; }
@ -188,21 +184,6 @@ internal class ProfileService : IProfileService, IRenderer
} }
} }
/// <inheritdoc />
public void Render(SKCanvas canvas, double delta)
{
if (ProfileRenderingDisabled)
return;
UpdateProfiles(delta);
RenderProfiles(canvas);
}
/// <inheritdoc />
public void PostRender(SKTexture texture)
{
}
/// <inheritdoc /> /// <inheritdoc />
public void LoadProfileConfigurationIcon(ProfileConfiguration profileConfiguration) public void LoadProfileConfigurationIcon(ProfileConfiguration profileConfiguration)
{ {

View File

@ -23,6 +23,8 @@ public class SurfaceDeviceViewModel : ActivatableViewModelBase
private double _dragOffsetX; private double _dragOffsetX;
private double _dragOffsetY; private double _dragOffsetY;
private bool _isSelected; private bool _isSelected;
private float _x;
private float _y;
public SurfaceDeviceViewModel(ArtemisDevice device, SurfaceEditorViewModel surfaceEditorViewModel, IDeviceService deviceService, ISettingsService settingsService, IWindowService windowService) public SurfaceDeviceViewModel(ArtemisDevice device, SurfaceEditorViewModel surfaceEditorViewModel, IDeviceService deviceService, ISettingsService settingsService, IWindowService windowService)
{ {
@ -33,6 +35,8 @@ public class SurfaceDeviceViewModel : ActivatableViewModelBase
Device = device; Device = device;
SurfaceEditorViewModel = surfaceEditorViewModel; SurfaceEditorViewModel = surfaceEditorViewModel;
DetectInput = ReactiveCommand.CreateFromTask(ExecuteDetectInput, this.WhenAnyValue(vm => vm.CanDetectInput)); DetectInput = ReactiveCommand.CreateFromTask(ExecuteDetectInput, this.WhenAnyValue(vm => vm.CanDetectInput));
X = device.X;
Y = device.Y;
} }
public ReactiveCommand<Unit, Unit> DetectInput { get; } public ReactiveCommand<Unit, Unit> DetectInput { get; }
@ -47,6 +51,18 @@ public class SurfaceDeviceViewModel : ActivatableViewModelBase
set => RaiseAndSetIfChanged(ref _isSelected, value); 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) public void StartMouseDrag(Point mouseStartPosition)
{ {
if (!IsSelected) if (!IsSelected)
@ -73,16 +89,16 @@ public class SurfaceDeviceViewModel : ActivatableViewModelBase
if (Fits(x, y, ignoreOverlap)) if (Fits(x, y, ignoreOverlap))
{ {
Device.X = x; X = x;
Device.Y = y; Y = y;
} }
else if (Fits(x, Device.Y, ignoreOverlap)) else if (Fits(x, Device.Y, ignoreOverlap))
{ {
Device.X = x; X = x;
} }
else if (Fits(Device.X, y, ignoreOverlap)) else if (Fits(Device.X, y, ignoreOverlap))
{ {
Device.Y = y; Y = y;
} }
} }
@ -100,10 +116,9 @@ public class SurfaceDeviceViewModel : ActivatableViewModelBase
IEnumerable<SKRect> own = Device.Leds IEnumerable<SKRect> own = Device.Leds
.Select(l => SKRect.Create(l.Rectangle.Left + x, l.Rectangle.Top + y, l.Rectangle.Width, l.Rectangle.Height)); .Select(l => SKRect.Create(l.Rectangle.Left + x, l.Rectangle.Top + y, l.Rectangle.Width, l.Rectangle.Height));
IEnumerable<SKRect> others = _deviceService.EnabledDevices IEnumerable<SKRect> others = SurfaceEditorViewModel.SurfaceDeviceViewModels
.Where(d => d != Device && d.IsEnabled) .Where(vm => vm != this && vm.Device.IsEnabled)
.SelectMany(d => d.Leds) .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)));
.Select(l => SKRect.Create(l.Rectangle.Left + l.Device.X, l.Rectangle.Top + l.Device.Y, l.Rectangle.Width, l.Rectangle.Height));
return !own.Any(o => others.Any(l => l.IntersectsWith(o))); return !own.Any(o => others.Any(l => l.IntersectsWith(o)));
} }
@ -122,4 +137,10 @@ public class SurfaceDeviceViewModel : ActivatableViewModelBase
if (viewModel.MadeChanges) if (viewModel.MadeChanges)
_deviceService.SaveDevice(Device); _deviceService.SaveDevice(Device);
} }
public void Apply()
{
Device.X = X;
Device.Y = Y;
}
} }

View File

@ -82,8 +82,8 @@
<ItemsControl Name="DeviceContainer" ItemsSource="{CompiledBinding SurfaceDeviceViewModels}" ClipToBounds="False"> <ItemsControl Name="DeviceContainer" ItemsSource="{CompiledBinding SurfaceDeviceViewModels}" ClipToBounds="False">
<ItemsControl.Styles> <ItemsControl.Styles>
<Style Selector="ContentPresenter"> <Style Selector="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Device.X}" /> <Setter Property="Canvas.Left" Value="{CompiledBinding X, DataType=surfaceEditor:SurfaceDeviceViewModel}" />
<Setter Property="Canvas.Top" Value="{Binding Device.Y}" /> <Setter Property="Canvas.Top" Value="{CompiledBinding Y, DataType=surfaceEditor:SurfaceDeviceViewModel}" />
</Style> </Style>
</ItemsControl.Styles> </ItemsControl.Styles>
<ItemsControl.ItemsPanel> <ItemsControl.ItemsPanel>

View File

@ -135,6 +135,8 @@ public class SurfaceEditorViewModel : RoutableScreen, IMainScreenViewModel
try try
{ {
_saving = true; _saving = true;
foreach (SurfaceDeviceViewModel surfaceDeviceViewModel in SurfaceDeviceViewModels)
surfaceDeviceViewModel.Apply();
_deviceService.SaveDevices(); _deviceService.SaveDevices();
} }
catch (Exception e) catch (Exception e)