mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-11 19:36:28 +00:00
Sidebar - Refactored category VM to fix all issues with it I could find
Sidebar - Streamlined design Sidebar - Increase width on wide window sizes Profile editor - Implement File and Help menus
This commit is contained in:
1 parent
35f83e58e5
commit
78479c0fa2
79 files changed
+1093
-946
No files matched your search
+2
-2
@@ -27,7 +27,7 @@
|
||||
HorizontalAlignment="Right"
|
||||
Margin="10"
|
||||
Command="{Binding OpenEditor}">
|
||||
<avalonia:MaterialIcon Kind="OpenInNew"></avalonia:MaterialIcon>
|
||||
<avalonia:MaterialIcon Kind="OpenInNew" />
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<TextBlock TextWrapping="Wrap" HorizontalAlignment="Center" TextAlignment="Center" Foreground="{DynamicResource TextFillColorSecondary}">
|
||||
When you enable data bindings you can no longer use keyframes or normal values for this property.
|
||||
</TextBlock>
|
||||
<controls:HyperlinkButton HorizontalAlignment="Center"
|
||||
<controls:HyperlinkButton HorizontalAlignment="Center"
|
||||
NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/profiles/data-bindings"
|
||||
Margin="0 10">
|
||||
Learn more
|
||||
|
||||
+12
-13
@@ -1,18 +1,17 @@
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.DataBinding
|
||||
{
|
||||
public partial class DataBindingView : ReactiveUserControl<DataBindingViewModel>
|
||||
{
|
||||
public DataBindingView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.DataBinding;
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
public class DataBindingView : ReactiveUserControl<DataBindingViewModel>
|
||||
{
|
||||
public DataBindingView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
+11
-11
@@ -11,7 +11,7 @@
|
||||
x:DataType="dialogs:AddEffectViewModel"
|
||||
Width="500">
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<TextBox Name="SearchBox" Text="{CompiledBinding SearchText}" Margin="0 0 0 15" Watermark="Search"></TextBox>
|
||||
<TextBox Name="SearchBox" Text="{CompiledBinding SearchText}" Margin="0 0 0 15" Watermark="Search" />
|
||||
<ListBox Name="EffectDescriptorsList"
|
||||
Grid.Row="1"
|
||||
Items="{CompiledBinding LayerEffectDescriptors}"
|
||||
@@ -21,17 +21,17 @@
|
||||
<ListBox.DataTemplates>
|
||||
<DataTemplate DataType="{x:Type layerEffects:LayerEffectDescriptor}">
|
||||
<Grid RowDefinitions="Auto,*"
|
||||
ColumnDefinitions="Auto,Auto"
|
||||
Background="Transparent"
|
||||
ColumnDefinitions="Auto,Auto"
|
||||
Background="Transparent"
|
||||
PointerReleased="InputElement_OnPointerReleased"
|
||||
Margin="0 4"
|
||||
VerticalAlignment="Center">
|
||||
<shared:ArtemisIcon Grid.Column="0"
|
||||
Grid.RowSpan="2"
|
||||
<shared:ArtemisIcon Grid.Column="0"
|
||||
Grid.RowSpan="2"
|
||||
Icon="{CompiledBinding Icon}"
|
||||
Width="24"
|
||||
Height="24"
|
||||
VerticalAlignment="Center"
|
||||
Height="24"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0 0 15 0" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Grid.Row="0"
|
||||
@@ -51,14 +51,14 @@
|
||||
</DataTemplate>
|
||||
</ListBox.DataTemplates>
|
||||
</ListBox>
|
||||
<Grid Grid.Row="1" Height="300">
|
||||
<Grid Grid.Row="1" Height="300">
|
||||
<StackPanel VerticalAlignment="Center"
|
||||
Spacing="20"
|
||||
IsVisible="{CompiledBinding !LayerEffectDescriptors.Count}">
|
||||
<avalonia:MaterialIcon Kind="CloseCircle" Width="32" Height="32"></avalonia:MaterialIcon>
|
||||
<avalonia:MaterialIcon Kind="CloseCircle" Width="32" Height="32" />
|
||||
<TextBlock Classes="h5" TextAlignment="Center">None of the effects match your search</TextBlock>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
+3
-4
@@ -14,8 +14,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Properties.Dialogs;
|
||||
|
||||
public class AddEffectViewModel : ContentDialogViewModelBase
|
||||
{
|
||||
private readonly RenderProfileElement _renderProfileElement;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly RenderProfileElement _renderProfileElement;
|
||||
private string? _searchText;
|
||||
|
||||
public AddEffectViewModel(RenderProfileElement renderProfileElement, IProfileEditorService profileEditorService, ILayerEffectService layerEffectService)
|
||||
@@ -39,7 +39,7 @@ public class AddEffectViewModel : ContentDialogViewModelBase
|
||||
public string? SearchText
|
||||
{
|
||||
get => _searchText;
|
||||
set => this.RaiseAndSetIfChanged(ref _searchText, value);
|
||||
set => RaiseAndSetIfChanged(ref _searchText, value);
|
||||
}
|
||||
|
||||
public void AddLayerEffect(LayerEffectDescriptor descriptor)
|
||||
@@ -58,5 +58,4 @@ public class AddEffectViewModel : ContentDialogViewModelBase
|
||||
return data => data.DisplayName.Contains(search, StringComparison.InvariantCultureIgnoreCase) ||
|
||||
data.Description.Contains(search, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
xmlns:controls="clr-namespace:Artemis.UI.Controls"
|
||||
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.Properties"
|
||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="1200" d:DesignHeight="350"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.Properties.PropertiesView"
|
||||
x:DataType="local:PropertiesViewModel">
|
||||
@@ -13,7 +12,7 @@
|
||||
<StyleInclude Source="/Screens/ProfileEditor/Panels/Properties/Timeline/Segments/Segment.axaml" />
|
||||
</UserControl.Styles>
|
||||
<UserControl.Resources>
|
||||
<converters:DoubleToGridLengthConverter x:Key="DoubleToGridLengthConverter"></converters:DoubleToGridLengthConverter>
|
||||
<converters:DoubleToGridLengthConverter x:Key="DoubleToGridLengthConverter" />
|
||||
</UserControl.Resources>
|
||||
<Grid Name="ContainerGrid">
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -89,8 +88,7 @@
|
||||
StartPoint="0,0"
|
||||
EndPoint="{CompiledBinding #ContainerGrid.Bounds.BottomLeft}"
|
||||
StrokeThickness="2"
|
||||
Stroke="{DynamicResource SystemAccentColorLight1}">
|
||||
</Line>
|
||||
Stroke="{DynamicResource SystemAccentColorLight1}" />
|
||||
|
||||
<Line Name="StartSegmentLine"
|
||||
Canvas.Left="{CompiledBinding TimelineViewModel.StartSegmentViewModel.EndX}"
|
||||
@@ -100,8 +98,7 @@
|
||||
StrokeThickness="2"
|
||||
Stroke="{DynamicResource SystemAccentColorLight1}"
|
||||
StrokeDashArray="6,2"
|
||||
Opacity="0.5">
|
||||
</Line>
|
||||
Opacity="0.5" />
|
||||
<Line Name="MainSegmentLine"
|
||||
Canvas.Left="{CompiledBinding TimelineViewModel.MainSegmentViewModel.EndX}"
|
||||
IsVisible="{CompiledBinding !TimelineViewModel.MainSegmentViewModel.ShowAddMain}"
|
||||
@@ -110,8 +107,7 @@
|
||||
StrokeThickness="2"
|
||||
Stroke="{DynamicResource SystemAccentColorLight1}"
|
||||
StrokeDashArray="6,2"
|
||||
Opacity="0.5">
|
||||
</Line>
|
||||
Opacity="0.5" />
|
||||
<Line Name="EndSegmentLine"
|
||||
Canvas.Left="{CompiledBinding TimelineViewModel.EndSegmentViewModel.EndX}"
|
||||
IsVisible="{CompiledBinding !TimelineViewModel.MainSegmentViewModel.ShowAddEnd}"
|
||||
@@ -120,8 +116,7 @@
|
||||
StrokeThickness="2"
|
||||
Stroke="{DynamicResource SystemAccentColorLight1}"
|
||||
StrokeDashArray="6,2"
|
||||
Opacity="0.5">
|
||||
</Line>
|
||||
Opacity="0.5" />
|
||||
|
||||
<!-- Timeline segments -->
|
||||
<ContentControl Canvas.Left="{CompiledBinding TimelineViewModel.EndSegmentViewModel.StartX}"
|
||||
@@ -142,8 +137,7 @@
|
||||
PointerReleased="TimelineCaret_OnPointerReleased"
|
||||
PointerMoved="TimelineCaret_OnPointerMoved"
|
||||
Points="-8,0 -8,8 0,20, 8,8 8,0"
|
||||
Fill="{DynamicResource SystemAccentColorLight1}">
|
||||
</Polygon>
|
||||
Fill="{DynamicResource SystemAccentColorLight1}" />
|
||||
</Canvas>
|
||||
|
||||
<ScrollViewer Grid.Row="1"
|
||||
|
||||
@@ -15,10 +15,8 @@ using Artemis.UI.Screens.ProfileEditor.Playback;
|
||||
using Artemis.UI.Screens.ProfileEditor.Properties.DataBinding;
|
||||
using Artemis.UI.Screens.ProfileEditor.Properties.Dialogs;
|
||||
using Artemis.UI.Screens.ProfileEditor.Properties.Timeline;
|
||||
using Artemis.UI.Screens.Sidebar;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Shared.Services.Builders;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using ReactiveUI;
|
||||
|
||||
@@ -28,11 +26,11 @@ public class PropertiesViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private readonly Dictionary<LayerPropertyGroup, PropertyGroupViewModel> _cachedPropertyViewModels;
|
||||
private readonly IDataBindingVmFactory _dataBindingVmFactory;
|
||||
private readonly IWindowService _windowService;
|
||||
private readonly ILayerEffectService _layerEffectService;
|
||||
private readonly ILayerPropertyVmFactory _layerPropertyVmFactory;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly IWindowService _windowService;
|
||||
private DataBindingViewModel? _backgroundDataBindingViewModel;
|
||||
private DataBindingViewModel? _dataBindingViewModel;
|
||||
private ObservableAsPropertyHelper<ILayerProperty?>? _layerProperty;
|
||||
|
||||
+1
-1
@@ -16,4 +16,4 @@
|
||||
Margin="0 0 10 0" />
|
||||
<TextBlock Text="{CompiledBinding Description}" />
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
</UserControl>
|
||||
+12
-13
@@ -1,18 +1,17 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Keyframes
|
||||
{
|
||||
public partial class TimelineEasingView : UserControl
|
||||
{
|
||||
public TimelineEasingView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Keyframes;
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
public class TimelineEasingView : UserControl
|
||||
{
|
||||
public TimelineEasingView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -44,8 +44,8 @@
|
||||
</Template>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Command" Value="{Binding $parent[UserControl].DataContext.SelectEasingFunction}"></Setter>
|
||||
<Setter Property="CommandParameter" Value="{Binding EasingFunction}"></Setter>
|
||||
<Setter Property="Command" Value="{Binding $parent[UserControl].DataContext.SelectEasingFunction}" />
|
||||
<Setter Property="CommandParameter" Value="{Binding EasingFunction}" />
|
||||
</Style>
|
||||
</MenuItem.Styles>
|
||||
<MenuItem.Icon>
|
||||
|
||||
+3
-1
@@ -8,9 +8,9 @@ namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Keyframes;
|
||||
|
||||
public class TimelineKeyframeView : ReactiveUserControl<ITimelineKeyframeViewModel>
|
||||
{
|
||||
private bool _moved;
|
||||
private TimelinePropertyView? _timelinePropertyView;
|
||||
private TimelineView? _timelineView;
|
||||
private bool _moved;
|
||||
|
||||
public TimelineKeyframeView()
|
||||
{
|
||||
@@ -70,7 +70,9 @@ public class TimelineKeyframeView : ReactiveUserControl<ITimelineKeyframeViewMod
|
||||
|
||||
// Select the keyframe if the user didn't move
|
||||
if (!_moved)
|
||||
{
|
||||
ViewModel.Select(e.KeyModifiers.HasFlag(KeyModifiers.Shift), e.KeyModifiers.HasFlag(KeyModifiers.Control));
|
||||
}
|
||||
else
|
||||
{
|
||||
TimeSpan time = ViewModel.GetTimeSpanAtPosition(e.GetPosition(_timelinePropertyView).X);
|
||||
|
||||
+8
-9
@@ -15,10 +15,10 @@ namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Keyframes;
|
||||
public class TimelineKeyframeViewModel<T> : ActivatableViewModelBase, ITimelineKeyframeViewModel
|
||||
{
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private ObservableAsPropertyHelper<bool>? _isSelected;
|
||||
private string _timestamp;
|
||||
|
||||
private double _x;
|
||||
private string _timestamp;
|
||||
private ObservableAsPropertyHelper<bool>? _isSelected;
|
||||
|
||||
public TimelineKeyframeViewModel(LayerPropertyKeyframe<T> layerPropertyKeyframe, IProfileEditorService profileEditorService)
|
||||
{
|
||||
@@ -56,16 +56,16 @@ public class TimelineKeyframeViewModel<T> : ActivatableViewModelBase, ITimelineK
|
||||
set => RaiseAndSetIfChanged(ref _timestamp, value);
|
||||
}
|
||||
|
||||
public bool IsSelected => _isSelected?.Value ?? false;
|
||||
public TimeSpan Position => LayerPropertyKeyframe.Position;
|
||||
public ILayerPropertyKeyframe Keyframe => LayerPropertyKeyframe;
|
||||
|
||||
public void Update()
|
||||
{
|
||||
X = _pixelsPerSecond * LayerPropertyKeyframe.Position.TotalSeconds;
|
||||
Timestamp = $"{Math.Floor(LayerPropertyKeyframe.Position.TotalSeconds):00}.{LayerPropertyKeyframe.Position.Milliseconds:000}";
|
||||
}
|
||||
|
||||
public bool IsSelected => _isSelected?.Value ?? false;
|
||||
public TimeSpan Position => LayerPropertyKeyframe.Position;
|
||||
public ILayerPropertyKeyframe Keyframe => LayerPropertyKeyframe;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Select(bool expand, bool toggle)
|
||||
{
|
||||
@@ -157,12 +157,11 @@ public class TimelineKeyframeViewModel<T> : ActivatableViewModelBase, ITimelineK
|
||||
.Cast<Easings.Functions>()
|
||||
.Select(e => new TimelineEasingViewModel(e, Keyframe)));
|
||||
}
|
||||
|
||||
|
||||
public void SelectEasingFunction(Easings.Functions easingFunction)
|
||||
{
|
||||
_profileEditorService.ExecuteCommand(new ChangeKeyframeEasing(Keyframe, easingFunction));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
||||
+3
-3
@@ -28,7 +28,7 @@
|
||||
IsVisible="{CompiledBinding ShowAddMain}">
|
||||
<avalonia:MaterialIcon Kind="PlusCircle" />
|
||||
</Button>
|
||||
|
||||
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" ClipToBounds="True">
|
||||
<TextBlock Name="SegmentTitle"
|
||||
FontSize="13"
|
||||
@@ -43,7 +43,7 @@
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
||||
<Rectangle Name="KeyframeDragVisualRight"
|
||||
<Rectangle Name="KeyframeDragVisualRight"
|
||||
Grid.Column="3"
|
||||
Classes="resize-visual" />
|
||||
<Rectangle Name="KeyframeDragAnchor"
|
||||
@@ -52,7 +52,7 @@
|
||||
PointerPressed="KeyframeDragAnchor_OnPointerPressed"
|
||||
PointerMoved="KeyframeDragAnchor_OnPointerMoved"
|
||||
PointerReleased="KeyframeDragAnchor_OnPointerReleased"
|
||||
ToolTip.Tip="{CompiledBinding EndTimestamp}"/>
|
||||
ToolTip.Tip="{CompiledBinding EndTimestamp}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
||||
+34
-35
@@ -4,47 +4,46 @@ using Avalonia.Input;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Segments
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Segments;
|
||||
|
||||
public class EndSegmentView : ReactiveUserControl<EndSegmentViewModel>
|
||||
{
|
||||
public partial class EndSegmentView : ReactiveUserControl<EndSegmentViewModel>
|
||||
private readonly Rectangle _keyframeDragAnchor;
|
||||
private double _dragOffset;
|
||||
|
||||
public EndSegmentView()
|
||||
{
|
||||
private readonly Rectangle _keyframeDragAnchor;
|
||||
private double _dragOffset;
|
||||
InitializeComponent();
|
||||
_keyframeDragAnchor = this.Get<Rectangle>("KeyframeDragAnchor");
|
||||
}
|
||||
|
||||
public EndSegmentView()
|
||||
{
|
||||
InitializeComponent();
|
||||
_keyframeDragAnchor = this.Get<Rectangle>("KeyframeDragAnchor");
|
||||
}
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
private void KeyframeDragAnchor_OnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
return;
|
||||
e.Pointer.Capture(_keyframeDragAnchor);
|
||||
|
||||
private void KeyframeDragAnchor_OnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
return;
|
||||
e.Pointer.Capture(_keyframeDragAnchor);
|
||||
_dragOffset = ViewModel.Width - e.GetCurrentPoint(this).Position.X;
|
||||
ViewModel.StartResize();
|
||||
}
|
||||
|
||||
_dragOffset = ViewModel.Width - e.GetCurrentPoint(this).Position.X;
|
||||
ViewModel.StartResize();
|
||||
}
|
||||
private void KeyframeDragAnchor_OnPointerMoved(object? sender, PointerEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !ReferenceEquals(e.Pointer.Captured, _keyframeDragAnchor))
|
||||
return;
|
||||
ViewModel.UpdateResize(e.GetCurrentPoint(this).Position.X + _dragOffset);
|
||||
}
|
||||
|
||||
private void KeyframeDragAnchor_OnPointerMoved(object? sender, PointerEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !ReferenceEquals(e.Pointer.Captured, _keyframeDragAnchor))
|
||||
return;
|
||||
ViewModel.UpdateResize(e.GetCurrentPoint(this).Position.X + _dragOffset);
|
||||
}
|
||||
|
||||
private void KeyframeDragAnchor_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !ReferenceEquals(e.Pointer.Captured, _keyframeDragAnchor))
|
||||
return;
|
||||
e.Pointer.Capture(null);
|
||||
ViewModel.FinishResize(e.GetCurrentPoint(this).Position.X + _dragOffset);
|
||||
}
|
||||
private void KeyframeDragAnchor_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !ReferenceEquals(e.Pointer.Captured, _keyframeDragAnchor))
|
||||
return;
|
||||
e.Pointer.Capture(null);
|
||||
ViewModel.FinishResize(e.GetCurrentPoint(this).Position.X + _dragOffset);
|
||||
}
|
||||
}
|
||||
+7
-8
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
@@ -13,14 +11,14 @@ namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Segments;
|
||||
public class EndSegmentViewModel : TimelineSegmentViewModel
|
||||
{
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private RenderProfileElement? _profileElement;
|
||||
private int _pixelsPerSecond;
|
||||
private TimeSpan _time;
|
||||
private ObservableAsPropertyHelper<double>? _start;
|
||||
private readonly ObservableAsPropertyHelper<double> _width;
|
||||
private ObservableAsPropertyHelper<double>? _end;
|
||||
private ObservableAsPropertyHelper<string?>? _endTimestamp;
|
||||
private readonly ObservableAsPropertyHelper<double> _width;
|
||||
private TimeSpan _initialLength;
|
||||
private int _pixelsPerSecond;
|
||||
private RenderProfileElement? _profileElement;
|
||||
private ObservableAsPropertyHelper<double>? _start;
|
||||
private TimeSpan _time;
|
||||
|
||||
|
||||
public EndSegmentViewModel(IProfileEditorService profileEditorService) : base(profileEditorService)
|
||||
@@ -59,6 +57,7 @@ public class EndSegmentViewModel : TimelineSegmentViewModel
|
||||
public override double StartX => _start?.Value ?? 0;
|
||||
public override TimeSpan End => _profileElement?.Timeline.EndSegmentEndPosition ?? TimeSpan.Zero;
|
||||
public override double EndX => _end?.Value ?? 0;
|
||||
|
||||
public override TimeSpan Length
|
||||
{
|
||||
get => _profileElement?.Timeline.EndSegmentLength ?? TimeSpan.Zero;
|
||||
@@ -70,7 +69,7 @@ public class EndSegmentViewModel : TimelineSegmentViewModel
|
||||
}
|
||||
|
||||
public override double Width => _width.Value;
|
||||
|
||||
|
||||
public override string? EndTimestamp => _endTimestamp?.Value;
|
||||
public override ResizeTimelineSegment.SegmentType Type => ResizeTimelineSegment.SegmentType.End;
|
||||
}
|
||||
+2
-2
@@ -58,7 +58,7 @@
|
||||
<avalonia:MaterialIcon Kind="PlusCircle" />
|
||||
</Button>
|
||||
|
||||
<Rectangle Name="KeyframeDragVisual"
|
||||
<Rectangle Name="KeyframeDragVisual"
|
||||
Grid.Column="4"
|
||||
Classes="resize-visual" />
|
||||
<Rectangle Name="KeyframeDragAnchor"
|
||||
@@ -67,7 +67,7 @@
|
||||
PointerPressed="KeyframeDragAnchor_OnPointerPressed"
|
||||
PointerMoved="KeyframeDragAnchor_OnPointerMoved"
|
||||
PointerReleased="KeyframeDragAnchor_OnPointerReleased"
|
||||
ToolTip.Tip="{CompiledBinding EndTimestamp}"/>
|
||||
ToolTip.Tip="{CompiledBinding EndTimestamp}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
||||
+43
-44
@@ -4,59 +4,58 @@ using Avalonia.Input;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Segments
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Segments;
|
||||
|
||||
public class MainSegmentView : ReactiveUserControl<MainSegmentViewModel>
|
||||
{
|
||||
public partial class MainSegmentView : ReactiveUserControl<MainSegmentViewModel>
|
||||
private readonly Rectangle _keyframeDragAnchor;
|
||||
private double _dragOffset;
|
||||
|
||||
public MainSegmentView()
|
||||
{
|
||||
private readonly Rectangle _keyframeDragAnchor;
|
||||
private double _dragOffset;
|
||||
InitializeComponent();
|
||||
_keyframeDragAnchor = this.Get<Rectangle>("KeyframeDragAnchor");
|
||||
}
|
||||
|
||||
public MainSegmentView()
|
||||
{
|
||||
InitializeComponent();
|
||||
_keyframeDragAnchor = this.Get<Rectangle>("KeyframeDragAnchor");
|
||||
}
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
private void KeyframeDragAnchor_OnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
return;
|
||||
e.Pointer.Capture(_keyframeDragAnchor);
|
||||
|
||||
private void KeyframeDragAnchor_OnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
return;
|
||||
e.Pointer.Capture(_keyframeDragAnchor);
|
||||
_dragOffset = ViewModel.Width - e.GetCurrentPoint(this).Position.X;
|
||||
ViewModel.StartResize();
|
||||
}
|
||||
|
||||
_dragOffset = ViewModel.Width - e.GetCurrentPoint(this).Position.X;
|
||||
ViewModel.StartResize();
|
||||
}
|
||||
private void KeyframeDragAnchor_OnPointerMoved(object? sender, PointerEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !ReferenceEquals(e.Pointer.Captured, _keyframeDragAnchor))
|
||||
return;
|
||||
ViewModel.UpdateResize(e.GetCurrentPoint(this).Position.X + _dragOffset);
|
||||
}
|
||||
|
||||
private void KeyframeDragAnchor_OnPointerMoved(object? sender, PointerEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !ReferenceEquals(e.Pointer.Captured, _keyframeDragAnchor))
|
||||
return;
|
||||
ViewModel.UpdateResize(e.GetCurrentPoint(this).Position.X + _dragOffset);
|
||||
}
|
||||
private void KeyframeDragAnchor_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !ReferenceEquals(e.Pointer.Captured, _keyframeDragAnchor))
|
||||
return;
|
||||
e.Pointer.Capture(null);
|
||||
ViewModel.FinishResize(e.GetCurrentPoint(this).Position.X + _dragOffset);
|
||||
}
|
||||
|
||||
private void KeyframeDragAnchor_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !ReferenceEquals(e.Pointer.Captured, _keyframeDragAnchor))
|
||||
return;
|
||||
e.Pointer.Capture(null);
|
||||
ViewModel.FinishResize(e.GetCurrentPoint(this).Position.X + _dragOffset);
|
||||
}
|
||||
private void KeyframeDragStartAnchor_OnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
private void KeyframeDragStartAnchor_OnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
}
|
||||
private void KeyframeDragStartAnchor_OnPointerMoved(object? sender, PointerEventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
private void KeyframeDragStartAnchor_OnPointerMoved(object? sender, PointerEventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
private void KeyframeDragStartAnchor_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
}
|
||||
private void KeyframeDragStartAnchor_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
}
|
||||
}
|
||||
+10
-11
@@ -6,23 +6,22 @@
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
|
||||
<Style Selector="ContentControl.segment-content-control">
|
||||
</Style>
|
||||
<Style Selector="ContentControl.segment-content-control" />
|
||||
|
||||
<Style Selector="Border.segment-container">
|
||||
<Setter Property="Height" Value="18"></Setter>
|
||||
<Setter Property="Height" Value="18" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="Rectangle.resize-visual">
|
||||
<Setter Property="Fill" Value="{DynamicResource SystemAccentColorLight2}"/>
|
||||
<Setter Property="Width" Value="4"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Right"/>
|
||||
<Setter Property="Fill" Value="{DynamicResource SystemAccentColorLight2}" />
|
||||
<Setter Property="Width" Value="4" />
|
||||
<Setter Property="HorizontalAlignment" Value="Right" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="Rectangle.resize-anchor">
|
||||
<Setter Property="Fill" Value="Transparent"/>
|
||||
<Setter Property="Width" Value="10"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Right"/>
|
||||
<Setter Property="Cursor" Value="SizeWestEast"/>
|
||||
<Setter Property="Fill" Value="Transparent" />
|
||||
<Setter Property="Width" Value="10" />
|
||||
<Setter Property="HorizontalAlignment" Value="Right" />
|
||||
<Setter Property="Cursor" Value="SizeWestEast" />
|
||||
</Style>
|
||||
</Styles>
|
||||
</Styles>
|
||||
+1
-2
@@ -2,7 +2,6 @@
|
||||
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:system="clr-namespace:System;assembly=System.Runtime"
|
||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
xmlns:segments="clr-namespace:Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Segments"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="18"
|
||||
@@ -49,7 +48,7 @@
|
||||
PointerPressed="KeyframeDragAnchor_OnPointerPressed"
|
||||
PointerMoved="KeyframeDragAnchor_OnPointerMoved"
|
||||
PointerReleased="KeyframeDragAnchor_OnPointerReleased"
|
||||
ToolTip.Tip="{CompiledBinding EndTimestamp}"/>
|
||||
ToolTip.Tip="{CompiledBinding EndTimestamp}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
|
||||
+34
-35
@@ -4,47 +4,46 @@ using Avalonia.Input;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Segments
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Segments;
|
||||
|
||||
public class StartSegmentView : ReactiveUserControl<StartSegmentViewModel>
|
||||
{
|
||||
public partial class StartSegmentView : ReactiveUserControl<StartSegmentViewModel>
|
||||
private readonly Rectangle _keyframeDragAnchor;
|
||||
private double _dragOffset;
|
||||
|
||||
public StartSegmentView()
|
||||
{
|
||||
private readonly Rectangle _keyframeDragAnchor;
|
||||
private double _dragOffset;
|
||||
InitializeComponent();
|
||||
_keyframeDragAnchor = this.Get<Rectangle>("KeyframeDragAnchor");
|
||||
}
|
||||
|
||||
public StartSegmentView()
|
||||
{
|
||||
InitializeComponent();
|
||||
_keyframeDragAnchor = this.Get<Rectangle>("KeyframeDragAnchor");
|
||||
}
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
private void KeyframeDragAnchor_OnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
return;
|
||||
e.Pointer.Capture(_keyframeDragAnchor);
|
||||
|
||||
private void KeyframeDragAnchor_OnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
return;
|
||||
e.Pointer.Capture(_keyframeDragAnchor);
|
||||
_dragOffset = ViewModel.Width - e.GetCurrentPoint(this).Position.X;
|
||||
ViewModel.StartResize();
|
||||
}
|
||||
|
||||
_dragOffset = ViewModel.Width - e.GetCurrentPoint(this).Position.X;
|
||||
ViewModel.StartResize();
|
||||
}
|
||||
private void KeyframeDragAnchor_OnPointerMoved(object? sender, PointerEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !ReferenceEquals(e.Pointer.Captured, _keyframeDragAnchor))
|
||||
return;
|
||||
ViewModel.UpdateResize(e.GetCurrentPoint(this).Position.X + _dragOffset);
|
||||
}
|
||||
|
||||
private void KeyframeDragAnchor_OnPointerMoved(object? sender, PointerEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !ReferenceEquals(e.Pointer.Captured, _keyframeDragAnchor))
|
||||
return;
|
||||
ViewModel.UpdateResize(e.GetCurrentPoint(this).Position.X + _dragOffset);
|
||||
}
|
||||
|
||||
private void KeyframeDragAnchor_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !ReferenceEquals(e.Pointer.Captured, _keyframeDragAnchor))
|
||||
return;
|
||||
e.Pointer.Capture(null);
|
||||
ViewModel.FinishResize(e.GetCurrentPoint(this).Position.X + _dragOffset);
|
||||
}
|
||||
private void KeyframeDragAnchor_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
if (ViewModel == null || !ReferenceEquals(e.Pointer.Captured, _keyframeDragAnchor))
|
||||
return;
|
||||
e.Pointer.Capture(null);
|
||||
ViewModel.FinishResize(e.GetCurrentPoint(this).Position.X + _dragOffset);
|
||||
}
|
||||
}
|
||||
+5
-7
@@ -1,12 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
||||
using Avalonia.Controls.Mixins;
|
||||
using Castle.DynamicProxy.Generators;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Segments;
|
||||
@@ -14,13 +11,13 @@ namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Segments;
|
||||
public class StartSegmentViewModel : TimelineSegmentViewModel
|
||||
{
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private RenderProfileElement? _profileElement;
|
||||
private int _pixelsPerSecond;
|
||||
private TimeSpan _time;
|
||||
private readonly ObservableAsPropertyHelper<double> _width;
|
||||
private ObservableAsPropertyHelper<double>? _end;
|
||||
private ObservableAsPropertyHelper<string?>? _endTimestamp;
|
||||
private readonly ObservableAsPropertyHelper<double> _width;
|
||||
private TimeSpan _initialLength;
|
||||
private int _pixelsPerSecond;
|
||||
private RenderProfileElement? _profileElement;
|
||||
private TimeSpan _time;
|
||||
|
||||
public StartSegmentViewModel(IProfileEditorService profileEditorService) : base(profileEditorService)
|
||||
{
|
||||
@@ -52,6 +49,7 @@ public class StartSegmentViewModel : TimelineSegmentViewModel
|
||||
public override double StartX => 0;
|
||||
public override TimeSpan End => _profileElement?.Timeline.StartSegmentEndPosition ?? TimeSpan.Zero;
|
||||
public override double EndX => _end?.Value ?? 0;
|
||||
|
||||
public override TimeSpan Length
|
||||
{
|
||||
get => _profileElement?.Timeline.StartSegmentLength ?? TimeSpan.Zero;
|
||||
|
||||
+7
-5
@@ -15,14 +15,14 @@ public abstract class TimelineSegmentViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private static readonly TimeSpan NewSegmentLength = TimeSpan.FromSeconds(2);
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private RenderProfileElement? _profileElement;
|
||||
private TimeSpan _initialLength;
|
||||
private readonly Dictionary<ILayerPropertyKeyframe, TimeSpan> _originalKeyframePositions = new();
|
||||
private int _pixelsPerSecond;
|
||||
private Dictionary<ILayerPropertyKeyframe, TimeSpan> _originalKeyframePositions = new();
|
||||
private RenderProfileElement? _profileElement;
|
||||
private ObservableAsPropertyHelper<bool>? _showAddEnd;
|
||||
private ObservableAsPropertyHelper<bool>? _showAddMain;
|
||||
|
||||
private ObservableAsPropertyHelper<bool>? _showAddStart;
|
||||
private ObservableAsPropertyHelper<bool>? _showAddMain;
|
||||
private ObservableAsPropertyHelper<bool>? _showAddEnd;
|
||||
private TimeSpan _initialLength;
|
||||
|
||||
protected TimelineSegmentViewModel(IProfileEditorService profileEditorService)
|
||||
{
|
||||
@@ -136,8 +136,10 @@ public abstract class TimelineSegmentViewModel : ActivatableViewModelBase
|
||||
|
||||
// Delete keyframes in the segment
|
||||
foreach (ILayerPropertyKeyframe layerPropertyKeyframe in keyframes)
|
||||
{
|
||||
if (layerPropertyKeyframe.Position > Start && layerPropertyKeyframe.Position <= End)
|
||||
_profileEditorService.ExecuteCommand(new DeleteKeyframe(layerPropertyKeyframe));
|
||||
}
|
||||
|
||||
// Move keyframes after the segment forwards
|
||||
ShiftKeyframes(keyframes.Where(s => s.Position > End), new TimeSpan(Length.Ticks * -1));
|
||||
|
||||
@@ -8,13 +8,11 @@
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Timeline.TimelineView"
|
||||
x:DataType="timeline:TimelineViewModel">
|
||||
<UserControl.Resources>
|
||||
<x:Double x:Key="RailsHeight">28</x:Double>
|
||||
<x:Double x:Key="RailsBorderHeight">29</x:Double>
|
||||
</UserControl.Resources>
|
||||
<UserControl.Resources>
|
||||
</UserControl.Resources>
|
||||
<Grid Background="Transparent" PointerReleased="InputElement_OnPointerReleased" Focusable="True" MinWidth="{Binding MinWidth}">
|
||||
<Grid.KeyBindings>
|
||||
<KeyBinding Command="{Binding DeleteKeyframes}" Gesture="Delete"/>
|
||||
<KeyBinding Command="{Binding DeleteKeyframes}" Gesture="Delete" />
|
||||
</Grid.KeyBindings>
|
||||
<ItemsControl Items="{CompiledBinding PropertyGroupViewModels}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
@@ -23,8 +21,8 @@
|
||||
</TreeDataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<shared:SelectionRectangle Name="SelectionRectangle" InputElement="{CompiledBinding $parent}" SelectionFinished="SelectionRectangle_OnSelectionFinished"></shared:SelectionRectangle>
|
||||
</Grid>
|
||||
<shared:SelectionRectangle Name="SelectionRectangle" InputElement="{CompiledBinding $parent}" SelectionFinished="SelectionRectangle_OnSelectionFinished" />
|
||||
</Grid>
|
||||
|
||||
|
||||
</UserControl>
|
||||
+14
-8
@@ -3,12 +3,10 @@ using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Keyframes;
|
||||
using Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Segments;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
||||
using Avalonia.Controls.Mixins;
|
||||
using ReactiveUI;
|
||||
|
||||
@@ -18,13 +16,13 @@ public class TimelineViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private ObservableAsPropertyHelper<double>? _caretPosition;
|
||||
private ObservableAsPropertyHelper<int>? _pixelsPerSecond;
|
||||
private List<ITimelineKeyframeViewModel>? _moveKeyframes;
|
||||
private ObservableAsPropertyHelper<double> _minWidth;
|
||||
private List<ITimelineKeyframeViewModel>? _moveKeyframes;
|
||||
private ObservableAsPropertyHelper<int>? _pixelsPerSecond;
|
||||
|
||||
public TimelineViewModel(ObservableCollection<PropertyGroupViewModel> propertyGroupViewModels,
|
||||
StartSegmentViewModel startSegmentViewModel,
|
||||
MainSegmentViewModel mainSegmentViewModel,
|
||||
MainSegmentViewModel mainSegmentViewModel,
|
||||
EndSegmentViewModel endSegmentViewModel,
|
||||
IProfileEditorService profileEditorService)
|
||||
{
|
||||
@@ -141,8 +139,10 @@ public class TimelineViewModel : ActivatableViewModelBase
|
||||
|
||||
public void DuplicateKeyframes(ITimelineKeyframeViewModel? source = null)
|
||||
{
|
||||
if (source is { IsSelected: false })
|
||||
if (source is {IsSelected: false})
|
||||
{
|
||||
source.Delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
List<ITimelineKeyframeViewModel> keyframes = PropertyGroupViewModels.SelectMany(g => g.GetAllKeyframeViewModels(true)).Where(k => k.IsSelected).ToList();
|
||||
@@ -154,8 +154,10 @@ public class TimelineViewModel : ActivatableViewModelBase
|
||||
|
||||
public void CopyKeyframes(ITimelineKeyframeViewModel? source = null)
|
||||
{
|
||||
if (source is { IsSelected: false })
|
||||
if (source is {IsSelected: false})
|
||||
{
|
||||
source.Copy();
|
||||
}
|
||||
else
|
||||
{
|
||||
List<ITimelineKeyframeViewModel> keyframes = PropertyGroupViewModels.SelectMany(g => g.GetAllKeyframeViewModels(true)).Where(k => k.IsSelected).ToList();
|
||||
@@ -167,8 +169,10 @@ public class TimelineViewModel : ActivatableViewModelBase
|
||||
|
||||
public void PasteKeyframes(ITimelineKeyframeViewModel? source = null)
|
||||
{
|
||||
if (source is { IsSelected: false })
|
||||
if (source is {IsSelected: false})
|
||||
{
|
||||
source.Paste();
|
||||
}
|
||||
else
|
||||
{
|
||||
List<ITimelineKeyframeViewModel> keyframes = PropertyGroupViewModels.SelectMany(g => g.GetAllKeyframeViewModels(true)).Where(k => k.IsSelected).ToList();
|
||||
@@ -181,7 +185,9 @@ public class TimelineViewModel : ActivatableViewModelBase
|
||||
public void DeleteKeyframes(ITimelineKeyframeViewModel? source = null)
|
||||
{
|
||||
if (source is {IsSelected: false})
|
||||
{
|
||||
source.Delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
List<ITimelineKeyframeViewModel> keyframes = PropertyGroupViewModels.SelectMany(g => g.GetAllKeyframeViewModels(true)).Where(k => k.IsSelected).ToList();
|
||||
|
||||
+1
-1
@@ -10,6 +10,6 @@
|
||||
<StackPanel.KeyBindings>
|
||||
<KeyBinding Gesture="Enter" Command="{CompiledBinding Confirm}" />
|
||||
</StackPanel.KeyBindings>
|
||||
<TextBox Name="NameTextBox" Text="{CompiledBinding LayerEffectName}" Watermark="Layer effect name"/>
|
||||
<TextBox Name="NameTextBox" Text="{CompiledBinding LayerEffectName}" Watermark="Layer effect name" />
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
+26
-27
@@ -7,39 +7,38 @@ using FluentAvalonia.UI.Controls;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Validation.Extensions;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Tree.ContentDialogs
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Tree.ContentDialogs;
|
||||
|
||||
public class LayerEffectRenameViewModel : ContentDialogViewModelBase
|
||||
{
|
||||
public class LayerEffectRenameViewModel : ContentDialogViewModelBase
|
||||
private readonly BaseLayerEffect _layerEffect;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private string? _layerEffectName;
|
||||
|
||||
public LayerEffectRenameViewModel(IProfileEditorService profileEditorService, BaseLayerEffect layerEffect)
|
||||
{
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly BaseLayerEffect _layerEffect;
|
||||
private string? _layerEffectName;
|
||||
_profileEditorService = profileEditorService;
|
||||
_layerEffect = layerEffect;
|
||||
_layerEffectName = layerEffect.Name;
|
||||
|
||||
public LayerEffectRenameViewModel(IProfileEditorService profileEditorService, BaseLayerEffect layerEffect)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
_layerEffect = layerEffect;
|
||||
_layerEffectName = layerEffect.Name;
|
||||
Confirm = ReactiveCommand.Create(ExecuteConfirm, ValidationContext.Valid);
|
||||
this.ValidationRule(vm => vm.LayerEffectName, categoryName => !string.IsNullOrWhiteSpace(categoryName), "You must specify a valid name");
|
||||
}
|
||||
|
||||
Confirm = ReactiveCommand.Create(ExecuteConfirm, ValidationContext.Valid);
|
||||
this.ValidationRule(vm => vm.LayerEffectName, categoryName => !string.IsNullOrWhiteSpace(categoryName), "You must specify a valid name");
|
||||
}
|
||||
public string? LayerEffectName
|
||||
{
|
||||
get => _layerEffectName;
|
||||
set => RaiseAndSetIfChanged(ref _layerEffectName, value);
|
||||
}
|
||||
|
||||
public string? LayerEffectName
|
||||
{
|
||||
get => _layerEffectName;
|
||||
set => this.RaiseAndSetIfChanged(ref _layerEffectName, value);
|
||||
}
|
||||
public ReactiveCommand<Unit, Unit> Confirm { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> Confirm { get; }
|
||||
private void ExecuteConfirm()
|
||||
{
|
||||
if (LayerEffectName == null)
|
||||
return;
|
||||
|
||||
private void ExecuteConfirm()
|
||||
{
|
||||
if (LayerEffectName == null)
|
||||
return;
|
||||
|
||||
_profileEditorService.ExecuteCommand(new RenameLayerEffect(_layerEffect, LayerEffectName));
|
||||
ContentDialog?.Hide(ContentDialogResult.Primary);
|
||||
}
|
||||
_profileEditorService.ExecuteCommand(new RenameLayerEffect(_layerEffect, LayerEffectName));
|
||||
ContentDialog?.Hide(ContentDialogResult.Primary);
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -1,5 +1,4 @@
|
||||
using System.Reactive;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Tree;
|
||||
|
||||
@@ -71,14 +71,14 @@
|
||||
Height="29"
|
||||
ColumnDefinitions="Auto,Auto,Auto,*">
|
||||
<shared:ArtemisIcon Grid.Column="0"
|
||||
Icon="{CompiledBinding LayerBrush.Descriptor.Icon}"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="0 0 5 0" />
|
||||
Icon="{CompiledBinding LayerBrush.Descriptor.Icon}"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="0 0 5 0" />
|
||||
<TextBlock Grid.Column="1"
|
||||
ToolTip.Tip="{CompiledBinding LayerBrush.Descriptor.Description}"
|
||||
Margin="0 5 5 0">
|
||||
Brush -
|
||||
Brush -
|
||||
</TextBlock>
|
||||
<TextBlock Grid.Column="2"
|
||||
Text="{CompiledBinding LayerBrush.Descriptor.DisplayName}"
|
||||
|
||||
@@ -57,12 +57,25 @@ public class TreeGroupViewModel : ActivatableViewModelBase
|
||||
public BaseLayerEffect? LayerEffect => PropertyGroupViewModel.LayerEffect;
|
||||
public LayerPropertyGroupType GroupType { get; private set; }
|
||||
public ObservableCollection<ViewModelBase>? Children => PropertyGroupViewModel.IsExpanded ? PropertyGroupViewModel.Children : null;
|
||||
|
||||
|
||||
public ReactiveCommand<Unit, Unit> OpenBrushSettings { get; }
|
||||
public ReactiveCommand<Unit, Unit> OpenEffectSettings { get; }
|
||||
public ReactiveCommand<Unit, Unit> RenameEffect { get; }
|
||||
public ReactiveCommand<Unit, Unit> DeleteEffect { get; }
|
||||
|
||||
public double GetDepth()
|
||||
{
|
||||
int depth = 0;
|
||||
LayerPropertyGroup? current = LayerPropertyGroup.Parent;
|
||||
while (current != null)
|
||||
{
|
||||
depth++;
|
||||
current = current.Parent;
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
private async Task ExecuteOpenBrushSettings()
|
||||
{
|
||||
if (LayerBrush?.ConfigurationDialog is not LayerBrushConfigurationDialog configurationViewModel)
|
||||
@@ -145,19 +158,6 @@ public class TreeGroupViewModel : ActivatableViewModelBase
|
||||
_profileEditorService.ExecuteCommand(new RemoveLayerEffect(LayerEffect));
|
||||
}
|
||||
|
||||
public double GetDepth()
|
||||
{
|
||||
int depth = 0;
|
||||
LayerPropertyGroup? current = LayerPropertyGroup.Parent;
|
||||
while (current != null)
|
||||
{
|
||||
depth++;
|
||||
current = current.Parent;
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
private void CloseViewModels()
|
||||
{
|
||||
_effectConfigurationWindowViewModel?.Close(null);
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||
xmlns:sharedConverters="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
|
||||
xmlns:tree="clr-namespace:Artemis.UI.Screens.ProfileEditor.Properties.Tree"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Tree.TreePropertyView"
|
||||
@@ -39,7 +38,7 @@
|
||||
|
||||
<ContentControl Grid.Column="2"
|
||||
Margin="5 0"
|
||||
Content="{Binding PropertyInputViewModel}"/>
|
||||
Content="{Binding PropertyInputViewModel}" />
|
||||
|
||||
<Button Grid.Column="3"
|
||||
Margin="0 0 2 0"
|
||||
@@ -51,7 +50,7 @@
|
||||
<avalonia:MaterialIcon Kind="BackupRestore" />
|
||||
</Button>
|
||||
|
||||
<ToggleButton Grid.Column="4"
|
||||
<ToggleButton Grid.Column="4"
|
||||
Name="DataBindingToggleButton"
|
||||
Classes="icon-button"
|
||||
Margin="2 0 0 0"
|
||||
|
||||
+4
-3
@@ -15,9 +15,9 @@ namespace Artemis.UI.Screens.ProfileEditor.Properties.Tree;
|
||||
internal class TreePropertyViewModel<T> : ActivatableViewModelBase, ITreePropertyViewModel
|
||||
{
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private TimeSpan _time;
|
||||
private ObservableAsPropertyHelper<bool>? _isCurrentlySelected;
|
||||
private ObservableAsPropertyHelper<bool>? _dataBindingEnabled;
|
||||
private ObservableAsPropertyHelper<bool>? _isCurrentlySelected;
|
||||
private TimeSpan _time;
|
||||
|
||||
public TreePropertyViewModel(LayerProperty<T> layerProperty, PropertyViewModel propertyViewModel, IProfileEditorService profileEditorService, IPropertyInputService propertyInputService)
|
||||
{
|
||||
@@ -40,7 +40,6 @@ internal class TreePropertyViewModel<T> : ActivatableViewModelBase, ITreePropert
|
||||
}
|
||||
|
||||
public bool IsCurrentlySelected => _isCurrentlySelected?.Value ?? false;
|
||||
public bool DataBindingEnabled => _dataBindingEnabled?.Value ?? false;
|
||||
public LayerProperty<T> LayerProperty { get; }
|
||||
public PropertyViewModel PropertyViewModel { get; }
|
||||
public PropertyInputViewModel<T>? PropertyInputViewModel { get; }
|
||||
@@ -65,6 +64,8 @@ internal class TreePropertyViewModel<T> : ActivatableViewModelBase, ITreePropert
|
||||
_profileEditorService.ExecuteCommand(new ResetLayerProperty<T>(LayerProperty));
|
||||
}
|
||||
|
||||
public bool DataBindingEnabled => _dataBindingEnabled?.Value ?? false;
|
||||
|
||||
public ILayerProperty BaseLayerProperty => LayerProperty;
|
||||
|
||||
public double GetDepth()
|
||||
|
||||
-1
@@ -2,7 +2,6 @@
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.LayerBrushes;
|
||||
using Avalonia.Threading;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Windows;
|
||||
|
||||
|
||||
-1
@@ -2,7 +2,6 @@
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.LayerEffects;
|
||||
using Avalonia.Threading;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Windows;
|
||||
|
||||
|
||||
Reference in new issue
Block a user