Handle failed extraction

- Don't open audio player during json export
- Don't link to directory that might not exist (would take us to desktop)
- Show real amount of exported assets
This commit is contained in:
Masusder
2026-03-17 01:45:19 +01:00
parent 36ad881a8d
commit a06a6a97a1
3 changed files with 48 additions and 23 deletions

View File

@@ -162,6 +162,8 @@ public class CUE4ParseViewModel : ViewModel
public CriWareProvider CriWareProvider => _criWareProviderLazy?.Value;
public ConcurrentBag<string> UnknownExtensions = [];
public int ExportedCount;
public CUE4ParseViewModel()
{
var currentDir = UserSettings.Default.CurrentDir;
@@ -1426,6 +1428,7 @@ public class CUE4ParseViewModel : ViewModel
if (conversionSuccess) savedAudioPath = wavFilePath;
}
Interlocked.Increment(ref ExportedCount);
Log.Information("Successfully saved {FilePath}", savedAudioPath);
if (updateUi && conversionSuccess)
{
@@ -1439,6 +1442,9 @@ public class CUE4ParseViewModel : ViewModel
return;
}
if (!updateUi)
return;
// TODO
// since we are currently in a thread, the audio player's lifetime (memory-wise) will keep the current thread up and running until fmodel itself closes
// the solution would be to kill the current thread at this line and then open the audio player without "Application.Current.Dispatcher.Invoke"
@@ -1456,6 +1462,7 @@ public class CUE4ParseViewModel : ViewModel
var toSaveDirectory = new DirectoryInfo(UserSettings.Default.ModelDirectory);
if (toSave.TryWriteToDir(toSaveDirectory, out var label, out var savedFilePath))
{
Interlocked.Increment(ref ExportedCount);
Log.Information("Successfully saved {FilePath}", savedFilePath);
if (updateUi)
{
@@ -1489,6 +1496,7 @@ public class CUE4ParseViewModel : ViewModel
}
});
Interlocked.Increment(ref ExportedCount);
Log.Information("{FileName} successfully exported", entry.Name);
if (updateUi)
{

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections;
using System.Data;
using System.IO;
using System.Linq;
using System.Threading;
@@ -16,9 +17,7 @@ public class RightClickMenuCommand : ViewModelCommand<ApplicationViewModel>
{
private ThreadWorkerViewModel _threadWorkerView => ApplicationService.ThreadWorkerView;
public RightClickMenuCommand(ApplicationViewModel contextViewModel) : base(contextViewModel)
{
}
public RightClickMenuCommand(ApplicationViewModel contextViewModel) : base(contextViewModel) { }
private enum EAction
{
@@ -47,7 +46,7 @@ public class RightClickMenuCommand : ViewModelCommand<ApplicationViewModel>
var assets = param
.Select(static item => item switch
{
GameFile gf => gf,
GameFile gf => gf, // Search view passes GameFile directly
GameFileViewModel gvm => gvm.Asset,
_ => null
})
@@ -74,6 +73,7 @@ public class RightClickMenuCommand : ViewModelCommand<ApplicationViewModel>
_ => throw new ArgumentOutOfRangeException("Unsupported asset action."),
};
Interlocked.Exchange(ref contextViewModel.CUE4Parse.ExportedCount, 0);
await _threadWorkerView.Begin(cancellationToken =>
{
if (action is EAction.Show)
@@ -126,11 +126,7 @@ public class RightClickMenuCommand : ViewModelCommand<ApplicationViewModel>
folderAction(folder);
var path = Path.Combine(dirType, UserSettings.Default.KeepDirectoryStructure ? folder.PathAtThisPoint : folder.PathAtThisPoint.SubstringAfterLast('/')).Replace('\\', '/');
FLogger.Append(ELog.Information, () =>
{
FLogger.Text($"Successfully exported {filetype} from ", Constants.WHITE);
FLogger.Link(folder.PathAtThisPoint, path, true);
});
LogExport(contextViewModel, folder.PathAtThisPoint, path, dirType, filetype);
}
Action<GameFile, EBulkType, bool> fileAction = bulktype switch
@@ -155,13 +151,31 @@ public class RightClickMenuCommand : ViewModelCommand<ApplicationViewModel>
if (update)
{
var path = Path.Combine(dirType, UserSettings.Default.KeepDirectoryStructure ? directory : directory.SubstringAfterLast('/')).Replace('\\', '/');
FLogger.Append(ELog.Information, () =>
{
FLogger.Text($"Successfully exported {list.Length} {filetype} from ", Constants.WHITE);
FLogger.Link(directory, path, true);
});
LogExport(contextViewModel, directory, path, dirType, filetype);
}
}
});
}
private void LogExport(ApplicationViewModel contextViewModel, string directory, string path, string basePath, string fileType)
{
if (contextViewModel.CUE4Parse.ExportedCount > 0)
{
FLogger.Append(ELog.Information, () =>
{
FLogger.Text($"Successfully exported {contextViewModel.CUE4Parse.ExportedCount} {fileType} from ", Constants.WHITE);
FLogger.Link(directory, Path.Exists(path) ? path : basePath, true);
});
}
else
{
// Not an error because folder simply might not contain type of asset user is trying to save
FLogger.Append(ELog.Warning, () =>
{
FLogger.Text($"Failed to export any {fileType} from {directory}", Constants.WHITE, true);
});
}
Interlocked.Exchange(ref contextViewModel.CUE4Parse.ExportedCount, 0);
}
}

View File

@@ -1,6 +1,17 @@
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Media.Imaging;
using CUE4Parse.FileProvider.Objects;
using CUE4Parse.UE4.Assets.Exports.Texture;
using CUE4Parse.Utils;
using CUE4Parse_Conversion.Textures;
using FModel.Extensions;
using FModel.Framework;
using FModel.Services;
using FModel.Settings;
using FModel.ViewModels.Commands;
using FModel.Views.Resources.Controls;
@@ -8,15 +19,6 @@ using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Highlighting;
using Serilog;
using SkiaSharp;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Media.Imaging;
using CUE4Parse.UE4.Assets.Exports.Texture;
using CUE4Parse_Conversion.Textures;
using CUE4Parse.FileProvider.Objects;
using CUE4Parse.Utils;
namespace FModel.ViewModels;
@@ -412,6 +414,7 @@ public class TabItem : ViewModel
{
if (File.Exists(path))
{
Interlocked.Increment(ref ApplicationService.ApplicationView.CUE4Parse.ExportedCount);
Log.Information("{FileName} successfully saved", fileName);
if (updateUi)
{