improved CustomRichTextBox + updateUi parameter to speed up savings

This commit is contained in:
4sval
2023-03-12 00:11:59 +01:00
parent 3f57ce6276
commit 39f5855b12
9 changed files with 95 additions and 97 deletions

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -33,7 +33,7 @@ public class MenuCommand : ViewModelCommand<ApplicationViewModel>
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();

View File

@@ -43,14 +43,14 @@ public class RightClickMenuCommand : ViewModelCommand<ApplicationViewModel>
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":

View File

@@ -37,13 +37,13 @@ public class TabCommand : ViewModelCommand<TabItem>
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":

View File

@@ -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);
}
}
}
}

View File

@@ -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;