mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-12 03:48:56 +00:00
Core - Refactored display conditions
Profile editor - Added UIs for each condition type
This commit is contained in:
1 parent
66ea718316
commit
3dfc25b092
47 files changed
+1305
-546
No files matched your search
+12
-13
@@ -1,19 +1,18 @@
|
||||
using System;
|
||||
using Artemis.UI.Shared;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayCondition
|
||||
{
|
||||
public class ConditionTypeViewModel : ViewModelBase
|
||||
{
|
||||
public ConditionTypeViewModel(string name, string description, Type? conditionType)
|
||||
{
|
||||
Name = name;
|
||||
Description = description;
|
||||
ConditionType = conditionType;
|
||||
}
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayCondition;
|
||||
|
||||
public string Name { get; }
|
||||
public string Description { get; }
|
||||
public Type? ConditionType { get; }
|
||||
public class ConditionTypeViewModel : ViewModelBase
|
||||
{
|
||||
public ConditionTypeViewModel(string name, string description, Type conditionType)
|
||||
{
|
||||
Name = name;
|
||||
Description = description;
|
||||
ConditionType = conditionType;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public string Description { get; }
|
||||
public Type ConditionType { get; }
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
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:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="300" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes.AlwaysOnConditionView">
|
||||
|
||||
<DockPanel VerticalAlignment="Top" Margin="0 5">
|
||||
<avalonia:MaterialIcon Kind="InfoCircle" Margin="5 0"/>
|
||||
<TextBlock Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
TextWrapping="Wrap">
|
||||
After playing the start segment, the main segment is endlessly repeated.
|
||||
</TextBlock>
|
||||
</DockPanel>
|
||||
</UserControl>
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes;
|
||||
|
||||
public class AlwaysOnConditionView : UserControl
|
||||
{
|
||||
public AlwaysOnConditionView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Shared;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes;
|
||||
|
||||
public class AlwaysOnConditionViewModel : ViewModelBase
|
||||
{
|
||||
private readonly AlwaysOnCondition _alwaysOnCondition;
|
||||
|
||||
public AlwaysOnConditionViewModel(AlwaysOnCondition alwaysOnCondition)
|
||||
{
|
||||
_alwaysOnCondition = alwaysOnCondition;
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
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:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker;assembly=Artemis.UI.Shared"
|
||||
xmlns:conditionTypes="clr-namespace:Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes.EventConditionView"
|
||||
x:DataType="conditionTypes:EventConditionViewModel">
|
||||
<DockPanel HorizontalAlignment="Stretch">
|
||||
<DockPanel.Styles>
|
||||
<Style Selector="DockPanel > TextBlock">
|
||||
<Setter Property="Margin" Value="0 5" />
|
||||
</Style>
|
||||
</DockPanel.Styles>
|
||||
<TextBlock DockPanel.Dock="Top">Triggered by event</TextBlock>
|
||||
<dataModelPicker:DataModelPickerButton Placeholder="Select an event"
|
||||
DockPanel.Dock="Top"
|
||||
HorizontalAlignment="Stretch"
|
||||
FilterTypes="{CompiledBinding FilterTypes}"
|
||||
DataModelPath="{CompiledBinding EventPath}"/>
|
||||
|
||||
<TextBlock DockPanel.Dock="Top">When the event fires..</TextBlock>
|
||||
<ComboBox PlaceholderText="Select a play mode" HorizontalAlignment="Stretch" DockPanel.Dock="Top" SelectedIndex="{CompiledBinding SelectedTriggerMode}">
|
||||
<ComboBoxItem>
|
||||
Play the timeline once
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
Toggle the element on or off
|
||||
</ComboBoxItem>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock DockPanel.Dock="Top" IsVisible="{CompiledBinding ShowOverlapOptions}">And if already playing..</TextBlock>
|
||||
<ComboBox PlaceholderText="Select a play mode"
|
||||
HorizontalAlignment="Stretch"
|
||||
DockPanel.Dock="Top"
|
||||
SelectedIndex="{CompiledBinding SelectedOverlapMode}"
|
||||
IsVisible="{CompiledBinding ShowOverlapOptions}">
|
||||
<ComboBoxItem>
|
||||
Restart the timeline
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem IsEnabled="{CompiledBinding IsConditionForLayer}">
|
||||
Play a second copy
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
Do nothing
|
||||
</ComboBoxItem>
|
||||
</ComboBox>
|
||||
|
||||
<Button DockPanel.Dock="Bottom"
|
||||
ToolTip.Tip="Open editor"
|
||||
Margin="0 15 0 5"
|
||||
Command="{CompiledBinding OpenEditor}"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Bottom">
|
||||
Edit condition script
|
||||
</Button>
|
||||
</DockPanel>
|
||||
</UserControl>
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes;
|
||||
|
||||
public class EventConditionView : ReactiveUserControl<EventConditionViewModel>
|
||||
{
|
||||
public EventConditionView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Screens.VisualScripting;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
||||
using Avalonia.Controls.Mixins;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes;
|
||||
|
||||
public class EventConditionViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private readonly EventCondition _eventCondition;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly ObservableAsPropertyHelper<bool> _showOverlapOptions;
|
||||
private readonly IWindowService _windowService;
|
||||
private ObservableAsPropertyHelper<DataModelPath?>? _eventPath;
|
||||
private ObservableAsPropertyHelper<int>? _selectedOverlapMode;
|
||||
private ObservableAsPropertyHelper<int>? _selectedTriggerMode;
|
||||
|
||||
public EventConditionViewModel(EventCondition eventCondition, IProfileEditorService profileEditorService, IWindowService windowService)
|
||||
{
|
||||
_eventCondition = eventCondition;
|
||||
_profileEditorService = profileEditorService;
|
||||
_windowService = windowService;
|
||||
_showOverlapOptions = this.WhenAnyValue(vm => vm.SelectedTriggerMode)
|
||||
.Select(m => m == 0)
|
||||
.ToProperty(this, vm => vm.ShowOverlapOptions);
|
||||
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
_eventPath = eventCondition.WhenAnyValue(c => c.EventPath).ToProperty(this, vm => vm.EventPath).DisposeWith(d);
|
||||
_selectedTriggerMode = eventCondition.WhenAnyValue(c => c.TriggerMode).Select(m => (int) m).ToProperty(this, vm => vm.SelectedTriggerMode).DisposeWith(d);
|
||||
_selectedOverlapMode = eventCondition.WhenAnyValue(c => c.OverlapMode).Select(m => (int) m).ToProperty(this, vm => vm.SelectedOverlapMode).DisposeWith(d);
|
||||
});
|
||||
|
||||
OpenEditor = ReactiveCommand.CreateFromTask(ExecuteOpenEditor);
|
||||
}
|
||||
|
||||
public ObservableCollection<Type> FilterTypes { get; } = new() {typeof(IDataModelEvent)};
|
||||
public ReactiveCommand<Unit, Unit> OpenEditor { get; }
|
||||
public bool ShowOverlapOptions => _showOverlapOptions.Value;
|
||||
public bool IsConditionForLayer => _eventCondition.ProfileElement is Layer;
|
||||
|
||||
public DataModelPath? EventPath
|
||||
{
|
||||
get => _eventPath?.Value != null ? new DataModelPath(_eventPath.Value) : null;
|
||||
set => _profileEditorService.ExecuteCommand(new UpdateEventConditionPath(_eventCondition, value != null ? new DataModelPath(value) : null));
|
||||
}
|
||||
|
||||
public int SelectedTriggerMode
|
||||
{
|
||||
get => _selectedTriggerMode?.Value ?? 0;
|
||||
set => _profileEditorService.ExecuteCommand(new UpdateEventTriggerMode(_eventCondition, (EventTriggerMode) value));
|
||||
}
|
||||
|
||||
public int SelectedOverlapMode
|
||||
{
|
||||
get => _selectedOverlapMode?.Value ?? 0;
|
||||
set => _profileEditorService.ExecuteCommand(new UpdateEventOverlapMode(_eventCondition, (EventOverlapMode) value));
|
||||
}
|
||||
|
||||
private async Task ExecuteOpenEditor()
|
||||
{
|
||||
await _windowService.ShowDialogAsync<NodeScriptWindowViewModel, bool>(("nodeScript", _eventCondition.NodeScript));
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
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:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes.PlayOnceConditionView">
|
||||
<DockPanel VerticalAlignment="Top" Margin="0 5">
|
||||
<avalonia:MaterialIcon Kind="InfoCircle" Margin="5 0"/>
|
||||
<TextBlock Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
TextWrapping="Wrap">
|
||||
Every segment of the timeline is played once.
|
||||
</TextBlock>
|
||||
</DockPanel>
|
||||
</UserControl>
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes;
|
||||
|
||||
public class PlayOnceConditionView : UserControl
|
||||
{
|
||||
public PlayOnceConditionView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Shared;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes;
|
||||
|
||||
public class PlayOnceConditionViewModel : ViewModelBase
|
||||
{
|
||||
private readonly PlayOnceCondition _playOnceCondition;
|
||||
|
||||
public PlayOnceConditionViewModel(PlayOnceCondition playOnceCondition)
|
||||
{
|
||||
_playOnceCondition = playOnceCondition;
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
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:conditionTypes="clr-namespace:Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes"
|
||||
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.ProfileEditor.DisplayCondition.ConditionTypes.StaticConditionView"
|
||||
x:DataType="conditionTypes:StaticConditionViewModel">
|
||||
<DockPanel HorizontalAlignment="Stretch">
|
||||
<DockPanel.Styles>
|
||||
<Style Selector="DockPanel > TextBlock">
|
||||
<Setter Property="Margin" Value="0 5" />
|
||||
</Style>
|
||||
</DockPanel.Styles>
|
||||
<TextBlock DockPanel.Dock="Top">While condition is met..</TextBlock>
|
||||
<ComboBox DockPanel.Dock="Top" PlaceholderText="Select a play mode" HorizontalAlignment="Stretch" SelectedIndex="{CompiledBinding SelectedPlayMode}">
|
||||
<ComboBoxItem>Repeat the main segment</ComboBoxItem>
|
||||
<ComboBoxItem>Play the main segment once</ComboBoxItem>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock DockPanel.Dock="Top">And when no longer met..</TextBlock>
|
||||
<ComboBox DockPanel.Dock="Top" PlaceholderText="Select a stop mode" HorizontalAlignment="Stretch" SelectedIndex="{CompiledBinding SelectedStopMode}">
|
||||
<ComboBoxItem>Finish the main segment</ComboBoxItem>
|
||||
<ComboBoxItem>Skip forward to the end segment</ComboBoxItem>
|
||||
</ComboBox>
|
||||
|
||||
<DockPanel DockPanel.Dock="Top" Margin="0 5">
|
||||
<avalonia:MaterialIcon Kind="InfoCircle" Margin="5 0" />
|
||||
<TextBlock Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
TextWrapping="Wrap">
|
||||
The start- and end-segments are played once each time the condition is met.
|
||||
</TextBlock>
|
||||
</DockPanel>
|
||||
|
||||
<Button DockPanel.Dock="Bottom"
|
||||
ToolTip.Tip="Open editor"
|
||||
Margin="0 15 0 5"
|
||||
Command="{CompiledBinding OpenEditor}"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Bottom">
|
||||
Edit condition script
|
||||
</Button>
|
||||
</DockPanel>
|
||||
</UserControl>
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes;
|
||||
|
||||
public class StaticConditionView : ReactiveUserControl<StaticConditionViewModel>
|
||||
{
|
||||
public StaticConditionView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
using System.Reactive;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Screens.VisualScripting;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes;
|
||||
|
||||
public class StaticConditionViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly StaticCondition _staticCondition;
|
||||
private readonly IWindowService _windowService;
|
||||
private ObservableAsPropertyHelper<int>? _selectedPlayMode;
|
||||
private ObservableAsPropertyHelper<int>? _selectedStopMode;
|
||||
|
||||
public StaticConditionViewModel(StaticCondition staticCondition, IProfileEditorService profileEditorService, IWindowService windowService)
|
||||
{
|
||||
_staticCondition = staticCondition;
|
||||
_profileEditorService = profileEditorService;
|
||||
_windowService = windowService;
|
||||
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
_selectedPlayMode = staticCondition.WhenAnyValue(c => c.PlayMode).Select(m => (int) m).ToProperty(this, vm => vm.SelectedPlayMode).DisposeWith(d);
|
||||
_selectedStopMode = staticCondition.WhenAnyValue(c => c.StopMode).Select(m => (int) m).ToProperty(this, vm => vm.SelectedStopMode).DisposeWith(d);
|
||||
});
|
||||
|
||||
OpenEditor = ReactiveCommand.CreateFromTask(ExecuteOpenEditor);
|
||||
}
|
||||
|
||||
public ReactiveCommand<Unit, Unit> OpenEditor { get; }
|
||||
|
||||
public int SelectedPlayMode
|
||||
{
|
||||
get => _selectedPlayMode?.Value ?? 0;
|
||||
set => _profileEditorService.ExecuteCommand(new UpdateStaticPlayMode(_staticCondition, (StaticPlayMode) value));
|
||||
}
|
||||
|
||||
public int SelectedStopMode
|
||||
{
|
||||
get => _selectedStopMode?.Value ?? 0;
|
||||
set => _profileEditorService.ExecuteCommand(new UpdateStaticStopMode(_staticCondition, (StaticStopMode) value));
|
||||
}
|
||||
|
||||
private async Task ExecuteOpenEditor()
|
||||
{
|
||||
await _windowService.ShowDialogAsync<NodeScriptWindowViewModel, bool>(("nodeScript", _staticCondition.NodeScript));
|
||||
}
|
||||
}
|
||||
+7
-71
@@ -3,8 +3,6 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:displayCondition="clr-namespace:Artemis.UI.Screens.ProfileEditor.DisplayCondition"
|
||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d" d:DesignWidth="200" d:DesignHeight="650"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.DisplayCondition.DisplayConditionScriptView"
|
||||
x:DataType="displayCondition:DisplayConditionScriptViewModel">
|
||||
@@ -20,19 +18,14 @@
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
<ScrollViewer>
|
||||
<DockPanel LastChildFill="False">
|
||||
<DockPanel.Styles>
|
||||
<Style Selector="DockPanel > TextBlock">
|
||||
<Setter Property="Margin" Value="0 5"></Setter>
|
||||
</Style>
|
||||
|
||||
</DockPanel.Styles>
|
||||
<TextBlock DockPanel.Dock="Top">Condition type</TextBlock>
|
||||
<Grid RowDefinitions="Auto,Auto,*">
|
||||
<TextBlock Grid.Row="0" Margin="0 5">Activation type</TextBlock>
|
||||
<ComboBox Name="ConditionType"
|
||||
DockPanel.Dock="Top"
|
||||
Grid.Row="1"
|
||||
Classes="condition-type"
|
||||
PlaceholderText="Select a condition type"
|
||||
PlaceholderText="Select an activation type"
|
||||
Items="{CompiledBinding ConditionTypeViewModels}"
|
||||
IsEnabled="{CompiledBinding ProfileElement, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||
SelectedItem="{CompiledBinding SelectedConditionTypeViewModel}"
|
||||
HorizontalAlignment="Stretch">
|
||||
<ComboBox.ItemTemplate>
|
||||
@@ -44,64 +37,7 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<!-- Event options -->
|
||||
<DockPanel IsVisible="{CompiledBinding ShowEventOptions}" DockPanel.Dock="Top" HorizontalAlignment="Stretch">
|
||||
<TextBlock DockPanel.Dock="Top">Triggered by event</TextBlock>
|
||||
<dataModelPicker:DataModelPickerButton Placeholder="Select an event"
|
||||
DockPanel.Dock="Top"
|
||||
HorizontalAlignment="Stretch" />
|
||||
|
||||
<TextBlock DockPanel.Dock="Top">When the event fires..</TextBlock>
|
||||
<ComboBox PlaceholderText="Select a play mode" HorizontalAlignment="Stretch" DockPanel.Dock="Top">
|
||||
<ComboBoxItem>
|
||||
Play the timeline once
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
Toggle the element on or off
|
||||
</ComboBoxItem>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock DockPanel.Dock="Top">And if already playing..</TextBlock>
|
||||
<ComboBox PlaceholderText="Select a play mode" HorizontalAlignment="Stretch" DockPanel.Dock="Top">
|
||||
<ComboBoxItem>
|
||||
Restart the timeline
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
Play a second copy
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
Do nothing
|
||||
</ComboBoxItem>
|
||||
</ComboBox>
|
||||
</DockPanel>
|
||||
|
||||
<!-- Static options -->
|
||||
<DockPanel IsVisible="{CompiledBinding ShowStaticOptions}" HorizontalAlignment="Stretch" DockPanel.Dock="Top">
|
||||
<TextBlock DockPanel.Dock="Top">While condition is met..</TextBlock>
|
||||
<ComboBox DockPanel.Dock="Top" PlaceholderText="Select a play mode" HorizontalAlignment="Stretch">
|
||||
<ComboBoxItem>Play the main segment once</ComboBoxItem>
|
||||
<ComboBoxItem>Repeat the main segment</ComboBoxItem>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock DockPanel.Dock="Top">And when no longer met..</TextBlock>
|
||||
<ComboBox DockPanel.Dock="Top" PlaceholderText="Select a stop mode" HorizontalAlignment="Stretch">
|
||||
<ComboBoxItem>Finish the main segment</ComboBoxItem>
|
||||
<ComboBoxItem>Skip forward to the end segment</ComboBoxItem>
|
||||
</ComboBox>
|
||||
|
||||
<DockPanel DockPanel.Dock="Top" Margin="0 5">
|
||||
<avalonia:MaterialIcon Kind="InfoCircle" Margin="5 0"></avalonia:MaterialIcon>
|
||||
<TextBlock Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
TextWrapping="Wrap">
|
||||
The start- and end-segments are always played once.
|
||||
</TextBlock>
|
||||
</DockPanel>
|
||||
</DockPanel>
|
||||
|
||||
<Button DockPanel.Dock="Bottom" ToolTip.Tip="Open editor" Margin="0 15 0 5" Command="{Binding OpenEditor}" HorizontalAlignment="Stretch">
|
||||
Edit condition script
|
||||
</Button>
|
||||
</DockPanel>
|
||||
<ContentControl Grid.Row="2" Content="{CompiledBinding ConditionViewModel}" />
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
+12
-13
@@ -1,18 +1,17 @@
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayCondition
|
||||
{
|
||||
public partial class DisplayConditionScriptView : ReactiveUserControl<DisplayConditionScriptViewModel>
|
||||
{
|
||||
public DisplayConditionScriptView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayCondition;
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
public class DisplayConditionScriptView : ReactiveUserControl<DisplayConditionScriptViewModel>
|
||||
{
|
||||
public DisplayConditionScriptView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
+46
-52
@@ -1,13 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Screens.VisualScripting;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
||||
using Avalonia.Controls.Mixins;
|
||||
@@ -17,81 +13,79 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayCondition;
|
||||
|
||||
public class DisplayConditionScriptViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private readonly ObservableAsPropertyHelper<ViewModelBase?> _conditionViewModel;
|
||||
private readonly IConditionVmFactory _conditionVmFactory;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly ObservableAsPropertyHelper<bool> _showEventOptions;
|
||||
private readonly ObservableAsPropertyHelper<bool> _showStaticOptions;
|
||||
private readonly IWindowService _windowService;
|
||||
private ObservableAsPropertyHelper<NodeScriptViewModel?>? _nodeScriptViewModel;
|
||||
private RenderProfileElement? _profileElement;
|
||||
private ObservableAsPropertyHelper<RenderProfileElement?>? _profileElement;
|
||||
private ObservableAsPropertyHelper<ConditionTypeViewModel?>? _selectedConditionTypeViewModel;
|
||||
|
||||
public DisplayConditionScriptViewModel(IProfileEditorService profileEditorService, INodeVmFactory nodeVmFactory, IWindowService windowService)
|
||||
public DisplayConditionScriptViewModel(IProfileEditorService profileEditorService, IConditionVmFactory conditionVmFactory)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
_windowService = windowService;
|
||||
_conditionVmFactory = conditionVmFactory;
|
||||
|
||||
ConditionTypeViewModels = new ObservableCollection<ConditionTypeViewModel>
|
||||
{
|
||||
new("None", "The element is always active.", null),
|
||||
new("Regular", "The element is activated when the provided visual script ends in true.", typeof(StaticCondition)),
|
||||
new("Event", "The element is activated when the selected event fires.\r\n" +
|
||||
"Events that contain data can conditionally trigger the layer using a visual script.", typeof(EventCondition))
|
||||
new("Always", "The element is always active.", typeof(AlwaysOnCondition)),
|
||||
new("Once", "The element is shown once until its timeline is finished.", typeof(PlayOnceCondition)),
|
||||
new("Conditional", "The element is activated when the provided visual script ends in true.", typeof(StaticCondition)),
|
||||
new("On event", "The element is activated when the selected event fires.\r\n" +
|
||||
"Events that contain data can conditionally trigger the layer using a visual script.", typeof(EventCondition))
|
||||
};
|
||||
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
profileEditorService.ProfileElement.Subscribe(p => _profileElement = p).DisposeWith(d);
|
||||
|
||||
_nodeScriptViewModel = profileEditorService.ProfileElement
|
||||
.Select(p => p?.WhenAnyValue(element => element.DisplayCondition) ?? Observable.Never<ICondition?>())
|
||||
.Switch()
|
||||
.Select(c => c is INodeScriptCondition {NodeScript: NodeScript nodeScript} ? nodeVmFactory.NodeScriptViewModel(nodeScript, true) : null)
|
||||
.ToProperty(this, vm => vm.NodeScriptViewModel)
|
||||
.DisposeWith(d);
|
||||
_profileElement = profileEditorService.ProfileElement.ToProperty(this, vm => vm.ProfileElement).DisposeWith(d);
|
||||
_selectedConditionTypeViewModel = profileEditorService.ProfileElement
|
||||
.Select(p => p?.WhenAnyValue(element => element.DisplayCondition) ?? Observable.Never<ICondition?>())
|
||||
.Select(p => p?.WhenAnyValue(element => element.DisplayCondition) ?? Observable.Return<ICondition?>(null))
|
||||
.Switch()
|
||||
.Select(c => c != null ? ConditionTypeViewModels.FirstOrDefault(vm => vm.ConditionType == c.GetType()) : null)
|
||||
.ToProperty(this, vm => vm.SelectedConditionTypeViewModel)
|
||||
.DisposeWith(d);
|
||||
});
|
||||
|
||||
_showStaticOptions = this.WhenAnyValue(vm => vm.SelectedConditionTypeViewModel)
|
||||
.Select(c => c != null && c.ConditionType == typeof(StaticCondition))
|
||||
.ToProperty(this, vm => vm.ShowStaticOptions);
|
||||
_showEventOptions = this.WhenAnyValue(vm => vm.SelectedConditionTypeViewModel)
|
||||
.Select(c => c != null && c.ConditionType == typeof(EventCondition))
|
||||
.ToProperty(this, vm => vm.ShowEventOptions);
|
||||
_conditionViewModel = this.WhenAnyValue(vm => vm.SelectedConditionTypeViewModel).Select(_ => CreateConditionViewModel()).ToProperty(this, vm => vm.ConditionViewModel);
|
||||
}
|
||||
|
||||
public NodeScriptViewModel? NodeScriptViewModel => _nodeScriptViewModel?.Value;
|
||||
public RenderProfileElement? ProfileElement => _profileElement?.Value;
|
||||
public ViewModelBase? ConditionViewModel => _conditionViewModel.Value;
|
||||
public ObservableCollection<ConditionTypeViewModel> ConditionTypeViewModels { get; }
|
||||
|
||||
public ConditionTypeViewModel? SelectedConditionTypeViewModel
|
||||
{
|
||||
get => _selectedConditionTypeViewModel?.Value;
|
||||
set
|
||||
{
|
||||
if (_profileElement == null)
|
||||
return;
|
||||
|
||||
ICondition? condition = null;
|
||||
if (value?.ConditionType == typeof(StaticCondition))
|
||||
condition = new StaticCondition(_profileElement);
|
||||
else if (value?.ConditionType == typeof(EventCondition))
|
||||
condition = new EventCondition(_profileElement);
|
||||
|
||||
_profileEditorService.ExecuteCommand(new ChangeConditionType(_profileElement, condition));
|
||||
}
|
||||
set => ApplyConditionType(value);
|
||||
}
|
||||
|
||||
public bool ShowStaticOptions => _showStaticOptions.Value;
|
||||
public bool ShowEventOptions => _showEventOptions.Value;
|
||||
|
||||
|
||||
public async Task OpenEditor()
|
||||
private ViewModelBase? CreateConditionViewModel()
|
||||
{
|
||||
if (_profileElement?.DisplayCondition is StaticCondition staticCondition)
|
||||
await _windowService.ShowDialogAsync<NodeScriptWindowViewModel, bool>(("nodeScript", staticCondition.Script));
|
||||
if (ProfileElement == null)
|
||||
return null;
|
||||
|
||||
if (ProfileElement.DisplayCondition is AlwaysOnCondition alwaysOnCondition)
|
||||
return _conditionVmFactory.AlwaysOnConditionViewModel(alwaysOnCondition);
|
||||
if (ProfileElement.DisplayCondition is PlayOnceCondition playOnceCondition)
|
||||
return _conditionVmFactory.PlayOnceConditionViewModel(playOnceCondition);
|
||||
if (ProfileElement.DisplayCondition is StaticCondition staticCondition)
|
||||
return _conditionVmFactory.StaticConditionViewModel(staticCondition);
|
||||
if (ProfileElement.DisplayCondition is EventCondition eventCondition)
|
||||
return _conditionVmFactory.EventConditionViewModel(eventCondition);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void ApplyConditionType(ConditionTypeViewModel? value)
|
||||
{
|
||||
if (ProfileElement == null || value == null || ProfileElement.DisplayCondition.GetType() == value.ConditionType)
|
||||
return;
|
||||
|
||||
if (value.ConditionType == typeof(AlwaysOnCondition))
|
||||
_profileEditorService.ExecuteCommand(new ChangeConditionType(ProfileElement, new AlwaysOnCondition(ProfileElement)));
|
||||
if (value.ConditionType == typeof(PlayOnceCondition))
|
||||
_profileEditorService.ExecuteCommand(new ChangeConditionType(ProfileElement, new PlayOnceCondition(ProfileElement)));
|
||||
if (value.ConditionType == typeof(StaticCondition))
|
||||
_profileEditorService.ExecuteCommand(new ChangeConditionType(ProfileElement, new StaticCondition(ProfileElement)));
|
||||
if (value.ConditionType == typeof(EventCondition))
|
||||
_profileEditorService.ExecuteCommand(new ChangeConditionType(ProfileElement, new EventCondition(ProfileElement)));
|
||||
}
|
||||
}
|
||||
-7
@@ -46,13 +46,6 @@
|
||||
Command="{Binding DisableSegment}">
|
||||
<avalonia:MaterialIcon Kind="CloseCircle" />
|
||||
</Button>
|
||||
<ToggleButton Name="SegmentRepeat"
|
||||
Classes="icon-button icon-button-small"
|
||||
ToolTip.Tip="Repeat this segment"
|
||||
IsChecked="{CompiledBinding RepeatSegment}"
|
||||
Padding="0">
|
||||
<avalonia:MaterialIcon Kind="Repeat" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
|
||||
<Button Name="AddEndSegment"
|
||||
|
||||
+3
-19
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
@@ -13,12 +10,11 @@ namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Segments;
|
||||
|
||||
public class MainSegmentViewModel : TimelineSegmentViewModel
|
||||
{
|
||||
private RenderProfileElement? _profileElement;
|
||||
private ObservableAsPropertyHelper<double>? _start;
|
||||
private readonly ObservableAsPropertyHelper<double> _width;
|
||||
private ObservableAsPropertyHelper<double>? _end;
|
||||
private ObservableAsPropertyHelper<string?>? _endTimestamp;
|
||||
private ObservableAsPropertyHelper<bool>? _repeatSegment;
|
||||
private readonly ObservableAsPropertyHelper<double> _width;
|
||||
private RenderProfileElement? _profileElement;
|
||||
private ObservableAsPropertyHelper<double>? _start;
|
||||
|
||||
public MainSegmentViewModel(IProfileEditorService profileEditorService) : base(profileEditorService)
|
||||
{
|
||||
@@ -44,12 +40,6 @@ public class MainSegmentViewModel : TimelineSegmentViewModel
|
||||
.Select(p => $"{Math.Floor(p.TotalSeconds):00}.{p.Milliseconds:000}")
|
||||
.ToProperty(this, vm => vm.EndTimestamp)
|
||||
.DisposeWith(d);
|
||||
_repeatSegment = profileEditorService.ProfileElement
|
||||
.Select(p => p?.WhenAnyValue(element => element.Timeline.PlayMode) ?? Observable.Never<TimelinePlayMode>())
|
||||
.Switch()
|
||||
.Select(p => p == TimelinePlayMode.Repeat)
|
||||
.ToProperty(this, vm => vm.RepeatSegment)
|
||||
.DisposeWith(d);
|
||||
});
|
||||
|
||||
_width = this.WhenAnyValue(vm => vm.StartX, vm => vm.EndX).Select(t => t.Item2 - t.Item1).ToProperty(this, vm => vm.Width);
|
||||
@@ -73,10 +63,4 @@ public class MainSegmentViewModel : TimelineSegmentViewModel
|
||||
public override double Width => _width.Value;
|
||||
public override string? EndTimestamp => _endTimestamp?.Value;
|
||||
public override ResizeTimelineSegment.SegmentType Type => ResizeTimelineSegment.SegmentType.Main;
|
||||
|
||||
public bool RepeatSegment
|
||||
{
|
||||
get => _repeatSegment?.Value ?? false;
|
||||
set => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
|
||||
public SurfaceEditorViewModel(IScreen hostScreen,
|
||||
IRgbService rgbService,
|
||||
SurfaceVmFactory surfaceVmFactory,
|
||||
ISurfaceVmFactory surfaceVmFactory,
|
||||
ISettingsService settingsService) : base(hostScreen, "surface-editor")
|
||||
{
|
||||
_rgbService = rgbService;
|
||||
|
||||
@@ -3,9 +3,30 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:visualScripting="clr-namespace:Artemis.UI.Screens.VisualScripting"
|
||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.VisualScripting.NodeScriptWindowView"
|
||||
x:DataType="visualScripting:NodeScriptWindowViewModel"
|
||||
Title="VisualEditorWindowView">
|
||||
<ContentControl Content="{CompiledBinding NodeScriptViewModel}" />
|
||||
Title="Artemis | Visual Script Editor"
|
||||
Width="1200"
|
||||
Height="800">
|
||||
<Grid Margin="15" ColumnDefinitions="*,*" RowDefinitions="Auto,*">
|
||||
<StackPanel Grid.Row="0">
|
||||
<TextBlock Classes="h4" Text="{CompiledBinding NodeScript.Name}"/>
|
||||
<TextBlock Classes="subtitle" Margin="0 0 0 10" Text="{CompiledBinding NodeScript.Description}"/>
|
||||
</StackPanel>
|
||||
<controls:HyperlinkButton Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Right"
|
||||
NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/profiles/conditions">
|
||||
Learn more about visual scripts
|
||||
</controls:HyperlinkButton>
|
||||
|
||||
<Border Classes="card" Grid.Row="1" Grid.ColumnSpan="2">
|
||||
<ContentControl Content="{CompiledBinding NodeScriptViewModel}" />
|
||||
</Border>
|
||||
|
||||
</Grid>
|
||||
|
||||
</Window>
|
||||
Reference in new issue
Block a user