diff --git a/src/.idea/.idea.Artemis/.idea/avalonia.xml b/src/.idea/.idea.Artemis/.idea/avalonia.xml index a1aaa2a1a..5d5fcf5ff 100644 --- a/src/.idea/.idea.Artemis/.idea/avalonia.xml +++ b/src/.idea/.idea.Artemis/.idea/avalonia.xml @@ -19,12 +19,21 @@ + + + + + + + + + @@ -38,6 +47,7 @@ + diff --git a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs index 206cfd5f2..aab383528 100644 --- a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs +++ b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs @@ -142,7 +142,10 @@ namespace Artemis.UI.Shared Point scaledPosition = new(x * Device.Rectangle.Width, y * Device.Rectangle.Height); DeviceVisualizerLed? deviceVisualizerLed = _deviceVisualizerLeds.FirstOrDefault(l => l.HitTest(scaledPosition)); if (deviceVisualizerLed != null) - OnLedClicked(new LedClickedEventArgs(deviceVisualizerLed.Led.Device, deviceVisualizerLed.Led)); + { + OnLedClicked(new LedClickedEventArgs(deviceVisualizerLed.Led.Device, deviceVisualizerLed.Led, e)); + e.Handled = true; + } } private void DevicePropertyChanged(object? sender, PropertyChangedEventArgs e) diff --git a/src/Artemis.UI.Shared/Events/LedClickedEventArgs.cs b/src/Artemis.UI.Shared/Events/LedClickedEventArgs.cs index cfaa9a160..53ed595f8 100644 --- a/src/Artemis.UI.Shared/Events/LedClickedEventArgs.cs +++ b/src/Artemis.UI.Shared/Events/LedClickedEventArgs.cs @@ -1,27 +1,33 @@ using System; using Artemis.Core; +using Avalonia.Input; -namespace Artemis.UI.Shared.Events +namespace Artemis.UI.Shared.Events; + +/// +/// Provides data on LED click events raised by the device visualizer +/// +public class LedClickedEventArgs : EventArgs { - /// - /// Provides data on LED click events raised by the device visualizer - /// - public class LedClickedEventArgs : EventArgs + internal LedClickedEventArgs(ArtemisDevice device, ArtemisLed led, PointerReleasedEventArgs pointerReleasedEventArgs) { - internal LedClickedEventArgs(ArtemisDevice device, ArtemisLed led) - { - Device = device; - Led = led; - } - - /// - /// The device that was clicked - /// - public ArtemisDevice Device { get; set; } - - /// - /// The LED that was clicked - /// - public ArtemisLed Led { get; set; } + Device = device; + Led = led; + PointerReleasedEventArgs = pointerReleasedEventArgs; } + + /// + /// Gets the device that was clicked. + /// + public ArtemisDevice Device { get; set; } + + /// + /// Gets the LED that was clicked. + /// + public ArtemisLed Led { get; set; } + + /// + /// Gets the original pointer released event arguments. + /// + public PointerReleasedEventArgs PointerReleasedEventArgs { get; } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Device/DevicePropertiesView.axaml b/src/Artemis.UI/Screens/Device/DevicePropertiesView.axaml index 31070f5e3..fed6b9938 100644 --- a/src/Artemis.UI/Screens/Device/DevicePropertiesView.axaml +++ b/src/Artemis.UI/Screens/Device/DevicePropertiesView.axaml @@ -1,16 +1,20 @@ - + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:controls1="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" + xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared" + xmlns:device="clr-namespace:Artemis.UI.Screens.Device" + mc:Ignorable="d" d:DesignWidth="1200" d:DesignHeight="800" + x:Class="Artemis.UI.Screens.Device.DevicePropertiesView" + x:DataType="device:DevicePropertiesViewModel" + Icon="/Assets/Images/Logo/application.ico" + Title="Artemis | Device Properties" + Width="1250" + Height="900"> + + + @@ -24,45 +28,46 @@ - + - + + IsVisible="{CompiledBinding Device.Layout.RgbLayout.Author, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"> - + - - + + - + - + - + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Device/DevicePropertiesView.axaml.cs b/src/Artemis.UI/Screens/Device/DevicePropertiesView.axaml.cs index b5fd26391..f4a0fab43 100644 --- a/src/Artemis.UI/Screens/Device/DevicePropertiesView.axaml.cs +++ b/src/Artemis.UI/Screens/Device/DevicePropertiesView.axaml.cs @@ -1,22 +1,40 @@ +using System; +using Artemis.UI.Shared; +using Artemis.UI.Shared.Events; using Avalonia; +using Avalonia.Input; using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; -namespace Artemis.UI.Screens.Device +namespace Artemis.UI.Screens.Device; + +public class DevicePropertiesView : ReactiveCoreWindow { - public partial class DevicePropertiesView : ReactiveCoreWindow + public DevicePropertiesView() { - public DevicePropertiesView() - { - InitializeComponent(); + InitializeComponent(); #if DEBUG - this.AttachDevTools(); + this.AttachDevTools(); #endif - } - - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - } } -} + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + + private void DeviceVisualizer_OnLedClicked(object? sender, LedClickedEventArgs e) + { + if (ViewModel == null) + return; + + if (!e.PointerReleasedEventArgs.KeyModifiers.HasFlag(KeyModifiers.Shift)) + ViewModel.SelectedLeds.Clear(); + ViewModel.SelectedLeds.Add(e.Led); + } + + private void DeviceDisplayGrid_OnPointerReleased(object? sender, PointerReleasedEventArgs e) + { + if (!e.KeyModifiers.HasFlag(KeyModifiers.Shift)) + ViewModel?.ClearSelectedLeds.Execute().Subscribe(); + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Device/DevicePropertiesViewModel.cs b/src/Artemis.UI/Screens/Device/DevicePropertiesViewModel.cs index 039d776f3..1bf75fae2 100644 --- a/src/Artemis.UI/Screens/Device/DevicePropertiesViewModel.cs +++ b/src/Artemis.UI/Screens/Device/DevicePropertiesViewModel.cs @@ -1,15 +1,22 @@ -using System.Collections.ObjectModel; +using System; +using System.Collections.ObjectModel; +using System.Linq; +using System.Reactive; +using System.Reactive.Disposables; using Artemis.Core; +using Artemis.Core.Services; using Artemis.UI.Ninject.Factories; using Artemis.UI.Shared; +using ReactiveUI; using RGB.NET.Core; +using SkiaSharp; using ArtemisLed = Artemis.Core.ArtemisLed; namespace Artemis.UI.Screens.Device { public class DevicePropertiesViewModel : DialogViewModelBase { - public DevicePropertiesViewModel(ArtemisDevice device, IDeviceVmFactory deviceVmFactory) + public DevicePropertiesViewModel(ArtemisDevice device, ICoreService coreService, IDeviceVmFactory deviceVmFactory) { Device = device; SelectedLeds = new ObservableCollection(); @@ -17,13 +24,39 @@ namespace Artemis.UI.Screens.Device Tabs.Add(deviceVmFactory.DevicePropertiesTabViewModel(device)); Tabs.Add(deviceVmFactory.DeviceInfoTabViewModel(device)); - if (Device .DeviceType == RGBDeviceType.Keyboard) + if (Device.DeviceType == RGBDeviceType.Keyboard) Tabs.Add(deviceVmFactory.InputMappingsTabViewModel(device, SelectedLeds)); Tabs.Add(deviceVmFactory.DeviceLedsTabViewModel(device, SelectedLeds)); + + this.WhenActivated(d => + { + coreService.FrameRendering += CoreServiceOnFrameRendering; + Disposable.Create(() => coreService.FrameRendering -= CoreServiceOnFrameRendering).DisposeWith(d); + }); + + ClearSelectedLeds = ReactiveCommand.Create(ExecuteClearSelectedLeds); } public ArtemisDevice Device { get; } public ObservableCollection SelectedLeds { get; } public ObservableCollection Tabs { get; } + + public ReactiveCommand ClearSelectedLeds { get; } + + private void ExecuteClearSelectedLeds() + { + SelectedLeds.Clear(); + } + + private void CoreServiceOnFrameRendering(object? sender, FrameRenderingEventArgs e) + { + if (!SelectedLeds.Any()) + return; + + using SKPaint highlightPaint = new() {Color = SKColors.White}; + using SKPaint dimPaint = new() {Color = new SKColor(0, 0, 0, 192)}; + foreach (ArtemisLed artemisLed in Device.Leds) + e.Canvas.DrawRect(artemisLed.AbsoluteRectangle, SelectedLeds.Contains(artemisLed) ? highlightPaint : dimPaint); + } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Device/Tabs/DeviceInfoTabView.axaml.cs b/src/Artemis.UI/Screens/Device/Tabs/DeviceInfoTabView.axaml.cs index 21a067882..38c072053 100644 --- a/src/Artemis.UI/Screens/Device/Tabs/DeviceInfoTabView.axaml.cs +++ b/src/Artemis.UI/Screens/Device/Tabs/DeviceInfoTabView.axaml.cs @@ -1,9 +1,10 @@ using Avalonia.Controls; using Avalonia.Markup.Xaml; +using Avalonia.ReactiveUI; namespace Artemis.UI.Screens.Device { - public partial class DeviceInfoTabView : UserControl + public partial class DeviceInfoTabView : ReactiveUserControl { public DeviceInfoTabView() { diff --git a/src/Artemis.UI/Screens/Device/Tabs/DeviceLedsTabView.axaml.cs b/src/Artemis.UI/Screens/Device/Tabs/DeviceLedsTabView.axaml.cs index 2caa0fb1e..262741787 100644 --- a/src/Artemis.UI/Screens/Device/Tabs/DeviceLedsTabView.axaml.cs +++ b/src/Artemis.UI/Screens/Device/Tabs/DeviceLedsTabView.axaml.cs @@ -1,9 +1,10 @@ using Avalonia.Controls; using Avalonia.Markup.Xaml; +using Avalonia.ReactiveUI; namespace Artemis.UI.Screens.Device { - public partial class DeviceLedsTabView : UserControl + public partial class DeviceLedsTabView : ReactiveUserControl { public DeviceLedsTabView() { diff --git a/src/Artemis.UI/Screens/Device/Tabs/DevicePropertiesTabView.axaml b/src/Artemis.UI/Screens/Device/Tabs/DevicePropertiesTabView.axaml index 07aa6519a..556a94ee3 100644 --- a/src/Artemis.UI/Screens/Device/Tabs/DevicePropertiesTabView.axaml +++ b/src/Artemis.UI/Screens/Device/Tabs/DevicePropertiesTabView.axaml @@ -138,7 +138,12 @@ ClipValueToMinMax="True" /> - + @@ -168,7 +173,7 @@ UseFloatingWatermark="True" IsReadOnly="True" PointerReleased="InputElement_OnPointerReleased" - Padding="10 5 36 6"/> + Padding="10 5 36 6" /> @@ -181,16 +186,13 @@ - - - + + diff --git a/src/Artemis.UI/Screens/Device/Tabs/DevicePropertiesTabViewModel.cs b/src/Artemis.UI/Screens/Device/Tabs/DevicePropertiesTabViewModel.cs index ceeb37852..6f8a3e781 100644 --- a/src/Artemis.UI/Screens/Device/Tabs/DevicePropertiesTabViewModel.cs +++ b/src/Artemis.UI/Screens/Device/Tabs/DevicePropertiesTabViewModel.cs @@ -240,9 +240,9 @@ namespace Artemis.UI.Screens.Device HasRoomCategory = Device.Categories.Contains(DeviceCategory.Room); HasPeripheralsCategory = Device.Categories.Contains(DeviceCategory.Peripherals); - Device.RedScale = _initialRedScale; - Device.GreenScale = _initialGreenScale; - Device.BlueScale = _initialBlueScale; + RedScale = _initialRedScale * 100; + GreenScale = _initialGreenScale * 100; + BlueScale = _initialBlueScale * 100; } private bool GetCategory(DeviceCategory category) @@ -254,7 +254,7 @@ namespace Artemis.UI.Screens.Device { if (value && !_categories.Contains(category)) _categories.Add(category); - else + else if (!value) _categories.Remove(category); this.RaisePropertyChanged($"Has{category}Category"); diff --git a/src/Artemis.UI/Screens/Device/Tabs/InputMappingsTabView.axaml b/src/Artemis.UI/Screens/Device/Tabs/InputMappingsTabView.axaml index 4eb1d82af..704a9b52b 100644 --- a/src/Artemis.UI/Screens/Device/Tabs/InputMappingsTabView.axaml +++ b/src/Artemis.UI/Screens/Device/Tabs/InputMappingsTabView.axaml @@ -2,7 +2,73 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:device="clr-namespace:Artemis.UI.Screens.Device" + xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" - x:Class="Artemis.UI.Screens.Device.InputMappingsTabView"> - Welcome to Avalonia! - + x:Class="Artemis.UI.Screens.Device.InputMappingsTabView" + x:DataType="device:InputMappingsTabViewModel"> + + + + + + + + + Introduction + + + In some cases you may want Artemis to map key presses to different LEDs. + + + This is useful when your logical layout swaps keys around (like Hungarian layouts where the Z and Y keys are swapped). In this tab you can set up these custom input mappings, simply click on a LED and press a key, Artemis will from then on consider that LED pressed whenever you press the same key again. + + + + + Select a LED in the preview on the left side to get started... + + + + + Current target LED: + + + + Press the key you want to remap + + to ... + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Device/Tabs/InputMappingsTabView.axaml.cs b/src/Artemis.UI/Screens/Device/Tabs/InputMappingsTabView.axaml.cs index 5b74ae0bf..6cd004c92 100644 --- a/src/Artemis.UI/Screens/Device/Tabs/InputMappingsTabView.axaml.cs +++ b/src/Artemis.UI/Screens/Device/Tabs/InputMappingsTabView.axaml.cs @@ -1,9 +1,10 @@ using Avalonia.Controls; using Avalonia.Markup.Xaml; +using Avalonia.ReactiveUI; namespace Artemis.UI.Screens.Device { - public partial class InputMappingsTabView : UserControl + public partial class InputMappingsTabView : ReactiveUserControl { public InputMappingsTabView() { diff --git a/src/Artemis.UI/Screens/Device/Tabs/InputMappingsTabViewModel.cs b/src/Artemis.UI/Screens/Device/Tabs/InputMappingsTabViewModel.cs index e7ba90cda..83aa460aa 100644 --- a/src/Artemis.UI/Screens/Device/Tabs/InputMappingsTabViewModel.cs +++ b/src/Artemis.UI/Screens/Device/Tabs/InputMappingsTabViewModel.cs @@ -2,6 +2,7 @@ using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Linq; +using System.Reactive.Disposables; using Artemis.Core; using Artemis.Core.Services; using Artemis.UI.Exceptions; @@ -30,8 +31,23 @@ namespace Artemis.UI.Screens.Device Device = device; DisplayName = "Input Mappings"; InputMappings = new ObservableCollection<(ArtemisLed, ArtemisLed)>(); + + this.WhenActivated(d => + { + _selectedLeds.CollectionChanged += SelectedLedsOnCollectionChanged; + _inputService.KeyboardKeyUp += InputServiceOnKeyboardKeyUp; + UpdateInputMappings(); + + Disposable.Create(() => + { + _selectedLeds.CollectionChanged -= SelectedLedsOnCollectionChanged; + _inputService.KeyboardKeyUp -= InputServiceOnKeyboardKeyUp; + InputMappings.Clear(); + }).DisposeWith(d); + }); } + public ArtemisDevice Device { get; } public ArtemisLed? SelectedLed @@ -42,13 +58,13 @@ namespace Artemis.UI.Screens.Device public ObservableCollection<(ArtemisLed, ArtemisLed)> InputMappings { get; } - public void DeleteMapping(Tuple inputMapping) + public void DeleteMapping((ArtemisLed, ArtemisLed) inputMapping) { Device.InputMappings.Remove(inputMapping.Item1); UpdateInputMappings(); } - private void InputServiceOnKeyboardKeyUp(object sender, ArtemisKeyboardKeyEventArgs e) + private void InputServiceOnKeyboardKeyUp(object? sender, ArtemisKeyboardKeyEventArgs e) { if (SelectedLed == null || e.Led == null) return; @@ -64,7 +80,7 @@ namespace Artemis.UI.Screens.Device // Apply the new LED mapping Device.InputMappings[SelectedLed] = artemisLed; _rgbService.SaveDevice(Device); - // ((DeviceDialogViewModel) Parent).SelectedLeds.Clear(); + _selectedLeds.Clear(); UpdateInputMappings(); } @@ -74,35 +90,13 @@ namespace Artemis.UI.Screens.Device if (InputMappings.Any()) InputMappings.Clear(); - // InputMappings.AddRange(Device.InputMappings.Select(m => new Tuple(m.Key, m.Value))); + foreach ((ArtemisLed, ArtemisLed) tuple in Device.InputMappings.Select(m => (m.Key, m.Value))) + InputMappings.Add(tuple); } - private void SelectedLedsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + private void SelectedLedsOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { - // SelectedLed = ((DeviceDialogViewModel) Parent).SelectedLeds.FirstOrDefault(); + SelectedLed = _selectedLeds.FirstOrDefault(); } - // - // #region Overrides of Screen - // - // /// - // protected override void OnActivate() - // { - // UpdateInputMappings(); - // _inputService.KeyboardKeyUp += InputServiceOnKeyboardKeyUp; - // ((DeviceDialogViewModel) Parent).SelectedLeds.CollectionChanged += SelectedLedsOnCollectionChanged; - // - // base.OnActivate(); - // } - // - // /// - // protected override void OnDeactivate() - // { - // InputMappings.Clear(); - // _inputService.KeyboardKeyUp -= InputServiceOnKeyboardKeyUp; - // ((DeviceDialogViewModel) Parent).SelectedLeds.CollectionChanged -= SelectedLedsOnCollectionChanged; - // base.OnDeactivate(); - // } - // - // #endregion } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarView.axaml b/src/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarView.axaml index e6cd7d39d..10c365f83 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarView.axaml +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarView.axaml @@ -35,7 +35,7 @@ - + diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarViewModel.cs index 532441416..31589458d 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarViewModel.cs @@ -55,6 +55,7 @@ public class MenuBarViewModel : ActivatableViewModelBase AddFolder = ReactiveCommand.Create(ExecuteAddFolder); AddLayer = ReactiveCommand.Create(ExecuteAddLayer); ViewProperties = ReactiveCommand.CreateFromTask(ExecuteViewProperties, this.WhenAnyValue(vm => vm.ProfileConfiguration).Select(c => c != null)); + AdaptProfile = ReactiveCommand.CreateFromTask(ExecuteAdaptProfile, this.WhenAnyValue(vm => vm.ProfileConfiguration).Select(c => c != null)); ToggleSuspended = ReactiveCommand.Create(ExecuteToggleSuspended, this.WhenAnyValue(vm => vm.ProfileConfiguration).Select(c => c != null)); DeleteProfile = ReactiveCommand.CreateFromTask(ExecuteDeleteProfile, this.WhenAnyValue(vm => vm.ProfileConfiguration).Select(c => c != null)); ExportProfile = ReactiveCommand.CreateFromTask(ExecuteExportProfile, this.WhenAnyValue(vm => vm.ProfileConfiguration).Select(c => c != null)); @@ -68,6 +69,7 @@ public class MenuBarViewModel : ActivatableViewModelBase public ReactiveCommand AddLayer { get; } public ReactiveCommand ToggleSuspended { get; } public ReactiveCommand ViewProperties { get; } + public ReactiveCommand AdaptProfile { get; } public ReactiveCommand DeleteProfile { get; } public ReactiveCommand ExportProfile { get; } public ReactiveCommand DuplicateProfile { get; } @@ -121,6 +123,16 @@ public class MenuBarViewModel : ActivatableViewModelBase ("profileConfiguration", ProfileConfiguration) ); } + private async Task ExecuteAdaptProfile() + { + if (ProfileConfiguration?.Profile == null) + return; + + if (!await _windowService.ShowConfirmContentDialog("Adapt profile", "Are you sure you want to adapt the profile to your current surface? Layer assignments may change.")) + return; + + _profileService.AdaptProfile(ProfileConfiguration.Profile); + } private void ExecuteToggleSuspended() { diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/FolderTreeItemViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/FolderTreeItemViewModel.cs index 13c9deefd..fbf182b06 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/FolderTreeItemViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/FolderTreeItemViewModel.cs @@ -56,6 +56,19 @@ public class FolderTreeItemViewModel : TreeItemViewModel ProfileEditorService.ExecuteCommand(new AddProfileElement(pasted, parent, Folder.Order - 1)); } + private async Task ExecutePasteInto() + { + RenderProfileElement? pasted = await Folder.PasteChildFromClipboard(); + if (pasted == null) + return; + + // If the target contains an element with the same name, affix with " - copy" + if (Folder.Children.Any(c => c.Name == pasted.Name)) + pasted.Name = Folder.GetNewFolderName(pasted.Name + " - copy"); + + ProfileEditorService.ExecuteCommand(new AddProfileElement(pasted, Folder, 0)); + } + /// public override bool SupportsChildren => true; diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml index 6ed6ef893..22cff3a34 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml @@ -112,7 +112,7 @@ - + @@ -128,7 +128,7 @@ - + diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/Keyframes/TimelineKeyframeView.axaml b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/Keyframes/TimelineKeyframeView.axaml index 38ad8293c..49836e813 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/Keyframes/TimelineKeyframeView.axaml +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/Keyframes/TimelineKeyframeView.axaml @@ -6,8 +6,7 @@ xmlns:timeline="clr-namespace:Artemis.UI.Screens.ProfileEditor.Properties.Timeline" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Keyframes.TimelineKeyframeView" - ClipToBounds="False" - Height="{DynamicResource RailsHeight}"> + ClipToBounds="False"> - + @@ -68,7 +67,7 @@ - + diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelineGroupView.axaml b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelineGroupView.axaml index b63e8f7bb..e83d92de2 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelineGroupView.axaml +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelineGroupView.axaml @@ -9,7 +9,7 @@ x:DataType="timeline:TimelineGroupViewModel"> @@ -21,16 +21,17 @@ - + Margin="-5 0 0 0" /> diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelineGroupViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelineGroupViewModel.cs index 76c010225..a8f8f35fc 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelineGroupViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelineGroupViewModel.cs @@ -11,7 +11,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline; public class TimelineGroupViewModel : ActivatableViewModelBase { private ObservableCollection? _keyframePositions; - private int _pixelsPerSecond; + private ObservableAsPropertyHelper? _pixelsPerSecond; public TimelineGroupViewModel(PropertyGroupViewModel propertyGroupViewModel, IProfileEditorService profileEditorService) { @@ -19,16 +19,16 @@ public class TimelineGroupViewModel : ActivatableViewModelBase this.WhenActivated(d => { - profileEditorService.PixelsPerSecond.Subscribe(p => - { - _pixelsPerSecond = p; - UpdateKeyframePositions(); - }).DisposeWith(d); - this.WhenAnyValue(vm => vm.PropertyGroupViewModel.IsExpanded).Subscribe(_ => UpdateKeyframePositions()).DisposeWith(d); + _pixelsPerSecond = profileEditorService.PixelsPerSecond.ToProperty(this, vm => vm.PixelsPerSecond).DisposeWith(d); + profileEditorService.PixelsPerSecond.Subscribe(p => UpdateKeyframePositions()).DisposeWith(d); PropertyGroupViewModel.WhenAnyValue(vm => vm.IsExpanded).Subscribe(_ => this.RaisePropertyChanged(nameof(Children))).DisposeWith(d); + PropertyGroupViewModel.WhenAnyValue(vm => vm.IsExpanded).Subscribe(_ => UpdateKeyframePositions()).DisposeWith(d); + this.WhenAnyValue(vm => vm.PixelsPerSecond).Subscribe(_ => UpdateKeyframePositions()).DisposeWith(d); + UpdateKeyframePositions(); }); } + public int PixelsPerSecond => _pixelsPerSecond?.Value ?? 0; public PropertyGroupViewModel PropertyGroupViewModel { get; } public ObservableCollection? Children => PropertyGroupViewModel.IsExpanded ? PropertyGroupViewModel.Children : null; @@ -43,6 +43,6 @@ public class TimelineGroupViewModel : ActivatableViewModelBase { KeyframePositions = new ObservableCollection(PropertyGroupViewModel .GetAllKeyframeViewModels(false) - .Select(p => p.Position.TotalSeconds * _pixelsPerSecond)); + .Select(p => p.Position.TotalSeconds * PixelsPerSecond)); } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelinePropertyView.axaml b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelinePropertyView.axaml index ff04b5406..2184894c9 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelinePropertyView.axaml +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelinePropertyView.axaml @@ -4,7 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Timeline.TimelinePropertyView"> - + @@ -14,6 +14,7 @@