mirror of
https://github.com/4sval/FModel.git
synced 2026-03-21 17:24:26 -05:00
Merge pull request #372 from GICodeWarrior/patch-1
Improve TreeView and Export performance
This commit is contained in:
commit
928834fd4b
|
|
@ -4,6 +4,8 @@
|
||||||
xmlns:local="clr-namespace:FModel"
|
xmlns:local="clr-namespace:FModel"
|
||||||
xmlns:controls="clr-namespace:FModel.Views.Resources.Controls"
|
xmlns:controls="clr-namespace:FModel.Views.Resources.Controls"
|
||||||
xmlns:converters="clr-namespace:FModel.Views.Resources.Converters"
|
xmlns:converters="clr-namespace:FModel.Views.Resources.Converters"
|
||||||
|
xmlns:settings="clr-namespace:FModel.Settings"
|
||||||
|
xmlns:services="clr-namespace:FModel.Services"
|
||||||
xmlns:adonisUi="clr-namespace:AdonisUI;assembly=AdonisUI"
|
xmlns:adonisUi="clr-namespace:AdonisUI;assembly=AdonisUI"
|
||||||
xmlns:adonisControls="clr-namespace:AdonisUI.Controls;assembly=AdonisUI"
|
xmlns:adonisControls="clr-namespace:AdonisUI.Controls;assembly=AdonisUI"
|
||||||
xmlns:adonisExtensions="clr-namespace:AdonisUI.Extensions;assembly=AdonisUI"
|
xmlns:adonisExtensions="clr-namespace:AdonisUI.Extensions;assembly=AdonisUI"
|
||||||
|
|
@ -95,7 +97,7 @@
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<Separator />
|
<Separator />
|
||||||
<MenuItem Header="Auto Open Sounds" IsCheckable="True" StaysOpenOnClick="True"
|
<MenuItem Header="Auto Open Sounds" IsCheckable="True" StaysOpenOnClick="True"
|
||||||
IsChecked="{Binding IsAutoOpenSounds, Source={x:Static local:Settings.UserSettings.Default}}" />
|
IsChecked="{Binding IsAutoOpenSounds, Source={x:Static settings:UserSettings.Default}}" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="Views">
|
<MenuItem Header="Views">
|
||||||
<MenuItem Header="3D Viewer" Command="{Binding MenuCommand}" CommandParameter="Views_3dViewer">
|
<MenuItem Header="3D Viewer" Command="{Binding MenuCommand}" CommandParameter="Views_3dViewer">
|
||||||
|
|
@ -221,7 +223,7 @@
|
||||||
|
|
||||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Loading Mode" VerticalAlignment="Center" />
|
<TextBlock Grid.Row="0" Grid.Column="0" Text="Loading Mode" VerticalAlignment="Center" />
|
||||||
<ComboBox Grid.Row="0" Grid.Column="2" ItemsSource="{Binding LoadingModes.Modes}" IsEnabled="{Binding Status.IsReady}"
|
<ComboBox Grid.Row="0" Grid.Column="2" ItemsSource="{Binding LoadingModes.Modes}" IsEnabled="{Binding Status.IsReady}"
|
||||||
SelectedItem="{Binding LoadingMode, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}">
|
SelectedItem="{Binding LoadingMode, Source={x:Static settings:UserSettings.Default}, Mode=TwoWay}">
|
||||||
<ComboBox.ItemTemplate>
|
<ComboBox.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<TextBlock Text="{Binding Converter={x:Static converters:EnumToStringConverter.Instance}}" />
|
<TextBlock Text="{Binding Converter={x:Static converters:EnumToStringConverter.Instance}}" />
|
||||||
|
|
@ -327,7 +329,7 @@
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Separator Grid.Row="1" Style="{StaticResource CustomSeparator}" Margin="0" />
|
<Separator Grid.Row="1" Style="{StaticResource CustomSeparator}" Margin="0" />
|
||||||
<TreeView Grid.Row="2" x:Name="AssetsFolderName" Style="{StaticResource AssetsFolderTreeView}" PreviewMouseDoubleClick="OnAssetsTreeMouseDoubleClick">
|
<TreeView Grid.Row="2" x:Name="AssetsFolderName" Style="{StaticResource AssetsFolderTreeView}" PreviewMouseDoubleClick="OnAssetsTreeMouseDoubleClick" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" ScrollViewer.CanContentScroll="True">
|
||||||
<TreeView.ContextMenu>
|
<TreeView.ContextMenu>
|
||||||
<ContextMenu>
|
<ContextMenu>
|
||||||
<MenuItem Header="Extract Folder's Packages" Click="OnFolderExtractClick">
|
<MenuItem Header="Extract Folder's Packages" Click="OnFolderExtractClick">
|
||||||
|
|
@ -671,7 +673,7 @@
|
||||||
|
|
||||||
<TabControl Grid.Row="0" x:Name="TabControlName" Style="{StaticResource GameFilesTabControl}" />
|
<TabControl Grid.Row="0" x:Name="TabControlName" Style="{StaticResource GameFilesTabControl}" />
|
||||||
<Expander Grid.Row="1" Margin="0 5 0 5" ExpandDirection="Down"
|
<Expander Grid.Row="1" Margin="0 5 0 5" ExpandDirection="Down"
|
||||||
IsExpanded="{Binding IsLoggerExpanded, Source={x:Static local:Settings.UserSettings.Default}}">
|
IsExpanded="{Binding IsLoggerExpanded, Source={x:Static settings:UserSettings.Default}}">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
|
|
@ -734,7 +736,7 @@
|
||||||
<Setter Property="Background" Value="{DynamicResource {x:Static adonisUi:Brushes.ErrorBrush}}" />
|
<Setter Property="Background" Value="{DynamicResource {x:Static adonisUi:Brushes.ErrorBrush}}" />
|
||||||
<Setter Property="Foreground" Value="White" />
|
<Setter Property="Foreground" Value="White" />
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
<DataTrigger Binding="{Binding StatusChangeAttempted, Source={x:Static local:Services.ApplicationService.ThreadWorkerView}}" Value="True">
|
<DataTrigger Binding="{Binding StatusChangeAttempted, Source={x:Static services:ApplicationService.ThreadWorkerView}}" Value="True">
|
||||||
<DataTrigger.EnterActions>
|
<DataTrigger.EnterActions>
|
||||||
<BeginStoryboard>
|
<BeginStoryboard>
|
||||||
<Storyboard Duration="0:0:0.8">
|
<Storyboard Duration="0:0:0.8">
|
||||||
|
|
@ -751,7 +753,7 @@
|
||||||
</BeginStoryboard>
|
</BeginStoryboard>
|
||||||
</DataTrigger.EnterActions>
|
</DataTrigger.EnterActions>
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
<DataTrigger Binding="{Binding OperationCancelled, Source={x:Static local:Services.ApplicationService.ThreadWorkerView}}" Value="True">
|
<DataTrigger Binding="{Binding OperationCancelled, Source={x:Static services:ApplicationService.ThreadWorkerView}}" Value="True">
|
||||||
<DataTrigger.EnterActions>
|
<DataTrigger.EnterActions>
|
||||||
<BeginStoryboard>
|
<BeginStoryboard>
|
||||||
<Storyboard Duration="0:0:1">
|
<Storyboard Duration="0:0:1">
|
||||||
|
|
@ -780,7 +782,7 @@
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
<MultiDataTrigger>
|
<MultiDataTrigger>
|
||||||
<MultiDataTrigger.Conditions>
|
<MultiDataTrigger.Conditions>
|
||||||
<Condition Binding="{Binding CanBeCanceled, Source={x:Static local:Services.ApplicationService.ThreadWorkerView}}" Value="True" />
|
<Condition Binding="{Binding CanBeCanceled, Source={x:Static services:ApplicationService.ThreadWorkerView}}" Value="True" />
|
||||||
<Condition Binding="{Binding Status.Kind}" Value="{x:Static local:EStatusKind.Loading}" />
|
<Condition Binding="{Binding Status.Kind}" Value="{x:Static local:EStatusKind.Loading}" />
|
||||||
</MultiDataTrigger.Conditions>
|
</MultiDataTrigger.Conditions>
|
||||||
<Setter Property="Text" Value="{Binding Status.Label, StringFormat='{}{0} … ESC to Cancel'}" />
|
<Setter Property="Text" Value="{Binding Status.Label, StringFormat='{}{0} … ESC to Cancel'}" />
|
||||||
|
|
@ -805,7 +807,7 @@
|
||||||
<StatusBarItem.Style>
|
<StatusBarItem.Style>
|
||||||
<Style TargetType="StatusBarItem">
|
<Style TargetType="StatusBarItem">
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
<DataTrigger Binding="{Binding IsAutoOpenSounds, Source={x:Static local:Settings.UserSettings.Default}}" Value="False">
|
<DataTrigger Binding="{Binding IsAutoOpenSounds, Source={x:Static settings:UserSettings.Default}}" Value="False">
|
||||||
<Setter Property="Visibility" Value="Hidden" />
|
<Setter Property="Visibility" Value="Hidden" />
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
|
|
|
||||||
|
|
@ -507,7 +507,7 @@ public class CUE4ParseViewModel : ViewModel
|
||||||
{
|
{
|
||||||
foreach (var asset in assetItems)
|
foreach (var asset in assetItems)
|
||||||
{
|
{
|
||||||
Thread.Sleep(10);
|
Thread.Yield();
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
Extract(cancellationToken, asset.FullPath, TabControl.HasNoTabs);
|
Extract(cancellationToken, asset.FullPath, TabControl.HasNoTabs);
|
||||||
}
|
}
|
||||||
|
|
@ -517,7 +517,7 @@ public class CUE4ParseViewModel : ViewModel
|
||||||
{
|
{
|
||||||
foreach (var asset in folder.AssetsList.Assets)
|
foreach (var asset in folder.AssetsList.Assets)
|
||||||
{
|
{
|
||||||
Thread.Sleep(10);
|
Thread.Yield();
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Diagnostics;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using AdonisUI.Controls;
|
using AdonisUI.Controls;
|
||||||
using FModel.Extensions;
|
using FModel.Extensions;
|
||||||
|
|
@ -79,19 +80,13 @@ public class MenuCommand : ViewModelCommand<ApplicationViewModel>
|
||||||
case "ToolBox_Expand_All":
|
case "ToolBox_Expand_All":
|
||||||
await ApplicationService.ThreadWorkerView.Begin(cancellationToken =>
|
await ApplicationService.ThreadWorkerView.Begin(cancellationToken =>
|
||||||
{
|
{
|
||||||
foreach (var folder in contextViewModel.CUE4Parse.AssetsFolder.Folders)
|
SetFoldersIsExpanded(contextViewModel.CUE4Parse.AssetsFolder, true, cancellationToken);
|
||||||
{
|
|
||||||
LoopFolders(cancellationToken, folder, true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "ToolBox_Collapse_All":
|
case "ToolBox_Collapse_All":
|
||||||
await ApplicationService.ThreadWorkerView.Begin(cancellationToken =>
|
await ApplicationService.ThreadWorkerView.Begin(cancellationToken =>
|
||||||
{
|
{
|
||||||
foreach (var folder in contextViewModel.CUE4Parse.AssetsFolder.Folders)
|
SetFoldersIsExpanded(contextViewModel.CUE4Parse.AssetsFolder, false, cancellationToken);
|
||||||
{
|
|
||||||
LoopFolders(cancellationToken, folder, false);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case TreeItem selectedFolder:
|
case TreeItem selectedFolder:
|
||||||
|
|
@ -101,15 +96,44 @@ public class MenuCommand : ViewModelCommand<ApplicationViewModel>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoopFolders(CancellationToken cancellationToken, TreeItem parent, bool isExpanded)
|
private static void SetFoldersIsExpanded(AssetsFolderViewModel root, bool isExpanded, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (parent.IsExpanded != isExpanded)
|
LinkedList<TreeItem> nodes = new();
|
||||||
|
foreach (TreeItem folder in root.Folders)
|
||||||
{
|
{
|
||||||
parent.IsExpanded = isExpanded;
|
nodes.AddLast(folder);
|
||||||
Thread.Sleep(10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
LinkedListNode<TreeItem> current = nodes.First;
|
||||||
foreach (var f in parent.Folders) LoopFolders(cancellationToken, f, isExpanded);
|
while (current != null)
|
||||||
|
{
|
||||||
|
TreeItem folder = current.Value;
|
||||||
|
|
||||||
|
// Collapse top-down (reduce layout updates)
|
||||||
|
if (!isExpanded)
|
||||||
|
{
|
||||||
|
folder.IsExpanded = isExpanded;
|
||||||
|
Thread.Yield();
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (TreeItem child in folder.Folders)
|
||||||
|
{
|
||||||
|
nodes.AddLast(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current.Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expand bottom-up (reduce layout updates)
|
||||||
|
if (isExpanded)
|
||||||
|
{
|
||||||
|
for (LinkedListNode<TreeItem> node = nodes.Last; node != null; node = node.Previous)
|
||||||
|
{
|
||||||
|
node.Value.IsExpanded = isExpanded;
|
||||||
|
Thread.Yield();
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
xmlns:soundOut="clr-namespace:CSCore.SoundOut;assembly=CSCore"
|
xmlns:soundOut="clr-namespace:CSCore.SoundOut;assembly=CSCore"
|
||||||
xmlns:audioControls="clr-namespace:FModel.Views.Resources.Controls.Aup"
|
xmlns:audioControls="clr-namespace:FModel.Views.Resources.Controls.Aup"
|
||||||
xmlns:converters="clr-namespace:FModel.Views.Resources.Converters"
|
xmlns:converters="clr-namespace:FModel.Views.Resources.Converters"
|
||||||
|
xmlns:settings="clr-namespace:FModel.Settings"
|
||||||
xmlns:avalonedit="http://icsharpcode.net/sharpdevelop/avalonedit"
|
xmlns:avalonedit="http://icsharpcode.net/sharpdevelop/avalonedit"
|
||||||
xmlns:folding="clr-namespace:ICSharpCode.AvalonEdit.Folding;assembly=ICSharpCode.AvalonEdit"
|
xmlns:folding="clr-namespace:ICSharpCode.AvalonEdit.Folding;assembly=ICSharpCode.AvalonEdit"
|
||||||
xmlns:adonisUi="clr-namespace:AdonisUI;assembly=AdonisUI"
|
xmlns:adonisUi="clr-namespace:AdonisUI;assembly=AdonisUI"
|
||||||
|
|
@ -182,19 +183,19 @@
|
||||||
</Setter.Value>
|
</Setter.Value>
|
||||||
</Setter>
|
</Setter>
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static local:Settings.UserSettings.Default}}" Value="{x:Static local:ELoadingMode.Single}">
|
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static settings:UserSettings.Default}}" Value="{x:Static local:ELoadingMode.Single}">
|
||||||
<Setter Property="SelectionMode" Value="Single" />
|
<Setter Property="SelectionMode" Value="Single" />
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static local:Settings.UserSettings.Default}}" Value="{x:Static local:ELoadingMode.Multiple}">
|
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static settings:UserSettings.Default}}" Value="{x:Static local:ELoadingMode.Multiple}">
|
||||||
<Setter Property="SelectionMode" Value="Extended" />
|
<Setter Property="SelectionMode" Value="Extended" />
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static local:Settings.UserSettings.Default}}" Value="{x:Static local:ELoadingMode.All}">
|
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static settings:UserSettings.Default}}" Value="{x:Static local:ELoadingMode.All}">
|
||||||
<Setter Property="SelectionMode" Value="Extended" />
|
<Setter Property="SelectionMode" Value="Extended" />
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static local:Settings.UserSettings.Default}}" Value="{x:Static local:ELoadingMode.AllButNew}">
|
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static settings:UserSettings.Default}}" Value="{x:Static local:ELoadingMode.AllButNew}">
|
||||||
<Setter Property="SelectionMode" Value="Extended" />
|
<Setter Property="SelectionMode" Value="Extended" />
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static local:Settings.UserSettings.Default}}" Value="{x:Static local:ELoadingMode.AllButModified}">
|
<DataTrigger Binding="{Binding LoadingMode, Source={x:Static settings:UserSettings.Default}}" Value="{x:Static local:ELoadingMode.AllButModified}">
|
||||||
<Setter Property="SelectionMode" Value="Extended" />
|
<Setter Property="SelectionMode" Value="Extended" />
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
|
|
@ -247,7 +248,7 @@
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style x:Key="AssetsFolderTreeView" TargetType="TreeView" BasedOn="{StaticResource {x:Type TreeView}}">
|
<Style x:Key="AssetsFolderTreeView" TargetType="TreeView" BasedOn="{StaticResource {x:Type TreeView}}">
|
||||||
<Setter Property="ItemsSource" Value="{Binding CUE4Parse.AssetsFolder.FoldersView, IsAsync=True}" />
|
<Setter Property="ItemsSource" Value="{Binding CUE4Parse.AssetsFolder.FoldersView}" />
|
||||||
<Setter Property="adonisExtensions:ScrollViewerExtension.VerticalScrollBarExpansionMode" Value="NeverExpand"/>
|
<Setter Property="adonisExtensions:ScrollViewerExtension.VerticalScrollBarExpansionMode" Value="NeverExpand"/>
|
||||||
<Setter Property="adonisExtensions:ScrollViewerExtension.VerticalScrollBarPlacement" Value="Docked"/>
|
<Setter Property="adonisExtensions:ScrollViewerExtension.VerticalScrollBarPlacement" Value="Docked"/>
|
||||||
<Setter Property="adonisExtensions:ScrollViewerExtension.HorizontalScrollBarExpansionMode" Value="NeverExpand"/>
|
<Setter Property="adonisExtensions:ScrollViewerExtension.HorizontalScrollBarExpansionMode" Value="NeverExpand"/>
|
||||||
|
|
@ -255,7 +256,7 @@
|
||||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||||
<Setter Property="ItemTemplate">
|
<Setter Property="ItemTemplate">
|
||||||
<Setter.Value>
|
<Setter.Value>
|
||||||
<HierarchicalDataTemplate ItemsSource="{Binding FoldersView, IsAsync=True}">
|
<HierarchicalDataTemplate ItemsSource="{Binding FoldersView}">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<Image x:Name="TreeImage" Source="/FModel;component/Resources/folder.png"
|
<Image x:Name="TreeImage" Source="/FModel;component/Resources/folder.png"
|
||||||
Width="16" Height="16" HorizontalAlignment="Center" Margin="0 0 3.5 0" />
|
Width="16" Height="16" HorizontalAlignment="Center" Margin="0 0 3.5 0" />
|
||||||
|
|
@ -647,7 +648,7 @@
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="{Binding AvalonImageSize, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" />
|
<ColumnDefinition Width="{Binding AvalonImageSize, Source={x:Static settings:UserSettings.Default}, Mode=TwoWay}" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<controls:AvalonEditor x:Name="DynamicArea" Grid.Column="0" DataContext="{Binding SelectedItem, ElementName=TabControlName}" />
|
<controls:AvalonEditor x:Name="DynamicArea" Grid.Column="0" DataContext="{Binding SelectedItem, ElementName=TabControlName}" />
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user