Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Lottie Viewer] Markers improvement [DRAFT] #466

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions LottieViewer/MainPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,9 @@
<DataTemplate x:Key="MarkerWithDurationTemplate" x:DataType="viewmodel:MarkerWithDuration">
<StackPanel Orientation="Horizontal" Margin="0,0,0,2" MaxWidth="310">
<TextBlock Foreground="White" TextAlignment="Right" TextWrapping="Wrap" MaxWidth="250" MinWidth="60" Padding="0,0,12,0">
<Hyperlink Foreground="{StaticResource LottieHyperlinkForegroundBrush}" Click="MarkerClick"><Run Text="{x:Bind InFrame}"/></Hyperlink> -
<Hyperlink Foreground="{StaticResource LottieHyperlinkForegroundBrush}" Click="MarkerEndClick"><Run Text="{x:Bind OutFrame}"/></Hyperlink>
<Hyperlink Foreground="{StaticResource LottieHyperlinkForegroundBrush}" Click="MarkerWithDurationClick">
<Run Text="{x:Bind InFrame}"/>-<Run Text="{x:Bind OutFrame}"/>
</Hyperlink>
</TextBlock>
<TextBlock Foreground="White" TextWrapping="Wrap" Text="{x:Bind Name}"/>
</StackPanel>
Expand Down
4 changes: 2 additions & 2 deletions LottieViewer/MainPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -433,11 +433,11 @@ void MarkerClick(Hyperlink sender, HyperlinkClickEventArgs args)
}

// Called when the user clicks on a marker-with-duration hyperlink.
void MarkerEndClick(Hyperlink sender, HyperlinkClickEventArgs args)
void MarkerWithDurationClick(Hyperlink sender, HyperlinkClickEventArgs args)
{
var dataContext = ((FrameworkElement)sender.ElementStart.Parent).DataContext;
var marker = (MarkerWithDuration)dataContext;
SeekToProgressValue(marker.ConstrainedOutProgress);
_ = _stage.Player?.PlayAsync(marker.ConstrainedInProgress, marker.ConstrainedOutProgress, looped: true);
}

// Sets the progress to the given value, and sets the focus to the scrubber
Expand Down
6 changes: 3 additions & 3 deletions LottieViewer/PropertiesTemplateSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ public sealed class PropertiesTemplateSelector : DataTemplateSelector
{
return Normal;
}
else if (item is Marker)
else if (item is MarkerWithDuration)
{
return Marker;
return MarkerWithDuration;
}
else
{
return MarkerWithDuration;
return Marker;
}
}
}
Expand Down
52 changes: 52 additions & 0 deletions LottieViewer/ViewModel/LottieVisualDiagnosticsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#nullable enable

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
Expand Down Expand Up @@ -68,8 +69,59 @@ public object? DiagnosticsObject
var totalFrames = framesPerSecond * duration;

var isFirst = true;

var usedMarkers = new List<string>();

// XAML AnimatedIcon uses NAME_Start -> NAME_End naming convention for markers.
// It uses two markers to specify animation segment for some state.
// This loop extracts matching pairs of markers of format NAME_Start and NAME_End
// and transforms them to MarkerWithDuration object so that in UI it will be displayed as single segment.
foreach (var startMarker in metadata.FilteredMarkers)
{
if (!startMarker.Name.EndsWith("_Start") || startMarker.Duration.Frames != 0)
{
continue;
}

foreach (var endMarker in metadata.FilteredMarkers)
{
if (!endMarker.Name.EndsWith("_End") || endMarker.Duration.Frames != 0)
{
continue;
}

string namePrefix = endMarker.Name.Substring(0, endMarker.Name.Length - "_End".Length);

if (startMarker.Name.StartsWith(namePrefix))
{
usedMarkers.Add(startMarker.Name);
usedMarkers.Add(endMarker.Name);

var propertyName = isFirst ? $"Marker{(composition.Markers.Count > 1 ? "s" : string.Empty)}" : string.Empty;

var inProgress = startMarker.Frame.GetNudgedProgress(NudgeFrameProportion);
var outProgress = endMarker.Frame.GetNudgedProgress(NudgeFrameProportion);

Markers.Add(new MarkerWithDuration(
namePrefix,
propertyName,
(int)startMarker.Frame.Number,
inProgress,
(int)endMarker.Frame.Number,
outProgress));

isFirst = false;
}
}
}

foreach (var m in metadata.FilteredMarkers)
{
if (usedMarkers.Contains(m.Name))
{
continue;
}

var inProgress = m.Frame.GetNudgedProgress(NudgeFrameProportion);
Marker marker;
var propertyName = isFirst ? $"Marker{(composition.Markers.Count > 1 ? "s" : string.Empty)}" : string.Empty;
Expand Down