From 39f5855b1204480ce502902bc8f4c7dd0853954b Mon Sep 17 00:00:00 2001 From: 4sval Date: Sun, 12 Mar 2023 00:11:59 +0100 Subject: [PATCH] improved CustomRichTextBox + updateUi parameter to speed up savings --- CUE4Parse | 2 +- FModel/MainWindow.xaml.cs | 6 ++ .../ApiEndpoints/FModelApiEndpoint.cs | 2 +- FModel/ViewModels/CUE4ParseViewModel.cs | 53 ++++++++------ FModel/ViewModels/Commands/MenuCommand.cs | 2 +- .../Commands/RightClickMenuCommand.cs | 4 +- FModel/ViewModels/Commands/TabCommand.cs | 4 +- FModel/ViewModels/TabControlViewModel.cs | 73 +++++++------------ .../Controls/Rtb/CustomRichTextBox.cs | 46 ++++++------ 9 files changed, 95 insertions(+), 97 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index cfdd02fc..04239c2e 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit cfdd02fc0aaa03b1f530c3a1f62585c043e04538 +Subproject commit 04239c2e1f7fd257c6671a0bb52a7896c0232930 diff --git a/FModel/MainWindow.xaml.cs b/FModel/MainWindow.xaml.cs index 69034bad..0c9d1b43 100644 --- a/FModel/MainWindow.xaml.cs +++ b/FModel/MainWindow.xaml.cs @@ -191,6 +191,9 @@ public partial class MainWindow if (AssetsFolderName.SelectedItem is TreeItem folder) { await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.SaveFolder(cancellationToken, folder); }); + FLogger.AppendInformation(); + FLogger.AppendText("Successfully saved ", Constants.WHITE); + FLogger.AppendLink(folder.PathAtThisPoint, UserSettings.Default.PropertiesDirectory, true); } } @@ -199,6 +202,9 @@ public partial class MainWindow if (AssetsFolderName.SelectedItem is TreeItem folder) { await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.TextureFolder(cancellationToken, folder); }); + FLogger.AppendInformation(); + FLogger.AppendText("Successfully saved ", Constants.WHITE); + FLogger.AppendLink(folder.PathAtThisPoint, UserSettings.Default.TextureDirectory, true); } } diff --git a/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs b/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs index bbd4ec09..2650fd00 100644 --- a/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs +++ b/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs @@ -180,7 +180,7 @@ public class FModelApiEndpoint : AbstractApiProvider _applicationView.CUE4Parse.TabControl.AddTab($"Release Notes: {args.CurrentVersion}"); _applicationView.CUE4Parse.TabControl.SelectedTab.Highlighter = AvalonExtensions.HighlighterSelector("changelog"); - _applicationView.CUE4Parse.TabControl.SelectedTab.SetDocumentText(response.Content, false); + _applicationView.CUE4Parse.TabControl.SelectedTab.SetDocumentText(response.Content, false, false); UserSettings.Default.ShowChangelog = false; } } diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 17c2782a..b566634a 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -578,8 +578,9 @@ public class CUE4ParseViewModel : ViewModel TabControl.SelectedTab.Directory = directory; } - var autoProperties = bulk == (EBulkType.Properties | EBulkType.Auto); - var autoTextures = bulk == (EBulkType.Textures | EBulkType.Auto); + var updateUi = !HasFlag(bulk, EBulkType.Auto); + var saveProperties = HasFlag(bulk, EBulkType.Properties); + var saveTextures = HasFlag(bulk, EBulkType.Textures); TabControl.SelectedTab.ClearImages(); TabControl.SelectedTab.ResetDocumentText(); TabControl.SelectedTab.ScrollTrigger = null; @@ -590,7 +591,7 @@ public class CUE4ParseViewModel : ViewModel case "umap": { var exports = Provider.LoadObjectExports(fullPath); // cancellationToken - TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(exports, Formatting.Indented), autoProperties); + TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(exports, Formatting.Indented), saveProperties, updateUi); if (HasFlag(bulk, EBulkType.Properties)) break; // do not search for viewable exports if we are dealing with jsons foreach (var e in exports) @@ -633,7 +634,7 @@ public class CUE4ParseViewModel : ViewModel using var stream = new MemoryStream(data) { Position = 0 }; using var reader = new StreamReader(stream); - TabControl.SelectedTab.SetDocumentText(reader.ReadToEnd(), autoProperties); + TabControl.SelectedTab.SetDocumentText(reader.ReadToEnd(), saveProperties, updateUi); } break; @@ -643,7 +644,7 @@ public class CUE4ParseViewModel : ViewModel if (Provider.TryCreateReader(fullPath, out var archive)) { var metadata = new FTextLocalizationMetaDataResource(archive); - TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(metadata, Formatting.Indented), autoProperties); + TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(metadata, Formatting.Indented), saveProperties, updateUi); } break; @@ -653,7 +654,7 @@ public class CUE4ParseViewModel : ViewModel if (Provider.TryCreateReader(fullPath, out var archive)) { var locres = new FTextLocalizationResource(archive); - TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(locres, Formatting.Indented), autoProperties); + TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(locres, Formatting.Indented), saveProperties, updateUi); } break; @@ -663,7 +664,7 @@ public class CUE4ParseViewModel : ViewModel if (Provider.TryCreateReader(fullPath, out var archive)) { var registry = new FAssetRegistryState(archive); - TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(registry, Formatting.Indented), autoProperties); + TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(registry, Formatting.Indented), saveProperties, updateUi); } break; @@ -674,7 +675,7 @@ public class CUE4ParseViewModel : ViewModel if (Provider.TryCreateReader(fullPath, out var archive)) { var wwise = new WwiseReader(archive); - TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(wwise, Formatting.Indented), autoProperties); + TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(wwise, Formatting.Indented), saveProperties, updateUi); foreach (var (name, data) in wwise.WwiseEncodedMedias) { SaveAndPlaySound(fullPath.SubstringBeforeWithLast("/") + name, "WEM", data); @@ -695,7 +696,7 @@ public class CUE4ParseViewModel : ViewModel if (Provider.TryCreateReader(fullPath, out var archive)) { var header = new FOodleDictionaryArchive(archive).Header; - TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(header, Formatting.Indented), autoProperties); + TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(header, Formatting.Indented), saveProperties, updateUi); } break; @@ -707,7 +708,7 @@ public class CUE4ParseViewModel : ViewModel if (Provider.TrySaveAsset(fullPath, out var data)) { using var stream = new MemoryStream(data) { Position = 0 }; - TabControl.SelectedTab.AddImage(fileName.SubstringBeforeLast("."), false, SKBitmap.Decode(stream), autoTextures); + TabControl.SelectedTab.AddImage(fileName.SubstringBeforeLast("."), false, SKBitmap.Decode(stream), saveTextures, updateUi); } break; @@ -727,7 +728,7 @@ public class CUE4ParseViewModel : ViewModel canvas.DrawPicture(svg.Picture, paint); } - TabControl.SelectedTab.AddImage(fileName.SubstringBeforeLast("."), false, bitmap, autoTextures); + TabControl.SelectedTab.AddImage(fileName.SubstringBeforeLast("."), false, bitmap, saveTextures, updateUi); } break; @@ -744,7 +745,7 @@ public class CUE4ParseViewModel : ViewModel if (Provider.TryCreateReader(fullPath, out var archive)) { var ar = new FShaderCodeArchive(archive); - TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(ar, Formatting.Indented), autoProperties); + TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(ar, Formatting.Indented), saveProperties, updateUi); } break; @@ -766,7 +767,7 @@ public class CUE4ParseViewModel : ViewModel var exports = Provider.LoadObjectExports(fullPath); // cancellationToken TabControl.SelectedTab.Highlighter = AvalonExtensions.HighlighterSelector(""); // json - TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(exports, Formatting.Indented), false); + TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(exports, Formatting.Indented), false, false); foreach (var e in exports) { @@ -778,7 +779,8 @@ public class CUE4ParseViewModel : ViewModel private bool CheckExport(CancellationToken cancellationToken, UObject export, EBulkType bulk = EBulkType.None) // return true once you wanna stop searching for exports { var isNone = bulk == EBulkType.None; - var loadTextures = isNone || HasFlag(bulk, EBulkType.Textures); + var updateUi = !HasFlag(bulk, EBulkType.Auto); + var saveTextures = HasFlag(bulk, EBulkType.Textures); switch (export) { case USolarisDigest solarisDigest when isNone: @@ -787,12 +789,12 @@ public class CUE4ParseViewModel : ViewModel TabControl.AddTab($"{solarisDigest.ProjectName}.verse"); TabControl.SelectedTab.Highlighter = AvalonExtensions.HighlighterSelector("verse"); - TabControl.SelectedTab.SetDocumentText(solarisDigest.ReadableCode, false); + TabControl.SelectedTab.SetDocumentText(solarisDigest.ReadableCode, false, false); return true; } - case UTexture2D { IsVirtual: false } texture when loadTextures: + case UTexture2D { IsVirtual: false } texture when isNone: { - TabControl.SelectedTab.AddImage(texture, HasFlag(bulk, EBulkType.Auto)); + TabControl.SelectedTab.AddImage(texture, saveTextures, updateUi); return false; } case UAkMediaAssetData when isNone: @@ -845,16 +847,16 @@ public class CUE4ParseViewModel : ViewModel } default: { - if (!loadTextures) - return false; + if (!isNone && !saveTextures) return false; using var package = new CreatorPackage(export, UserSettings.Default.CosmeticStyle); if (!package.TryConstructCreator(out var creator)) return false; creator.ParseForInfo(); - TabControl.SelectedTab.AddImage(export.Name, false, creator.Draw(), HasFlag(bulk, EBulkType.Auto)); + TabControl.SelectedTab.AddImage(export.Name, false, creator.Draw(), saveTextures, updateUi); return true; + } } } @@ -943,19 +945,22 @@ public class CUE4ParseViewModel : ViewModel } }); + Log.Information("{FileName} successfully exported", fileName); if (updateUi) { - Log.Information("{FileName} successfully exported", fileName); FLogger.AppendInformation(); FLogger.AppendText("Successfully exported ", Constants.WHITE); FLogger.AppendLink(fileName, path, true); } } - else if (updateUi) + else { Log.Error("{FileName} could not be exported", fileName); - FLogger.AppendError(); - FLogger.AppendText($"Could not export '{fileName}'", Constants.WHITE, true); + if (updateUi) + { + FLogger.AppendError(); + FLogger.AppendText($"Could not export '{fileName}'", Constants.WHITE, true); + } } } diff --git a/FModel/ViewModels/Commands/MenuCommand.cs b/FModel/ViewModels/Commands/MenuCommand.cs index b4263886..6d49bcb7 100644 --- a/FModel/ViewModels/Commands/MenuCommand.cs +++ b/FModel/ViewModels/Commands/MenuCommand.cs @@ -33,7 +33,7 @@ public class MenuCommand : ViewModelCommand case "Directory_ArchivesInfo": contextViewModel.CUE4Parse.TabControl.AddTab("Archives Info"); contextViewModel.CUE4Parse.TabControl.SelectedTab.Highlighter = AvalonExtensions.HighlighterSelector("json"); - contextViewModel.CUE4Parse.TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(contextViewModel.CUE4Parse.GameDirectory.DirectoryFiles, Formatting.Indented), false); + contextViewModel.CUE4Parse.TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(contextViewModel.CUE4Parse.GameDirectory.DirectoryFiles, Formatting.Indented), false, false); break; case "Views_3dViewer": contextViewModel.CUE4Parse.SnooperViewer.Run(); diff --git a/FModel/ViewModels/Commands/RightClickMenuCommand.cs b/FModel/ViewModels/Commands/RightClickMenuCommand.cs index 497cc518..821cf32b 100644 --- a/FModel/ViewModels/Commands/RightClickMenuCommand.cs +++ b/FModel/ViewModels/Commands/RightClickMenuCommand.cs @@ -43,14 +43,14 @@ public class RightClickMenuCommand : ViewModelCommand foreach (var asset in assetItems) { cancellationToken.ThrowIfCancellationRequested(); - contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, false, EBulkType.Properties | EBulkType.Auto); + contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, false, EBulkType.Properties); } break; case "Assets_Save_Textures": foreach (var asset in assetItems) { cancellationToken.ThrowIfCancellationRequested(); - contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, false, EBulkType.Textures | EBulkType.Auto); + contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, false, EBulkType.Textures); } break; case "Assets_Save_Models": diff --git a/FModel/ViewModels/Commands/TabCommand.cs b/FModel/ViewModels/Commands/TabCommand.cs index 17152ed5..ba9c2fe0 100644 --- a/FModel/ViewModels/Commands/TabCommand.cs +++ b/FModel/ViewModels/Commands/TabCommand.cs @@ -37,13 +37,13 @@ public class TabCommand : ViewModelCommand case "Asset_Save_Properties": await _threadWorkerView.Begin(cancellationToken => { - _applicationView.CUE4Parse.Extract(cancellationToken, contextViewModel.FullPath, false, EBulkType.Properties | EBulkType.Auto); + _applicationView.CUE4Parse.Extract(cancellationToken, contextViewModel.FullPath, false, EBulkType.Properties); }); break; case "Asset_Save_Textures": await _threadWorkerView.Begin(cancellationToken => { - _applicationView.CUE4Parse.Extract(cancellationToken, contextViewModel.FullPath, false, EBulkType.Textures | EBulkType.Auto); + _applicationView.CUE4Parse.Extract(cancellationToken, contextViewModel.FullPath, false, EBulkType.Textures); }); break; case "Asset_Save_Models": diff --git a/FModel/ViewModels/TabControlViewModel.cs b/FModel/ViewModels/TabControlViewModel.cs index c87b2381..c5a7bca2 100644 --- a/FModel/ViewModels/TabControlViewModel.cs +++ b/FModel/ViewModels/TabControlViewModel.cs @@ -230,21 +230,21 @@ public class TabItem : ViewModel }); } - public void AddImage(UTexture2D texture, bool bulkTexture) - => AddImage(texture.Name, texture.bRenderNearestNeighbor, texture.Decode(UserSettings.Default.OverridedPlatform), bulkTexture); + public void AddImage(UTexture2D texture, bool save, bool updateUi) + => AddImage(texture.Name, texture.bRenderNearestNeighbor, texture.Decode(UserSettings.Default.OverridedPlatform), save, updateUi); - public void AddImage(string name, bool rnn, SKBitmap[] img, bool bulkTexture) + public void AddImage(string name, bool rnn, SKBitmap[] img, bool save, bool updateUi) { - foreach (var i in img) AddImage(name, rnn, i, bulkTexture); + foreach (var i in img) AddImage(name, rnn, i, save, updateUi); } - public void AddImage(string name, bool rnn, SKBitmap img, bool bulkTexture) + public void AddImage(string name, bool rnn, SKBitmap img, bool save, bool updateUi) { Application.Current.Dispatcher.Invoke(() => { var t = new TabImage(name, rnn, img); - if (bulkTexture) - SaveImage(t); + if (save) SaveImage(t, updateUi); + if (!updateUi) return; _images.Add(t); SelectedImage ??= t; @@ -256,15 +256,14 @@ public class TabItem : ViewModel public void GoPreviousImage() => SelectedImage = _images.Previous(SelectedImage); public void GoNextImage() => SelectedImage = _images.Next(SelectedImage); - public void SetDocumentText(string text, bool bulkSave) + public void SetDocumentText(string text, bool save, bool updateUi) { Application.Current.Dispatcher.Invoke(() => { Document ??= new TextDocument(); Document.Text = text; - if (bulkSave) - SaveProperty(); + if (save) SaveProperty(updateUi); }); } @@ -277,30 +276,8 @@ public class TabItem : ViewModel }); } - public void SaveImages() - { - switch (_images.Count) - { - case 1: - SaveImage(); - break; - case > 1: - var directory = Path.Combine(UserSettings.Default.TextureDirectory, - UserSettings.Default.KeepDirectoryStructure ? Directory : "").Replace('\\', '/'); - System.IO.Directory.CreateDirectory(directory); - - foreach (var image in _images) - { - if (image == null) return; - var fileName = $"{image.ExportName}.png"; - SaveImage(image, Path.Combine(directory, fileName), fileName); - } - break; - } - } - - public void SaveImage() => SaveImage(SelectedImage); - private void SaveImage(TabImage image) + public void SaveImage() => SaveImage(SelectedImage, true); + private void SaveImage(TabImage image, bool updateUi) { if (image == null) return; var fileName = $"{image.ExportName}.png"; @@ -309,13 +286,13 @@ public class TabItem : ViewModel System.IO.Directory.CreateDirectory(path.SubstringBeforeLast('/')); - SaveImage(image, path, fileName); + SaveImage(image, path, fileName, updateUi); } - private void SaveImage(TabImage image, string path, string fileName) + private void SaveImage(TabImage image, string path, string fileName, bool updateUi) { SaveImage(image, path); - SaveCheck(path, fileName); + SaveCheck(path, fileName, updateUi); } private void SaveImage(TabImage image, string path) @@ -324,7 +301,7 @@ public class TabItem : ViewModel fs.Write(image.ImageBuffer, 0, image.ImageBuffer.Length); } - public void SaveProperty() + public void SaveProperty(bool updateUi) { var fileName = Path.ChangeExtension(Header, ".json"); var directory = Path.Combine(UserSettings.Default.PropertiesDirectory, @@ -333,23 +310,29 @@ public class TabItem : ViewModel System.IO.Directory.CreateDirectory(directory.SubstringBeforeLast('/')); Application.Current.Dispatcher.Invoke(() => File.WriteAllText(directory, Document.Text)); - SaveCheck(directory, fileName); + SaveCheck(directory, fileName, updateUi); } - private void SaveCheck(string path, string fileName) + private void SaveCheck(string path, string fileName, bool updateUi) { if (File.Exists(path)) { Log.Information("{FileName} successfully saved", fileName); - FLogger.AppendInformation(); - FLogger.AppendText("Successfully saved ", Constants.WHITE); - FLogger.AppendLink(fileName, path, true); + if (updateUi) + { + FLogger.AppendInformation(); + FLogger.AppendText("Successfully saved ", Constants.WHITE); + FLogger.AppendLink(fileName, path, true); + } } else { Log.Error("{FileName} could not be saved", fileName); - FLogger.AppendError(); - FLogger.AppendText($"Could not save '{fileName}'", Constants.WHITE, true); + if (updateUi) + { + FLogger.AppendError(); + FLogger.AppendText($"Could not save '{fileName}'", Constants.WHITE, true); + } } } } diff --git a/FModel/Views/Resources/Controls/Rtb/CustomRichTextBox.cs b/FModel/Views/Resources/Controls/Rtb/CustomRichTextBox.cs index 26e334bb..c60b3efc 100644 --- a/FModel/Views/Resources/Controls/Rtb/CustomRichTextBox.cs +++ b/FModel/Views/Resources/Controls/Rtb/CustomRichTextBox.cs @@ -22,6 +22,7 @@ public class FLogger : ITextFormatter { public static CustomRichTextBox Logger; private static readonly BrushConverter _brushConverter = new(); + private static int _previous; public static void AppendInformation() => AppendText("[INF] ", Constants.BLUE); public static void AppendWarning() => AppendText("[WRN] ", Constants.YELLOW); @@ -32,18 +33,17 @@ public class FLogger : ITextFormatter { Application.Current.Dispatcher.Invoke(delegate { - var textRange = new TextRange(Logger.Document.ContentEnd, Logger.Document.ContentEnd) - { - Text = newLine ? $"{message}{Environment.NewLine}" : message - }; - try { - textRange.ApplyPropertyValue(TextElement.ForegroundProperty, _brushConverter.ConvertFromString(color)); + Logger.Document.ContentEnd.InsertTextInRun(message); + if (newLine) Logger.Document.ContentEnd.InsertLineBreak(); + + Logger.Selection.Select(Logger.Document.ContentStart.GetPositionAtOffset(_previous), Logger.Document.ContentEnd); + Logger.Selection.ApplyPropertyValue(TextElement.ForegroundProperty, _brushConverter.ConvertFromString(color)); } finally { - Logger.ScrollToEnd(); + Finally(); } }); } @@ -52,29 +52,33 @@ public class FLogger : ITextFormatter { Application.Current.Dispatcher.Invoke(delegate { - var link = new Hyperlink(new Run(newLine ? $"{message}{Environment.NewLine}" : message), Logger.Document.ContentEnd) - { - NavigateUri = new Uri(url), - OverridesDefaultStyle = true, - Style = new Style(typeof(Hyperlink)) { Setters = - { - new Setter(FrameworkContentElement.CursorProperty, Cursors.Hand), - new Setter(TextBlock.TextDecorationsProperty, TextDecorations.Underline), - new Setter(TextElement.ForegroundProperty, Brushes.Cornsilk) - }} - }; - try { - link.Click += (sender, _) => Process.Start("explorer.exe", $"/select, \"{((Hyperlink)sender).NavigateUri.AbsoluteUri}\""); + new Hyperlink(new Run(newLine ? $"{message}{Environment.NewLine}" : message), Logger.Document.ContentEnd) + { + NavigateUri = new Uri(url), + OverridesDefaultStyle = true, + Style = new Style(typeof(Hyperlink)) { Setters = + { + new Setter(FrameworkContentElement.CursorProperty, Cursors.Hand), + new Setter(TextBlock.TextDecorationsProperty, TextDecorations.Underline), + new Setter(TextElement.ForegroundProperty, Brushes.Cornsilk) + }} + }.Click += (sender, _) => Process.Start("explorer.exe", $"/select, \"{((Hyperlink)sender).NavigateUri.AbsoluteUri}\""); } finally { - Logger.ScrollToEnd(); + Finally(); } }); } + private static void Finally() + { + Logger.ScrollToEnd(); + _previous = Math.Abs(Logger.Document.ContentEnd.GetOffsetToPosition(Logger.Document.ContentStart)) - 2; + } + public string GetText(FlowDocument document) { return new TextRange(document.ContentStart, document.ContentEnd).Text;