log results if export immediately

This commit is contained in:
Asval 2026-08-05 13:30:41 +02:00
parent 7c86ee47ec
commit c8539cb804
7 changed files with 104 additions and 20 deletions

@ -1 +1 @@
Subproject commit 7afcbb323c9fd9445d5452856b18b1d732d2dccd
Subproject commit 9ea4df652f1ce14684797d9e635c2984b30d3c26

View File

@ -64,12 +64,12 @@ public sealed class UserSettings : ViewModel
Default.TextureExportFormat,
Default.TextureQuality,
Default.SaveHdrTexturesAsHdr,
Default.ExportAllTextureMips,
Default.MaterialExportFormat,
Default.SaveEmbeddedMaterials,
Default.SaveMorphTargets,
Default.SocketExportFormat,
Default.CompressionFormat,
Default.ExportAllTextureMips
Default.CompressionFormat
);
}

View File

@ -228,11 +228,11 @@ public class ExportOptionsViewModel : ViewModel
SelectedTextureFormat,
TextureQuality,
ExportHdrTexturesAsHdr,
ExportAllTextureMips,
SelectedMaterialDepth,
ExportMaterials,
ExportMorphTargets,
SelectedSocketFormat,
SelectedCompressionFormat,
ExportAllTextureMips
SelectedCompressionFormat
);
}

View File

@ -1,8 +1,10 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -15,6 +17,7 @@ using FModel.Extensions;
using FModel.Framework;
using FModel.Settings;
using FModel.Views;
using FModel.Views.Resources.Controls;
using FModel.Views.Snooper;
using Serilog.Events;
@ -175,9 +178,9 @@ public class ExportSessionViewModel : ViewModel
});
}
public async Task ExportAsync()
public async Task<IReadOnlyList<ExportResult>> ExportAsync()
{
if (IsRunning || Session.TotalQueued == 0) return;
if (IsRunning || Session.TotalQueued == 0) return null;
IsRunning = true;
IsFinished = false;
@ -218,9 +221,10 @@ public class ExportSessionViewModel : ViewModel
});
});
IReadOnlyList<ExportResult> results = null;
try
{
await Session.RunAsync(exportDirectory, exportOptions, progress, _cts.Token).ConfigureAwait(false);
results = await Session.RunAsync(exportDirectory, exportOptions, progress, _cts.Token).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
@ -237,14 +241,86 @@ public class ExportSessionViewModel : ViewModel
UpdateElapsedAndEta();
});
}
return results;
}
public async Task ExportAutomaticallyAsync()
{
if (UserSettings.Default.ExportImmediately)
if (!UserSettings.Default.ExportImmediately) return;
var results = await ExportAsync();
if (results is { Count: > 0 }) LogSummary(results);
}
private static void LogSummary(IReadOnlyList<ExportResult> results)
{
if (results.Count == 1)
{
await ExportAsync();
var result = results[0];
switch (result.Success)
{
case true when result.DiskFilePaths is { Count: > 0 } files:
FLogger.Append(ELog.Information, () =>
{
FLogger.Text("Successfully exported ", Constants.WHITE);
FLogger.Link(Path.GetFileName(files[0]), files[0], true);
});
break;
case false when result.Error is { } exception:
FLogger.Append(exception);
break;
}
return;
}
var failed = 0;
var groups = new Dictionary<string, (int Count, string[] Source, string[] Directory)>(StringComparer.OrdinalIgnoreCase);
foreach (var result in results)
{
if (!result.Success)
{
failed++;
continue;
}
if (result.DiskFilePaths == null) continue;
foreach (var file in result.DiskFilePaths)
{
var extension = Path.GetExtension(file).TrimStart('.');
var source = SplitDirectory(result.ObjectPath);
var directory = SplitDirectory(file);
groups[extension] = groups.TryGetValue(extension, out var group)
? (group.Count + 1, CommonPrefix(group.Source, source), CommonPrefix(group.Directory, directory))
: (1, source, directory);
}
}
foreach (var (extension, group) in groups)
{
var source = string.Join('/', group.Source);
var directory = string.Join(Path.DirectorySeparatorChar, group.Directory);
FLogger.Append(ELog.Information, () =>
{
FLogger.Text($"Successfully exported {group.Count} {extension} from ", Constants.WHITE);
if (directory.Length > 0) FLogger.Link(source, directory, true);
else FLogger.Text(source, Constants.WHITE, true);
});
}
if (failed > 0)
{
FLogger.Append(ELog.Error, () => FLogger.Text($"Failed to export {failed} asset{(failed == 1 ? "" : "s")}", Constants.WHITE, true));
}
}
private static string[] SplitDirectory(string path) => Path.GetDirectoryName(path)?.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) ?? [];
private static string[] CommonPrefix(string[] a, string[] b)
{
var i = 0;
while (i < a.Length && i < b.Length && string.Equals(a[i], b[i], StringComparison.OrdinalIgnoreCase)) i++;
return i == a.Length ? a : a[..i];
}
public void CancelExport()

View File

@ -294,7 +294,7 @@ public class TabItem : ViewModel
var img = new CTexture[1];
if (texture is UTexture2DArray textureArray)
{
img = textureArray.DecodeTextureArray(UserSettings.Default.CurrentDir.TexturePlatform);
img = textureArray.DecodeTextureArray(null, UserSettings.Default.CurrentDir.TexturePlatform);
appendLayerNumber = true;
}
else

View File

@ -47,14 +47,22 @@
<Button Grid.Row="0" Grid.Column="4" Content="..." MinWidth="28" Click="OnBrowseOutputDirectory" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="Export Immediately" VerticalAlignment="Center" Margin="0 8 0 0"
Visibility="{Binding ShowExportImmediatelyOption, Converter={StaticResource BoolToVisibilityConverter}}"
ToolTip="Start exporting automatically after all selected assets have been queued." />
<CheckBox Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="3" Margin="0 8 0 0"
IsChecked="{Binding ExportImmediately, Mode=TwoWay}"
Content="{Binding IsChecked, RelativeSource={RelativeSource Self}, Converter={x:Static converters:BoolToToggleConverter.Instance}}"
Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}"
Visibility="{Binding ShowExportImmediatelyOption, Converter={StaticResource BoolToVisibilityConverter}}"
ToolTip="Start exporting automatically after all selected assets have been queued." />
Visibility="{Binding ShowExportImmediatelyOption, Converter={StaticResource BoolToVisibilityConverter}}" />
<Grid Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="3" Margin="0 8 0 0"
Visibility="{Binding ShowExportImmediatelyOption, Converter={StaticResource BoolToVisibilityConverter}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0"
IsChecked="{Binding ExportImmediately, Mode=TwoWay}"
Content="{Binding IsChecked, RelativeSource={RelativeSource Self}, Converter={x:Static converters:BoolToToggleConverter.Instance}}"
Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" />
<TextBlock Grid.Column="1" VerticalAlignment="Center" Margin="5 0 0 0" FontSize="11"
Foreground="{DynamicResource {x:Static adonisUi:Brushes.DisabledForegroundBrush}}"
Text="Start exporting automatically after all selected assets have been queued." />
</Grid>
<Separator Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="5" Style="{StaticResource CustomSeparator}" Tag="MESH" Margin="0 10 0 10" />

View File

@ -196,7 +196,7 @@ public class Options
var bitmap = o switch
{
UTexture2D texture2D => texture2D.Decode(UserSettings.Default.PreviewMaxTextureSize, UserSettings.Default.CurrentDir.TexturePlatform),
UTexture2DArray texture2DArray => texture2DArray.DecodeTextureArray(UserSettings.Default.CurrentDir.TexturePlatform)?.FirstOrDefault(),
UTexture2DArray texture2DArray => texture2DArray.DecodeTextureArray(null, UserSettings.Default.CurrentDir.TexturePlatform)?.FirstOrDefault(),
_ => o.Decode(UserSettings.Default.CurrentDir.TexturePlatform)
};