This commit is contained in:
Родитель
1f51334d7a
Коммит
f44baca6d0
|
@ -19,7 +19,23 @@
|
|||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="Margin" Value="0,10,0,10"/>
|
||||
</Style>
|
||||
|
||||
|
||||
<Style x:Key="StatsBorder" TargetType="Border">
|
||||
<Setter Property="BorderBrush" Value="DarkGray"/>
|
||||
<Setter Property="BorderThickness" Value="1.0"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="Margin" Value="0,2,0,2"/>
|
||||
<Setter Property="Padding" Value="6"/>
|
||||
<Setter Property="CornerRadius" Value="8"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="StatsSeparator" TargetType="Border">
|
||||
<Setter Property="BorderBrush" Value="DarkGray"/>
|
||||
<Setter Property="BorderThickness" Value="0,1,0,0"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="Margin" Value="0,2,0,2"/>
|
||||
</Style>
|
||||
|
||||
<Color x:Key="LottieBasic">#FF00D1C1</Color>
|
||||
<Color x:Key="DisabledColor">#FF888888</Color>
|
||||
<Color x:Key="ForegroundColor">#FFEBEBEB</Color>
|
||||
|
|
|
@ -85,7 +85,6 @@
|
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Anim.cs" />
|
||||
<Compile Include="AnimatedVisuals\LottieViewer_04_Playback.cs" />
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
|
@ -93,6 +92,9 @@
|
|||
<Compile Include="AnimatedVisuals\UiFeedbackAnimations.cs" />
|
||||
<Compile Include="AnimatedVisuals\LottieLogo.cs" />
|
||||
<Compile Include="ColorPaletteEntry.cs" />
|
||||
<Compile Include="PerfStats.xaml.cs">
|
||||
<DependentUpon>PerfStats.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="PixelViewElement.cs" />
|
||||
<Compile Include="FeedbackLottie.xaml.cs">
|
||||
<DependentUpon>FeedbackLottie.xaml</DependentUpon>
|
||||
|
@ -119,6 +121,7 @@
|
|||
<Compile Include="ViewModel\Marker.cs" />
|
||||
<Compile Include="ViewModel\MarkerWithDuration.cs" />
|
||||
<Compile Include="ViewModel\PairOfStrings.cs" />
|
||||
<Compile Include="ViewModel\StatsEntry.cs" />
|
||||
<Compile Include="VisibilityConverter.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -200,6 +203,10 @@
|
|||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="PerfStats.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="PlayStopButton.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
|
|
@ -83,12 +83,7 @@
|
|||
AutomationProperties.Name="View perf stats"
|
||||
ToolTipService.ToolTip="Animation perf stats"
|
||||
Style="{StaticResource ControlsToggleButtonStyle}">
|
||||
<Grid>
|
||||
<!-- Switch icon based on whether or not the Lottie file has any issues. -->
|
||||
<TextBlock Text="" Visibility="{x:Bind _stage.DiagnosticsViewModel.HasIssues, Converter={StaticResource VisibilityConverter}, ConverterParameter=not, Mode=OneWay}" AutomationProperties.AccessibilityView="Raw"/>
|
||||
<!-- Different color if there are issues. -->
|
||||
<TextBlock Text="" Visibility="{x:Bind _stage.DiagnosticsViewModel.HasIssues, Converter={StaticResource VisibilityConverter}, Mode=OneWay}" Foreground="Orange" AutomationProperties.AccessibilityView="Raw"/>
|
||||
</Grid>
|
||||

|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
@ -342,13 +337,12 @@
|
|||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
<!-- Info panel -->
|
||||
<!-- Perf panel -->
|
||||
<ScrollViewer
|
||||
x:Name="PerfPanel"
|
||||
Width="{StaticResource ControlPanelWidth}">
|
||||
|
||||
<StackPanel Padding="20,10,20,0">
|
||||
</StackPanel>
|
||||
<local:PerfStats x:Name="_perfStats"></local:PerfStats>
|
||||
</ScrollViewer>
|
||||
|
||||
</Grid>
|
||||
|
|
|
@ -104,21 +104,18 @@ namespace LottieViewer
|
|||
|
||||
void DiagnosticsViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
var list = PropertiesList;
|
||||
var viewModel = _stage.DiagnosticsViewModel;
|
||||
|
||||
if (viewModel is null)
|
||||
_perfStats.Update(viewModel);
|
||||
|
||||
PropertiesList.Clear();
|
||||
MarkersList.Clear();
|
||||
|
||||
if (viewModel is not null)
|
||||
{
|
||||
list.Clear();
|
||||
MarkersList.Clear();
|
||||
}
|
||||
else if (e.PropertyName == nameof(viewModel.FileName))
|
||||
{
|
||||
list.Clear();
|
||||
MarkersList.Clear();
|
||||
if (!string.IsNullOrWhiteSpace(viewModel.FileName))
|
||||
{
|
||||
list.Add(new PairOfStrings("File", viewModel.FileName));
|
||||
PropertiesList.Add(new PairOfStrings("File", viewModel.FileName));
|
||||
}
|
||||
|
||||
// If the Lottie has 0 duration then it isn't valid, so don't show properties
|
||||
|
@ -128,12 +125,12 @@ namespace LottieViewer
|
|||
// Not all Lotties have a name, so only add the name if it exists.
|
||||
if (!string.IsNullOrWhiteSpace(viewModel.Name))
|
||||
{
|
||||
list.Add(new PairOfStrings("Name", viewModel.Name));
|
||||
PropertiesList.Add(new PairOfStrings("Name", viewModel.Name));
|
||||
}
|
||||
|
||||
list.Add(new PairOfStrings("Size", viewModel.SizeText));
|
||||
list.Add(new PairOfStrings("Duration", viewModel.DurationText));
|
||||
list.Add(new PairOfStrings("Frames", $"{viewModel.FrameCountText} @ {viewModel.FramesPerSecond:0.#}fps"));
|
||||
PropertiesList.Add(new PairOfStrings("Size", viewModel.SizeText));
|
||||
PropertiesList.Add(new PairOfStrings("Duration", viewModel.DurationText));
|
||||
PropertiesList.Add(new PairOfStrings("Frames", $"{viewModel.FrameCountText} @ {viewModel.FramesPerSecond:0.#}fps"));
|
||||
|
||||
if (viewModel.Markers.Count > 0)
|
||||
{
|
||||
|
|
|
@ -239,11 +239,6 @@
|
|||
|
||||
<TextBlock FontWeight="Bold">Colors</TextBlock>
|
||||
<CheckBox x:Name="_showSolidBackground">Show solid background</CheckBox>
|
||||
|
||||
<muxc2:AnimatedVisualPlayer AutoPlay="True"
|
||||
Stretch="None">
|
||||
<av:Anim/>
|
||||
</muxc2:AnimatedVisualPlayer>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
<UserControl
|
||||
x:Class="LottieViewer.PerfStats"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:LottieViewer"
|
||||
xmlns:viewmodel="using:LottieViewer.ViewModel"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="900"
|
||||
d:DesignWidth="400">
|
||||
|
||||
<StackPanel Grid.Row="2" Orientation="Vertical" Padding="20,10,20,0">
|
||||
|
||||
<TextBlock Text="Total animation complexity score" Grid.Column="1" TextWrapping="Wrap" Foreground="White" HorizontalAlignment="Center" FontSize="18"/>
|
||||
<TextBlock Text="0.0" x:Name="ScoreValue" Grid.Column="1" TextWrapping="Wrap" Foreground="White" HorizontalAlignment="Center" FontSize="40"/>
|
||||
<!--
|
||||
<TextBlock FontWeight="Bold">Input (lottie objects):</TextBlock>
|
||||
|
||||
<Border Style="{StaticResource StatsBorder}">
|
||||
<StackPanel>
|
||||
<ItemsControl ItemsSource="{x:Bind InputLayers, Mode=OneWay}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="viewmodel:StatsEntry">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{x:Bind Name}" Grid.Column="0" TextWrapping="Wrap" Foreground="LightGray"/>
|
||||
<TextBlock Text="{x:Bind Count}" Grid.Column="1" TextWrapping="Wrap" Foreground="White" HorizontalAlignment="Right"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
|
||||
<Border Style="{StaticResource StatsSeparator}" Padding="0"/>
|
||||
|
||||
<ItemsControl ItemsSource="{x:Bind InputMasks, Mode=OneWay}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="viewmodel:StatsEntry">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{x:Bind Name}" Grid.Column="0" TextWrapping="Wrap" Foreground="LightGray"/>
|
||||
<TextBlock Text="{x:Bind Count}" Grid.Column="1" TextWrapping="Wrap" Foreground="White" HorizontalAlignment="Right"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<Border Style="{StaticResource StatsSeparator}" Padding="0"/>
|
||||
|
||||
<ItemsControl ItemsSource="{x:Bind InputEffects, Mode=OneWay}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="viewmodel:StatsEntry">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{x:Bind Name}" Grid.Column="0" TextWrapping="Wrap" Foreground="LightGray"/>
|
||||
<TextBlock Text="{x:Bind Count}" Grid.Column="1" TextWrapping="Wrap" Foreground="White" HorizontalAlignment="Right"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</Border>-->
|
||||
|
||||
<TextBlock FontWeight="Bold">Details:</TextBlock>
|
||||
|
||||
<Border Style="{StaticResource StatsBorder}">
|
||||
|
||||
<StackPanel>
|
||||
<ItemsControl ItemsSource="{x:Bind OutputTotal, Mode=OneWay}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="viewmodel:StatsEntry">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{x:Bind Name}" Grid.Column="0" TextWrapping="Wrap" Foreground="LightGray"/>
|
||||
<TextBlock Text="{x:Bind Count}" Grid.Column="1" TextWrapping="Wrap" Foreground="White" HorizontalAlignment="Right"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<!-- Separator -->
|
||||
<Border Style="{StaticResource StatsSeparator}" Padding="0"/>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition></RowDefinition>
|
||||
<RowDefinition></RowDefinition>
|
||||
<RowDefinition></RowDefinition>
|
||||
<RowDefinition></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" TextWrapping="Wrap" Foreground="LightGray" Text="Animations complexity"/>
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" TextWrapping="Wrap" Foreground="White" HorizontalAlignment="Right" Text="0.0" x:Name="AnimationsComplexity"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" TextWrapping="Wrap" Foreground="LightGray" Text="Geometry complexity"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" TextWrapping="Wrap" Foreground="White" HorizontalAlignment="Right" Text="0.0" x:Name="GeometryComplexity"/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" TextWrapping="Wrap" Foreground="LightGray" Text="Effects complexity"/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" TextWrapping="Wrap" Foreground="White" HorizontalAlignment="Right" Text="0.0" x:Name="EffectsComplexity"/>
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" TextWrapping="Wrap" Foreground="LightGray" Text="Visual tree complexity"/>
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" TextWrapping="Wrap" Foreground="White" HorizontalAlignment="Right" Text="0.0" x:Name="TreeComplexity"/>
|
||||
</Grid>
|
||||
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
</StackPanel>
|
||||
</UserControl>
|
|
@ -0,0 +1,89 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using LottieViewer.ViewModel;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
namespace LottieViewer
|
||||
{
|
||||
/// <summary>
|
||||
/// Displays perf stats.
|
||||
/// </summary>
|
||||
internal sealed partial class PerfStats : UserControl
|
||||
{
|
||||
public PerfStats()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
public ObservableCollection<object> InputLayers { get; } = new ObservableCollection<object>();
|
||||
|
||||
public ObservableCollection<object> InputMasks { get; } = new ObservableCollection<object>();
|
||||
|
||||
public ObservableCollection<object> InputEffects { get; } = new ObservableCollection<object>();
|
||||
|
||||
public ObservableCollection<object> OutputTotal { get; } = new ObservableCollection<object>();
|
||||
|
||||
public ObservableCollection<object> OutputVisuals { get; } = new ObservableCollection<object>();
|
||||
|
||||
public ObservableCollection<object> OutputAnimations { get; } = new ObservableCollection<object>();
|
||||
|
||||
public ObservableCollection<object> OutputEffects { get; } = new ObservableCollection<object>();
|
||||
|
||||
public void Update(LottieVisualDiagnosticsViewModel diagnostics)
|
||||
{
|
||||
InputLayers.Clear();
|
||||
InputMasks.Clear();
|
||||
InputEffects.Clear();
|
||||
OutputTotal.Clear();
|
||||
OutputVisuals.Clear();
|
||||
OutputAnimations.Clear();
|
||||
OutputEffects.Clear();
|
||||
|
||||
foreach (var statsEntry in diagnostics.Stats)
|
||||
{
|
||||
if ((statsEntry.Tags & ~(StatsEntry.LOTTIE_COMPOSITION_TAG | StatsEntry.LAYER_TAG)) == 0)
|
||||
{
|
||||
InputLayers.Add(statsEntry);
|
||||
}
|
||||
|
||||
if ((statsEntry.Tags & ~(StatsEntry.LOTTIE_COMPOSITION_TAG | StatsEntry.MASK_TAG)) == 0)
|
||||
{
|
||||
InputMasks.Add(statsEntry);
|
||||
}
|
||||
|
||||
if ((statsEntry.Tags & ~(StatsEntry.LOTTIE_COMPOSITION_TAG | StatsEntry.EFFECT_TAG)) == 0)
|
||||
{
|
||||
InputEffects.Add(statsEntry);
|
||||
}
|
||||
|
||||
if ((statsEntry.Tags & ~StatsEntry.WINDOWS_COMPOSITION_TAG) == 0)
|
||||
{
|
||||
OutputTotal.Add(statsEntry);
|
||||
}
|
||||
}
|
||||
|
||||
if (diagnostics.LottieVisualDiagnostics is not null && diagnostics.LottieVisualDiagnostics.WinCompStats is not null)
|
||||
{
|
||||
ScoreValue.Text = string.Format("{0:0.00}", diagnostics.LottieVisualDiagnostics!.WinCompStats!.CalculateApproximateComplexity());
|
||||
AnimationsComplexity.Text = string.Format("{0:0.00}", diagnostics.LottieVisualDiagnostics!.WinCompStats!.CalculateApproximateAnimationsComplexity());
|
||||
GeometryComplexity.Text = string.Format("{0:0.00}", diagnostics.LottieVisualDiagnostics!.WinCompStats!.CalculateApproximateGeometryComplexity());
|
||||
EffectsComplexity.Text = string.Format("{0:0.00}", diagnostics.LottieVisualDiagnostics!.WinCompStats!.CalculateApproximateEffectsComplexity());
|
||||
TreeComplexity.Text = string.Format("{0:0.00}", diagnostics.LottieVisualDiagnostics!.WinCompStats!.CalculateApproximateTreeComplexity());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,6 +37,7 @@ namespace LottieViewer.ViewModel
|
|||
LottieVisualDiagnostics = (LottieVisualDiagnostics?)value;
|
||||
Issues.Clear();
|
||||
Markers.Clear();
|
||||
Stats.Clear();
|
||||
ThemePropertyBindings.Clear();
|
||||
ThemingPropertySet = null;
|
||||
|
||||
|
@ -52,6 +53,37 @@ namespace LottieViewer.ViewModel
|
|||
Issues.Add(issue);
|
||||
}
|
||||
|
||||
if (LottieVisualDiagnostics.LottieCompositionStats is not null)
|
||||
{
|
||||
uint tags = StatsEntry.LOTTIE_COMPOSITION_TAG | StatsEntry.LAYER_TAG;
|
||||
Stats.Add(new StatsEntry("Solid layers", LottieVisualDiagnostics.LottieCompositionStats.SolidLayerCount, tags));
|
||||
Stats.Add(new StatsEntry("Shape layers", LottieVisualDiagnostics.LottieCompositionStats.ShapeLayerCount, tags));
|
||||
Stats.Add(new StatsEntry("PreComp layers", LottieVisualDiagnostics.LottieCompositionStats.PreCompLayerCount, tags));
|
||||
Stats.Add(new StatsEntry("Image layers", LottieVisualDiagnostics.LottieCompositionStats.ImageLayerCount, tags));
|
||||
|
||||
tags = StatsEntry.LOTTIE_COMPOSITION_TAG | StatsEntry.MASK_TAG;
|
||||
Stats.Add(new StatsEntry("Masks", LottieVisualDiagnostics.LottieCompositionStats.MaskCount, tags));
|
||||
Stats.Add(new StatsEntry("Matte layers", LottieVisualDiagnostics.LottieCompositionStats.MatteLayerCount, tags));
|
||||
|
||||
tags = StatsEntry.LOTTIE_COMPOSITION_TAG | StatsEntry.EFFECT_TAG;
|
||||
Stats.Add(new StatsEntry("Drop shadow", LottieVisualDiagnostics.LottieCompositionStats.DropShadowEffectCount, tags));
|
||||
Stats.Add(new StatsEntry("Gaussian blur", LottieVisualDiagnostics.LottieCompositionStats.GaussianBlurEffectCount, tags));
|
||||
}
|
||||
|
||||
if (LottieVisualDiagnostics.WinCompStats is not null)
|
||||
{
|
||||
uint tags = StatsEntry.WINDOWS_COMPOSITION_TAG;
|
||||
|
||||
Stats.Add(new StatsEntry("Keyframe animators", LottieVisualDiagnostics.WinCompStats.KeyframeAnimatorCount, tags));
|
||||
Stats.Add(new StatsEntry("Expression animators", LottieVisualDiagnostics.WinCompStats.ExpressionAnimatorCount, tags));
|
||||
Stats.Add(new StatsEntry("Keyframe count", LottieVisualDiagnostics.WinCompStats.KeyframeCount, tags));
|
||||
Stats.Add(new StatsEntry("Geometries count", LottieVisualDiagnostics.WinCompStats.GeometriesCount, tags));
|
||||
Stats.Add(new StatsEntry("Path commands count", LottieVisualDiagnostics.WinCompStats.PathCommandsCount, tags));
|
||||
Stats.Add(new StatsEntry("Effect brush", LottieVisualDiagnostics.WinCompStats.EffectBrushCount, tags));
|
||||
Stats.Add(new StatsEntry("Effect factory", LottieVisualDiagnostics.WinCompStats.EffectFactoryCount, tags));
|
||||
Stats.Add(new StatsEntry("Composition objects", LottieVisualDiagnostics.WinCompStats.CompositionObjectCount, tags));
|
||||
}
|
||||
|
||||
// Populate the marker info.
|
||||
var composition = LottieVisualDiagnostics.LottieComposition;
|
||||
if (composition is not null)
|
||||
|
@ -160,6 +192,8 @@ namespace LottieViewer.ViewModel
|
|||
|
||||
public ObservableCollection<Issue> Issues { get; } = new ObservableCollection<Issue>();
|
||||
|
||||
public ObservableCollection<StatsEntry> Stats { get; } = new ObservableCollection<StatsEntry>();
|
||||
|
||||
public string SizeText
|
||||
{
|
||||
get
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LottieViewer.ViewModel
|
||||
{
|
||||
public class StatsEntry
|
||||
{
|
||||
public const uint LOTTIE_COMPOSITION_TAG = 1 << 0;
|
||||
public const uint WINDOWS_COMPOSITION_TAG = 1 << 1;
|
||||
public const uint LAYER_TAG = 1 << 2;
|
||||
public const uint MASK_TAG = 1 << 3;
|
||||
public const uint EFFECT_TAG = 1 << 4;
|
||||
|
||||
internal StatsEntry(string name, int count, uint tags)
|
||||
{
|
||||
Name = name;
|
||||
Count = count;
|
||||
Tags = tags;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public int Count { get; }
|
||||
|
||||
public uint Tags { get; }
|
||||
}
|
||||
}
|
|
@ -92,7 +92,15 @@ namespace CommunityToolkit.WinUI.Lottie
|
|||
|
||||
if (lottieComposition is not null)
|
||||
{
|
||||
lottieComposition = LottieMergeOptimizer.Optimize(lottieComposition);
|
||||
if (diagnostics is not null)
|
||||
{
|
||||
diagnostics.LottieCompositionStats = new LottieData.Tools.Stats(lottieComposition);
|
||||
}
|
||||
|
||||
if (options.HasFlag(LottieVisualOptions.Optimize))
|
||||
{
|
||||
lottieComposition = LottieMergeOptimizer.Optimize(lottieComposition);
|
||||
}
|
||||
}
|
||||
|
||||
if (diagnostics is not null)
|
||||
|
@ -177,6 +185,11 @@ namespace CommunityToolkit.WinUI.Lottie
|
|||
diagnostics.OptimizationTime = timeMeasurer.GetElapsedAndRestart();
|
||||
}
|
||||
}
|
||||
|
||||
if (diagnostics is not null)
|
||||
{
|
||||
diagnostics.WinCompStats = new UIData.Tools.Stats(wincompDataRootVisual);
|
||||
}
|
||||
});
|
||||
|
||||
if (wincompDataRootVisual is null)
|
||||
|
|
|
@ -72,6 +72,10 @@ namespace CommunityToolkit.WinUI.Lottie
|
|||
// Describes the property bindings in the ThemingPropertySet.
|
||||
internal IReadOnlyList<PropertyBinding>? ThemePropertyBindings { get; set; }
|
||||
|
||||
internal LottieData.Tools.Stats? LottieCompositionStats { get; set; }
|
||||
|
||||
internal UIData.Tools.Stats? WinCompStats { get; set; }
|
||||
|
||||
internal LottieVisualDiagnostics Clone() =>
|
||||
new LottieVisualDiagnostics
|
||||
{
|
||||
|
@ -90,6 +94,8 @@ namespace CommunityToolkit.WinUI.Lottie
|
|||
TranslationIssues = TranslationIssues,
|
||||
TranslationTime = TranslationTime,
|
||||
ValidationTime = ValidationTime,
|
||||
LottieCompositionStats = LottieCompositionStats,
|
||||
WinCompStats = WinCompStats,
|
||||
};
|
||||
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
|
||||
}
|
||||
|
|
|
@ -85,7 +85,23 @@ namespace CommunityToolkit.WinUI.Lottie.LottieData.Tools
|
|||
}
|
||||
}
|
||||
|
||||
MaskCount += layer.Masks.Count;
|
||||
foreach (var effect in layer.Effects)
|
||||
{
|
||||
switch (effect.Type)
|
||||
{
|
||||
case Effect.EffectType.DropShadow:
|
||||
DropShadowEffectCount++;
|
||||
break;
|
||||
case Effect.EffectType.GaussianBlur:
|
||||
GaussianBlurEffectCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (layer.LayerMatteType != Layer.MatteType.None)
|
||||
{
|
||||
MatteLayerCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,6 +117,8 @@ namespace CommunityToolkit.WinUI.Lottie.LottieData.Tools
|
|||
|
||||
public int MaskCount { get; }
|
||||
|
||||
public int MatteLayerCount { get; }
|
||||
|
||||
public int MaskAddCount { get; }
|
||||
|
||||
public int MaskDarkenCount { get; }
|
||||
|
@ -123,6 +141,10 @@ namespace CommunityToolkit.WinUI.Lottie.LottieData.Tools
|
|||
|
||||
public int TextLayerCount { get; }
|
||||
|
||||
public int GaussianBlurEffectCount { get; }
|
||||
|
||||
public int DropShadowEffectCount { get; }
|
||||
|
||||
public double Width { get; }
|
||||
|
||||
public double Height { get; }
|
||||
|
|
|
@ -0,0 +1,268 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.WinUI.Lottie.WinCompData;
|
||||
|
||||
namespace CommunityToolkit.WinUI.Lottie.UIData.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// Calculates stats for a WinCompData tree. Used to report the size of data
|
||||
/// and the effectiveness of optimization.
|
||||
/// </summary>
|
||||
#if PUBLIC_UIData
|
||||
public
|
||||
#endif
|
||||
sealed class Stats
|
||||
{
|
||||
public Stats(CompositionObject? root)
|
||||
{
|
||||
if (root is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var objectGraph = Graph.FromCompositionObject(root, includeVertices: false);
|
||||
|
||||
CompositionPathCount = objectGraph.CompositionPathNodes.Count();
|
||||
CanvasGeometryCount = objectGraph.CanvasGeometryNodes.Count();
|
||||
|
||||
var v = new HashSet<CompositionObject>();
|
||||
|
||||
foreach (var (_, obj) in objectGraph.CompositionObjectNodes)
|
||||
{
|
||||
AnimatorCount += obj.Animators.Count;
|
||||
|
||||
var expressionAnimatorCount = obj.Animators.Where(a => a.Animation.Type == CompositionObjectType.ExpressionAnimation).Count();
|
||||
|
||||
ExpressionAnimatorCount += expressionAnimatorCount;
|
||||
KeyframeAnimatorCount += obj.Animators.Count - expressionAnimatorCount;
|
||||
|
||||
foreach (var animator in obj.Animators)
|
||||
{
|
||||
AnimatorCountByPropertyName[animator.AnimatedProperty] = AnimatorCountByPropertyName.GetValueOrDefault(animator.AnimatedProperty) + 1;
|
||||
}
|
||||
|
||||
AnimatorCountByPropertyName[obj.Type.ToString()] = AnimatorCountByPropertyName.GetValueOrDefault(obj.Type.ToString()) + 1;
|
||||
|
||||
CompositionObjectCount++;
|
||||
switch (obj.Type)
|
||||
{
|
||||
case CompositionObjectType.AnimationController:
|
||||
AnimationControllerCount++;
|
||||
break;
|
||||
case CompositionObjectType.BooleanKeyFrameAnimation:
|
||||
BooleanKeyFrameAnimationCount++;
|
||||
break;
|
||||
case CompositionObjectType.ColorKeyFrameAnimation:
|
||||
ColorKeyFrameAnimationCount++;
|
||||
break;
|
||||
case CompositionObjectType.CompositionColorBrush:
|
||||
ColorBrushCount++;
|
||||
break;
|
||||
case CompositionObjectType.CompositionColorGradientStop:
|
||||
ColorGradientStopCount++;
|
||||
break;
|
||||
case CompositionObjectType.CompositionContainerShape:
|
||||
ContainerShapeCount++;
|
||||
break;
|
||||
case CompositionObjectType.CompositionEffectBrush:
|
||||
EffectBrushCount++;
|
||||
break;
|
||||
case CompositionObjectType.CompositionEllipseGeometry:
|
||||
EllipseGeometryCount++;
|
||||
break;
|
||||
case CompositionObjectType.CompositionGeometricClip:
|
||||
GeometricClipCount++;
|
||||
break;
|
||||
case CompositionObjectType.CompositionLinearGradientBrush:
|
||||
LinearGradientBrushCount++;
|
||||
break;
|
||||
case CompositionObjectType.CompositionMaskBrush:
|
||||
MaskBrushCount++;
|
||||
break;
|
||||
case CompositionObjectType.CompositionPathGeometry:
|
||||
PathGeometryCount++;
|
||||
break;
|
||||
case CompositionObjectType.CompositionPropertySet:
|
||||
{
|
||||
var propertyCount = ((CompositionPropertySet)obj).Names.Count();
|
||||
if (propertyCount > 0)
|
||||
{
|
||||
PropertySetCount++;
|
||||
PropertySetPropertyCount += propertyCount;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case CompositionObjectType.CompositionRadialGradientBrush:
|
||||
RadialGradientBrushCount++;
|
||||
break;
|
||||
case CompositionObjectType.CompositionRectangleGeometry:
|
||||
RectangleGeometryCount++;
|
||||
break;
|
||||
case CompositionObjectType.CompositionRoundedRectangleGeometry:
|
||||
RoundedRectangleGeometryCount++;
|
||||
break;
|
||||
case CompositionObjectType.CompositionSpriteShape:
|
||||
SpriteShapeCount++;
|
||||
break;
|
||||
case CompositionObjectType.CompositionSurfaceBrush:
|
||||
SurfaceBrushCount++;
|
||||
break;
|
||||
case CompositionObjectType.CompositionViewBox:
|
||||
ViewBoxCount++;
|
||||
break;
|
||||
case CompositionObjectType.CompositionVisualSurface:
|
||||
VisualSurfaceCount++;
|
||||
break;
|
||||
case CompositionObjectType.ContainerVisual:
|
||||
ContainerVisualCount++;
|
||||
break;
|
||||
case CompositionObjectType.CubicBezierEasingFunction:
|
||||
CubicBezierEasingFunctionCount++;
|
||||
break;
|
||||
case CompositionObjectType.DropShadow:
|
||||
DropShadowCount++;
|
||||
break;
|
||||
case CompositionObjectType.ExpressionAnimation:
|
||||
ExpressionAnimationCount++;
|
||||
break;
|
||||
case CompositionObjectType.InsetClip:
|
||||
InsetClipCount++;
|
||||
break;
|
||||
case CompositionObjectType.LayerVisual:
|
||||
LayerVisualCount++;
|
||||
break;
|
||||
case CompositionObjectType.LinearEasingFunction:
|
||||
LinearEasingFunctionCount++;
|
||||
break;
|
||||
case CompositionObjectType.PathKeyFrameAnimation:
|
||||
PathKeyFrameAnimationCount++;
|
||||
break;
|
||||
case CompositionObjectType.ScalarKeyFrameAnimation:
|
||||
ScalarKeyFrameAnimationCount++;
|
||||
break;
|
||||
case CompositionObjectType.ShapeVisual:
|
||||
ShapeVisualCount++;
|
||||
break;
|
||||
case CompositionObjectType.SpriteVisual:
|
||||
SpriteVisualCount++;
|
||||
break;
|
||||
case CompositionObjectType.StepEasingFunction:
|
||||
StepEasingFunctionCount++;
|
||||
break;
|
||||
case CompositionObjectType.Vector2KeyFrameAnimation:
|
||||
Vector2KeyFrameAnimationCount++;
|
||||
break;
|
||||
case CompositionObjectType.Vector3KeyFrameAnimation:
|
||||
Vector3KeyFrameAnimationCount++;
|
||||
break;
|
||||
case CompositionObjectType.Vector4KeyFrameAnimation:
|
||||
Vector4KeyFrameAnimationCount++;
|
||||
break;
|
||||
case CompositionObjectType.CompositionEffectFactory:
|
||||
EffectFactoryCount++;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int AnimationControllerCount { get; }
|
||||
|
||||
public int AnimatorCount { get; }
|
||||
|
||||
public int ExpressionAnimatorCount { get; }
|
||||
|
||||
public int KeyframeAnimatorCount { get; }
|
||||
|
||||
public Dictionary<string, int> AnimatorCountByPropertyName { get; } = new Dictionary<string, int>();
|
||||
|
||||
public int BooleanKeyframeAnimatorCount { get; }
|
||||
|
||||
public int BooleanKeyFrameAnimationCount { get; }
|
||||
|
||||
public int CanvasGeometryCount { get; }
|
||||
|
||||
public int ColorKeyFrameAnimationCount { get; }
|
||||
|
||||
public int ColorBrushCount { get; }
|
||||
|
||||
public int ColorGradientStopCount { get; }
|
||||
|
||||
public int CompositionObjectCount { get; }
|
||||
|
||||
public int CompositionPathCount { get; }
|
||||
|
||||
public int ContainerShapeCount { get; }
|
||||
|
||||
public int DropShadowCount { get; }
|
||||
|
||||
public int EffectBrushCount { get; }
|
||||
|
||||
public int EffectFactoryCount { get; }
|
||||
|
||||
public int EllipseGeometryCount { get; }
|
||||
|
||||
public int GeometricClipCount { get; }
|
||||
|
||||
public int LinearGradientBrushCount { get; }
|
||||
|
||||
public int MaskBrushCount { get; }
|
||||
|
||||
public int PathGeometryCount { get; }
|
||||
|
||||
public int PropertySetPropertyCount { get; }
|
||||
|
||||
public int PropertySetCount { get; }
|
||||
|
||||
public int RadialGradientBrushCount { get; }
|
||||
|
||||
public int RectangleGeometryCount { get; }
|
||||
|
||||
public int RoundedRectangleGeometryCount { get; }
|
||||
|
||||
public int SpriteShapeCount { get; }
|
||||
|
||||
public int SurfaceBrushCount { get; }
|
||||
|
||||
public int ViewBoxCount { get; }
|
||||
|
||||
public int VisualSurfaceCount { get; }
|
||||
|
||||
public int ContainerVisualCount { get; }
|
||||
|
||||
public int CubicBezierEasingFunctionCount { get; }
|
||||
|
||||
public int ExpressionAnimationCount { get; }
|
||||
|
||||
public int InsetClipCount { get; }
|
||||
|
||||
public int LayerVisualCount { get; }
|
||||
|
||||
public int LinearEasingFunctionCount { get; }
|
||||
|
||||
public int PathKeyFrameAnimationCount { get; }
|
||||
|
||||
public int ScalarKeyFrameAnimationCount { get; }
|
||||
|
||||
public int ShapeVisualCount { get; }
|
||||
|
||||
public int SpriteVisualCount { get; }
|
||||
|
||||
public int StepEasingFunctionCount { get; }
|
||||
|
||||
public int Vector2KeyFrameAnimationCount { get; }
|
||||
|
||||
public int Vector3KeyFrameAnimationCount { get; }
|
||||
|
||||
public int Vector4KeyFrameAnimationCount { get; }
|
||||
}
|
||||
}
|
|
@ -5,8 +5,10 @@
|
|||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.WinUI.Lottie.WinCompData;
|
||||
using CommunityToolkit.WinUI.Lottie.WinCompData.Mgcg;
|
||||
|
||||
namespace CommunityToolkit.WinUI.Lottie.UIData.Tools
|
||||
{
|
||||
|
@ -19,6 +21,63 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.Tools
|
|||
#endif
|
||||
sealed class Stats
|
||||
{
|
||||
private int CountNumberOfPathCommands(CanvasGeometry geometry)
|
||||
{
|
||||
if (geometry is CanvasGeometry.Path path)
|
||||
{
|
||||
return path.Commands.Length;
|
||||
}
|
||||
|
||||
if (geometry is CanvasGeometry.Combination combination)
|
||||
{
|
||||
return CountNumberOfPathCommands(combination.A) + CountNumberOfPathCommands(combination.B);
|
||||
}
|
||||
|
||||
if (geometry is CanvasGeometry.TransformedGeometry transformed)
|
||||
{
|
||||
return CountNumberOfPathCommands(transformed.SourceGeometry);
|
||||
}
|
||||
|
||||
if (geometry is CanvasGeometry.Group group)
|
||||
{
|
||||
int res = 0;
|
||||
foreach (var g in group.Geometries)
|
||||
{
|
||||
res += CountNumberOfPathCommands(g);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int CountNumberOfGeometries(CanvasGeometry geometry)
|
||||
{
|
||||
if (geometry is CanvasGeometry.Combination combination)
|
||||
{
|
||||
return CountNumberOfGeometries(combination.A) + CountNumberOfGeometries(combination.B);
|
||||
}
|
||||
|
||||
if (geometry is CanvasGeometry.TransformedGeometry transformed)
|
||||
{
|
||||
return CountNumberOfGeometries(transformed.SourceGeometry);
|
||||
}
|
||||
|
||||
if (geometry is CanvasGeometry.Group group)
|
||||
{
|
||||
int res = 0;
|
||||
foreach (var g in group.Geometries)
|
||||
{
|
||||
res += CountNumberOfGeometries(g);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public Stats(CompositionObject? root)
|
||||
{
|
||||
if (root is null)
|
||||
|
@ -31,10 +90,58 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.Tools
|
|||
CompositionPathCount = objectGraph.CompositionPathNodes.Count();
|
||||
CanvasGeometryCount = objectGraph.CanvasGeometryNodes.Count();
|
||||
|
||||
var v = new HashSet<CompositionObject>();
|
||||
|
||||
foreach (var (_, obj) in objectGraph.CompositionObjectNodes)
|
||||
{
|
||||
AnimatorCount += obj.Animators.Count;
|
||||
|
||||
var expressionAnimatorCount = obj.Animators.Where(a => a.Animation.Type == CompositionObjectType.ExpressionAnimation).Count();
|
||||
|
||||
ExpressionAnimatorCount += expressionAnimatorCount;
|
||||
KeyframeAnimatorCount += obj.Animators.Count - expressionAnimatorCount;
|
||||
|
||||
foreach (var animator in obj.Animators)
|
||||
{
|
||||
// AnimatorCountByPropertyName[animator.AnimatedProperty] = AnimatorCountByPropertyName.GetValueOrDefault(animator.AnimatedProperty) + 1;
|
||||
if (animator.Animation is KeyFrameAnimation_ animation)
|
||||
{
|
||||
KeyframeCount += animation.KeyFrameCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (obj is CompositionSpriteShape spriteShape)
|
||||
{
|
||||
if (spriteShape.Geometry is CompositionPathGeometry geometry)
|
||||
{
|
||||
if (geometry.Path?.Source is CanvasGeometry canvasGeometry)
|
||||
{
|
||||
PathCommandsCount += CountNumberOfPathCommands(canvasGeometry);
|
||||
GeometriesCount += CountNumberOfGeometries(canvasGeometry);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GeometriesCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (obj is PathKeyFrameAnimation pathAnimation)
|
||||
{
|
||||
foreach (var keyframe in pathAnimation.KeyFrames)
|
||||
{
|
||||
if (keyframe is PathKeyFrameAnimation.ValueKeyFrame valueKeyframe)
|
||||
{
|
||||
if (valueKeyframe.Value.Source is CanvasGeometry geometry)
|
||||
{
|
||||
PathCommandsCount += CountNumberOfPathCommands(geometry);
|
||||
GeometriesCount += CountNumberOfGeometries(geometry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AnimatorCountByPropertyName[obj.Type.ToString()] = AnimatorCountByPropertyName.GetValueOrDefault(obj.Type.ToString()) + 1;
|
||||
CompositionObjectCount++;
|
||||
switch (obj.Type)
|
||||
{
|
||||
|
@ -160,12 +267,94 @@ namespace CommunityToolkit.WinUI.Lottie.UIData.Tools
|
|||
}
|
||||
}
|
||||
|
||||
public int AnimationControllerListCount { get; }
|
||||
public float CalculateApproximateAnimationsComplexity()
|
||||
{
|
||||
var complexity = 0.0f;
|
||||
|
||||
var otherKeyframeAnimators = KeyframeAnimatorCount;
|
||||
|
||||
complexity += ExpressionAnimatorCount * 15;
|
||||
|
||||
otherKeyframeAnimators -= AnimatorCountByPropertyName.GetValueOrDefault("IsVisible");
|
||||
complexity += AnimatorCountByPropertyName.GetValueOrDefault("IsVisible") * 5;
|
||||
|
||||
otherKeyframeAnimators -= AnimatorCountByPropertyName.GetValueOrDefault("Opacity");
|
||||
complexity += AnimatorCountByPropertyName.GetValueOrDefault("Opacity") * 30;
|
||||
|
||||
otherKeyframeAnimators -= AnimatorCountByPropertyName.GetValueOrDefault("Color");
|
||||
complexity += AnimatorCountByPropertyName.GetValueOrDefault("Color") * 30;
|
||||
|
||||
complexity += otherKeyframeAnimators * 10;
|
||||
|
||||
complexity += KeyframeCount * 5;
|
||||
|
||||
return complexity / 1000.0f;
|
||||
}
|
||||
|
||||
public float CalculateApproximateGeometryComplexity()
|
||||
{
|
||||
var complexity = 0.0f;
|
||||
|
||||
complexity += PathCommandsCount * 4;
|
||||
complexity += GeometriesCount * 20;
|
||||
|
||||
return complexity / 1000.0f;
|
||||
}
|
||||
|
||||
public float CalculateApproximateEffectsComplexity()
|
||||
{
|
||||
var complexity = 0.0f;
|
||||
|
||||
complexity += EffectBrushCount * 500;
|
||||
complexity += EffectFactoryCount * 1000;
|
||||
|
||||
return complexity / 1000.0f;
|
||||
}
|
||||
|
||||
public float CalculateApproximateTreeComplexity()
|
||||
{
|
||||
var complexity = 0.0f;
|
||||
|
||||
complexity += ContainerVisualCount * 5;
|
||||
complexity += LayerVisualCount * 5;
|
||||
complexity += ShapeVisualCount * 5;
|
||||
complexity += SpriteVisualCount * 20;
|
||||
complexity += ContainerShapeCount * 5;
|
||||
complexity += CompositionObjectCount;
|
||||
|
||||
return complexity / 1000.0f;
|
||||
}
|
||||
|
||||
public float CalculateApproximateComplexity()
|
||||
{
|
||||
var complexity = 0.0f;
|
||||
|
||||
complexity += CalculateApproximateAnimationsComplexity();
|
||||
complexity += CalculateApproximateGeometryComplexity();
|
||||
complexity += CalculateApproximateEffectsComplexity();
|
||||
complexity += CalculateApproximateTreeComplexity();
|
||||
|
||||
return complexity;
|
||||
}
|
||||
|
||||
public int AnimationControllerCount { get; }
|
||||
|
||||
public int AnimatorCount { get; }
|
||||
|
||||
public int ExpressionAnimatorCount { get; }
|
||||
|
||||
public int KeyframeAnimatorCount { get; }
|
||||
|
||||
public int KeyframeCount { get; }
|
||||
|
||||
public int PathCommandsCount { get; }
|
||||
|
||||
public int GeometriesCount { get; }
|
||||
|
||||
public Dictionary<string, int> AnimatorCountByPropertyName { get; } = new Dictionary<string, int>();
|
||||
|
||||
public int BooleanKeyframeAnimatorCount { get; }
|
||||
|
||||
public int BooleanKeyFrameAnimationCount { get; }
|
||||
|
||||
public int CanvasGeometryCount { get; }
|
||||
|
|
Загрузка…
Ссылка в новой задаче