mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Added timeline scrolling
Added timeline caret
This commit is contained in:
parent
884bd0f03b
commit
615f5b0b40
@ -18,13 +18,17 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline.Contr
|
||||
new FrameworkPropertyMetadata(default(int), FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
|
||||
public static readonly DependencyProperty FrameStartProperty = DependencyProperty.Register(nameof(FrameStart), typeof(int), typeof(TimelineTime),
|
||||
new FrameworkPropertyMetadata(default(int), FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.Register(nameof(HorizontalOffset), typeof(double), typeof(TimelineTime),
|
||||
new FrameworkPropertyMetadata(default(double), FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public static readonly DependencyProperty VisibleWidthProperty = DependencyProperty.Register(nameof(VisibleWidth), typeof(double), typeof(TimelineTime),
|
||||
new FrameworkPropertyMetadata(default(double), FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
private double _subd1;
|
||||
private double _subd2;
|
||||
private double _subd3;
|
||||
|
||||
|
||||
public Brush Fill
|
||||
{
|
||||
get => (Brush) GetValue(FillProperty);
|
||||
@ -43,31 +47,45 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline.Contr
|
||||
set => SetValue(PixelsPerSecondProperty, value);
|
||||
}
|
||||
|
||||
public int FrameStart
|
||||
public double HorizontalOffset
|
||||
{
|
||||
get => (int) GetValue(FrameStartProperty);
|
||||
set => SetValue(FrameStartProperty, value);
|
||||
get => (double) GetValue(HorizontalOffsetProperty);
|
||||
set => SetValue(HorizontalOffsetProperty, value);
|
||||
}
|
||||
|
||||
public double VisibleWidth
|
||||
{
|
||||
get => (double) GetValue(VisibleWidthProperty);
|
||||
set => SetValue(VisibleWidthProperty, value);
|
||||
}
|
||||
|
||||
// TODO: Does this get called when the size changes?
|
||||
protected override void OnRender(DrawingContext drawingContext)
|
||||
{
|
||||
SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
|
||||
base.OnRender(drawingContext);
|
||||
UpdateTimeScale();
|
||||
|
||||
var linePen = new Pen(Fill, 1);
|
||||
var width = RenderSize.Width;
|
||||
var width = HorizontalOffset + VisibleWidth;
|
||||
var frameStart = 0;
|
||||
|
||||
var units = PixelsPerSecond / _subd1;
|
||||
var offsetUnits = FrameStart * PixelsPerSecond % units;
|
||||
var offsetUnits = frameStart * PixelsPerSecond % units;
|
||||
|
||||
// Labels
|
||||
var count = (width + offsetUnits) / units;
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var x = i * units - offsetUnits;
|
||||
var t = TimeSpan.FromSeconds((i * units - offsetUnits) / PixelsPerSecond + FrameStart);
|
||||
if (PixelsPerSecond > 200)
|
||||
var x = i * units - offsetUnits + 1;
|
||||
// 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)
|
||||
RenderLabel(drawingContext, "0.00", x);
|
||||
else if (PixelsPerSecond > 200)
|
||||
RenderLabel(drawingContext, $"{Math.Floor(t.TotalSeconds):00}.{t.Milliseconds:000}", x);
|
||||
else if (PixelsPerSecond > 60)
|
||||
RenderLabel(drawingContext, $"{Math.Floor(t.TotalSeconds):00}.{t.Milliseconds:000}", x);
|
||||
@ -80,8 +98,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline.Contr
|
||||
count = (width + offsetUnits) / units;
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var x = i * units - offsetUnits;
|
||||
drawingContext.DrawLine(linePen, new Point(x, 15), new Point(x, 30));
|
||||
var x = i * units - offsetUnits + 1;
|
||||
if (x > HorizontalOffset && x < HorizontalOffset + width)
|
||||
drawingContext.DrawLine(linePen, new Point(x, 20), new Point(x, 30));
|
||||
}
|
||||
|
||||
// Small ticks
|
||||
@ -91,8 +110,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline.Contr
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
if (Math.Abs(i % mul) < 0.001) continue;
|
||||
var x = i * units - offsetUnits;
|
||||
drawingContext.DrawLine(linePen, new Point(x, 22), new Point(x, 30));
|
||||
var x = i * units - offsetUnits + 1;
|
||||
if (x > HorizontalOffset && x < HorizontalOffset + width)
|
||||
drawingContext.DrawLine(linePen, new Point(x, 25), new Point(x, 30));
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,7 +120,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline.Contr
|
||||
{
|
||||
var typeFace = new Typeface(FontFamily, new FontStyle(), new FontWeight(), new FontStretch());
|
||||
var formattedText = new FormattedText(text, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, typeFace, 9, Fill, null, VisualTreeHelper.GetDpi(this).PixelsPerDip);
|
||||
drawingContext.DrawText(formattedText, new Point(x, 0));
|
||||
if (x == 1)
|
||||
drawingContext.DrawText(formattedText, new Point(x, 2));
|
||||
else
|
||||
drawingContext.DrawText(formattedText, new Point(x - formattedText.Width /2, 2));
|
||||
|
||||
}
|
||||
|
||||
private void UpdateTimeScale()
|
||||
|
||||
@ -9,36 +9,6 @@
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
d:DataContext="{d:DesignInstance timeline:LayerPropertiesTimelineViewModel}">
|
||||
<UserControl.Resources>
|
||||
<Style x:Key="ItemsControlVirtualizedStyle" TargetType="ItemsControl">
|
||||
<Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True" />
|
||||
<Setter Property="ScrollViewer.CanContentScroll" Value="True" />
|
||||
<Setter Property="ItemsPanel">
|
||||
<Setter.Value>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ItemsControl">
|
||||
<Border
|
||||
BorderThickness="{TemplateBinding Border.BorderThickness}"
|
||||
Padding="{TemplateBinding Control.Padding}"
|
||||
BorderBrush="{TemplateBinding Border.BorderBrush}"
|
||||
Background="{TemplateBinding Panel.Background}"
|
||||
SnapsToDevicePixels="True">
|
||||
<ScrollViewer Padding="{TemplateBinding Control.Padding}" Focusable="False">
|
||||
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
@ -48,15 +18,24 @@
|
||||
<ScrollViewer x:Name="Keyframes"
|
||||
Grid.Row="0"
|
||||
HorizontalScrollBarVisibility="Visible"
|
||||
VerticalScrollBarVisibility="Hidden"
|
||||
Padding="5 0 5 0">
|
||||
<StackPanel>
|
||||
<controls:TimelineTime Height="30" Fill="{StaticResource MaterialDesignBody}" PixelsPerSecond="{Binding PixelsPerSecond}"/>
|
||||
|
||||
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}" />
|
||||
<ContentControl s:View.Model="{Binding}" HorizontalAlignment="Stretch" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Markup;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
|
||||
@ -11,6 +14,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
|
||||
{
|
||||
TimelinePropertyRailViewModels = new BindableCollection<TimelinePropertyRailViewModel>();
|
||||
|
||||
TimeCaretTime = TimeSpan.FromSeconds(3);
|
||||
CreateTestValues();
|
||||
Update();
|
||||
}
|
||||
@ -25,6 +29,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
@ -9,8 +9,12 @@
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
d:DataContext="{d:DesignInstance local:TimelinePropertyRailViewModel}">
|
||||
<Border BorderThickness="0,1" BorderBrush="{StaticResource MaterialDesignTextAreaBorder}" Height="25" Margin="0,0,0,-1">
|
||||
<ItemsControl ItemsSource="{Binding TimelineKeyframeViewModels}">
|
||||
<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 />
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
|
||||
@ -13,6 +14,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
|
||||
}
|
||||
|
||||
public BindableCollection<TimelineKeyframeViewModel> TimelineKeyframeViewModels { get; set; }
|
||||
public double Width { get; set; }
|
||||
|
||||
public void CreateTestValues()
|
||||
{
|
||||
@ -31,8 +33,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
|
||||
foreach (var timelineKeyframeViewModel in TimelineKeyframeViewModels)
|
||||
timelineKeyframeViewModel.Update(pixelsPerSecond);
|
||||
|
||||
if (pixelsPerSecond == 10)
|
||||
Console.WriteLine();
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -126,7 +126,7 @@ namespace Artemis.UI.Screens.Settings
|
||||
{
|
||||
_windowManager.ShowWindow(_kernel.Get<DebugViewModel>());
|
||||
}
|
||||
|
||||
|
||||
public void ShowLogsFolder()
|
||||
{
|
||||
Process.Start(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs"));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user