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

Started implementing logic behind the timeline UI

This commit is contained in:
SpoinkyNL 2020-01-05 22:10:37 +01:00
parent e67b44b741
commit 8f438abe49
31 changed files with 501 additions and 408 deletions

View File

@ -12,7 +12,7 @@
<AssemblyName>Artemis.Core</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ShouldIncludeNativeSkiaSharp>false</ShouldIncludeNativeSkiaSharp>
<ShouldIncludeNativeSkiaSharp>false</ShouldIncludeNativeSkiaSharp>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFrameworkProfile />
@ -149,6 +149,7 @@
<Compile Include="Extensions\TypeExtensions.cs" />
<Compile Include="JsonConverters\SKColorConverter.cs" />
<Compile Include="Models\DataModelDescription.cs" />
<Compile Include="Models\Profile\Keyframe.cs" />
<Compile Include="Models\Profile\LayerShapes\Ellipse.cs" />
<Compile Include="Models\Profile\LayerShapes\Fill.cs" />
<Compile Include="Models\Profile\LayerShapes\Polygon.cs" />
@ -160,6 +161,7 @@
<Compile Include="Ninject\LoggerProvider.cs" />
<Compile Include="Ninject\PluginSettingsProvider.cs" />
<Compile Include="Ninject\SettingsServiceProvider.cs" />
<Compile Include="Models\Profile\LayerProperty.cs" />
<Compile Include="Plugins\Abstract\ModuleDataModel.cs" />
<Compile Include="Plugins\Abstract\ModuleViewModel.cs" />
<Compile Include="Plugins\Abstract\ProfileModule.cs" />

View File

@ -0,0 +1,13 @@
using System;
namespace Artemis.Core.Models.Profile
{
public class Keyframe
{
public Layer Layer { get; set; }
public LayerProperty Property { get; set; }
public TimeSpan Position { get; set; }
public object Value { get; set; }
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.Models.Profile
{
public class LayerProperty
{
internal LayerProperty(Layer layer, LayerProperty parent)
{
Layer = layer;
Parent = parent;
Children = new List<LayerProperty>();
}
public Layer Layer { get; }
public LayerProperty Parent { get; }
public List<LayerProperty> Children { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public Type Type { get; set; }
public object BaseValue { get; set; }
public List<Keyframe> Keyframes { get; set; }
}
}

View File

@ -159,23 +159,14 @@
<DependentUpon>LayerPropertiesView.xaml</DependentUpon>
</Compile>
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\LayerPropertiesViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\Controls\TimelineTime.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\LayerPropertiesTimelineView.xaml.cs">
<DependentUpon>LayerPropertiesTimelineView.xaml</DependentUpon>
</Compile>
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\LayerPropertiesTimelineViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelineKeyframeView.xaml.cs">
<DependentUpon>TimelineKeyframeView.xaml</DependentUpon>
</Compile>
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelineKeyframeViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePropertyRailView.xaml.cs">
<DependentUpon>TimelinePropertyRailView.xaml</DependentUpon>
</Compile>
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePropertyRailViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePropertyView.xaml.cs">
<DependentUpon>TimelinePropertyView.xaml</DependentUpon>
</Compile>
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePropertyViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\LayerPropertyViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeChildViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeParentViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTrackKeyframeViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTimelineHeader.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTrackViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTimelineViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\Visualization\CanvasViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\Visualization\ProfileLayerView.xaml.cs">
<DependentUpon>ProfileLayerView.xaml</DependentUpon>
@ -310,19 +301,19 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\LayerPropertiesTimelineView.xaml">
<Page Include="Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeChildView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelineKeyframeView.xaml">
<Page Include="Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePropertyRailView.xaml">
<Page Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTrackView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePropertyView.xaml">
<Page Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTimelineView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>

View File

@ -1,13 +1,78 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.LayerPropertiesView"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties"
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
xmlns:timeline="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<ContentControl s:View.Model="{Binding Timeline}" />
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<!-- Left side -->
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="56" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Misc controls & time display -->
<StackPanel Grid.Row="0">
<TextBlock>A play button, current time etc. etc.!</TextBlock>
</StackPanel>
<!-- Properties tree -->
<ScrollViewer Grid.Row="1" x:Name="PropertyTreeScrollViewer">
<ContentControl s:View.Model="{Binding PropertyTree}" />
</ScrollViewer>
</Grid>
<!-- Right side -->
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="56" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- Timeline header -->
<ScrollViewer Grid.Row="0" x:Name="TimelineHeaderScrollViewer" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
<StackPanel>
<!-- Caret -->
<Canvas ZIndex="10" Height="25" Margin="{Binding TimeCaretPosition}" ClipToBounds="False">
<Polygon Points="-10,0 0,20, 10,00" Fill="{StaticResource SecondaryAccentBrush}" />
<Line X1="0" X2="0" Y1="0" Y2="10000" StrokeThickness="2" Stroke="{StaticResource SecondaryAccentBrush}" />
</Canvas>
<!-- Time -->
<timeline:PropertyTimelineHeader Fill="{DynamicResource MaterialDesignBody}"
PixelsPerSecond="{Binding PixelsPerSecond}"
HorizontalOffset="{Binding ContentHorizontalOffset, ElementName=TimelineHeaderScrollViewer}"
VisibleWidth="{Binding ActualWidth, ElementName=TimelineHeaderScrollViewer}" />
</StackPanel>
</ScrollViewer>
<!-- Timeline rails -->
<ScrollViewer Grid.Row="1" x:Name="TimelineRailsScrollViewer">
<ContentControl s:View.Model="{Binding PropertyTimeline}" />
</ScrollViewer>
<!-- Zoom control -->
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right">
<TextBlock Text="{Binding PixelsPerSecond}" VerticalAlignment="Center" />
<Slider Orientation="Horizontal"
HorizontalAlignment="Right"
Margin="10"
TickFrequency="5"
Minimum="1"
Maximum="600"
Value="{Binding PixelsPerSecond}"
Width="600" />
</StackPanel>
</Grid>
</Grid>
</UserControl>
</UserControl>

View File

@ -24,5 +24,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
{
InitializeComponent();
}
// Keeping the scroll viewers in sync is up to the view, not a viewmodel concern
}
}

View File

@ -1,4 +1,7 @@
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline;
using System;
using System.Windows;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
{
@ -6,9 +9,44 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
{
public LayerPropertiesViewModel()
{
Timeline = new LayerPropertiesTimelineViewModel();
PropertyTree = new PropertyTreeViewModel(this);
PropertyTimeline = new PropertyTimelineViewModel(this);
}
public LayerPropertiesTimelineViewModel Timeline { get; set; }
public TimeSpan CurrentTime { get; set; }
public int PixelsPerSecond { get; set; }
public Thickness TimeCaretPosition
{
get => new Thickness(CurrentTime.TotalSeconds * PixelsPerSecond, 0, 0, 0);
set => CurrentTime = TimeSpan.FromSeconds(value.Left / PixelsPerSecond);
}
public PropertyTreeViewModel PropertyTree { get; set; }
public PropertyTimelineViewModel PropertyTimeline { get; set; }
private void CreateTestValues()
{
// var propertyRailViewModels = new List<TimelinePropertyRailViewModel>();
// for (var i = 0; i < 20; i++)
// propertyRailViewModels.Add(new TimelinePropertyRailViewModel());
//
// TimelinePropertyRailViewModels.AddRange(propertyRailViewModels);
//
// // Transform will be the only built-in properties so test with that
// var testVm = new TimelinePropertiesViewModel { PropertiesName = "Transform" };
// testVm.Properties.Add(new TimelinePropertyViewModel { PropertyName = "Anchor Point" });
// testVm.Properties.Add(new TimelinePropertyViewModel { PropertyName = "Position" });
// testVm.Properties.Add(new TimelinePropertyViewModel { PropertyName = "Scale" });
// testVm.Properties.Add(new TimelinePropertyViewModel { PropertyName = "Rotation" });
// testVm.Properties.Add(new TimelinePropertyViewModel { PropertyName = "Opacity" });
// // Purely for testing, add a nested property
// var subTestVm = new TimelinePropertiesViewModel() { PropertiesName = "Sub Properties" };
// subTestVm.Properties.Add(new TimelinePropertyViewModel { PropertyName = "Sub Property 1" });
// subTestVm.Properties.Add(new TimelinePropertyViewModel { PropertyName = "Sub Property 2" });
// subTestVm.Properties.Add(new TimelinePropertyViewModel { PropertyName = "Sub Property 3" });
// testVm.Properties.Add(subTestVm);
//
// TimelinePropertiesViewModels.Add(testVm);
}
}
}

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Artemis.Core.Models.Profile;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
{
public class LayerPropertyViewModel : PropertyChangedBase
{
public LayerProperty LayerProperty { get; }
public LayerPropertyViewModel(LayerProperty layerProperty)
{
LayerProperty = layerProperty;
}
public bool IsCollapsed { get; set; }
}
}

View File

@ -0,0 +1,45 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyTreeChildView"
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.Module.ProfileEditor.LayerProperties.PropertyTree"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="20" d:DesignWidth="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ToggleButton Grid.Column="0"
Style="{StaticResource MaterialDesignFlatToggleButton}"
ToolTip="Toggle key-framing"
Width="18"
Height="18"
IsChecked="{Binding KeyframesEnabled}"
VerticalAlignment="Center" Padding="-25">
<materialDesign:PackIcon Kind="Stopwatch" Height="13" Width="13" />
</ToggleButton>
<TextBlock Grid.Column="1"
Margin="5,0,0,0"
Padding="0,0,5,0"
VerticalAlignment="Center"
TextTrimming="CharacterEllipsis"
Text="{Binding PropertyName}"
HorizontalAlignment="Left" />
<Button Grid.Column="2"
Style="{StaticResource MaterialDesignOutlinedButton}"
Margin="0,1,0,1.2"
Padding="0"
Width="110"
Height="17"
ToolTip="Change the property's data binding"
VerticalAlignment="Center">
<TextBlock FontSize="10">DATA BINDING</TextBlock>
</Button>
</Grid>
</UserControl>

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
{
public class PropertyTreeChildViewModel : PropertyChangedBase
{
public LayerPropertyViewModel LayerPropertyViewModel { get; }
public PropertyTreeChildViewModel(LayerPropertyViewModel layerPropertyViewModel)
{
LayerPropertyViewModel = layerPropertyViewModel;
}
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
{
public class PropertyTreeParentViewModel : PropertyTreeItemViewModel
{
public string Name { get; set; }
public PropertyTreeItemViewModel Children { get; set; }
}
public class PropertyTreeItemViewModel : PropertyChangedBase
{
}
}

View File

@ -0,0 +1,36 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyTreeView"
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.Module.ProfileEditor.LayerProperties.PropertyTree"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:timeline="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:profile="clr-namespace:Artemis.Core.Models.Profile;assembly=Artemis.Core"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<TreeView ItemsSource="{Binding PropertyTreeItemViewModels}"
HorizontalContentAlignment="Stretch"
materialDesign:RippleAssist.IsDisabled="True"
Background="{DynamicResource MaterialDesignToolBarBackground}">
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem" BasedOn="{StaticResource MaterialDesignTreeViewItem}">
<!-- TODO: Disable hover -->
<Setter Property="Focusable" Value="False" />
<Setter Property="Padding" Value="2" />
<Setter Property="BorderBrush" Value="{x:Null}" />
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<!-- Parents only show their name and children -->
<HierarchicalDataTemplate DataType="{x:Type local:PropertyTreeParentViewModel}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}" Margin="3 2" />
</HierarchicalDataTemplate>
<!-- Children show their full view -->
<DataTemplate DataType="{x:Type local:PropertyTreeChildViewModel}">
<ContentControl s:View.Model="{Binding}" />
</DataTemplate>
</TreeView.Resources>
</TreeView>
</UserControl>

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
{
public class PropertyTreeViewModel : PropertyChangedBase
{
public LayerPropertiesViewModel LayerPropertiesViewModel { get; }
public BindableCollection<PropertyTreeChildViewModel> PropertyTreeItemViewModels { get; set; }
public PropertyTreeViewModel(LayerPropertiesViewModel layerPropertiesViewModel)
{
LayerPropertiesViewModel = layerPropertiesViewModel;
}
}
}

View File

@ -1,62 +0,0 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline.LayerPropertiesTimelineView"
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:timeline="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:controls="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance timeline:LayerPropertiesTimelineViewModel}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollViewer x:Name="Keyframes"
Grid.Row="0"
HorizontalScrollBarVisibility="Visible"
VerticalScrollBarVisibility="Hidden">
<StackPanel x:Name="KeyframesContainer">
<!-- Time caret -->
<Canvas ZIndex="10" Height="25" Margin="{Binding TimeCaretPosition}">
<Polygon Points="-10,0 0,20, 10,00" Fill="{StaticResource SecondaryAccentBrush}" />
<Line X1="0" X2="0" Y1="0" Y2="10000" StrokeThickness="2" Stroke="{StaticResource SecondaryAccentBrush}" />
</Canvas>
<!-- Time -->
<controls:TimelineTime Height="30"
Fill="{DynamicResource MaterialDesignBody}"
PixelsPerSecond="{Binding PixelsPerSecond}"
HorizontalOffset="{Binding ContentHorizontalOffset, ElementName=Keyframes}"
VisibleWidth="{Binding ActualWidth, ElementName=Keyframes}" />
<!-- Keyframes -->
<ItemsControl ItemsSource="{Binding TimelinePropertyRailViewModels}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding}" HorizontalAlignment="Stretch" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
<StackPanel Grid.Row="1"
Orientation="Horizontal"
HorizontalAlignment="Right">
<TextBlock Text="{Binding PixelsPerSecond}" />
<Slider Grid.Row="2"
Orientation="Horizontal"
HorizontalAlignment="Right"
Margin="10"
TickFrequency="5"
Minimum="1"
Maximum="600"
Value="{Binding PixelsPerSecond}"
Width="600" />
</StackPanel>
</Grid>
</UserControl>

View File

@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{
/// <summary>
/// Interaction logic for LayerPropertiesTimelineView.xaml
/// </summary>
public partial class LayerPropertiesTimelineView : UserControl
{
public LayerPropertiesTimelineView()
{
InitializeComponent();
}
}
}

View File

@ -1,56 +0,0 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Markup;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{
public class LayerPropertiesTimelineViewModel : PropertyChangedBase
{
private int _pixelsPerSecond = 1;
public LayerPropertiesTimelineViewModel()
{
TimelinePropertyRailViewModels = new BindableCollection<TimelinePropertyRailViewModel>();
TimeCaretTime = TimeSpan.FromSeconds(3);
CreateTestValues();
Update();
}
public int PixelsPerSecond
{
get => _pixelsPerSecond;
set
{
_pixelsPerSecond = value;
Update();
}
}
public TimeSpan TimeCaretTime { get; set; }
public Thickness TimeCaretPosition
{
get => new Thickness(TimeCaretTime.TotalSeconds * PixelsPerSecond, 0, 0, 0);
set => TimeCaretTime = TimeSpan.FromSeconds(value.Left / PixelsPerSecond);
}
public BindableCollection<TimelinePropertyRailViewModel> TimelinePropertyRailViewModels { get; set; }
private void CreateTestValues()
{
var propertyRailViewModels = new List<TimelinePropertyRailViewModel>();
for (var i = 0; i < 20; i++)
propertyRailViewModels.Add(new TimelinePropertyRailViewModel());
TimelinePropertyRailViewModels.AddRange(propertyRailViewModels);
}
public void Update()
{
foreach (var timelinePropertyRailViewModel in TimelinePropertyRailViewModels)
timelinePropertyRailViewModel.Update(PixelsPerSecond);
}
}
}

View File

@ -16,11 +16,11 @@ using System.Windows.Shapes;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{
/// <summary>
/// Interaction logic for TimelineKeyframeView.xaml
/// Interaction logic for PropertyRailItemView.xaml
/// </summary>
public partial class TimelineKeyframeView : UserControl
public partial class PropertyTrackView : UserControl
{
public TimelineKeyframeView()
public PropertyTrackView()
{
InitializeComponent();
}

View File

@ -4,31 +4,30 @@ using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline.Controls
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{
public class TimelineTime : FrameworkElement
public class PropertyTimelineHeader : FrameworkElement
{
public static readonly DependencyProperty FillProperty = DependencyProperty.Register(nameof(Fill), typeof(Brush), typeof(TimelineTime),
public static readonly DependencyProperty FillProperty = DependencyProperty.Register(nameof(Fill), typeof(Brush), typeof(PropertyTimelineHeader),
new FrameworkPropertyMetadata(default(Brush), FrameworkPropertyMetadataOptions.AffectsRender));
public static readonly DependencyProperty FontFamilyProperty = DependencyProperty.Register(nameof(FontFamily), typeof(FontFamily), typeof(TimelineTime),
public static readonly DependencyProperty FontFamilyProperty = DependencyProperty.Register(nameof(FontFamily), typeof(FontFamily), typeof(PropertyTimelineHeader),
new FrameworkPropertyMetadata(TextBlock.FontFamilyProperty.DefaultMetadata.DefaultValue, FrameworkPropertyMetadataOptions.AffectsRender));
public static readonly DependencyProperty PixelsPerSecondProperty = DependencyProperty.Register(nameof(PixelsPerSecond), typeof(int), typeof(TimelineTime),
public static readonly DependencyProperty PixelsPerSecondProperty = DependencyProperty.Register(nameof(PixelsPerSecond), typeof(int), typeof(PropertyTimelineHeader),
new FrameworkPropertyMetadata(default(int), FrameworkPropertyMetadataOptions.AffectsRender));
public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.Register(nameof(HorizontalOffset), typeof(double), typeof(TimelineTime),
public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.Register(nameof(HorizontalOffset), typeof(double), typeof(PropertyTimelineHeader),
new FrameworkPropertyMetadata(default(double), FrameworkPropertyMetadataOptions.AffectsRender));
public static readonly DependencyProperty VisibleWidthProperty = DependencyProperty.Register(nameof(VisibleWidth), typeof(double), typeof(TimelineTime),
public static readonly DependencyProperty VisibleWidthProperty = DependencyProperty.Register(nameof(VisibleWidth), typeof(double), typeof(PropertyTimelineHeader),
new FrameworkPropertyMetadata(default(double), FrameworkPropertyMetadataOptions.AffectsRender));
private double _subd1;
private double _subd2;
private double _subd3;
public Brush Fill
{
get => (Brush) GetValue(FillProperty);
@ -80,7 +79,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline.Contr
// Add a 100px margin to allow the text to partially render when needed
if (x < HorizontalOffset - 100 || x > HorizontalOffset + width)
continue;
var t = TimeSpan.FromSeconds((i * units - offsetUnits) / PixelsPerSecond + frameStart);
// 0.00 is always formatted as 0.00
if (t == TimeSpan.Zero)
@ -123,8 +122,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline.Contr
if (x == 1)
drawingContext.DrawText(formattedText, new Point(x, 2));
else
drawingContext.DrawText(formattedText, new Point(x - formattedText.Width /2, 2));
drawingContext.DrawText(formattedText, new Point(x - formattedText.Width / 2, 2));
}
private void UpdateTimeScale()

View File

@ -0,0 +1,33 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline.PropertyTimelineView"
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.Module.ProfileEditor.LayerProperties.Timeline"
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
d:DesignHeight="25"
d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:PropertyTimelineViewModel}">
<ItemsControl ItemsSource="{Binding TimelineKeyframeViewModels}"
Width="{Binding Width}"
MinWidth="{Binding ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ScrollViewer}}"
Background="{DynamicResource MaterialDesignToolBarBackground}"
HorizontalAlignment="Left">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Canvas.Left" Value="{Binding X}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>

View File

@ -0,0 +1,29 @@
using System;
using System.Linq;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{
public class PropertyTimelineViewModel : PropertyChangedBase
{
public PropertyTimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel)
{
LayerPropertiesViewModel = layerPropertiesViewModel;
RailItemViewModels = new BindableCollection<PropertyTrackViewModel>();
}
public LayerPropertiesViewModel LayerPropertiesViewModel { get; }
public double Width { get; set; }
public BindableCollection<PropertyTrackViewModel> RailItemViewModels { get; set; }
public void UpdateEndTime()
{
// End time is the last keyframe + 10 sec
var lastKeyFrame = RailItemViewModels.SelectMany(r => r.KeyframeViewModels).OrderByDescending(t => t.Keyframe.Position).FirstOrDefault();
var endTime = lastKeyFrame?.Keyframe.Position.Add(new TimeSpan(0, 0, 0, 10)) ?? TimeSpan.FromSeconds(10);
Width = endTime.TotalSeconds * LayerPropertiesViewModel.PixelsPerSecond;
}
}
}

View File

@ -0,0 +1,25 @@
using System;
using Artemis.Core.Models.Profile;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{
public class PropertyTrackKeyframeViewModel : PropertyChangedBase
{
public PropertyTrackKeyframeViewModel(Keyframe keyframe)
{
Keyframe = keyframe;
}
public Keyframe Keyframe { get; }
public double X { get; set; }
public string Timestamp { get; set; }
public void Update(int pixelsPerSecond)
{
X = pixelsPerSecond * Keyframe.Position.TotalSeconds;
Timestamp = $"{Math.Floor(Keyframe.Position.TotalSeconds):00}.{Keyframe.Position.Milliseconds:000}";
}
}
}

View File

@ -0,0 +1,31 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline.PropertyTrackView"
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.Module.ProfileEditor.LayerProperties.Timeline"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
d:DesignHeight="20" d:DesignWidth="600"
d:DataContext="{d:DesignInstance local:PropertyTrackViewModel}">
<ItemsControl ItemsSource="{Binding KeyframeViewModels}"
Background="{DynamicResource MaterialDesignToolBarBackground}"
HorizontalAlignment="Left">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Canvas.Left" Value="{Binding X}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Fill="{StaticResource PrimaryHueMidBrush}" Width="10" Height="10" Margin="-5,6,0,0" ToolTip="{Binding Timestamp}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>

View File

@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{
public class PropertyTrackViewModel : PropertyChangedBase
{
public PropertyTimelineViewModel PropertyTimelineViewModel { get; }
public LayerPropertyViewModel LayerPropertyViewModel { get; }
public BindableCollection<PropertyTrackKeyframeViewModel> KeyframeViewModels { get; set; }
public PropertyTrackViewModel(PropertyTimelineViewModel propertyTimelineViewModel, LayerPropertyViewModel layerPropertyViewModel)
{
PropertyTimelineViewModel = propertyTimelineViewModel;
LayerPropertyViewModel = layerPropertyViewModel;
KeyframeViewModels = new BindableCollection<PropertyTrackKeyframeViewModel>();
PopulateKeyframes();
UpdateKeyframes(propertyTimelineViewModel.LayerPropertiesViewModel.PixelsPerSecond);
}
public void PopulateKeyframes()
{
foreach (var keyframe in LayerPropertyViewModel.LayerProperty.Keyframes)
{
if (KeyframeViewModels.Any(k => k.Keyframe == keyframe))
continue;
KeyframeViewModels.Add(new PropertyTrackKeyframeViewModel(keyframe));
}
}
public void UpdateKeyframes(int pixelsPerSecond)
{
foreach (var keyframeViewModel in KeyframeViewModels)
{
keyframeViewModel.Update(pixelsPerSecond);
}
}
}
}

View File

@ -1,11 +0,0 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline.TimelineKeyframeView"
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.Module.ProfileEditor.LayerProperties.Timeline"
mc:Ignorable="d"
d:DesignHeight="50" d:DesignWidth="50"
d:DataContext="{d:DesignInstance local:TimelineKeyframeViewModel}">
<Ellipse Fill="{StaticResource PrimaryHueMidBrush}" Width="10" Height="10" Margin="-5,6,0,0" ToolTip="{Binding Timestamp}"></Ellipse>
</UserControl>

View File

@ -1,23 +0,0 @@
using System;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{
public class TimelineKeyframeViewModel : PropertyChangedBase
{
private const double BaseSize = 60.0;
public TimeSpan Position { get; set; }
public double X { get; set; }
public string Timestamp { get; set; }
public void Update(int pixelsPerSecond)
{
// var timelinePartWidth = pixelsPerSecond % BaseSize + BaseSize;
// var millisecondsPerPart = extraParts > 0 ? BaseSize * 1000 / extraParts : BaseSize * 1000;
X = pixelsPerSecond * Position.TotalSeconds;
Timestamp = $"{Math.Floor(Position.TotalSeconds):00}.{Position.Milliseconds:000}";
}
}
}

View File

@ -1,35 +0,0 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline.TimelinePropertyRailView"
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.Module.ProfileEditor.LayerProperties.Timeline"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:TimelinePropertyRailViewModel}">
<Border BorderThickness="0,1" BorderBrush="{DynamicResource MaterialDesignDivider}" Height="25" Margin="0,0,0,-1">
<ItemsControl ItemsSource="{Binding TimelineKeyframeViewModels}"
Width="{Binding Width}"
MinWidth="{Binding ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ScrollViewer}}"
Background="{DynamicResource MaterialDesignToolBarBackground}"
HorizontalAlignment="Left">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Canvas.Left" Value="{Binding X}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
</UserControl>

View File

@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{
/// <summary>
/// Interaction logic for TimelinePropertyRailView.xaml
/// </summary>
public partial class TimelinePropertyRailView : UserControl
{
public TimelinePropertyRailView()
{
InitializeComponent();
}
}
}

View File

@ -1,43 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{
public class TimelinePropertyRailViewModel : PropertyChangedBase
{
public TimelinePropertyRailViewModel()
{
TimelineKeyframeViewModels = new BindableCollection<TimelineKeyframeViewModel>();
CreateTestValues();
}
public BindableCollection<TimelineKeyframeViewModel> TimelineKeyframeViewModels { get; set; }
public double Width { get; set; }
public void CreateTestValues()
{
var keyframeViewModels = new List<TimelineKeyframeViewModel>();
for (var i = 0; i < 20; i++)
{
keyframeViewModels.Add(new TimelineKeyframeViewModel());
keyframeViewModels[i].Position = TimeSpan.FromSeconds(i);
}
TimelineKeyframeViewModels.AddRange(keyframeViewModels);
}
public void Update(int pixelsPerSecond)
{
foreach (var timelineKeyframeViewModel in TimelineKeyframeViewModels)
timelineKeyframeViewModel.Update(pixelsPerSecond);
// End time is the last keyframe + 10 sec
var lastKeyFrame = TimelineKeyframeViewModels.OrderByDescending(t => t.Position).FirstOrDefault();
var endTime = lastKeyFrame?.Position.Add(new TimeSpan(0, 0, 0, 10)) ?? TimeSpan.FromSeconds(10);
Width = endTime.TotalSeconds * pixelsPerSecond;
}
}
}

View File

@ -1,37 +0,0 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline.TimelinePropertyView"
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.Module.ProfileEditor.LayerProperties.Timeline"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:TimelinePropertyViewModel}">
<Border BorderThickness="0,1" BorderBrush="{DynamicResource MaterialDesignDivider}" Height="25" Margin="0,0,0,-1">
<StackPanel Orientation="Horizontal">
<Button Style="{StaticResource MaterialDesignFloatingActionMiniButton}"
HorizontalAlignment="Left"
ToolTip="MaterialDesignFloatingActionMiniButton"
Width="21"
Height="21">
<materialDesign:PackIcon
Kind="Stopwatch"
Height="14"
Width="14" />
</Button>
<TextBlock Margin="5,0,0,0" Padding="0,0,5,0" VerticalAlignment="Center" Width="150" TextTrimming="CharacterEllipsis">Lorem ipsum dolor sit amet, consectetur adipisicing </TextBlock>
<Button Style="{StaticResource MaterialDesignOutlinedButton}"
Margin="0,1,0,1.2"
Padding="0"
Width="110"
Height="21"
ToolTip="Change the property's data binding">
<TextBlock FontSize="10">DATA BINDING</TextBlock>
</Button>
</StackPanel>
</Border>
</UserControl>

View File

@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{
/// <summary>
/// Interaction logic for TimelinePropertyView.xaml
/// </summary>
public partial class TimelinePropertyView : UserControl
{
public TimelinePropertyView()
{
InitializeComponent();
}
}
}

View File

@ -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.Module.ProfileEditor.LayerProperties.Timeline
{
public class TimelinePropertyViewModel : PropertyChangedBase
{
}
}