Profiles - Split conditions into different types

Profile configurations - Added broken state (not yet shown in UI)
This commit is contained in:
Robert committed 2021-09-14 22:17:31 +02:00
1 parent 8ac1431a2f
commit d657e7844e
18 files changed
+694 -375

No files matched your search

@@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
{
public class DisplayConditionEventViewModel : Screen
{
}
}
@@ -37,10 +37,28 @@
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<RadioButton Grid.Column="0"
Style="{StaticResource MaterialDesignTabRadioButton}"
IsChecked="{Binding IsEventCondition, Converter={StaticResource InverseBooleanConverter}}"
IsChecked="{Binding Path=DisplayConditionType, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static displayConditions:DisplayConditionType.None}}"
MinWidth="0"
Padding="10 0">
<RadioButton.ToolTip>
<ToolTip Placement="Center" VerticalOffset="-40">
<TextBlock>
No condition, the element is always displayed
</TextBlock>
</ToolTip>
</RadioButton.ToolTip>
<TextBlock VerticalAlignment="Center" FontSize="12">
<materialDesign:PackIcon Kind="Close" VerticalAlignment="Center" Margin="0 0 2 -3" />
NONE
</TextBlock>
</RadioButton>
<RadioButton Grid.Column="1"
Style="{StaticResource MaterialDesignTabRadioButton}"
IsChecked="{Binding Path=DisplayConditionType, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static displayConditions:DisplayConditionType.Static}}"
MinWidth="0"
Padding="10 0">
<RadioButton.ToolTip>
@@ -55,9 +73,9 @@
CONSTANT
</TextBlock>
</RadioButton>
<RadioButton Grid.Column="1"
<RadioButton Grid.Column="2"
Style="{StaticResource MaterialDesignTabRadioButton}"
IsChecked="{Binding IsEventCondition}"
IsChecked="{Binding Path=DisplayConditionType, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static displayConditions:DisplayConditionType.Events}}"
MinWidth="0"
Padding="10 0">
<RadioButton.ToolTip>
@@ -78,200 +96,10 @@
<Separator Grid.Row="1" Grid.Column="0" Style="{StaticResource MaterialDesignDarkSeparator}" Margin="-2 0" />
<Grid Grid.Row="2" Visibility="{Binding IsEventCondition, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay}">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" MouseUp="{s:Action ScriptGridMouseUp}" Cursor="Hand">
<controls:VisualScriptPresenter Script="{Binding RenderProfileElement.DisplayCondition}"
AutoFitScript="True"
Visibility="{Binding RenderProfileElement.DisplayCondition, Converter={StaticResource NullToVisibilityConverter}}" />
<Border Opacity="0">
<Border.Background>
<SolidColorBrush Color="{Binding Color, Source={StaticResource MaterialDesignCardBackground}}" Opacity="0.75" />
</Border.Background>
<Border.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type Grid}, Mode=FindAncestor}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" VerticalAlignment="Center" Grid.Column="0">
Click to edit script
</TextBlock>
<materialDesign:PackIcon Kind="OpenInNew" Margin="10 " Width="30" Height="30" Grid.Column="1" VerticalAlignment="Center" />
</Grid>
</Border>
</Grid>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="22" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MinWidth="140" />
<ColumnDefinition Width="*" MinWidth="170" />
</Grid.ColumnDefinitions>
<!-- Play mode -->
<TextBlock Grid.Column="0" Text="Play mode" VerticalAlignment="Center">
<TextBlock.ToolTip>
<ToolTip Placement="Center" VerticalOffset="-30">
<TextBlock>
Configure how the layer should act while the conditions above are met
</TextBlock>
</ToolTip>
</TextBlock.ToolTip>
</TextBlock>
<materialDesign:ColorZone Grid.Row="1" Grid.Column="0" Mode="Standard" CornerRadius="3" Margin="0 0 2 0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<RadioButton Grid.Column="0"
Style="{StaticResource MaterialDesignTabRadioButton}"
IsChecked="{Binding DisplayContinuously}"
MinWidth="0"
Padding="5 0">
<RadioButton.ToolTip>
<ToolTip Placement="Center" VerticalOffset="-40">
<TextBlock>
Continue repeating the main segment of the timeline while the condition is met
</TextBlock>
</ToolTip>
</RadioButton.ToolTip>
<TextBlock VerticalAlignment="Center" FontSize="12">
<materialDesign:PackIcon Kind="Repeat" VerticalAlignment="Center" Margin="-3 0 0 -3" />
REPEAT
</TextBlock>
</RadioButton>
<RadioButton Grid.Column="1"
Style="{StaticResource MaterialDesignTabRadioButton}"
IsChecked="{Binding DisplayContinuously, Converter={StaticResource InverseBooleanConverter}}"
MinWidth="0"
Padding="5 0">
<RadioButton.ToolTip>
<ToolTip Placement="Center" VerticalOffset="-40">
<TextBlock>
Only play the timeline once when the condition is met
</TextBlock>
</ToolTip>
</RadioButton.ToolTip>
<TextBlock VerticalAlignment="Center" FontSize="12">
<materialDesign:PackIcon Kind="StopwatchOutline" VerticalAlignment="Center" Margin="-3 0 0 -3" />
ONCE
</TextBlock>
</RadioButton>
</Grid>
</materialDesign:ColorZone>
<!-- Stop mode -->
<TextBlock Grid.Row="0" Grid.Column="1" Text="Stop mode">
<TextBlock.ToolTip>
<ToolTip Placement="Center" VerticalOffset="-30">
<TextBlock>
Configure how the layer should act when the conditions above are no longer met
</TextBlock>
</ToolTip>
</TextBlock.ToolTip>
</TextBlock>
<materialDesign:ColorZone Grid.Row="1" Grid.Column="1" Mode="Standard" CornerRadius="3" Margin="2 0 0 0" HorizontalAlignment="Stretch">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition MinWidth="100" />
</Grid.ColumnDefinitions>
<RadioButton Grid.Column="0"
Style="{StaticResource MaterialDesignTabRadioButton}"
IsChecked="{Binding AlwaysFinishTimeline}"
MinWidth="0"
Padding="5 0">
<RadioButton.ToolTip>
<ToolTip Placement="Center" VerticalOffset="-40">
<TextBlock>
When conditions are no longer met, finish the the current run of the main timeline
</TextBlock>
</ToolTip>
</RadioButton.ToolTip>
<TextBlock VerticalAlignment="Center" FontSize="12">
<materialDesign:PackIcon Kind="PlayOutline" VerticalAlignment="Center" Margin="-3 0 0 -3" />
FINISH
</TextBlock>
</RadioButton>
<RadioButton Grid.Column="1"
Style="{StaticResource MaterialDesignTabRadioButton}"
IsChecked="{Binding AlwaysFinishTimeline, Converter={StaticResource InverseBooleanConverter}}"
MinWidth="0"
Padding="5 0">
<RadioButton.ToolTip>
<ToolTip Placement="Center" VerticalOffset="-40">
<TextBlock>
When conditions are no longer met, skip to the end segment of the timeline
</TextBlock>
</ToolTip>
</RadioButton.ToolTip>
<TextBlock VerticalAlignment="Center" FontSize="12">
<materialDesign:PackIcon Kind="SkipNextOutline" VerticalAlignment="Center" Margin="-3 0 0 -3" />
SKIP TO END
</TextBlock>
</RadioButton>
</Grid>
</materialDesign:ColorZone>
</Grid>
</Grid>
<TabControl Grid.Row="2"
Visibility="{Binding IsEventCondition, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}"
ItemsSource="{Binding Items}"
SelectedItem="{Binding ActiveItem}"
Style="{StaticResource MaterialDesignTabControl}"
Background="{DynamicResource MaterialDesignPaper}">
<TabControl.ItemTemplate>
<DataTemplate>
<DockPanel LastChildFill="True" Margin="-15 0">
<Button DockPanel.Dock="Right"
Style="{StaticResource MaterialDesignIconForegroundButton}"
Width="25"
Height="25">
<materialDesign:PackIcon Kind="Close" Width="15" Height="15" Foreground="{DynamicResource MaterialDesignBody}" />
</Button>
<Label Content="{Binding DisplayName}" DockPanel.Dock="Left" />
</DockPanel>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding IsAsync=True}"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch"
IsTabStop="False"
TextElement.Foreground="{DynamicResource MaterialDesignBody}" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
<ContentControl Grid.Row="2"
s:View.Model="{Binding ActiveItem}"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch"
IsTabStop="False"/>
</Grid>
</UserControl>
@@ -1,6 +1,4 @@
using System.ComponentModel;
using System.Windows.Input;
using Artemis.Core;
using Artemis.Core;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
@@ -8,84 +6,31 @@ using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
{
public class DisplayConditionsViewModel : Conductor<DisplayConditionEventViewModel>.Collection.OneActive, IProfileEditorPanelViewModel
public class DisplayConditionsViewModel : Conductor<Screen>, IProfileEditorPanelViewModel
{
private readonly INodeVmFactory _nodeVmFactory;
private readonly IConditionVmFactory _conditionVmFactory;
private readonly IProfileEditorService _profileEditorService;
private readonly IWindowManager _windowManager;
private bool _isEventCondition;
private RenderProfileElement _renderProfileElement;
private DisplayConditionType _displayConditionType;
public DisplayConditionsViewModel(IProfileEditorService profileEditorService, IWindowManager windowManager, INodeVmFactory nodeVmFactory)
public DisplayConditionsViewModel(IProfileEditorService profileEditorService, IConditionVmFactory conditionVmFactory)
{
_profileEditorService = profileEditorService;
_windowManager = windowManager;
_nodeVmFactory = nodeVmFactory;
Items.Add(new DisplayConditionEventViewModel() { DisplayName = "Event 1"});
Items.Add(new DisplayConditionEventViewModel() { DisplayName = "Event 2"});
Items.Add(new DisplayConditionEventViewModel() { DisplayName = "Event 3"});
Items.Add(new DisplayConditionEventViewModel() { DisplayName = "Event 4"});
_conditionVmFactory = conditionVmFactory;
}
public bool IsEventCondition
public DisplayConditionType DisplayConditionType
{
get => _isEventCondition;
set => SetAndNotify(ref _isEventCondition, value);
}
public RenderProfileElement RenderProfileElement
{
get => _renderProfileElement;
get => _displayConditionType;
set
{
if (!SetAndNotify(ref _renderProfileElement, value)) return;
NotifyOfPropertyChange(nameof(DisplayContinuously));
NotifyOfPropertyChange(nameof(AlwaysFinishTimeline));
NotifyOfPropertyChange(nameof(EventOverlapMode));
if (!SetAndNotify(ref _displayConditionType, value)) return;
ChangeConditionType();
}
}
public bool DisplayContinuously
{
get => RenderProfileElement?.Timeline.PlayMode == TimelinePlayMode.Repeat;
set
{
TimelinePlayMode playMode = value ? TimelinePlayMode.Repeat : TimelinePlayMode.Once;
if (RenderProfileElement == null || RenderProfileElement?.Timeline.PlayMode == playMode) return;
RenderProfileElement.Timeline.PlayMode = playMode;
_profileEditorService.SaveSelectedProfileElement();
}
}
public bool AlwaysFinishTimeline
{
get => RenderProfileElement?.Timeline.StopMode == TimelineStopMode.Finish;
set
{
TimelineStopMode stopMode = value ? TimelineStopMode.Finish : TimelineStopMode.SkipToEnd;
if (RenderProfileElement == null || RenderProfileElement?.Timeline.StopMode == stopMode) return;
RenderProfileElement.Timeline.StopMode = stopMode;
_profileEditorService.SaveSelectedProfileElement();
}
}
public TimeLineEventOverlapMode EventOverlapMode
{
get => RenderProfileElement?.Timeline.EventOverlapMode ?? TimeLineEventOverlapMode.Restart;
set
{
if (RenderProfileElement == null || RenderProfileElement?.Timeline.EventOverlapMode == value) return;
RenderProfileElement.Timeline.EventOverlapMode = value;
_profileEditorService.SaveSelectedProfileElement();
}
}
public bool ConditionBehaviourEnabled => RenderProfileElement != null;
protected override void OnInitialActivate()
{
_profileEditorService.SelectedProfileElementChanged += SelectedProfileEditorServiceOnSelectedProfileElementChanged;
_profileEditorService.SelectedProfileElementChanged += ProfileEditorServiceOnSelectedProfileElementChanged;
Update(_profileEditorService.SelectedProfileElement);
base.OnInitialActivate();
@@ -93,55 +38,63 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
protected override void OnClose()
{
_profileEditorService.SelectedProfileElementChanged -= SelectedProfileEditorServiceOnSelectedProfileElementChanged;
_profileEditorService.SelectedProfileElementChanged -= ProfileEditorServiceOnSelectedProfileElementChanged;
base.OnClose();
}
private void ChangeConditionType()
{
if (_profileEditorService.SelectedProfileElement == null)
return;
if (DisplayConditionType == DisplayConditionType.Static)
_profileEditorService.SelectedProfileElement.ChangeDisplayCondition(new StaticCondition(_profileEditorService.SelectedProfileElement));
else if (DisplayConditionType == DisplayConditionType.Events)
_profileEditorService.SelectedProfileElement.ChangeDisplayCondition(new EventsCondition(_profileEditorService.SelectedProfileElement));
else
_profileEditorService.SelectedProfileElement.ChangeDisplayCondition(null);
_profileEditorService.SaveSelectedProfileElement();
Update(_profileEditorService.SelectedProfileElement);
}
private void Update(RenderProfileElement renderProfileElement)
{
if (RenderProfileElement != null)
RenderProfileElement.Timeline.PropertyChanged -= TimelineOnPropertyChanged;
RenderProfileElement = renderProfileElement;
NotifyOfPropertyChange(nameof(DisplayContinuously));
NotifyOfPropertyChange(nameof(AlwaysFinishTimeline));
NotifyOfPropertyChange(nameof(ConditionBehaviourEnabled));
if (RenderProfileElement != null)
RenderProfileElement.Timeline.PropertyChanged += TimelineOnPropertyChanged;
}
#region Event handlers
public void ScriptGridMouseUp(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton != MouseButton.Left)
return;
if (RenderProfileElement == null)
if (renderProfileElement == null)
{
ActiveItem = null;
return;
}
// _windowManager.ShowDialog(_nodeVmFactory.NodeScriptWindowViewModel(RenderProfileElement.DisplayCondition));
_profileEditorService.SaveSelectedProfileElement();
if (renderProfileElement.DisplayCondition is StaticCondition staticCondition)
{
ActiveItem = _conditionVmFactory.StaticConditionViewModel(staticCondition);
_displayConditionType = DisplayConditionType.Static;
}
else if (renderProfileElement.DisplayCondition is EventsCondition eventsCondition)
{
ActiveItem = _conditionVmFactory.EventsConditionViewModel(eventsCondition);
_displayConditionType = DisplayConditionType.Events;
}
else
{
ActiveItem = null;
_displayConditionType = DisplayConditionType.None;
}
NotifyOfPropertyChange(nameof(DisplayConditionType));
}
public void EventTriggerModeSelected()
{
_profileEditorService.SaveSelectedProfileElement();
}
private void SelectedProfileEditorServiceOnSelectedProfileElementChanged(object sender, RenderProfileElementEventArgs e)
private void ProfileEditorServiceOnSelectedProfileElementChanged(object sender, RenderProfileElementEventArgs e)
{
Update(e.RenderProfileElement);
}
}
private void TimelineOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
NotifyOfPropertyChange(nameof(DisplayContinuously));
NotifyOfPropertyChange(nameof(AlwaysFinishTimeline));
NotifyOfPropertyChange(nameof(EventOverlapMode));
}
#endregion
public enum DisplayConditionType
{
None,
Static,
Events
}
}
@@ -0,0 +1,81 @@
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.DisplayConditions.Event.EventConditionView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.DisplayConditions.Event"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:controls="clr-namespace:Artemis.VisualScripting.Editor.Controls;assembly=Artemis.VisualScripting"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:shared="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance {x:Type local:EventConditionViewModel}}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<shared:DataModelPicker Grid.Row="0"
Grid.Column="0"
Margin="0 5"
ButtonBrush="DarkGoldenrod"
DataModelPath="{Binding EventCondition.EventPath}"
DataModelPathSelected="{s:Action DataModelPathSelected}"
FilterTypes="{Binding FilterTypes}"
Modules="{Binding Modules}" />
<Button Grid.Row="0"
Grid.Column="1"
Margin="0 5"
Command="{s:Action AddEvent}"
s:View.ActionTarget="{Binding Parent}"
Content="ADD EVENT" />
<Grid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" MouseUp="{s:Action ScriptGridMouseUp}" Cursor="Hand">
<controls:VisualScriptPresenter Script="{Binding EventCondition.Script}" AutoFitScript="True" />
<Border VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Border.Background>
<SolidColorBrush Color="{Binding Color, Source={StaticResource MaterialDesignPaper}}" Opacity="0.75" />
</Border.Background>
<Border.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type Grid}, Mode=FindAncestor}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" VerticalAlignment="Center" Grid.Column="0">
Click to edit script
</TextBlock>
<materialDesign:PackIcon Kind="OpenInNew" Margin="10 " Width="30" Height="30" Grid.Column="1" VerticalAlignment="Center" />
</Grid>
</Border>
</Grid>
</Grid>
</UserControl>
@@ -0,0 +1,83 @@
using System;
using System.Collections.Specialized;
using System.Linq;
using System.Windows.Input;
using Artemis.Core;
using Artemis.Core.Modules;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions.Event
{
public class EventConditionViewModel : Screen
{
private readonly INodeVmFactory _nodeVmFactory;
private readonly IProfileEditorService _profileEditorService;
private readonly IWindowManager _windowManager;
public EventConditionViewModel(EventCondition eventCondition, IWindowManager windowManager, INodeVmFactory nodeVmFactory, IProfileEditorService profileEditorService)
{
_windowManager = windowManager;
_nodeVmFactory = nodeVmFactory;
_profileEditorService = profileEditorService;
EventCondition = eventCondition;
DisplayName = EventCondition.EventPath?.Segments.LastOrDefault()?.GetPropertyDescription()?.Name ?? "Invalid event";
FilterTypes = new BindableCollection<Type> {typeof(IDataModelEvent) };
Modules = new BindableCollection<Module>();
if (_profileEditorService.SelectedProfileConfiguration?.Module != null)
Modules.Add(_profileEditorService.SelectedProfileConfiguration.Module);
}
public EventCondition EventCondition { get; }
public BindableCollection<Type> FilterTypes { get; }
public BindableCollection<Module> Modules { get; }
public bool CanDeleteEvent => ((EventsConditionViewModel) Parent).Items.Count > 1;
public void DeleteEvent()
{
((EventsConditionViewModel) Parent).DeleteEvent(this);
}
public void DataModelPathSelected(object sender, DataModelSelectedEventArgs e)
{
EventCondition.UpdateEventNode();
DisplayName = EventCondition.EventPath?.Segments.LastOrDefault()?.GetPropertyDescription()?.Name ?? "Invalid event";
}
public void ScriptGridMouseUp(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton != MouseButton.Left)
return;
_windowManager.ShowDialog(_nodeVmFactory.NodeScriptWindowViewModel(EventCondition.Script));
_profileEditorService.SaveSelectedProfileElement();
}
#region Overrides of Screen
/// <inheritdoc />
protected override void OnInitialActivate()
{
((EventsConditionViewModel) Parent).Items.CollectionChanged += ItemsOnCollectionChanged;
base.OnInitialActivate();
}
/// <inheritdoc />
protected override void OnClose()
{
((EventsConditionViewModel) Parent).Items.CollectionChanged -= ItemsOnCollectionChanged;
base.OnClose();
}
#endregion
private void ItemsOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
NotifyOfPropertyChange(nameof(CanDeleteEvent));
}
}
}
@@ -1,17 +1,17 @@
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.DisplayConditions.DisplayConditionEventView"
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.DisplayConditions.Event.EventsConditionView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.DisplayConditions"
xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.DisplayConditions.Event"
xmlns:converters="clr-namespace:Artemis.UI.Converters"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:controls="clr-namespace:Artemis.VisualScripting.Editor.Controls;assembly=Artemis.VisualScripting"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance {x:Type local:DisplayConditionEventViewModel}}">
d:DataContext="{d:DesignInstance {x:Type local:EventsConditionViewModel}}">
<UserControl.Resources>
<converters:ComparisonConverter x:Key="ComparisonConverter" />
</UserControl.Resources>
@@ -22,48 +22,37 @@
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" MouseUp="{s:Action ScriptGridMouseUp}" Cursor="Hand">
<controls:VisualScriptPresenter Script="{Binding RenderProfileElement.DisplayCondition}"
AutoFitScript="True"
Visibility="{Binding RenderProfileElement.DisplayCondition, Converter={StaticResource NullToVisibilityConverter}}" />
<Border Opacity="0">
<Border.Background>
<SolidColorBrush Color="{Binding Color, Source={StaticResource MaterialDesignCardBackground}}" Opacity="0.75" />
</Border.Background>
<Border.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type Grid}, Mode=FindAncestor}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" VerticalAlignment="Center" Grid.Column="0">
Click to edit script
</TextBlock>
<materialDesign:PackIcon Kind="OpenInNew" Margin="10 " Width="30" Height="30" Grid.Column="1" VerticalAlignment="Center" />
</Grid>
</Border>
</Grid>
<TabControl Grid.Row="0"
VerticalAlignment="Stretch"
ItemsSource="{Binding Items}"
SelectedItem="{Binding ActiveItem}"
Style="{StaticResource MaterialDesignTabControl}">
<TabControl.ItemTemplate>
<DataTemplate>
<DockPanel LastChildFill="True" Margin="-15 0">
<Button DockPanel.Dock="Right"
Style="{StaticResource MaterialDesignIconForegroundButton}"
Command="{s:Action DeleteEvent}"
s:View.ActionTarget="{Binding}"
CommandParameter="{Binding}"
Width="25"
Height="25">
<materialDesign:PackIcon Kind="Close" Width="15" Height="15" Foreground="{DynamicResource MaterialDesignBody}" />
</Button>
<Label Content="{Binding DisplayName}" DockPanel.Dock="Left" />
</DockPanel>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding IsAsync=True}"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch"
IsTabStop="False"
TextElement.Foreground="{DynamicResource MaterialDesignBody}" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
<!-- Trigger mode -->
<TextBlock Grid.Row="1" Grid.Column="0" Text="Trigger mode" VerticalAlignment="Center">
@@ -0,0 +1,65 @@
using System.Linq;
using Artemis.Core;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Shared.Services;
using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions.Event
{
public class EventsConditionViewModel : Conductor<EventConditionViewModel>.Collection.OneActive
{
private readonly IConditionVmFactory _conditionVmFactory;
private readonly IProfileEditorService _profileEditorService;
public EventsConditionViewModel(EventsCondition eventsCondition, IConditionVmFactory conditionVmFactory, IProfileEditorService profileEditorService)
{
_conditionVmFactory = conditionVmFactory;
_profileEditorService = profileEditorService;
EventsCondition = eventsCondition;
}
public EventsCondition EventsCondition { get; }
public TimeLineEventOverlapMode EventOverlapMode
{
get => EventsCondition.EventOverlapMode;
set
{
if (EventsCondition.EventOverlapMode == value) return;
EventsCondition.EventOverlapMode = value;
_profileEditorService.SaveSelectedProfileElement();
}
}
public void AddEvent()
{
EventCondition eventCondition = EventsCondition.AddEventCondition();
Items.Add(_conditionVmFactory.EventConditionViewModel(eventCondition));
_profileEditorService.SaveSelectedProfileElement();
}
public void DeleteEvent(EventConditionViewModel eventConditionViewModel)
{
EventsCondition.RemoveEventCondition(eventConditionViewModel.EventCondition);
Items.Remove(eventConditionViewModel);
_profileEditorService.SaveSelectedProfileElement();
}
#region Overrides of Screen
/// <inheritdoc />
protected override void OnInitialActivate()
{
if (!EventsCondition.Events.Any())
EventsCondition.AddEventCondition();
foreach (EventCondition eventCondition in EventsCondition.Events)
Items.Add(_conditionVmFactory.EventConditionViewModel(eventCondition));
base.OnInitialActivate();
}
#endregion
}
}
@@ -0,0 +1,181 @@
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.DisplayConditions.Static.StaticConditionView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.DisplayConditions.Static"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:controls="clr-namespace:Artemis.VisualScripting.Editor.Controls;assembly=Artemis.VisualScripting"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:converters="clr-namespace:Artemis.UI.Converters"
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance {x:Type local:StaticConditionViewModel}}">
<UserControl.Resources>
<converters:InverseBooleanConverter x:Key="InverseBooleanConverter" />
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" MouseUp="{s:Action ScriptGridMouseUp}" Cursor="Hand">
<controls:VisualScriptPresenter Script="{Binding StaticCondition.Script}" AutoFitScript="True"/>
<Border Opacity="0">
<Border.Background>
<SolidColorBrush Color="{Binding Color, Source={StaticResource MaterialDesignCardBackground}}" Opacity="0.75" />
</Border.Background>
<Border.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type Grid}, Mode=FindAncestor}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" VerticalAlignment="Center" Grid.Column="0">
Click to edit script
</TextBlock>
<materialDesign:PackIcon Kind="OpenInNew" Margin="10 " Width="30" Height="30" Grid.Column="1" VerticalAlignment="Center" />
</Grid>
</Border>
</Grid>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="22" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MinWidth="140" />
<ColumnDefinition Width="*" MinWidth="170" />
</Grid.ColumnDefinitions>
<!-- Play mode -->
<TextBlock Grid.Column="0" Text="Play mode" VerticalAlignment="Center">
<TextBlock.ToolTip>
<ToolTip Placement="Center" VerticalOffset="-30">
<TextBlock>
Configure how the layer should act while the conditions above are met
</TextBlock>
</ToolTip>
</TextBlock.ToolTip>
</TextBlock>
<materialDesign:ColorZone Grid.Row="1" Grid.Column="0" Mode="Standard" CornerRadius="3" Margin="0 0 2 0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<RadioButton Grid.Column="0"
Style="{StaticResource MaterialDesignTabRadioButton}"
IsChecked="{Binding DisplayContinuously}"
MinWidth="0"
Padding="5 0">
<RadioButton.ToolTip>
<ToolTip Placement="Center" VerticalOffset="-40">
<TextBlock>
Continue repeating the main segment of the timeline while the condition is met
</TextBlock>
</ToolTip>
</RadioButton.ToolTip>
<TextBlock VerticalAlignment="Center" FontSize="12">
<materialDesign:PackIcon Kind="Repeat" VerticalAlignment="Center" Margin="-3 0 0 -3" />
REPEAT
</TextBlock>
</RadioButton>
<RadioButton Grid.Column="1"
Style="{StaticResource MaterialDesignTabRadioButton}"
IsChecked="{Binding DisplayContinuously, Converter={StaticResource InverseBooleanConverter}}"
MinWidth="0"
Padding="5 0">
<RadioButton.ToolTip>
<ToolTip Placement="Center" VerticalOffset="-40">
<TextBlock>
Only play the timeline once when the condition is met
</TextBlock>
</ToolTip>
</RadioButton.ToolTip>
<TextBlock VerticalAlignment="Center" FontSize="12">
<materialDesign:PackIcon Kind="StopwatchOutline" VerticalAlignment="Center" Margin="-3 0 0 -3" />
ONCE
</TextBlock>
</RadioButton>
</Grid>
</materialDesign:ColorZone>
<!-- Stop mode -->
<TextBlock Grid.Row="0" Grid.Column="1" Text="Stop mode">
<TextBlock.ToolTip>
<ToolTip Placement="Center" VerticalOffset="-30">
<TextBlock>
Configure how the layer should act when the conditions above are no longer met
</TextBlock>
</ToolTip>
</TextBlock.ToolTip>
</TextBlock>
<materialDesign:ColorZone Grid.Row="1" Grid.Column="1" Mode="Standard" CornerRadius="3" Margin="2 0 0 0" HorizontalAlignment="Stretch">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition MinWidth="100" />
</Grid.ColumnDefinitions>
<RadioButton Grid.Column="0"
Style="{StaticResource MaterialDesignTabRadioButton}"
IsChecked="{Binding AlwaysFinishTimeline}"
MinWidth="0"
Padding="5 0">
<RadioButton.ToolTip>
<ToolTip Placement="Center" VerticalOffset="-40">
<TextBlock>
When conditions are no longer met, finish the the current run of the main timeline
</TextBlock>
</ToolTip>
</RadioButton.ToolTip>
<TextBlock VerticalAlignment="Center" FontSize="12">
<materialDesign:PackIcon Kind="PlayOutline" VerticalAlignment="Center" Margin="-3 0 0 -3" />
FINISH
</TextBlock>
</RadioButton>
<RadioButton Grid.Column="1"
Style="{StaticResource MaterialDesignTabRadioButton}"
IsChecked="{Binding AlwaysFinishTimeline, Converter={StaticResource InverseBooleanConverter}}"
MinWidth="0"
Padding="5 0">
<RadioButton.ToolTip>
<ToolTip Placement="Center" VerticalOffset="-40">
<TextBlock>
When conditions are no longer met, skip to the end segment of the timeline
</TextBlock>
</ToolTip>
</RadioButton.ToolTip>
<TextBlock VerticalAlignment="Center" FontSize="12">
<materialDesign:PackIcon Kind="SkipNextOutline" VerticalAlignment="Center" Margin="-3 0 0 -3" />
SKIP TO END
</TextBlock>
</RadioButton>
</Grid>
</materialDesign:ColorZone>
</Grid>
</Grid>
</UserControl>
@@ -0,0 +1,60 @@
using System.Windows.Input;
using Artemis.Core;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Shared.Services;
using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions.Static
{
public class StaticConditionViewModel : Screen
{
private readonly IWindowManager _windowManager;
private readonly INodeVmFactory _nodeVmFactory;
private readonly IProfileEditorService _profileEditorService;
private readonly RenderProfileElement _renderProfileElement;
public StaticConditionViewModel(StaticCondition staticCondition, IWindowManager windowManager, INodeVmFactory nodeVmFactory, IProfileEditorService profileEditorService)
{
_windowManager = windowManager;
_nodeVmFactory = nodeVmFactory;
_profileEditorService = profileEditorService;
_renderProfileElement = (RenderProfileElement) staticCondition.ProfileElement;
StaticCondition = staticCondition;
}
public StaticCondition StaticCondition { get; }
public bool DisplayContinuously
{
get => _renderProfileElement.Timeline.PlayMode == TimelinePlayMode.Repeat;
set
{
TimelinePlayMode playMode = value ? TimelinePlayMode.Repeat : TimelinePlayMode.Once;
if (_renderProfileElement.Timeline.PlayMode == playMode) return;
_renderProfileElement.Timeline.PlayMode = playMode;
_profileEditorService.SaveSelectedProfileElement();
}
}
public bool AlwaysFinishTimeline
{
get => _renderProfileElement?.Timeline.StopMode == TimelineStopMode.Finish;
set
{
TimelineStopMode stopMode = value ? TimelineStopMode.Finish : TimelineStopMode.SkipToEnd;
if (_renderProfileElement.Timeline.StopMode == stopMode) return;
_renderProfileElement.Timeline.StopMode = stopMode;
_profileEditorService.SaveSelectedProfileElement();
}
}
public void ScriptGridMouseUp(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton != MouseButton.Left)
return;
_windowManager.ShowDialog(_nodeVmFactory.NodeScriptWindowViewModel(StaticCondition.Script));
_profileEditorService.SaveSelectedProfileElement();
}
}
}