diff --git a/CUE4Parse b/CUE4Parse
index 11a92870..2aed4da1 160000
--- a/CUE4Parse
+++ b/CUE4Parse
@@ -1 +1 @@
-Subproject commit 11a92870024a088888aae79c74d8ae0c6c8af3e5
+Subproject commit 2aed4da1ee440cd421222526bdc501031f685be6
diff --git a/FModel/Creator/CreatorPackage.cs b/FModel/Creator/CreatorPackage.cs
index ee169896..7c2b154b 100644
--- a/FModel/Creator/CreatorPackage.cs
+++ b/FModel/Creator/CreatorPackage.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using CUE4Parse.UE4.Assets.Exports;
using FModel.Creator.Bases;
@@ -30,7 +31,7 @@ public class CreatorPackage : IDisposable
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool TryConstructCreator(out UCreator creator)
+ public bool TryConstructCreator([MaybeNullWhen(false)] out UCreator creator)
{
switch (_exportType)
{
diff --git a/FModel/Extensions/CUE4ParseExtensions.cs b/FModel/Extensions/CUE4ParseExtensions.cs
new file mode 100644
index 00000000..463a668e
--- /dev/null
+++ b/FModel/Extensions/CUE4ParseExtensions.cs
@@ -0,0 +1,70 @@
+using System;
+using CUE4Parse.FileProvider;
+using CUE4Parse.FileProvider.Objects;
+using CUE4Parse.UE4.Assets;
+using CUE4Parse.UE4.Objects.UObject;
+using FModel.Settings;
+
+namespace FModel.Extensions;
+
+public static class CUE4ParseExtensions
+{
+ public class LoadPackageResult
+ {
+ // more than 1 export per page currently break the inner package navigation feature
+ // if you have 1k exports per page, at page 2, you click on export index 932
+ // it will find the export index 932 in the current page, which would realistically be 1932
+ // fix would be to use InclusiveStart and ExclusiveEnd to determine the page the export index is in
+ // giving the document access to this would fix the issue and we could re-use Package instead of reloading it but it's quite a bit of work atm
+
+ private const int PaginationThreshold = 5000;
+ private const int MaxExportPerPage = 1;
+
+ public IPackage Package;
+ public int RequestedIndex;
+
+ public bool IsPaginated => Package.ExportMapLength >= PaginationThreshold;
+
+ ///
+ /// index of the first export on the current page
+ /// this index is the starting point for additional data preview
+ ///
+ /// it can be >0 even if is false if we want to focus data preview on a specific export
+ /// in this case, we will display all exports but only the focused one will be checked for data preview
+ ///
+ public int InclusiveStart => Math.Max(0, RequestedIndex - RequestedIndex % MaxExportPerPage);
+ ///
+ /// last exclusive export index of the current page
+ ///
+ public int ExclusiveEnd => IsPaginated
+ ? Math.Min(InclusiveStart + MaxExportPerPage, Package.ExportMapLength)
+ : Package.ExportMapLength;
+ public int PageSize => ExclusiveEnd - InclusiveStart;
+
+ public string TabTitleExtra => IsPaginated ? $"Export{(PageSize > 1 ? "s" : "")} {InclusiveStart}{(PageSize > 1 ? $"-{ExclusiveEnd - 1}" : "")} of {Package.ExportMapLength - 1}" : null;
+
+ ///
+ /// display all exports unless paginated
+ ///
+ /// if we save the data we will display all exports even if is true
+ ///
+ public object GetDisplayData(bool save = false) => !save && IsPaginated
+ ? Package.GetExports(InclusiveStart, PageSize)
+ : Package.GetExports();
+ }
+
+ public static LoadPackageResult GetLoadPackageResult(this IFileProvider provider, GameFile file, string objectName = null)
+ {
+ var result = new LoadPackageResult { Package = provider.LoadPackage(file) };
+ if (result.IsPaginated || (result.Package.HasFlags(EPackageFlags.PKG_ContainsMap) && UserSettings.Default.PreviewWorlds)) // focus on UWorld if it's a map we want to preview
+ {
+ result.RequestedIndex = result.Package.GetExportIndex(file.NameWithoutExtension);
+ if (objectName != null)
+ {
+ result.RequestedIndex = int.TryParse(objectName, out var index) ? index : result.Package.GetExportIndex(objectName);
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/FModel/Extensions/StringExtensions.cs b/FModel/Extensions/StringExtensions.cs
index 07d6873c..cc8b523c 100644
--- a/FModel/Extensions/StringExtensions.cs
+++ b/FModel/Extensions/StringExtensions.cs
@@ -6,14 +6,14 @@ using ICSharpCode.AvalonEdit.Document;
namespace FModel.Extensions;
-public static class StringExtensions
+public static partial class StringExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string GetReadableSize(double size)
{
if (size == 0) return "0 B";
- string[] sizes = { "B", "KB", "MB", "GB", "TB" };
+ string[] sizes = ["B", "KB", "MB", "GB", "TB"];
var order = 0;
while (size >= 1024 && order < sizes.Length - 1)
{
@@ -27,21 +27,22 @@ public static class StringExtensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetNameLineNumber(this string s, string lineToFind)
{
+ if (KismetRegex().IsMatch(lineToFind))
+ return s.GetKismetLineNumber(lineToFind);
if (int.TryParse(lineToFind, out var index))
return s.GetLineNumber(index);
lineToFind = $" \"Name\": \"{lineToFind}\",";
using var reader = new StringReader(s);
var lineNum = 0;
- string line;
- while ((line = reader.ReadLine()) != null)
+ while (reader.ReadLine() is { } line)
{
lineNum++;
if (line.Equals(lineToFind, StringComparison.OrdinalIgnoreCase))
return lineNum;
}
- return 1;
+ return -1;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -64,18 +65,17 @@ public static class StringExtensions
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int GetKismetLineNumber(this string s, string input)
+ private static int GetKismetLineNumber(this string s, string input)
{
- var match = Regex.Match(input, @"^(.+)\[(\d+)\]$");
+ var match = KismetRegex().Match(input);
var name = match.Groups[1].Value;
int index = int.Parse(match.Groups[2].Value);
var lineToFind = $" \"Name\": \"{name}\",";
var offset = $"\"StatementIndex\": {index}";
using var reader = new StringReader(s);
var lineNum = 0;
- string line;
- while ((line = reader.ReadLine()) != null)
+ while (reader.ReadLine() is { } line)
{
lineNum++;
if (line.Equals(lineToFind, StringComparison.OrdinalIgnoreCase))
@@ -91,7 +91,7 @@ public static class StringExtensions
}
}
- return 1;
+ return -1;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -99,8 +99,7 @@ public static class StringExtensions
{
using var reader = new StringReader(s);
var lineNum = 0;
- string line;
- while ((line = reader.ReadLine()) != null)
+ while (reader.ReadLine() is { } line)
{
lineNum++;
if (line.Equals(" {"))
@@ -110,6 +109,9 @@ public static class StringExtensions
return lineNum + 1;
}
- return 1;
+ return -1;
}
+
+ [GeneratedRegex(@"^(.+)\[(\d+)\]$", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)]
+ private static partial Regex KismetRegex();
}
diff --git a/FModel/MainWindow.xaml b/FModel/MainWindow.xaml
index d85febbe..198d8b59 100644
--- a/FModel/MainWindow.xaml
+++ b/FModel/MainWindow.xaml
@@ -506,7 +506,7 @@
diff --git a/FModel/MainWindow.xaml.cs b/FModel/MainWindow.xaml.cs
index b4200026..6e469d96 100644
--- a/FModel/MainWindow.xaml.cs
+++ b/FModel/MainWindow.xaml.cs
@@ -85,7 +85,7 @@ public partial class MainWindow
#if DEBUG
// await _threadWorkerView.Begin(cancellationToken =>
// _applicationView.CUE4Parse.Extract(cancellationToken,
- // "Marvel/Content/Marvel/Characters/1016/1016501/Meshes/SK_1016_1016501.uasset"));
+ // _applicationView.CUE4Parse.Provider["Marvel/Content/Marvel/Characters/1050/1050300/Meshes/SK_1050_1050300_Lobby.uasset"]));
// await _threadWorkerView.Begin(cancellationToken =>
// _applicationView.CUE4Parse.Extract(cancellationToken,
// "RED/Content/Chara/ABA/Costume01/Animation/Charaselect/body/stand_body01.uasset"));
diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs
index fdcc086d..2d668df1 100644
--- a/FModel/ViewModels/CUE4ParseViewModel.cs
+++ b/FModel/ViewModels/CUE4ParseViewModel.cs
@@ -133,17 +133,18 @@ public class CUE4ParseViewModel : ViewModel
customVersions: new FCustomVersionContainer(currentDir.Versioning.CustomVersions),
optionOverrides: currentDir.Versioning.Options,
mapStructTypesOverrides: currentDir.Versioning.MapStructTypes);
+ var pathComparer = StringComparer.OrdinalIgnoreCase;
switch (gameDirectory)
{
case Constants._FN_LIVE_TRIGGER:
{
- Provider = new StreamedFileProvider("FortniteLive", true, versionContainer);
+ Provider = new StreamedFileProvider("FortniteLive", versionContainer, pathComparer);
break;
}
case Constants._VAL_LIVE_TRIGGER:
{
- Provider = new StreamedFileProvider("ValorantLive", true, versionContainer);
+ Provider = new StreamedFileProvider("ValorantLive", versionContainer, pathComparer);
break;
}
default:
@@ -155,12 +156,12 @@ public class CUE4ParseViewModel : ViewModel
[
new(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\StateOfDecay2\\Saved\\Paks"),
new(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\StateOfDecay2\\Saved\\DisabledPaks")
- ], SearchOption.AllDirectories, true, versionContainer),
+ ], SearchOption.AllDirectories, versionContainer, pathComparer),
"eFootball" => new DefaultFileProvider(new DirectoryInfo(gameDirectory),
[
new(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\KONAMI\\eFootball\\ST\\Download")
- ], SearchOption.AllDirectories, true, versionContainer),
- _ => new DefaultFileProvider(gameDirectory, SearchOption.AllDirectories, true, versionContainer)
+ ], SearchOption.AllDirectories, versionContainer, pathComparer),
+ _ => new DefaultFileProvider(gameDirectory, SearchOption.AllDirectories, versionContainer, pathComparer)
};
break;
@@ -571,16 +572,18 @@ public class CUE4ParseViewModel : ViewModel
case "uasset":
case "umap":
{
- var pkg = Provider.LoadPackage(entry);
+ var result = Provider.GetLoadPackageResult(entry);
+ TabControl.SelectedTab.TitleExtra = result.TabTitleExtra;
+
if (saveProperties || updateUi)
{
- TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(pkg.GetExports(), Formatting.Indented), saveProperties, updateUi);
+ TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(result.GetDisplayData(saveProperties), Formatting.Indented), saveProperties, updateUi);
if (saveProperties) break; // do not search for viewable exports if we are dealing with jsons
}
- for (var i = 0; i < pkg.ExportMapLength; i++)
+ for (var i = result.InclusiveStart; i < result.ExclusiveEnd; i++)
{
- if (CheckExport(cancellationToken, pkg, i, bulk))
+ if (CheckExport(cancellationToken, result.Package, i, bulk))
break;
}
@@ -743,13 +746,15 @@ public class CUE4ParseViewModel : ViewModel
TabControl.AddTab(entry, parentExportType);
TabControl.SelectedTab.ScrollTrigger = objectName;
- var pkg = Provider.LoadPackage(entry);
- TabControl.SelectedTab.Highlighter = AvalonExtensions.HighlighterSelector(""); // json
- TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(pkg.GetExports(), Formatting.Indented), false, false);
+ var result = Provider.GetLoadPackageResult(entry, objectName);
- for (var i = 0; i < pkg.ExportMapLength; i++)
+ TabControl.SelectedTab.TitleExtra = result.TabTitleExtra;
+ TabControl.SelectedTab.Highlighter = AvalonExtensions.HighlighterSelector(""); // json
+ TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(result.GetDisplayData(), Formatting.Indented), false, false);
+
+ for (var i = result.InclusiveStart; i < result.ExclusiveEnd; i++)
{
- if (CheckExport(cancellationToken, pkg, i))
+ if (CheckExport(cancellationToken, result.Package, i))
break;
}
}
@@ -907,7 +912,10 @@ public class CUE4ParseViewModel : ViewModel
{
var package = Provider.LoadPackage(entry);
- TabControl.AddTab($"{entry.Name} (Metadata)");
+ if (TabControl.CanAddTabs) TabControl.AddTab(entry);
+ else TabControl.SelectedTab.SoftReset(entry);
+
+ TabControl.SelectedTab.TitleExtra = "Metadata";
TabControl.SelectedTab.Highlighter = AvalonExtensions.HighlighterSelector("");
TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(package, Formatting.Indented), false, false);
diff --git a/FModel/ViewModels/Commands/ImageCommand.cs b/FModel/ViewModels/Commands/ImageCommand.cs
index 264255ac..0201c989 100644
--- a/FModel/ViewModels/Commands/ImageCommand.cs
+++ b/FModel/ViewModels/Commands/ImageCommand.cs
@@ -14,34 +14,34 @@ public class ImageCommand : ViewModelCommand
{
}
- public override void Execute(TabItem contextViewModel, object parameter)
+ public override void Execute(TabItem tabViewModel, object parameter)
{
- if (parameter == null || !contextViewModel.HasImage) return;
+ if (parameter == null || !tabViewModel.HasImage) return;
switch (parameter)
{
case "Open":
{
- Helper.OpenWindow(contextViewModel.SelectedImage.ExportName + " (Image)", () =>
+ Helper.OpenWindow(tabViewModel.SelectedImage.ExportName + " (Image)", () =>
{
var popout = new ImagePopout
{
- Title = contextViewModel.SelectedImage.ExportName + " (Image)",
- Width = contextViewModel.SelectedImage.Image.Width,
- Height = contextViewModel.SelectedImage.Image.Height,
- WindowState = contextViewModel.SelectedImage.Image.Height > 1000 ? WindowState.Maximized : WindowState.Normal,
- ImageCtrl = { Source = contextViewModel.SelectedImage.Image }
+ Title = tabViewModel.SelectedImage.ExportName + " (Image)",
+ Width = tabViewModel.SelectedImage.Image.Width,
+ Height = tabViewModel.SelectedImage.Image.Height,
+ WindowState = tabViewModel.SelectedImage.Image.Height > 1000 ? WindowState.Maximized : WindowState.Normal,
+ ImageCtrl = { Source = tabViewModel.SelectedImage.Image }
};
- RenderOptions.SetBitmapScalingMode(popout.ImageCtrl, BoolToRenderModeConverter.Instance.Convert(contextViewModel.SelectedImage.RenderNearestNeighbor));
+ RenderOptions.SetBitmapScalingMode(popout.ImageCtrl, BoolToRenderModeConverter.Instance.Convert(tabViewModel.SelectedImage.RenderNearestNeighbor));
popout.Show();
});
break;
}
case "Copy":
- ClipboardExtensions.SetImage(contextViewModel.SelectedImage.ImageBuffer, $"{contextViewModel.SelectedImage.ExportName}.png");
+ ClipboardExtensions.SetImage(tabViewModel.SelectedImage.ImageBuffer, $"{tabViewModel.SelectedImage.ExportName}.png");
break;
case "Save":
- contextViewModel.SaveImage();
+ tabViewModel.SaveImage();
break;
}
}
diff --git a/FModel/ViewModels/Commands/TabCommand.cs b/FModel/ViewModels/Commands/TabCommand.cs
index 5abbc4e3..a7911782 100644
--- a/FModel/ViewModels/Commands/TabCommand.cs
+++ b/FModel/ViewModels/Commands/TabCommand.cs
@@ -15,7 +15,7 @@ public class TabCommand : ViewModelCommand
{
}
- public override async void Execute(TabItem contextViewModel, object parameter)
+ public override async void Execute(TabItem tabViewModel, object parameter)
{
switch (parameter)
{
@@ -23,53 +23,53 @@ public class TabCommand : ViewModelCommand
_applicationView.CUE4Parse.TabControl.RemoveTab(mdlClick);
break;
case "Close_Tab":
- _applicationView.CUE4Parse.TabControl.RemoveTab(contextViewModel);
+ _applicationView.CUE4Parse.TabControl.RemoveTab(tabViewModel);
break;
case "Close_All_Tabs":
_applicationView.CUE4Parse.TabControl.RemoveAllTabs();
break;
case "Close_Other_Tabs":
- _applicationView.CUE4Parse.TabControl.RemoveOtherTabs(contextViewModel);
+ _applicationView.CUE4Parse.TabControl.RemoveOtherTabs(tabViewModel);
break;
case "Asset_Export_Data":
- await _threadWorkerView.Begin(_ => _applicationView.CUE4Parse.ExportData(contextViewModel.Entry));
+ await _threadWorkerView.Begin(_ => _applicationView.CUE4Parse.ExportData(tabViewModel.Entry));
break;
case "Asset_Save_Properties":
await _threadWorkerView.Begin(cancellationToken =>
{
- _applicationView.CUE4Parse.Extract(cancellationToken, contextViewModel.Entry, false, EBulkType.Properties);
+ _applicationView.CUE4Parse.Extract(cancellationToken, tabViewModel.Entry, false, EBulkType.Properties);
});
break;
case "Asset_Save_Textures":
await _threadWorkerView.Begin(cancellationToken =>
{
- _applicationView.CUE4Parse.Extract(cancellationToken, contextViewModel.Entry, false, EBulkType.Textures);
+ _applicationView.CUE4Parse.Extract(cancellationToken, tabViewModel.Entry, false, EBulkType.Textures);
});
break;
case "Asset_Save_Models":
await _threadWorkerView.Begin(cancellationToken =>
{
- _applicationView.CUE4Parse.Extract(cancellationToken, contextViewModel.Entry, false, EBulkType.Meshes);
+ _applicationView.CUE4Parse.Extract(cancellationToken, tabViewModel.Entry, false, EBulkType.Meshes);
});
break;
case "Asset_Save_Animations":
await _threadWorkerView.Begin(cancellationToken =>
{
- _applicationView.CUE4Parse.Extract(cancellationToken, contextViewModel.Entry, false, EBulkType.Animations);
+ _applicationView.CUE4Parse.Extract(cancellationToken, tabViewModel.Entry, false, EBulkType.Animations);
});
break;
case "Open_Properties":
- if (contextViewModel.Entry.Name == "New Tab" || contextViewModel.Document == null) return;
- Helper.OpenWindow(contextViewModel.Entry.Name + " (Properties)", () =>
+ if (tabViewModel.Header == "New Tab" || tabViewModel.Document == null) return;
+ Helper.OpenWindow(tabViewModel.Header + " (Properties)", () =>
{
- new PropertiesPopout(contextViewModel)
+ new PropertiesPopout(tabViewModel)
{
- Title = contextViewModel.Entry.Name + " (Properties)"
+ Title = tabViewModel.Header + " (Properties)"
}.Show();
});
break;
case "Copy_Asset_Path":
- Clipboard.SetText(contextViewModel.Entry.Path);
+ Clipboard.SetText(tabViewModel.Entry.Path);
break;
}
}
diff --git a/FModel/ViewModels/TabControlViewModel.cs b/FModel/ViewModels/TabControlViewModel.cs
index 1eda1e1c..39edaced 100644
--- a/FModel/ViewModels/TabControlViewModel.cs
+++ b/FModel/ViewModels/TabControlViewModel.cs
@@ -97,7 +97,22 @@ public class TabItem : ViewModel
public GameFile Entry
{
get => _entry;
- set => SetProperty(ref _entry, value);
+ set
+ {
+ SetProperty(ref _entry, value);
+ RaisePropertyChanged(nameof(Header));
+ }
+ }
+
+ private string _titleExtra;
+ public string TitleExtra
+ {
+ get => _titleExtra;
+ set
+ {
+ SetProperty(ref _titleExtra, value);
+ RaisePropertyChanged(nameof(Header));
+ }
}
private bool _hasSearchOpen;
@@ -194,6 +209,8 @@ public class TabItem : ViewModel
}
}
+ public string Header => $"{Entry.Name}{(string.IsNullOrEmpty(TitleExtra) ? "" : $" ({TitleExtra})")}";
+
public bool HasImage => SelectedImage != null;
public bool HasMultipleImages => _images.Count > 1;
public string Page => $"{_images.IndexOf(_selectedImage) + 1} / {_images.Count}";
@@ -219,6 +236,7 @@ public class TabItem : ViewModel
public void SoftReset(GameFile entry)
{
Entry = entry;
+ TitleExtra = string.Empty;
ParentExportType = string.Empty;
ScrollTrigger = null;
Application.Current.Dispatcher.Invoke(() =>
@@ -389,7 +407,7 @@ public class TabControlViewModel : ViewModel
public void AddTab(string title) => AddTab(new FakeGameFile(title));
public void AddTab(GameFile entry, string parentExportType = null)
{
- if (SelectedTab?.Entry.Name == "New Tab")
+ if (SelectedTab?.Header == "New Tab")
{
SelectedTab.Entry = entry;
return;
diff --git a/FModel/Views/Resources/Controls/Aed/GamePathVisualLineText.cs b/FModel/Views/Resources/Controls/Aed/GamePathVisualLineText.cs
index 86fdb4d4..ea19954c 100644
--- a/FModel/Views/Resources/Controls/Aed/GamePathVisualLineText.cs
+++ b/FModel/Views/Resources/Controls/Aed/GamePathVisualLineText.cs
@@ -70,34 +70,24 @@ public class GamePathVisualLineText : VisualLineText
{
var obj = gamePath.SubstringAfterLast('.');
var package = gamePath.SubstringBeforeLast('.');
- var fullPath = _applicationView.CUE4Parse.Provider.FixPath(package, StringComparison.Ordinal);
+ var fullPath = _applicationView.CUE4Parse.Provider.FixPath(package);
var firstLine = a.ParentVisualLine.Document.GetLineByNumber(2);
if (a.ParentVisualLine.Document.FileName.Equals(fullPath.SubstringBeforeLast('.'), StringComparison.OrdinalIgnoreCase) &&
!a.ParentVisualLine.Document.GetText(firstLine.Offset, firstLine.Length).Equals(" \"Summary\": {")) // Show Metadata case
{
- int lineNumber;
- DocumentLine line;
-
- if (Regex.IsMatch(obj, @"^(.+)\[(\d+)\]$"))
+ var lineNumber = a.ParentVisualLine.Document.Text.GetNameLineNumber(obj);
+ if (lineNumber > -1)
{
- lineNumber = a.ParentVisualLine.Document.Text.GetKismetLineNumber(obj);
- line = a.ParentVisualLine.Document.GetLineByNumber(lineNumber);
- }
- else
- {
- lineNumber = a.ParentVisualLine.Document.Text.GetNameLineNumber(obj);
- line = a.ParentVisualLine.Document.GetLineByNumber(lineNumber);
+ var line = a.ParentVisualLine.Document.GetLineByNumber(lineNumber);
+ AvalonEditor.YesWeEditor.Select(line.Offset, line.Length);
+ AvalonEditor.YesWeEditor.ScrollToLine(lineNumber);
+ return;
}
+ }
- AvalonEditor.YesWeEditor.Select(line.Offset, line.Length);
- AvalonEditor.YesWeEditor.ScrollToLine(lineNumber);
- }
- else
- {
- await _threadWorkerView.Begin(cancellationToken =>
- _applicationView.CUE4Parse.ExtractAndScroll(cancellationToken, fullPath, obj, parentExportType));
- }
+ await _threadWorkerView.Begin(cancellationToken =>
+ _applicationView.CUE4Parse.ExtractAndScroll(cancellationToken, fullPath, obj, parentExportType));
};
return a;
}
diff --git a/FModel/Views/Resources/Controls/AvalonEditor.xaml.cs b/FModel/Views/Resources/Controls/AvalonEditor.xaml.cs
index bc5fdab8..cdf50ae0 100644
--- a/FModel/Views/Resources/Controls/AvalonEditor.xaml.cs
+++ b/FModel/Views/Resources/Controls/AvalonEditor.xaml.cs
@@ -127,6 +127,8 @@ public partial class AvalonEditor
if (!tabItem.ShouldScroll) return;
var lineNumber = avalonEditor.Document.Text.GetNameLineNumber(tabItem.ScrollTrigger);
+ if (lineNumber == -1) lineNumber = 1;
+
var line = avalonEditor.Document.GetLineByNumber(lineNumber);
avalonEditor.Select(line.Offset, line.Length);
avalonEditor.ScrollToLine(lineNumber);
diff --git a/FModel/Views/Resources/Controls/ImagePopout.xaml b/FModel/Views/Resources/Controls/ImagePopout.xaml
index 31bf8301..b28330aa 100644
--- a/FModel/Views/Resources/Controls/ImagePopout.xaml
+++ b/FModel/Views/Resources/Controls/ImagePopout.xaml
@@ -15,7 +15,9 @@
-
-
+
+
+
+
diff --git a/FModel/Views/Resources/Resources.xaml b/FModel/Views/Resources/Resources.xaml
index 0a4af432..1d1500ed 100644
--- a/FModel/Views/Resources/Resources.xaml
+++ b/FModel/Views/Resources/Resources.xaml
@@ -651,7 +651,7 @@
-
+
@@ -858,7 +858,7 @@