From c72b4ecf1ad4dc422f695110b85f7fb62422c3ec Mon Sep 17 00:00:00 2001 From: GMatrixGames Date: Sun, 11 Jul 2021 11:29:19 -0400 Subject: [PATCH 01/58] line split fix for FN Alpha assets. --- FModel/Creator/Utils.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FModel/Creator/Utils.cs b/FModel/Creator/Utils.cs index f451a22d..d93a7ece 100644 --- a/FModel/Creator/Utils.cs +++ b/FModel/Creator/Utils.cs @@ -251,7 +251,7 @@ namespace FModel.Creator if (string.IsNullOrEmpty(text)) return null; var spaceWidth = paint.MeasureText(" "); - var lines = text.Split('\n', StringSplitOptions.RemoveEmptyEntries); + var lines = text.Replace("\\n", "\n").Split('\n', StringSplitOptions.RemoveEmptyEntries); var ret = new List(lines.Length); foreach (var line in lines) From dd932aed97a1ef86684eb33c461f3d5a092c3868 Mon Sep 17 00:00:00 2001 From: GMatrixGames Date: Sun, 11 Jul 2021 11:58:51 -0400 Subject: [PATCH 02/58] CUE4Parse update --- CUE4Parse | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CUE4Parse b/CUE4Parse index a520ada3..291277cd 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit a520ada39b9736d06db1df3321c7695873b23c44 +Subproject commit 291277cdfe645f8c9759961f0851366bffa2f233 From 08050aee7853de3e8d407d40b48bc9161514de47 Mon Sep 17 00:00:00 2001 From: iAmAsval Date: Tue, 13 Jul 2021 01:17:21 +0200 Subject: [PATCH 03/58] release notes --- FModel/Constants.cs | 1 - FModel/Extensions/AvalonExtensions.cs | 3 + FModel/FModel.csproj | 2 + FModel/MainWindow.xaml | 2 +- FModel/Resources/Changelog.xshd | 39 +++++++++++++ FModel/Settings/UserSettings.cs | 7 +++ FModel/ViewModels/ApiEndpoints/FModelApi.cs | 26 ++++++++- FModel/ViewModels/CUE4ParseViewModel.cs | 62 ++++++++------------- FModel/ViewModels/Commands/MenuCommand.cs | 4 +- FModel/ViewModels/TabControlViewModel.cs | 16 ++++++ FModel/Views/Resources/Resources.xaml | 2 +- 11 files changed, 117 insertions(+), 47 deletions(-) create mode 100644 FModel/Resources/Changelog.xshd diff --git a/FModel/Constants.cs b/FModel/Constants.cs index a33827d5..66e3bd14 100644 --- a/FModel/Constants.cs +++ b/FModel/Constants.cs @@ -16,7 +16,6 @@ namespace FModel public const string BLUE = "#528BCC"; public const string DONATE_LINK = "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EP9SSWG8MW4UC&source=url"; - public const string CHANGELOG_LINK = "https://github.com/iAmAsval/FModel/releases/latest"; public const string ISSUE_LINK = "https://github.com/iAmAsval/FModel/issues/new"; public const string DISCORD_LINK = "https://discord.gg/fdkNYYQ"; diff --git a/FModel/Extensions/AvalonExtensions.cs b/FModel/Extensions/AvalonExtensions.cs index 486c1f35..55c6449c 100644 --- a/FModel/Extensions/AvalonExtensions.cs +++ b/FModel/Extensions/AvalonExtensions.cs @@ -12,6 +12,7 @@ namespace FModel.Extensions private static readonly IHighlightingDefinition _iniHighlighter = LoadHighlighter("Ini.xshd"); private static readonly IHighlightingDefinition _xmlHighlighter = LoadHighlighter("Xml.xshd"); private static readonly IHighlightingDefinition _cppHighlighter = LoadHighlighter("Cpp.xshd"); + private static readonly IHighlightingDefinition _changelogHighlighter = LoadHighlighter("Changelog.xshd"); [MethodImpl(MethodImplOptions.AggressiveInlining)] private static IHighlightingDefinition LoadHighlighter(string resourceName) @@ -35,6 +36,8 @@ namespace FModel.Extensions case "h": case "cpp": return _cppHighlighter; + case "changelog": + return _changelogHighlighter; case "bat": case "txt": case "po": diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index 01cc0e98..fbdc1c1a 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -70,6 +70,7 @@ + @@ -96,6 +97,7 @@ + diff --git a/FModel/MainWindow.xaml b/FModel/MainWindow.xaml index 9a0ef621..600d3f2b 100644 --- a/FModel/MainWindow.xaml +++ b/FModel/MainWindow.xaml @@ -194,7 +194,7 @@ - + diff --git a/FModel/Resources/Changelog.xshd b/FModel/Resources/Changelog.xshd new file mode 100644 index 00000000..c09cf031 --- /dev/null +++ b/FModel/Resources/Changelog.xshd @@ -0,0 +1,39 @@ + + + + + ^\+ + .*(?:\t|\s{2,})+ + + + ^\- + .*(?:\t|\s{2,})+ + + + ^\~ + .*(?:\t|\s{2,})+ + + + + + + .*(?:\t|\#{1}|\s{2,})+ + \r\n + + + ^[0-9]\..* + + + ADDED + FIXED + REMOVED + IMPROVED + + + + + + + + + \ No newline at end of file diff --git a/FModel/Settings/UserSettings.cs b/FModel/Settings/UserSettings.cs index 759796e8..6b3796e9 100644 --- a/FModel/Settings/UserSettings.cs +++ b/FModel/Settings/UserSettings.cs @@ -35,6 +35,13 @@ namespace FModel.Settings { if (File.Exists(FilePath)) File.Delete(FilePath); } + + private bool _showChangelog = true; + public bool ShowChangelog + { + get => _showChangelog; + set => SetProperty(ref _showChangelog, value); + } private string _outputDirectory; public string OutputDirectory diff --git a/FModel/ViewModels/ApiEndpoints/FModelApi.cs b/FModel/ViewModels/ApiEndpoints/FModelApi.cs index 73041505..8a5c6b3c 100644 --- a/FModel/ViewModels/ApiEndpoints/FModelApi.cs +++ b/FModel/ViewModels/ApiEndpoints/FModelApi.cs @@ -5,6 +5,8 @@ using System.Threading; using System.Threading.Tasks; using System.Windows; using AutoUpdaterDotNET; +using FModel.Extensions; +using FModel.Services; using FModel.Settings; using FModel.ViewModels.ApiEndpoints.Models; using Newtonsoft.Json; @@ -23,6 +25,7 @@ namespace FModel.ViewModels.ApiEndpoints private Info _infos; private Backup[] _backups; private readonly IDictionary _communityDesigns = new Dictionary(); + private ApplicationViewModel _applicationView => ApplicationService.ApplicationView; public FModelApi(IRestClient client) : base(client) { @@ -106,12 +109,17 @@ namespace FModel.ViewModels.ApiEndpoints } } - private void CheckForUpdateEvent(UpdateInfoEventArgs args) + private async void CheckForUpdateEvent(UpdateInfoEventArgs args) { if (args is {CurrentVersion: { }}) { var currentVersion = new Version(args.CurrentVersion); - if (currentVersion == args.InstalledVersion) return; + if (currentVersion == args.InstalledVersion) + { + if (UserSettings.Default.ShowChangelog) + await ShowChangelog(args); + return; + } var downgrade = currentVersion < args.InstalledVersion; var messageBox = new MessageBoxModel @@ -125,16 +133,18 @@ namespace FModel.ViewModels.ApiEndpoints MessageBox.Show(messageBox); if (messageBox.Result != MessageBoxResult.Yes) return; - + try { if (AutoUpdater.DownloadUpdate(args)) { + UserSettings.Default.ShowChangelog = true; Application.Current.Shutdown(); } } catch (Exception exception) { + UserSettings.Default.ShowChangelog = false; MessageBox.Show(exception.Message, exception.GetType().ToString(), MessageBoxButton.OK, MessageBoxImage.Error); } } @@ -145,5 +155,15 @@ namespace FModel.ViewModels.ApiEndpoints "Update Check Failed", MessageBoxButton.OK, MessageBoxImage.Error); } } + + private async Task ShowChangelog(UpdateInfoEventArgs args) + { + var request = new RestRequest(args.ChangelogURL, Method.GET); + var response = await _client.ExecuteAsync(request).ConfigureAwait(false); + _applicationView.CUE4Parse.TabControl.AddTab($"Release Notes: {args.CurrentVersion}"); + _applicationView.CUE4Parse.TabControl.SelectedTab.Highlighter = AvalonExtensions.HighlighterSelector("changelog"); + _applicationView.CUE4Parse.TabControl.SelectedTab.SetDocumentText(response.Content, false); + UserSettings.Default.ShowChangelog = false; + } } } \ No newline at end of file diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index eead9d3c..4172df76 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -418,7 +418,6 @@ namespace FModel.ViewModels TabControl.SelectedTab.SetDocumentText(reader.ReadToEnd(), bulkSave); } - break; } case "locmeta": @@ -429,7 +428,6 @@ namespace FModel.ViewModels var metadata = new FTextLocalizationMetaDataResource(archive); TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(metadata, Formatting.Indented), bulkSave); } - break; } case "locres": @@ -440,7 +438,6 @@ namespace FModel.ViewModels var locres = new FTextLocalizationResource(archive); TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(locres, Formatting.Indented), bulkSave); } - break; } case "bin": @@ -451,7 +448,6 @@ namespace FModel.ViewModels var registry = new FAssetRegistryState(archive); TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(registry, Formatting.Indented), bulkSave); } - break; } case "bnk": @@ -467,7 +463,6 @@ namespace FModel.ViewModels SaveAndPlaySound(fullPath.SubstringBeforeWithLast("/") + name, "WEM", data); } } - break; } case "wem": @@ -486,7 +481,6 @@ namespace FModel.ViewModels var header = new FOodleDictionaryArchive(archive).Header; TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(header, Formatting.Indented), bulkSave); } - break; } case "png": @@ -496,9 +490,8 @@ namespace FModel.ViewModels if (Provider.TrySaveAsset(fullPath, out var data)) { using var stream = new MemoryStream(data) {Position = 0}; - SetImage(SKImage.FromBitmap(SKBitmap.Decode(stream))); + TabControl.SelectedTab.SetImage(SKImage.FromBitmap(SKBitmap.Decode(stream))); } - break; } case "ufont": @@ -509,13 +502,11 @@ namespace FModel.ViewModels case "ushadercode": { TabControl.SelectedTab.Image = null; - if (Provider.TryCreateReader(fullPath, out var archive)) { var ar = new FShaderCodeArchive(archive); TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(ar, Formatting.Indented), bulkSave); } - break; } default: @@ -562,7 +553,7 @@ namespace FModel.ViewModels trigger.Text.EndsWith("TF_Nearest", StringComparison.OrdinalIgnoreCase); TabControl.SelectedTab.ImageRender = bNearest ? BitmapScalingMode.NearestNeighbor : BitmapScalingMode.Linear; - SetImage(texture.Decode(bNearest)); + TabControl.SelectedTab.SetImage(texture.Decode(bNearest)); return true; } case UAkMediaAssetData: @@ -576,25 +567,31 @@ namespace FModel.ViewModels SaveAndPlaySound(Path.Combine(TabControl.SelectedTab.Directory, TabControl.SelectedTab.Header.SubstringBeforeLast('.')).Replace('\\', '/'), audioFormat, data); return false; } - case UMaterialInterface when UserSettings.Default.IsAutoSaveMaterials: - case UStaticMesh when UserSettings.Default.IsAutoSaveMeshes: - case USkeletalMesh when UserSettings.Default.IsAutoSaveMeshes: + case UMaterialInterface: + case UStaticMesh: + case USkeletalMesh: { - var toSave = new Exporter(export, UserSettings.Default.TextureExportFormat, UserSettings.Default.LodExportFormat); - var toSaveDirectory = new DirectoryInfo(Path.Combine(UserSettings.Default.OutputDirectory, "Saves")); - if (toSave.TryWriteToDir(toSaveDirectory, out var savedFileName)) + if (UserSettings.Default.IsAutoSaveMeshes || UserSettings.Default.IsAutoSaveMaterials) { - Log.Information("Successfully saved {FileName}", savedFileName); - FLogger.AppendInformation(); - FLogger.AppendText($"Successfully saved {savedFileName}", Constants.WHITE, true); + var toSave = new Exporter(export, UserSettings.Default.TextureExportFormat, UserSettings.Default.LodExportFormat); + var toSaveDirectory = new DirectoryInfo(Path.Combine(UserSettings.Default.OutputDirectory, "Saves")); + if (toSave.TryWriteToDir(toSaveDirectory, out var savedFileName)) + { + Log.Information("Successfully saved {FileName}", savedFileName); + FLogger.AppendInformation(); + FLogger.AppendText($"Successfully saved {savedFileName}", Constants.WHITE, true); + } + else + { + Log.Error("{FileName} could not be saved", savedFileName); + FLogger.AppendError(); + FLogger.AppendText($"Could not save '{savedFileName}'", Constants.WHITE, true); + } } else { - Log.Error("{FileName} could not be saved", savedFileName); - FLogger.AppendError(); - FLogger.AppendText($"Could not save '{savedFileName}'", Constants.WHITE, true); + // preview } - return false; } default: @@ -603,27 +600,12 @@ namespace FModel.ViewModels if (!package.TryConstructCreator(out var creator)) return false; creator.ParseForInfo(); - SetImage(creator.Draw()); + TabControl.SelectedTab.SetImage(creator.Draw()); return true; } } } - private void SetImage(SKImage img) - { - using var stream = img.Encode().AsStream(); - var image = new BitmapImage(); - image.BeginInit(); - image.CacheOption = BitmapCacheOption.OnLoad; - image.StreamSource = stream; - image.EndInit(); - image.Freeze(); - - TabControl.SelectedTab.Image = image; - if (UserSettings.Default.IsAutoSaveTextures) - TabControl.SelectedTab.SaveImage(true); - } - private void SaveAndPlaySound(string fullPath, string ext, byte[] data) { var userDir = Path.Combine(UserSettings.Default.OutputDirectory, "Sounds"); diff --git a/FModel/ViewModels/Commands/MenuCommand.cs b/FModel/ViewModels/Commands/MenuCommand.cs index 237f386c..caf38ae9 100644 --- a/FModel/ViewModels/Commands/MenuCommand.cs +++ b/FModel/ViewModels/Commands/MenuCommand.cs @@ -1,6 +1,7 @@ using System.Diagnostics; using AdonisUI.Controls; using FModel.Framework; +using FModel.Services; using FModel.Settings; using FModel.Views; using FModel.Views.Resources.Controls; @@ -45,7 +46,8 @@ namespace FModel.ViewModels.Commands Process.Start(new ProcessStartInfo {FileName = Constants.DONATE_LINK, UseShellExecute = true}); break; case "Help_Changelog": - Process.Start(new ProcessStartInfo {FileName = Constants.CHANGELOG_LINK, UseShellExecute = true}); + UserSettings.Default.ShowChangelog = true; + ApplicationService.ApiEndpointView.FModelApi.CheckForUpdates(UserSettings.Default.UpdateMode); break; case "Help_BugsReport": Process.Start(new ProcessStartInfo {FileName = Constants.ISSUE_LINK, UseShellExecute = true}); diff --git a/FModel/ViewModels/TabControlViewModel.cs b/FModel/ViewModels/TabControlViewModel.cs index 458bec22..8c42d24c 100644 --- a/FModel/ViewModels/TabControlViewModel.cs +++ b/FModel/ViewModels/TabControlViewModel.cs @@ -14,6 +14,7 @@ using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Highlighting; using Microsoft.Win32; using Serilog; +using SkiaSharp; namespace FModel.ViewModels { @@ -197,6 +198,21 @@ namespace FModel.ViewModels Application.Current.Dispatcher.Invoke(() => File.WriteAllText(directory, Document.Text)); SaveCheck(directory, fileName); } + + public void SetImage(SKImage img) + { + using var stream = img.Encode().AsStream(); + var image = new BitmapImage(); + image.BeginInit(); + image.CacheOption = BitmapCacheOption.OnLoad; + image.StreamSource = stream; + image.EndInit(); + image.Freeze(); + + Image = image; + if (UserSettings.Default.IsAutoSaveTextures) + SaveImage(true); + } public void SaveImage(bool autoSave) { diff --git a/FModel/Views/Resources/Resources.xaml b/FModel/Views/Resources/Resources.xaml index 783022e1..008e152b 100644 --- a/FModel/Views/Resources/Resources.xaml +++ b/FModel/Views/Resources/Resources.xaml @@ -35,7 +35,7 @@ M22,24L16.75,19L17.38,21H4.5A2.5,2.5 0 0,1 2,18.5V3.5A2.5,2.5 0 0,1 4.5,1H19.5A2.5,2.5 0 0,1 22,3.5V24M12,6.8C9.32,6.8 7.44,7.95 7.44,7.95C8.47,7.03 10.27,6.5 10.27,6.5L10.1,6.33C8.41,6.36 6.88,7.53 6.88,7.53C5.16,11.12 5.27,14.22 5.27,14.22C6.67,16.03 8.75,15.9 8.75,15.9L9.46,15C8.21,14.73 7.42,13.62 7.42,13.62C7.42,13.62 9.3,14.9 12,14.9C14.7,14.9 16.58,13.62 16.58,13.62C16.58,13.62 15.79,14.73 14.54,15L15.25,15.9C15.25,15.9 17.33,16.03 18.73,14.22C18.73,14.22 18.84,11.12 17.12,7.53C17.12,7.53 15.59,6.36 13.9,6.33L13.73,6.5C13.73,6.5 15.53,7.03 16.56,7.95C16.56,7.95 14.68,6.8 12,6.8M9.93,10.59C10.58,10.59 11.11,11.16 11.1,11.86C11.1,12.55 10.58,13.13 9.93,13.13C9.29,13.13 8.77,12.55 8.77,11.86C8.77,11.16 9.28,10.59 9.93,10.59M14.1,10.59C14.75,10.59 15.27,11.16 15.27,11.86C15.27,12.55 14.75,13.13 14.1,13.13C13.46,13.13 12.94,12.55 12.94,11.86C12.94,11.16 13.45,10.59 14.1,10.59Z M14,12H10V10H14M14,16H10V14H14M20,8H17.19C16.74,7.22 16.12,6.55 15.37,6.04L17,4.41L15.59,3L13.42,5.17C12.96,5.06 12.5,5 12,5C11.5,5 11.04,5.06 10.59,5.17L8.41,3L7,4.41L8.62,6.04C7.88,6.55 7.26,7.22 6.81,8H4V10H6.09C6.04,10.33 6,10.66 6,11V12H4V14H6V15C6,15.34 6.04,15.67 6.09,16H4V18H6.81C7.85,19.79 9.78,21 12,21C14.22,21 16.15,19.79 17.19,18H20V16H17.91C17.96,15.67 18,15.34 18,15V14H20V12H18V11C18,10.66 17.96,10.33 17.91,10H20V8Z M22 10.92L19.26 9.33C21.9 7.08 19.25 2.88 16.08 4.31L15.21 4.68L15.1 3.72C15 2.64 14.44 1.87 13.7 1.42C12.06 .467 9.56 1.12 9.16 3.5L6.41 1.92C5.45 1.36 4.23 1.69 3.68 2.65L2.68 4.38C2.4 4.86 2.57 5.47 3.05 5.75L10.84 10.25L12.34 7.65L14.07 8.65L12.57 11.25L20.36 15.75C20.84 16 21.46 15.86 21.73 15.38L22.73 13.65C23.28 12.69 22.96 11.47 22 10.92M12.37 5C11.5 5.25 10.8 4.32 11.24 3.55C11.5 3.07 12.13 2.91 12.61 3.18C13.38 3.63 13.23 4.79 12.37 5M17.56 8C16.7 8.25 16 7.32 16.44 6.55C16.71 6.07 17.33 5.91 17.8 6.18C18.57 6.63 18.42 7.79 17.56 8M20.87 16.88C21.28 16.88 21.67 16.74 22 16.5V20C22 21.11 21.11 22 20 22H4C2.9 22 2 21.11 2 20V11H10.15L11 11.5V20H13V12.65L19.87 16.61C20.17 16.79 20.5 16.88 20.87 16.88Z - M12,2A10,10 0 0,0 2,12C2,16.42 4.87,20.17 8.84,21.5C9.34,21.58 9.5,21.27 9.5,21C9.5,20.77 9.5,20.14 9.5,19.31C6.73,19.91 6.14,17.97 6.14,17.97C5.68,16.81 5.03,16.5 5.03,16.5C4.12,15.88 5.1,15.9 5.1,15.9C6.1,15.97 6.63,16.93 6.63,16.93C7.5,18.45 8.97,18 9.54,17.76C9.63,17.11 9.89,16.67 10.17,16.42C7.95,16.17 5.62,15.31 5.62,11.5C5.62,10.39 6,9.5 6.65,8.79C6.55,8.54 6.2,7.5 6.75,6.15C6.75,6.15 7.59,5.88 9.5,7.17C10.29,6.95 11.15,6.84 12,6.84C12.85,6.84 13.71,6.95 14.5,7.17C16.41,5.88 17.25,6.15 17.25,6.15C17.8,7.5 17.45,8.54 17.35,8.79C18,9.5 18.38,10.39 18.38,11.5C18.38,15.32 16.04,16.16 13.81,16.41C14.17,16.72 14.5,17.33 14.5,18.26C14.5,19.6 14.5,20.68 14.5,21C14.5,21.27 14.66,21.59 15.17,21.5C19.14,20.16 22,16.42 22,12A10,10 0 0,0 12,2Z + M4 10.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-6c-.83 0-1.5.67-1.5 1.5S3.17 7.5 4 7.5 5.5 6.83 5.5 6 4.83 4.5 4 4.5zm0 12c-.83 0-1.5.68-1.5 1.5s.68 1.5 1.5 1.5 1.5-.68 1.5-1.5-.67-1.5-1.5-1.5zM8 19h12c.55 0 1-.45 1-1s-.45-1-1-1H8c-.55 0-1 .45-1 1s.45 1 1 1zm0-6h12c.55 0 1-.45 1-1s-.45-1-1-1H8c-.55 0-1 .45-1 1s.45 1 1 1zM7 6c0 .55.45 1 1 1h12c.55 0 1-.45 1-1s-.45-1-1-1H8c-.55 0-1 .45-1 1z M11.5,2C6.81,2,3,5.81,3,10.5S6.81,19,11.5,19H12v3c4.86-2.34,8-7,8-11.5C20,5.81,16.19,2,11.5,2z M11.48,16 c-0.59,0-1.05-0.47-1.05-1.05c0-0.59,0.47-1.04,1.05-1.04c0.59,0,1.04,0.45,1.04,1.04C12.52,15.53,12.08,16,11.48,16z M13.99,9.83 c-0.63,0.93-1.23,1.21-1.56,1.81c-0.08,0.14-0.13,0.26-0.16,0.49c-0.05,0.39-0.36,0.68-0.75,0.68h-0.03 c-0.44,0-0.79-0.38-0.75-0.82c0.03-0.28,0.09-0.57,0.25-0.84c0.41-0.73,1.18-1.16,1.63-1.8c0.48-0.68,0.21-1.94-1.14-1.94 c-0.61,0-1.01,0.32-1.26,0.7c-0.19,0.29-0.57,0.39-0.89,0.25l0,0c-0.42-0.18-0.6-0.7-0.34-1.07C9.5,6.55,10.35,6,11.47,6 c1.23,0,2.08,0.56,2.51,1.26C14.34,7.87,14.56,8.99,13.99,9.83z M6,19c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2V7H6V19z M9.17,12.59c-0.39-0.39-0.39-1.02,0-1.41c0.39-0.39,1.02-0.39,1.41,0 L12,12.59l1.41-1.41c0.39-0.39,1.02-0.39,1.41,0s0.39,1.02,0,1.41L13.41,14l1.41,1.41c0.39,0.39,0.39,1.02,0,1.41 s-1.02,0.39-1.41,0L12,15.41l-1.41,1.41c-0.39,0.39-1.02,0.39-1.41,0c-0.39-0.39-0.39-1.02,0-1.41L10.59,14L9.17,12.59z M18,4h-2.5 l-0.71-0.71C14.61,3.11,14.35,3,14.09,3H9.91c-0.26,0-0.52,0.11-0.7,0.29L8.5,4H6C5.45,4,5,4.45,5,5s0.45,1,1,1h12 c0.55,0,1-0.45,1-1S18.55,4,18,4z M18,4v16H6V4H18 M18,2H6C4.9,2,4,2.9,4,4v16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C20,2.9,19.1,2,18,2L18,2z M7,19h10v-6H7 V19z M10,10h4v1h3V5H7v6h3V10z From 983d9da8459f7d8753e096a8026c6f4e7c20eaf3 Mon Sep 17 00:00:00 2001 From: iAmAsval Date: Tue, 13 Jul 2021 16:55:26 +0200 Subject: [PATCH 04/58] scuffed but working model viewer --- CUE4Parse | 2 +- FModel/FModel.csproj | 1 + FModel/ViewModels/ApiEndpoints/FModelApi.cs | 2 + FModel/ViewModels/CUE4ParseViewModel.cs | 5 +- FModel/ViewModels/ModelViewerViewModel.cs | 146 ++++++++++++++++++++ FModel/Views/ModelViewer.xaml | 59 ++++++++ FModel/Views/ModelViewer.xaml.cs | 23 +++ 7 files changed, 236 insertions(+), 2 deletions(-) create mode 100644 FModel/ViewModels/ModelViewerViewModel.cs create mode 100644 FModel/Views/ModelViewer.xaml create mode 100644 FModel/Views/ModelViewer.xaml.cs diff --git a/CUE4Parse b/CUE4Parse index 291277cd..e5861dac 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 291277cdfe645f8c9759961f0851366bffa2f233 +Subproject commit e5861dac2390041a9b70c6623a99646c1503d4e5 diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index fbdc1c1a..ae6a0cc9 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -108,6 +108,7 @@ + diff --git a/FModel/ViewModels/ApiEndpoints/FModelApi.cs b/FModel/ViewModels/ApiEndpoints/FModelApi.cs index 8a5c6b3c..ef49112e 100644 --- a/FModel/ViewModels/ApiEndpoints/FModelApi.cs +++ b/FModel/ViewModels/ApiEndpoints/FModelApi.cs @@ -160,6 +160,8 @@ namespace FModel.ViewModels.ApiEndpoints { var request = new RestRequest(args.ChangelogURL, Method.GET); var response = await _client.ExecuteAsync(request).ConfigureAwait(false); + if (string.IsNullOrEmpty(response.Content)) return; + _applicationView.CUE4Parse.TabControl.AddTab($"Release Notes: {args.CurrentVersion}"); _applicationView.CUE4Parse.TabControl.SelectedTab.Highlighter = AvalonExtensions.HighlighterSelector("changelog"); _applicationView.CUE4Parse.TabControl.SelectedTab.SetDocumentText(response.Content, false); diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 4172df76..495dfca7 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -590,7 +590,10 @@ namespace FModel.ViewModels } else { - // preview + Application.Current.Dispatcher.Invoke(delegate + { + Helper.OpenWindow("Model Viewer", () => new ModelViewer(export).Show()); + }); } return false; } diff --git a/FModel/ViewModels/ModelViewerViewModel.cs b/FModel/ViewModels/ModelViewerViewModel.cs new file mode 100644 index 00000000..51f8f8d6 --- /dev/null +++ b/FModel/ViewModels/ModelViewerViewModel.cs @@ -0,0 +1,146 @@ +using CUE4Parse.UE4.Assets.Exports.SkeletalMesh; +using CUE4Parse.UE4.Assets.Exports.StaticMesh; +using FModel.Framework; +using HelixToolkit.SharpDX.Core; +using HelixToolkit.Wpf.SharpDX; +using SharpDX; + +namespace FModel.ViewModels +{ + public class ModelViewerViewModel : ViewModel + { + private EffectsManager _effectManager; + public EffectsManager EffectManager + { + get => _effectManager; + set => SetProperty(ref _effectManager, value); + } + + private Camera _cam; + public Camera Cam + { + get => _cam; + set => SetProperty(ref _cam, value); + } + + private Geometry3D _cubeMesh; + public Geometry3D CubeMesh + { + get => _cubeMesh; + set => SetProperty(ref _cubeMesh, value); + } + + private Material _red; + public Material Red + { + get => _red; + set => SetProperty(ref _red, value); + } + + public ModelViewerViewModel(UStaticMesh? mesh) + { + EffectManager = new DefaultEffectsManager(); + Cam = new PerspectiveCamera(); + if (mesh?.RenderData == null || mesh.RenderData.LODs.Length < 1) return; + + var builder = new MeshBuilder(); + for (var i = 0; i < mesh.RenderData.LODs.Length; i++) + { + if (mesh.RenderData.LODs[i] is not + { + VertexBuffer: not null, + PositionVertexBuffer: not null, + ColorVertexBuffer: not null, + IndexBuffer: not null + } srcLod) continue; + + var numVerts = srcLod.PositionVertexBuffer.Verts.Length; + for (var j = 0; j < numVerts; j++) + { + var suv = srcLod.VertexBuffer.UV[j]; + builder.Positions.Add(new Vector3(srcLod.PositionVertexBuffer.Verts[j].X, srcLod.PositionVertexBuffer.Verts[j].Y, srcLod.PositionVertexBuffer.Verts[j].Z)); + builder.Normals.Add(new Vector3(suv.Normal[2].X, suv.Normal[2].Y, suv.Normal[2].Z)); + } + + for (var j = 0; j < srcLod.IndexBuffer.Indices16.Length; j++) + { + builder.TriangleIndices.Add(srcLod.IndexBuffer[j]); + } + break; + } + builder.Scale(0.05, 0.05, 0.05); + CubeMesh = builder.ToMesh(); + Red = PhongMaterials.Red; + } + + public ModelViewerViewModel(USkeletalMesh? mesh) + { + EffectManager = new DefaultEffectsManager(); + Cam = new PerspectiveCamera(); + if (mesh == null || mesh.LODModels?.Length < 1) return; + + var builder = new MeshBuilder(); + for (var i = 0; i < mesh.LODModels.Length; i++) + { + if (mesh.LODModels[i] is not { } srcLod) continue; + + var bUseVerticesFromSections = false; + var vertexCount = srcLod.VertexBufferGPUSkin.GetVertexCount(); + if (vertexCount == 0 && srcLod.Sections.Length > 0 && srcLod.Sections[0].SoftVertices.Length > 0) + { + bUseVerticesFromSections = true; + for (var j = 0; j < srcLod.Sections.Length; j++) + { + vertexCount += srcLod.Sections[i].SoftVertices.Length; + } + } + + var chunkIndex = -1; + var chunkVertexIndex = 0; + long lastChunkVertex = -1; + var vertBuffer = srcLod.VertexBufferGPUSkin; + + for (var j = 0; j < vertexCount; j++) + { + while (j >= lastChunkVertex) // this will fix any issues with empty chunks or sections + { + // proceed to next chunk or section + if (srcLod.Chunks.Length > 0) + { + // pre-UE4.13 code: chunks + var c = srcLod.Chunks[++chunkIndex]; + lastChunkVertex = c.BaseVertexIndex + c.NumRigidVertices + c.NumSoftVertices; + } + else + { + // UE4.13+ code: chunk information migrated to sections + var s = srcLod.Sections[++chunkIndex]; + lastChunkVertex = s.BaseVertexIndex + s.NumVertices; + } + chunkVertexIndex = 0; + } + + FSkelMeshVertexBase v; + if (bUseVerticesFromSections) + v = srcLod.Sections[chunkIndex].SoftVertices[chunkVertexIndex++]; + else if (!vertBuffer.bUseFullPrecisionUVs) + v = vertBuffer.VertsHalf[j]; + else + v = vertBuffer.VertsFloat[j]; + + builder.Positions.Add(new Vector3(v.Pos.X, v.Pos.Y, v.Pos.Z)); + builder.Normals.Add(new Vector3(v.Normal[2].X, v.Normal[2].Y, v.Normal[2].Z)); + } + + for (var j = 0; j < srcLod.Indices.Indices16.Length; j++) + { + builder.TriangleIndices.Add(srcLod.Indices.Indices16[j]); + } + break; + } + builder.Scale(0.05, 0.05, 0.05); + CubeMesh = builder.ToMesh(); + Red = PhongMaterials.Red; + } + } +} \ No newline at end of file diff --git a/FModel/Views/ModelViewer.xaml b/FModel/Views/ModelViewer.xaml new file mode 100644 index 00000000..f64c57c1 --- /dev/null +++ b/FModel/Views/ModelViewer.xaml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FModel/Views/ModelViewer.xaml.cs b/FModel/Views/ModelViewer.xaml.cs new file mode 100644 index 00000000..e6a48ca5 --- /dev/null +++ b/FModel/Views/ModelViewer.xaml.cs @@ -0,0 +1,23 @@ +using System; +using CUE4Parse.UE4.Assets.Exports; +using CUE4Parse.UE4.Assets.Exports.SkeletalMesh; +using CUE4Parse.UE4.Assets.Exports.StaticMesh; +using FModel.ViewModels; + +namespace FModel.Views +{ + public partial class ModelViewer + { + public ModelViewer(UObject export) + { + DataContext = export switch + { + UStaticMesh st => new ModelViewerViewModel(st), + USkeletalMesh sk => new ModelViewerViewModel(sk), + _ => throw new NotImplementedException() + }; + + InitializeComponent(); + } + } +} \ No newline at end of file From db7fb35bd2e9a4a1f053b376bd25da1e1a09e96f Mon Sep 17 00:00:00 2001 From: iAmAsval Date: Tue, 13 Jul 2021 22:50:56 +0200 Subject: [PATCH 05/58] fixed the fucked up camera and meshes wrongly axed on Y --- CUE4Parse | 2 +- FModel/ViewModels/ApplicationViewModel.cs | 2 + FModel/ViewModels/CUE4ParseViewModel.cs | 3 +- FModel/ViewModels/ModelViewerViewModel.cs | 183 ++++++++++------------ FModel/Views/ModelViewer.xaml | 25 +-- FModel/Views/ModelViewer.xaml.cs | 20 +-- 6 files changed, 114 insertions(+), 121 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index e5861dac..85c993e2 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit e5861dac2390041a9b70c6623a99646c1503d4e5 +Subproject commit 85c993e2a1cab603654905ce58e5f38455edeb52 diff --git a/FModel/ViewModels/ApplicationViewModel.cs b/FModel/ViewModels/ApplicationViewModel.cs index bfc7aca2..9c53851c 100644 --- a/FModel/ViewModels/ApplicationViewModel.cs +++ b/FModel/ViewModels/ApplicationViewModel.cs @@ -69,6 +69,7 @@ namespace FModel.ViewModels public AesManagerViewModel AesManager { get; } public AudioPlayerViewModel AudioPlayer { get; } public MapViewerViewModel MapViewer { get; } + public ModelViewerViewModel ModelViewer { get; } public ApplicationViewModel() { @@ -89,6 +90,7 @@ namespace FModel.ViewModels AesManager = new AesManagerViewModel(CUE4Parse); MapViewer = new MapViewerViewModel(CUE4Parse); AudioPlayer = new AudioPlayerViewModel(); + ModelViewer = new ModelViewerViewModel(); Status = EStatusKind.Ready; } diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 495dfca7..3351f3dc 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -592,7 +592,8 @@ namespace FModel.ViewModels { Application.Current.Dispatcher.Invoke(delegate { - Helper.OpenWindow("Model Viewer", () => new ModelViewer(export).Show()); + var modelViewer = Helper.GetWindow("Model Viewer", () => new ModelViewer().Show()); + modelViewer.Load(export); }); } return false; diff --git a/FModel/ViewModels/ModelViewerViewModel.cs b/FModel/ViewModels/ModelViewerViewModel.cs index 51f8f8d6..ba8b06da 100644 --- a/FModel/ViewModels/ModelViewerViewModel.cs +++ b/FModel/ViewModels/ModelViewerViewModel.cs @@ -1,5 +1,8 @@ -using CUE4Parse.UE4.Assets.Exports.SkeletalMesh; +using System; +using CUE4Parse.UE4.Assets.Exports; +using CUE4Parse.UE4.Assets.Exports.SkeletalMesh; using CUE4Parse.UE4.Assets.Exports.StaticMesh; +using CUE4Parse_Conversion.Meshes; using FModel.Framework; using HelixToolkit.SharpDX.Core; using HelixToolkit.Wpf.SharpDX; @@ -23,124 +26,110 @@ namespace FModel.ViewModels set => SetProperty(ref _cam, value); } - private Geometry3D _cubeMesh; - public Geometry3D CubeMesh + private Geometry3D _mesh; + public Geometry3D Mesh { - get => _cubeMesh; - set => SetProperty(ref _cubeMesh, value); + get => _mesh; + set => SetProperty(ref _mesh, value); } - private Material _red; - public Material Red + private Material _meshMat; + public Material MeshMat { - get => _red; - set => SetProperty(ref _red, value); + get => _meshMat; + set => SetProperty(ref _meshMat, value); } - public ModelViewerViewModel(UStaticMesh? mesh) + public ModelViewerViewModel() { EffectManager = new DefaultEffectsManager(); - Cam = new PerspectiveCamera(); - if (mesh?.RenderData == null || mesh.RenderData.LODs.Length < 1) return; - - var builder = new MeshBuilder(); - for (var i = 0; i < mesh.RenderData.LODs.Length; i++) + Cam = new PerspectiveCamera { - if (mesh.RenderData.LODs[i] is not - { - VertexBuffer: not null, - PositionVertexBuffer: not null, - ColorVertexBuffer: not null, - IndexBuffer: not null - } srcLod) continue; - - var numVerts = srcLod.PositionVertexBuffer.Verts.Length; - for (var j = 0; j < numVerts; j++) - { - var suv = srcLod.VertexBuffer.UV[j]; - builder.Positions.Add(new Vector3(srcLod.PositionVertexBuffer.Verts[j].X, srcLod.PositionVertexBuffer.Verts[j].Y, srcLod.PositionVertexBuffer.Verts[j].Z)); - builder.Normals.Add(new Vector3(suv.Normal[2].X, suv.Normal[2].Y, suv.Normal[2].Z)); - } - - for (var j = 0; j < srcLod.IndexBuffer.Indices16.Length; j++) - { - builder.TriangleIndices.Add(srcLod.IndexBuffer[j]); - } - break; + NearPlaneDistance = 0.1, + FarPlaneDistance = 10000000, + FieldOfView = 80 + }; + } + + public void LoadExport(UObject export) + { + switch (export) + { + case UStaticMesh st: + LoadStaticMesh(st); + break; + case USkeletalMesh sk: + LoadSkeletalMesh(sk); + break; + default: + throw new ArgumentOutOfRangeException(); } - builder.Scale(0.05, 0.05, 0.05); - CubeMesh = builder.ToMesh(); - Red = PhongMaterials.Red; } - public ModelViewerViewModel(USkeletalMesh? mesh) + private void LoadStaticMesh(UStaticMesh mesh) { - EffectManager = new DefaultEffectsManager(); - Cam = new PerspectiveCamera(); - if (mesh == null || mesh.LODModels?.Length < 1) return; + if (!mesh.TryConvert(out var convertedMesh) || convertedMesh.LODs.Length <= 0) + { + return; + } + + var max = convertedMesh.BoundingBox.Max.Max(); + Cam.UpDirection = new System.Windows.Media.Media3D.Vector3D(0, 1, 0); + Cam.Position = new System.Windows.Media.Media3D.Point3D(max / 2, max, max / 2); + Cam.LookDirection = new System.Windows.Media.Media3D.Vector3D(-Cam.Position.X, -Cam.Position.Y / 2, -Cam.Position.Z); var builder = new MeshBuilder(); - for (var i = 0; i < mesh.LODModels.Length; i++) + for (var i = 0; i < convertedMesh.LODs.Length; i++) { - if (mesh.LODModels[i] is not { } srcLod) continue; - - var bUseVerticesFromSections = false; - var vertexCount = srcLod.VertexBufferGPUSkin.GetVertexCount(); - if (vertexCount == 0 && srcLod.Sections.Length > 0 && srcLod.Sections[0].SoftVertices.Length > 0) + for (var j = 0; j < convertedMesh.LODs[i].NumVerts; j++) { - bUseVerticesFromSections = true; - for (var j = 0; j < srcLod.Sections.Length; j++) - { - vertexCount += srcLod.Sections[i].SoftVertices.Length; - } + var suv = convertedMesh.LODs[i].Verts[j]; + builder.Positions.Add(new Vector3(suv.Position.X, suv.Position.Y, suv.Position.Z)); + builder.Normals.Add(new Vector3(suv.Normal.X, suv.Normal.Y, suv.Normal.Z)); } - - var chunkIndex = -1; - var chunkVertexIndex = 0; - long lastChunkVertex = -1; - var vertBuffer = srcLod.VertexBufferGPUSkin; - - for (var j = 0; j < vertexCount; j++) + + var numIndices = convertedMesh.LODs[i].Indices.Value.Length; + for (var j = 0; j < numIndices; j++) { - while (j >= lastChunkVertex) // this will fix any issues with empty chunks or sections - { - // proceed to next chunk or section - if (srcLod.Chunks.Length > 0) - { - // pre-UE4.13 code: chunks - var c = srcLod.Chunks[++chunkIndex]; - lastChunkVertex = c.BaseVertexIndex + c.NumRigidVertices + c.NumSoftVertices; - } - else - { - // UE4.13+ code: chunk information migrated to sections - var s = srcLod.Sections[++chunkIndex]; - lastChunkVertex = s.BaseVertexIndex + s.NumVertices; - } - chunkVertexIndex = 0; - } - - FSkelMeshVertexBase v; - if (bUseVerticesFromSections) - v = srcLod.Sections[chunkIndex].SoftVertices[chunkVertexIndex++]; - else if (!vertBuffer.bUseFullPrecisionUVs) - v = vertBuffer.VertsHalf[j]; - else - v = vertBuffer.VertsFloat[j]; - - builder.Positions.Add(new Vector3(v.Pos.X, v.Pos.Y, v.Pos.Z)); - builder.Normals.Add(new Vector3(v.Normal[2].X, v.Normal[2].Y, v.Normal[2].Z)); - } - - for (var j = 0; j < srcLod.Indices.Indices16.Length; j++) - { - builder.TriangleIndices.Add(srcLod.Indices.Indices16[j]); + builder.TriangleIndices.Add(convertedMesh.LODs[i].Indices.Value[j]); } break; } - builder.Scale(0.05, 0.05, 0.05); - CubeMesh = builder.ToMesh(); - Red = PhongMaterials.Red; + Mesh = builder.ToMesh(); + MeshMat = DiffuseMaterials.White; + } + + private void LoadSkeletalMesh(USkeletalMesh mesh) + { + if (!mesh.TryConvert(out var convertedMesh) || convertedMesh.LODs.Length <= 0) + { + return; + } + + var max = convertedMesh.BoundingBox.Max.Max(); + Cam.UpDirection = new System.Windows.Media.Media3D.Vector3D(0, 1, 0); + Cam.Position = new System.Windows.Media.Media3D.Point3D(max / 2, max, max / 2); + Cam.LookDirection = new System.Windows.Media.Media3D.Vector3D(-Cam.Position.X, -Cam.Position.Y / 2, -Cam.Position.Z); + + var builder = new MeshBuilder(); + for (var i = 0; i < convertedMesh.LODs.Length; i++) + { + for (var j = 0; j < convertedMesh.LODs[i].NumVerts; j++) + { + var suv = convertedMesh.LODs[i].Verts[j]; + builder.Positions.Add(new Vector3(suv.Position.X, suv.Position.Y, suv.Position.Z)); + builder.Normals.Add(new Vector3(suv.Normal.X, suv.Normal.Y, suv.Normal.Z)); + } + + var numIndices = convertedMesh.LODs[i].Indices.Value.Length; + for (var j = 0; j < numIndices; j++) + { + builder.TriangleIndices.Add(convertedMesh.LODs[i].Indices.Value[j]); + } + break; + } + Mesh = builder.ToMesh(); + MeshMat = DiffuseMaterials.White; } } } \ No newline at end of file diff --git a/FModel/Views/ModelViewer.xaml b/FModel/Views/ModelViewer.xaml index f64c57c1..346418f7 100644 --- a/FModel/Views/ModelViewer.xaml +++ b/FModel/Views/ModelViewer.xaml @@ -1,13 +1,12 @@  + Height="{Binding Source={x:Static SystemParameters.MaximizedPrimaryScreenHeight}, Converter={converters:RatioConverter}, ConverterParameter='0.50'}" + Width="{Binding Source={x:Static SystemParameters.MaximizedPrimaryScreenWidth}, Converter={converters:RatioConverter}, ConverterParameter='0.50'}"> - + + + + diff --git a/FModel/ViewModels/ApplicationViewModel.cs b/FModel/ViewModels/ApplicationViewModel.cs index 335821e6..3abef1de 100644 --- a/FModel/ViewModels/ApplicationViewModel.cs +++ b/FModel/ViewModels/ApplicationViewModel.cs @@ -1,4 +1,4 @@ -using FModel.Extensions; +using FModel.Extensions; using FModel.Framework; using FModel.Services; using FModel.Settings; @@ -61,7 +61,7 @@ namespace FModel.ViewModels public CopyCommand CopyCommand => _copyCommand ??= new CopyCommand(this); private CopyCommand _copyCommand; - public string TitleExtra => $"{CUE4Parse.Game.GetDescription()} ({UserSettings.Default.OverridedGame[CUE4Parse.Game]}){(Build != EBuildKind.Release ? $" ({Build})" : "")}"; + public string TitleExtra => $"{UserSettings.Default.UpdateMode} - {CUE4Parse.Game.GetDescription()} ({UserSettings.Default.OverridedGame[CUE4Parse.Game]}){(Build != EBuildKind.Release ? $" ({Build})" : "")}"; public LoadingModesViewModel LoadingModes { get; } public CustomDirectoriesViewModel CustomDirectories { get; } diff --git a/FModel/ViewModels/MapViewerViewModel.cs b/FModel/ViewModels/MapViewerViewModel.cs index e85b0064..d8793896 100644 --- a/FModel/ViewModels/MapViewerViewModel.cs +++ b/FModel/ViewModels/MapViewerViewModel.cs @@ -54,6 +54,13 @@ namespace FModel.ViewModels set => SetProperty(ref _brLandmarks, value, "ApolloGameplay_MapLandmarks"); } + private bool _brTagsLocation; + public bool BrTagsLocation + { + get => _brTagsLocation; + set => SetProperty(ref _brTagsLocation, value, "ApolloGameplay_TagsLocation"); + } + private bool _brPatrolsPath; public bool BrPatrolsPath { @@ -75,18 +82,25 @@ namespace FModel.ViewModels set => SetProperty(ref _brPhonebooths, value, "ApolloGameplay_Phonebooths"); } - private bool _brTagsLocation; - public bool BrTagsLocation + private bool _brVendingMachines; + public bool BrVendingMachines { - get => _brTagsLocation; - set => SetProperty(ref _brTagsLocation, value, "ApolloGameplay_TagsLocation"); + get => _brVendingMachines; + set => SetProperty(ref _brVendingMachines, value, "ApolloGameplay_VendingMachines"); } - private bool _brAlienArtifacts; - public bool BrAlienArtifacts + private bool _brFireflies; + public bool BrFireflies { - get => _brAlienArtifacts; - set => SetProperty(ref _brAlienArtifacts, value, "ApolloGameplay_AlienArtifacts"); + get => _brFireflies; + set => SetProperty(ref _brFireflies, value, "ApolloGameplay_Fireflies"); + } + + private bool _brInks; + public bool BrInks + { + get => _brInks; + set => SetProperty(ref _brInks, value, "ApolloGameplay_Inks"); } private bool _prLandmarks; @@ -243,6 +257,9 @@ namespace FModel.ViewModels case "PapayaGameplay_MapLandmarks": await LoadQuestIndicatorData(); break; + case "ApolloGameplay_TagsLocation": + await LoadTagsLocation(); + break; case "ApolloGameplay_PatrolsPath": await LoadPatrolsPath(); break; @@ -252,11 +269,14 @@ namespace FModel.ViewModels case "ApolloGameplay_Phonebooths": await LoadPhonebooths(); break; - case "ApolloGameplay_AlienArtifacts": - await LoadAlienArtifacts(); + case "ApolloGameplay_VendingMachines": + await LoadBrVendingMachines(); break; - case "ApolloGameplay_TagsLocation": - await LoadTagsLocation(); + case "ApolloGameplay_Fireflies": + await LoadFireflies(); + break; + case "ApolloGameplay_Inks": + await LoadInks(); break; case "PapayaGameplay_CannonballGame": await LoadCannonballGame(); @@ -274,7 +294,7 @@ namespace FModel.ViewModels await LoadWaypoint(EWaypointType.TimeTrials); break; case "PapayaGameplay_VendingMachines": - await LoadVendingMachines(); + await LoadPrVendingMachines(); break; case "PapayaGameplay_MusicBlocks": await LoadMusicBlocks(); @@ -453,24 +473,20 @@ namespace FModel.ViewModels var patrolsPathBitmap = new SKBitmap(_widthHeight, _widthHeight, SKColorType.Rgba8888, SKAlphaType.Premul); using var c = new SKCanvas(patrolsPathBitmap); - var exports = Utils.LoadExports("/NPCLibrary/LevelOverlays/Apollo_Terrain_NPCLibraryS17_Overlay"); + var exports = Utils.LoadExports("/NPCLibrary/LevelOverlays/Apollo_Terrain_NPCLibrary_Overlay_S18"); foreach (var export in exports) { - if (export is not { } uObject) continue; - if (!uObject.ExportType.Equals("FortAthenaPatrolPath", StringComparison.OrdinalIgnoreCase) || - !uObject.TryGetValue(out FGameplayTagContainer gameplayTags, "GameplayTags") || - !uObject.TryGetValue(out FPackageIndex[] patrolPoints, "PatrolPoints")) continue; + if (!export.ExportType.Equals("FortAthenaPatrolPath", StringComparison.OrdinalIgnoreCase) || + !export.TryGetValue(out FPackageIndex[] patrolPoints, "PatrolPoints")) continue; - var displayName = gameplayTags.GameplayTags[0].Text.SubstringAfterLast("."); - if (displayName.Equals("Generic", StringComparison.OrdinalIgnoreCase)) continue; - - if (!Utils.TryGetPackageIndexExport(patrolPoints[0], out uObject) || + if (!Utils.TryGetPackageIndexExport(patrolPoints[0], out UObject uObject) || !uObject.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || !Utils.TryGetPackageIndexExport(rootComponent, out uObject) || !uObject.TryGetValue(out FVector relativeLocation, "RelativeLocation")) continue; var path = new SKPath(); var vector = GetMapPosition(relativeLocation, _brRadius); + var displayName = export.Name["FortAthenaPatrolPath_Tandem_S18_".Length..]; path.MoveTo(vector.X, vector.Y); for (var i = 1; i < patrolPoints.Length; i++) @@ -504,12 +520,11 @@ namespace FModel.ViewModels var exports = Utils.LoadExports("/PapayaGameplay/LevelOverlays/PapayaGameplay_CannonballGame"); foreach (var export in exports) { - if (export is not { } uObject) continue; - if (!uObject.ExportType.Equals("BP_CannonballGame_Target_C", StringComparison.OrdinalIgnoreCase) && - !uObject.ExportType.Equals("CannonballGame_VehicleSpawner_C", StringComparison.OrdinalIgnoreCase)) continue; + if (!export.ExportType.Equals("BP_CannonballGame_Target_C", StringComparison.OrdinalIgnoreCase) && + !export.ExportType.Equals("CannonballGame_VehicleSpawner_C", StringComparison.OrdinalIgnoreCase)) continue; - if (!uObject.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || - !Utils.TryGetPackageIndexExport(rootComponent, out uObject) || + if (!export.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || + !Utils.TryGetPackageIndexExport(rootComponent, out UObject uObject) || !uObject.TryGetValue(out FVector relativeLocation, "RelativeLocation")) continue; var displayName = Utils.GetLocalizedResource("", "D998BEF44F051E0885C6C58565934BEA", "Cannonball"); @@ -535,12 +550,11 @@ namespace FModel.ViewModels var exports = Utils.LoadExports("/PapayaGameplay/LevelOverlays/PapayaGameplay_SkydiveGame"); foreach (var export in exports) { - if (export is not { } uObject) continue; - if (!uObject.ExportType.Equals("BP_Waypoint_Papaya_Skydive_Start_C", StringComparison.OrdinalIgnoreCase)) continue; + if (!export.ExportType.Equals("BP_Waypoint_Papaya_Skydive_Start_C", StringComparison.OrdinalIgnoreCase)) continue; - if (!uObject.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || - !uObject.TryGetValue(out FText minigameActivityName, "MinigameActivityName") || - !Utils.TryGetPackageIndexExport(rootComponent, out uObject) || + if (!export.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || + !export.TryGetValue(out FText minigameActivityName, "MinigameActivityName") || + !Utils.TryGetPackageIndexExport(rootComponent, out UObject uObject) || !uObject.TryGetValue(out FVector relativeLocation, "RelativeLocation")) continue; var vector = GetMapPosition(relativeLocation, _prRadius); @@ -566,11 +580,10 @@ namespace FModel.ViewModels var exports = Utils.LoadExports("/PapayaGameplay/LevelOverlays/PapayaGameplay_ShootingTargets"); foreach (var export in exports) { - if (export is not { } uObject) continue; - if (!uObject.ExportType.Equals("PapayaShootingTarget_C", StringComparison.OrdinalIgnoreCase)) continue; + if (!export.ExportType.Equals("PapayaShootingTarget_C", StringComparison.OrdinalIgnoreCase)) continue; - if (!uObject.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || - !Utils.TryGetPackageIndexExport(rootComponent, out uObject) || + if (!export.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || + !Utils.TryGetPackageIndexExport(rootComponent, out UObject uObject) || !uObject.TryGetValue(out FVector relativeLocation, "RelativeLocation")) continue; var vector = GetMapPosition(relativeLocation, _prRadius); @@ -614,21 +627,20 @@ namespace FModel.ViewModels var exports = Utils.LoadExports($"/PapayaGameplay/LevelOverlays/{file}"); foreach (var export in exports) { - if (export is not { } uObject) continue; - if (!uObject.ExportType.Equals("BP_Waypoint_Parent_Papaya_C", StringComparison.OrdinalIgnoreCase)) continue; + if (!export.ExportType.Equals("BP_Waypoint_Parent_Papaya_C", StringComparison.OrdinalIgnoreCase)) continue; - if (!uObject.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || + if (!export.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || !Utils.TryGetPackageIndexExport(rootComponent, out UObject root) || !root.TryGetValue(out FVector relativeLocation, "RelativeLocation")) continue; var vector = GetMapPosition(relativeLocation, _prRadius); - if (path.IsEmpty || uObject.TryGetValue(out bool startsTrial, "StartsTrial") && startsTrial) + if (path.IsEmpty || export.TryGetValue(out bool startsTrial, "StartsTrial") && startsTrial) { path.MoveTo(vector.X, vector.Y); c.DrawText(name, vector.X, vector.Y - 12.5F, _fillPaint); c.DrawText(name, vector.X, vector.Y - 12.5F, _textPaint); } - else if (uObject.TryGetValue(out bool endsTrial, "EndsTrial") && endsTrial) + else if (export.TryGetValue(out bool endsTrial, "EndsTrial") && endsTrial) { path.LineTo(vector.X, vector.Y); c.DrawPath(path, _pathPaint); @@ -641,7 +653,7 @@ namespace FModel.ViewModels }); } - private async Task LoadVendingMachines() + private async Task LoadPrVendingMachines() { await _threadWorkerView.Begin(_ => { @@ -653,27 +665,26 @@ namespace FModel.ViewModels var exports = Utils.LoadExports("/PapayaGameplay/LevelOverlays/PapayaGameplay_VendingMachines"); foreach (var export in exports) { - if (export is not { } uObject) continue; - if (!uObject.ExportType.Equals("B_Papaya_VendingMachine_Boat_C", StringComparison.OrdinalIgnoreCase) && - !uObject.ExportType.Equals("B_Papaya_VendingMachine_BoogieBomb_C", StringComparison.OrdinalIgnoreCase) && - !uObject.ExportType.Equals("B_Papaya_VendingMachine_Burger_C", StringComparison.OrdinalIgnoreCase) && - !uObject.ExportType.Equals("B_Papaya_VendingMachine_CrashPad_C", StringComparison.OrdinalIgnoreCase) && - !uObject.ExportType.Equals("B_Papaya_VendingMachine_FishingPole_C", StringComparison.OrdinalIgnoreCase) && - !uObject.ExportType.Equals("B_Papaya_VendingMachine_Grappler_C", StringComparison.OrdinalIgnoreCase) && - !uObject.ExportType.Equals("B_Papaya_VendingMachine_Jetpack_C", StringComparison.OrdinalIgnoreCase) && - !uObject.ExportType.Equals("B_Papaya_VendingMachine_PaintGrenade_Blue_C", StringComparison.OrdinalIgnoreCase) && - !uObject.ExportType.Equals("B_Papaya_VendingMachine_PaintGrenade_Red_C", StringComparison.OrdinalIgnoreCase) && - !uObject.ExportType.Equals("B_Papaya_VendingMachine_PaintLauncher_Blue_C", StringComparison.OrdinalIgnoreCase) && - !uObject.ExportType.Equals("B_Papaya_VendingMachine_PaintLauncher_Red_C", StringComparison.OrdinalIgnoreCase) && - !uObject.ExportType.Equals("B_Papaya_VendingMachine_PlungerBow_C", StringComparison.OrdinalIgnoreCase) && - !uObject.ExportType.Equals("B_Papaya_VendingMachine_Quad_C", StringComparison.OrdinalIgnoreCase) && - !uObject.ExportType.Equals("B_Papaya_VendingMachine_Tomato_C", StringComparison.OrdinalIgnoreCase)) continue; + if (!export.ExportType.Equals("B_Papaya_VendingMachine_Boat_C", StringComparison.OrdinalIgnoreCase) && + !export.ExportType.Equals("B_Papaya_VendingMachine_BoogieBomb_C", StringComparison.OrdinalIgnoreCase) && + !export.ExportType.Equals("B_Papaya_VendingMachine_Burger_C", StringComparison.OrdinalIgnoreCase) && + !export.ExportType.Equals("B_Papaya_VendingMachine_CrashPad_C", StringComparison.OrdinalIgnoreCase) && + !export.ExportType.Equals("B_Papaya_VendingMachine_FishingPole_C", StringComparison.OrdinalIgnoreCase) && + !export.ExportType.Equals("B_Papaya_VendingMachine_Grappler_C", StringComparison.OrdinalIgnoreCase) && + !export.ExportType.Equals("B_Papaya_VendingMachine_Jetpack_C", StringComparison.OrdinalIgnoreCase) && + !export.ExportType.Equals("B_Papaya_VendingMachine_PaintGrenade_Blue_C", StringComparison.OrdinalIgnoreCase) && + !export.ExportType.Equals("B_Papaya_VendingMachine_PaintGrenade_Red_C", StringComparison.OrdinalIgnoreCase) && + !export.ExportType.Equals("B_Papaya_VendingMachine_PaintLauncher_Blue_C", StringComparison.OrdinalIgnoreCase) && + !export.ExportType.Equals("B_Papaya_VendingMachine_PaintLauncher_Red_C", StringComparison.OrdinalIgnoreCase) && + !export.ExportType.Equals("B_Papaya_VendingMachine_PlungerBow_C", StringComparison.OrdinalIgnoreCase) && + !export.ExportType.Equals("B_Papaya_VendingMachine_Quad_C", StringComparison.OrdinalIgnoreCase) && + !export.ExportType.Equals("B_Papaya_VendingMachine_Tomato_C", StringComparison.OrdinalIgnoreCase)) continue; - if (!uObject.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || + if (!export.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || !Utils.TryGetPackageIndexExport(rootComponent, out UObject root) || !root.TryGetValue(out FVector relativeLocation, "RelativeLocation")) continue; - var name = uObject.ExportType.SubstringAfter("B_Papaya_VendingMachine_").SubstringBeforeLast("_C"); + var name = export.ExportType.SubstringAfter("B_Papaya_VendingMachine_").SubstringBeforeLast("_C"); var vector = GetMapPosition(relativeLocation, _prRadius); c.DrawPoint(vector.X, vector.Y, _pathPaint); if (!set.Add(name)) continue; @@ -698,11 +709,10 @@ namespace FModel.ViewModels var exports = Utils.LoadExports("/PapayaGameplay/LevelOverlays/PapayaGameplay_MusicBlocks"); foreach (var export in exports) { - if (export is not { } uObject) continue; - if (!uObject.ExportType.Equals("MusicBlock_Piano3_Papaya_C", StringComparison.OrdinalIgnoreCase)) continue; + if (!export.ExportType.Equals("MusicBlock_Piano3_Papaya_C", StringComparison.OrdinalIgnoreCase)) continue; - if (!uObject.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || - !Utils.TryGetPackageIndexExport(rootComponent, out uObject) || + if (!export.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || + !Utils.TryGetPackageIndexExport(rootComponent, out UObject uObject) || !uObject.TryGetValue(out FVector relativeLocation, "RelativeLocation")) continue; var vector = GetMapPosition(relativeLocation, _prRadius); @@ -729,12 +739,11 @@ namespace FModel.ViewModels var exports = Utils.LoadExports("/NPCLibrary/LevelOverlays/Apollo_Terrain_NPCLibrary_Stations_UpgradeBenches"); foreach (var export in exports) { - if (export is not { } uObject) continue; - if (!uObject.ExportType.Equals("B_Athena_Spawner_UpgradeStation_C", StringComparison.OrdinalIgnoreCase)) continue; - var displayName = uObject.Name["B_Athena_Spawner_".Length..]; + if (!export.ExportType.Equals("B_Athena_Spawner_UpgradeStation_C", StringComparison.OrdinalIgnoreCase)) continue; + var displayName = export.Name["B_Athena_Spawner_".Length..]; - if (!uObject.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || - !Utils.TryGetPackageIndexExport(rootComponent, out uObject) || + if (!export.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || + !Utils.TryGetPackageIndexExport(rootComponent, out UObject uObject) || !uObject.TryGetValue(out FVector relativeLocation, "RelativeLocation")) continue; var vector = GetMapPosition(relativeLocation, _brRadius); @@ -758,12 +767,11 @@ namespace FModel.ViewModels var exports = Utils.LoadExports("/NPCLibrary/LevelOverlays/Apollo_Terrain_NPCLibrary_Stations_Phonebooths"); foreach (var export in exports) { - if (export is not { } uObject) continue; - if (!uObject.ExportType.Equals("B_Athena_Spawner_Payphone_C", StringComparison.OrdinalIgnoreCase)) continue; - var displayName = uObject.Name["B_Athena_Spawner_".Length..]; + if (!export.ExportType.Equals("B_Athena_Spawner_Payphone_C", StringComparison.OrdinalIgnoreCase)) continue; + var displayName = export.Name["B_Athena_Spawner_".Length..]; - if (!uObject.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || - !Utils.TryGetPackageIndexExport(rootComponent, out uObject) || + if (!export.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || + !Utils.TryGetPackageIndexExport(rootComponent, out UObject uObject) || !uObject.TryGetValue(out FVector relativeLocation, "RelativeLocation")) continue; var vector = GetMapPosition(relativeLocation, _brRadius); @@ -776,23 +784,23 @@ namespace FModel.ViewModels }); } - private async Task LoadAlienArtifacts() + private async Task LoadBrVendingMachines() { await _threadWorkerView.Begin(_ => { _fillPaint.StrokeWidth = 5; - var alienArtifactsBitmap = new SKBitmap(_widthHeight, _widthHeight, SKColorType.Rgba8888, SKAlphaType.Premul); - using var c = new SKCanvas(alienArtifactsBitmap); + var vendingMachinesBitmap = new SKBitmap(_widthHeight, _widthHeight, SKColorType.Rgba8888, SKAlphaType.Premul); + using var c = new SKCanvas(vendingMachinesBitmap); - var exports = Utils.LoadExports("/BattlepassS17/Maps/Apollo_ItemCollect_S17_Overlay"); + var exports = Utils.LoadExports("FortniteGame/Content/Athena/Apollo/Maps/Special/ItemCollections/Apollo_Item_VendingMachines"); foreach (var export in exports) { - if (export is not { } uObject) continue; - if (!uObject.ExportType.Equals("BP_S17_AlienArtifact_Variant1_C", StringComparison.OrdinalIgnoreCase)) continue; - var displayName = uObject.Name; + if (!export.ExportType.Equals("B_Athena_Spawner_VendingMachine_MendingOnly_C", StringComparison.OrdinalIgnoreCase) && + !export.ExportType.Equals("B_Athena_Spawner_VendingMachine_Random_C", StringComparison.OrdinalIgnoreCase)) continue; + var displayName = $"{(export.ExportType.Contains("Mending") ? "MM" : "WOM")}_{export.Name["B_Athena_Spawner_VendingMachine_Random".Length..]}"; - if (!uObject.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || - !Utils.TryGetPackageIndexExport(rootComponent, out uObject) || + if (!export.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || + !Utils.TryGetPackageIndexExport(rootComponent, out UObject uObject) || !uObject.TryGetValue(out FVector relativeLocation, "RelativeLocation")) continue; var vector = GetMapPosition(relativeLocation, _brRadius); @@ -801,7 +809,74 @@ namespace FModel.ViewModels c.DrawText(displayName, vector.X, vector.Y - 12.5F, _textPaint); } - _bitmaps[0]["ApolloGameplay_AlienArtifacts"] = new MapLayer {Layer = alienArtifactsBitmap, IsEnabled = false}; + _bitmaps[0]["ApolloGameplay_VendingMachines"] = new MapLayer {Layer = vendingMachinesBitmap, IsEnabled = false}; + }); + } + + private async Task LoadInks() + { + await _threadWorkerView.Begin(_ => + { + _fillPaint.StrokeWidth = 5; + var inksBitmap = new SKBitmap(_widthHeight, _widthHeight, SKColorType.Rgba8888, SKAlphaType.Premul); + using var c = new SKCanvas(inksBitmap); + + if (!Utils.TryLoadObject("BattlePassS18/Maps/BattlepassS18_LevelOverlay_Config.BattlepassS18_LevelOverlay_Config", out UObject config) || + !config.TryGetValue(out FStructFallback[] overlayList, "OverlayList") || overlayList.Length < 1) + return; + + foreach (var overlay in overlayList) + { + if (!overlay.TryGetValue(out FSoftObjectPath overlayWorld, "OverlayWorld")) continue; + + var exports = Utils.LoadExports(overlayWorld.AssetPathName.Text.SubstringBeforeLast(".")); + foreach (var export in exports) + { + if (!export.ExportType.StartsWith("BP_S18_ToonInk_CollectibleColor", StringComparison.OrdinalIgnoreCase)) continue; + + if (!export.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || + !Utils.TryGetPackageIndexExport(rootComponent, out UObject uObject) || + !uObject.TryGetValue(out FVector relativeLocation, "RelativeLocation")) continue; + + if (!export.TryGetValue(out FPackageIndex questIconComponent, "QuestIconComponent") || + !Utils.TryGetPackageIndexExport(questIconComponent, out uObject) || + !uObject.TryGetValue(out FStructFallback mapIconData, "MapIconData") || + !mapIconData.TryGetValue(out FPackageIndex mapIcon, "MapIcon")) continue; + + var vector = GetMapPosition(relativeLocation, _brRadius); + c.DrawBitmap(Utils.GetBitmap(mapIcon), vector.X, vector.Y); + } + } + + _bitmaps[0]["ApolloGameplay_Inks"] = new MapLayer {Layer = inksBitmap, IsEnabled = false}; + }); + } + + private async Task LoadFireflies() + { + await _threadWorkerView.Begin(_ => + { + _fillPaint.StrokeWidth = 5; + var firefliesBitmap = new SKBitmap(_widthHeight, _widthHeight, SKColorType.Rgba8888, SKAlphaType.Premul); + using var c = new SKCanvas(firefliesBitmap); + + var exports = Utils.LoadExports("FortniteGame/Content/Athena/Apollo/Maps/Special/ItemCollections/Apollo_Item_Fireflies"); + foreach (var export in exports) + { + if (!export.ExportType.Equals("BP_BGACSpawner_Fireflies_C", StringComparison.OrdinalIgnoreCase)) continue; + var displayName = $"FF_{export.Name["BP_BGACSpawnerFireFlies".Length..]}"; + + if (!export.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || + !Utils.TryGetPackageIndexExport(rootComponent, out UObject uObject) || + !uObject.TryGetValue(out FVector relativeLocation, "RelativeLocation")) continue; + + var vector = GetMapPosition(relativeLocation, _brRadius); + c.DrawPoint(vector.X, vector.Y, _pathPaint); + c.DrawText(displayName, vector.X, vector.Y - 12.5F, _fillPaint); + c.DrawText(displayName, vector.X, vector.Y - 12.5F, _textPaint); + } + + _bitmaps[0]["ApolloGameplay_Fireflies"] = new MapLayer {Layer = firefliesBitmap, IsEnabled = false}; }); } diff --git a/FModel/Views/MapViewer.xaml b/FModel/Views/MapViewer.xaml index b68d3f7f..d42150b3 100644 --- a/FModel/Views/MapViewer.xaml +++ b/FModel/Views/MapViewer.xaml @@ -27,16 +27,20 @@ DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.MapViewer}}}" IsEnabled="{Binding IsReady}" /> + - - + + From 07282faf8cdf344f91b86fa7dd92b641ba4a739a Mon Sep 17 00:00:00 2001 From: MountainFlash Date: Wed, 15 Sep 2021 20:46:30 +0530 Subject: [PATCH 53/58] updated action --- .github/workflows/main.yml | 3 +++ CUE4Parse | 2 +- FModel/FModel.sln | 6 ------ 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 135a94ac..a56c0d4d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,6 +18,9 @@ jobs: with: submodules: 'true' + - name: Fetch Submodules Recursively + run: git submodule update --init --recursive + - name: .NET 5 Setup uses: actions/setup-dotnet@v1 with: diff --git a/CUE4Parse b/CUE4Parse index 36d50f3b..49beea8c 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 36d50f3b253327bb355a7c39385c9f1b9802203d +Subproject commit 49beea8c444aa357023d8eca209ddb8139b7a1c1 diff --git a/FModel/FModel.sln b/FModel/FModel.sln index 5fea2b89..a53a4881 100644 --- a/FModel/FModel.sln +++ b/FModel/FModel.sln @@ -11,8 +11,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUE4Parse-Fortnite", "..\CU EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUE4Parse-Conversion", "..\CUE4Parse\CUE4Parse-Conversion\CUE4Parse-Conversion.csproj", "{D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CUE4Parse-Natives", "..\CUE4Parse\CUE4Parse-Natives\builddir\CUE4Parse-Natives.vcxproj", "{5A57D90F-44F6-3F94-AC61-66E23DB2160E}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -35,10 +33,6 @@ Global {D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}.Debug|Any CPU.Build.0 = Debug|Any CPU {D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}.Release|Any CPU.ActiveCfg = Release|Any CPU {D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}.Release|Any CPU.Build.0 = Release|Any CPU - {5A57D90F-44F6-3F94-AC61-66E23DB2160E}.Debug|Any CPU.ActiveCfg = Debug|x64 - {5A57D90F-44F6-3F94-AC61-66E23DB2160E}.Debug|Any CPU.Build.0 = Debug|x64 - {5A57D90F-44F6-3F94-AC61-66E23DB2160E}.Release|Any CPU.ActiveCfg = Release|x64 - {5A57D90F-44F6-3F94-AC61-66E23DB2160E}.Release|Any CPU.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From c27d7425c55d178e13c7202cffba108ee7071dab Mon Sep 17 00:00:00 2001 From: iAmAsval Date: Thu, 16 Sep 2021 18:59:54 +0200 Subject: [PATCH 54/58] Corruption Zones --- CUE4Parse | 2 +- FModel/Constants.cs | 6 +- FModel/Creator/Utils.cs | 21 +++-- FModel/ViewModels/CUE4ParseViewModel.cs | 2 +- FModel/ViewModels/MapViewerViewModel.cs | 101 ++++++++++++------------ FModel/Views/MapViewer.xaml | 5 +- 6 files changed, 72 insertions(+), 65 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index 49beea8c..4736f823 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 49beea8c444aa357023d8eca209ddb8139b7a1c1 +Subproject commit 4736f8231f61631ffbc5afbd2b4a1281b8651be5 diff --git a/FModel/Constants.cs b/FModel/Constants.cs index 944402ca..2c00ab02 100644 --- a/FModel/Constants.cs +++ b/FModel/Constants.cs @@ -14,10 +14,10 @@ namespace FModel public const string GREEN = "#98C379"; public const string YELLOW = "#E5C07B"; public const string BLUE = "#528BCC"; - - public const string DONATE_LINK = "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EP9SSWG8MW4UC&source=url"; + public const string ISSUE_LINK = "https://github.com/iAmAsval/FModel/issues/new/choose"; - public const string DISCORD_LINK = "https://discord.gg/fdkNYYQ"; + public const string DONATE_LINK = "https://fmodel.app/donate"; + public const string DISCORD_LINK = "https://fmodel.app/discord"; public const string _FN_LIVE_TRIGGER = "fortnite-live.manifest"; public const string _VAL_LIVE_TRIGGER = "valorant-live.manifest"; diff --git a/FModel/Creator/Utils.cs b/FModel/Creator/Utils.cs index 0b965013..9a6fd51b 100644 --- a/FModel/Creator/Utils.cs +++ b/FModel/Creator/Utils.cs @@ -107,6 +107,13 @@ namespace FModel.Creator public static SKBitmap GetBitmap(UTexture2D texture) => texture.IsVirtual ? null : SKBitmap.Decode(texture.Decode()?.Encode()); public static SKBitmap GetBitmap(byte[] data) => SKBitmap.Decode(data); + public static SKBitmap ResizeWithRatio(this SKBitmap me, double width, double height) + { + var ratioX = width / me.Width; + var ratioY = height / me.Height; + var ratio = ratioX < ratioY ? ratioX : ratioY; + return me.Resize(Convert.ToInt32(me.Width * ratio), Convert.ToInt32(me.Height * ratio)); + } public static SKBitmap Resize(this SKBitmap me, int size) => me.Resize(size, size); public static SKBitmap Resize(this SKBitmap me, int width, int height) { @@ -115,12 +122,14 @@ namespace FModel.Creator me.ScalePixels(pixmap, SKFilterQuality.Medium); return bmp; } - public static SKBitmap ResizeWithRatio(this SKBitmap me, double width, double height) - { - var ratioX = width / me.Width; - var ratioY = height / me.Height; - var ratio = ratioX < ratioY ? ratioX : ratioY; - return me.Resize(Convert.ToInt32(me.Width * ratio), Convert.ToInt32(me.Height * ratio)); + + public static void ClearToTransparent(this SKBitmap me) { + var colors = me.Pixels; + for (var n = 0; n < colors.Length; n++) { + if (colors[n] != SKColors.Black) continue; + colors[n] = SKColors.Transparent; + } + me.Pixels = colors; } public static bool TryGetPackageIndexExport(FPackageIndex packageIndex, out T export) where T : UObject diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 95307c02..db93bd5c 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -349,7 +349,7 @@ namespace FModel.ViewModels if (VirtualPathCount > 0) { FLogger.AppendInformation(); - FLogger.AppendText($"{VirtualPathCount} virtual paths loaded!", Constants.WHITE, true); + FLogger.AppendText($"{VirtualPathCount} virtual paths loaded", Constants.WHITE, true); } else { diff --git a/FModel/ViewModels/MapViewerViewModel.cs b/FModel/ViewModels/MapViewerViewModel.cs index d8793896..b13a8306 100644 --- a/FModel/ViewModels/MapViewerViewModel.cs +++ b/FModel/ViewModels/MapViewerViewModel.cs @@ -10,7 +10,6 @@ using CUE4Parse.UE4.Assets.Exports.Texture; using CUE4Parse.UE4.Assets.Objects; using CUE4Parse.UE4.Objects.Core.i18N; using CUE4Parse.UE4.Objects.Core.Math; -using CUE4Parse.UE4.Objects.GameplayTags; using CUE4Parse.UE4.Objects.UObject; using FModel.Creator; using FModel.Extensions; @@ -96,11 +95,11 @@ namespace FModel.ViewModels set => SetProperty(ref _brFireflies, value, "ApolloGameplay_Fireflies"); } - private bool _brInks; - public bool BrInks + private bool _brCorruptionZones; + public bool BrCorruptionZones { - get => _brInks; - set => SetProperty(ref _brInks, value, "ApolloGameplay_Inks"); + get => _brCorruptionZones; + set => SetProperty(ref _brCorruptionZones, value, "ApolloGameplay_CorruptionZones"); } private bool _prLandmarks; @@ -228,8 +227,14 @@ namespace FModel.ViewModels foreach (var (key, value) in _bitmaps[MapIndex]) { - if (!value.IsEnabled || !withMap && key == _FIRST_BITMAP) continue; - c.DrawBitmap(value.Layer, new SKRect(0, 0, _widthHeight, _widthHeight)); + if (!value.IsEnabled || !withMap && key == _FIRST_BITMAP) + continue; + + SKPaint p = null; + if (key == "ApolloGameplay_CorruptionZones") + p = new SKPaint { BlendMode = SKBlendMode.Color }; + + c.DrawBitmap(value.Layer, new SKRect(0, 0, _widthHeight, _widthHeight), p); } return ret; @@ -275,8 +280,8 @@ namespace FModel.ViewModels case "ApolloGameplay_Fireflies": await LoadFireflies(); break; - case "ApolloGameplay_Inks": - await LoadInks(); + case "ApolloGameplay_CorruptionZones": + await LoadCorruptionZones(); break; case "PapayaGameplay_CannonballGame": await LoadCannonballGame(); @@ -387,7 +392,7 @@ namespace FModel.ViewModels !mapMaterial.TryGetValue(out FStructFallback cachedExpressionData, "CachedExpressionData") || !cachedExpressionData.TryGetValue(out FStructFallback parameters, "Parameters") || !parameters.TryGetValue(out UTexture2D[] textureValues, "TextureValues")) return; - + _bitmaps[0][_FIRST_BITMAP] = new MapLayer{Layer = Utils.GetBitmap(textureValues[0]), IsEnabled = true}; _brMiniMapImage = GetImageSource(_bitmaps[0][_FIRST_BITMAP].Layer); }); @@ -812,45 +817,6 @@ namespace FModel.ViewModels _bitmaps[0]["ApolloGameplay_VendingMachines"] = new MapLayer {Layer = vendingMachinesBitmap, IsEnabled = false}; }); } - - private async Task LoadInks() - { - await _threadWorkerView.Begin(_ => - { - _fillPaint.StrokeWidth = 5; - var inksBitmap = new SKBitmap(_widthHeight, _widthHeight, SKColorType.Rgba8888, SKAlphaType.Premul); - using var c = new SKCanvas(inksBitmap); - - if (!Utils.TryLoadObject("BattlePassS18/Maps/BattlepassS18_LevelOverlay_Config.BattlepassS18_LevelOverlay_Config", out UObject config) || - !config.TryGetValue(out FStructFallback[] overlayList, "OverlayList") || overlayList.Length < 1) - return; - - foreach (var overlay in overlayList) - { - if (!overlay.TryGetValue(out FSoftObjectPath overlayWorld, "OverlayWorld")) continue; - - var exports = Utils.LoadExports(overlayWorld.AssetPathName.Text.SubstringBeforeLast(".")); - foreach (var export in exports) - { - if (!export.ExportType.StartsWith("BP_S18_ToonInk_CollectibleColor", StringComparison.OrdinalIgnoreCase)) continue; - - if (!export.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || - !Utils.TryGetPackageIndexExport(rootComponent, out UObject uObject) || - !uObject.TryGetValue(out FVector relativeLocation, "RelativeLocation")) continue; - - if (!export.TryGetValue(out FPackageIndex questIconComponent, "QuestIconComponent") || - !Utils.TryGetPackageIndexExport(questIconComponent, out uObject) || - !uObject.TryGetValue(out FStructFallback mapIconData, "MapIconData") || - !mapIconData.TryGetValue(out FPackageIndex mapIcon, "MapIcon")) continue; - - var vector = GetMapPosition(relativeLocation, _brRadius); - c.DrawBitmap(Utils.GetBitmap(mapIcon), vector.X, vector.Y); - } - } - - _bitmaps[0]["ApolloGameplay_Inks"] = new MapLayer {Layer = inksBitmap, IsEnabled = false}; - }); - } private async Task LoadFireflies() { @@ -885,11 +851,11 @@ namespace FModel.ViewModels await _threadWorkerView.Begin(_ => { _fillPaint.StrokeWidth = 5; - var tagsLocationBitmap = new SKBitmap(_widthHeight, _widthHeight, SKColorType.Rgba8888, SKAlphaType.Premul); - using var c = new SKCanvas(tagsLocationBitmap); - if (!Utils.TryLoadObject("FortniteGame/Content/Quests/QuestTagToLocationDataRows.QuestTagToLocationDataRows", out UDataTable locationData)) return; + + var tagsLocationBitmap = new SKBitmap(_widthHeight, _widthHeight, SKColorType.Rgba8888, SKAlphaType.Premul); + using var c = new SKCanvas(tagsLocationBitmap); foreach (var (key, uObject) in locationData.RowMap) { @@ -912,5 +878,36 @@ namespace FModel.ViewModels _bitmaps[0]["ApolloGameplay_TagsLocation"] = new MapLayer {Layer = tagsLocationBitmap, IsEnabled = false}; }); } + + private async Task LoadCorruptionZones() + { + await _threadWorkerView.Begin(_ => + { + _fillPaint.StrokeWidth = 5; + if (!Utils.TryLoadObject("FortniteGame/Content/Athena/Apollo/Environments/Landscape/Materials/Corruption/T_InitialCorruptionAreas.T_InitialCorruptionAreas", out UTexture2D corruption)) + return; + + var overlay = Utils.GetBitmap(corruption); + var width = overlay.Width; + var height = overlay.Height; + var rotatedBitmap = new SKBitmap(width, height, SKColorType.Rgba8888, SKAlphaType.Opaque); + + using var c = new SKCanvas(rotatedBitmap); + c.Clear(); + c.Translate(0, width); + c.RotateDegrees(-90); + c.DrawRect(0, 0, width, height, new SKPaint + { + IsAntialias = true, FilterQuality = SKFilterQuality.High, + Shader = SKShader.CreateCompose(SKShader.CreateSweepGradient(new SKPoint(width / 2f, height / 2f),new [] { + SKColor.Parse("#352176"), SKColor.Parse("#fd78fa"), SKColor.Parse("#f0b843"), SKColor.Parse("#e54a21") + }, null), SKShader.CreatePerlinNoiseTurbulence(0.05f, 0.05f, 4, 0), SKBlendMode.SrcOver) + }); + c.DrawBitmap(overlay, 0, 0, new SKPaint { BlendMode = SKBlendMode.Darken }); + rotatedBitmap.ClearToTransparent(); + + _bitmaps[0]["ApolloGameplay_CorruptionZones"] = new MapLayer {Layer = rotatedBitmap.Resize(_widthHeight, _widthHeight), IsEnabled = false}; + }); + } } } diff --git a/FModel/Views/MapViewer.xaml b/FModel/Views/MapViewer.xaml index d42150b3..7c88543b 100644 --- a/FModel/Views/MapViewer.xaml +++ b/FModel/Views/MapViewer.xaml @@ -39,8 +39,9 @@ DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.MapViewer}}}" IsEnabled="{Binding IsReady}" /> - - + From 35ce351fbdf161de2c2720a93d47c8ffe0f6b686 Mon Sep 17 00:00:00 2001 From: iAmAsval Date: Fri, 17 Sep 2021 00:00:53 +0200 Subject: [PATCH 55/58] Cube Movements --- FModel/ViewModels/MapViewerViewModel.cs | 79 +++++++++++++++++++++++++ FModel/Views/MapViewer.xaml | 2 + 2 files changed, 81 insertions(+) diff --git a/FModel/ViewModels/MapViewerViewModel.cs b/FModel/ViewModels/MapViewerViewModel.cs index b13a8306..cd945bed 100644 --- a/FModel/ViewModels/MapViewerViewModel.cs +++ b/FModel/ViewModels/MapViewerViewModel.cs @@ -102,6 +102,13 @@ namespace FModel.ViewModels set => SetProperty(ref _brCorruptionZones, value, "ApolloGameplay_CorruptionZones"); } + private bool _brCubeMovements; + public bool BrCubeMovements + { + get => _brCubeMovements; + set => SetProperty(ref _brCubeMovements, value, "ApolloGameplay_CubeMovements"); + } + private bool _prLandmarks; public bool PrLandmarks { @@ -283,6 +290,9 @@ namespace FModel.ViewModels case "ApolloGameplay_CorruptionZones": await LoadCorruptionZones(); break; + case "ApolloGameplay_CubeMovements": + await LoadCubeMovements(); + break; case "PapayaGameplay_CannonballGame": await LoadCannonballGame(); break; @@ -909,5 +919,74 @@ namespace FModel.ViewModels _bitmaps[0]["ApolloGameplay_CorruptionZones"] = new MapLayer {Layer = rotatedBitmap.Resize(_widthHeight, _widthHeight), IsEnabled = false}; }); } + + /// + /// FortniteGame/Plugins/GameFeatures/CorruptionGameplay/Content/CorruptionGameplay_LevelOverlay.uasset + /// too lazy to filters + /// + private async Task LoadCubeMovements() + { + await _threadWorkerView.Begin(_ => + { + _fillPaint.StrokeWidth = 5; + var cubeMovementsBitmap = new SKBitmap(_widthHeight, _widthHeight, SKColorType.Rgba8888, SKAlphaType.Premul); + using var c = new SKCanvas(cubeMovementsBitmap); + + if (!Utils.TryLoadObject("/CorruptionGameplay/Levels/CorruptionGameplay_ApolloTerrain_Overlay.BP_CubeMovementGradient_2", out UObject overlay) || + !overlay.TryGetValue(out FSoftObjectPath[] cubeMovementStaticPaths, "cubeMovementStaticPaths") || cubeMovementStaticPaths.Length < 1) + return; + + var oldColor = _pathPaint.Color; + _pathPaint.Color = SKColors.Purple; + foreach (var cubeMovementStaticPath in cubeMovementStaticPaths) + { + var objectPath = cubeMovementStaticPath.AssetPathName.Text.SubstringBeforeLast("."); + var objectName = cubeMovementStaticPath.SubPathString.SubstringAfterLast("."); + if (!Utils.TryLoadObject($"{objectPath}.{objectName}", out UObject staticPath)) + continue; + + DrawCubeMovements(c, staticPath); + } + + if (Utils.TryLoadObject("/CorruptionGameplay/Levels/CubeMovement/Apollo_CM_Gold_Overlay.CM_Spline_Gold", out UObject goldPath)) + { + _pathPaint.Color = SKColors.Gold; + DrawCubeMovements(c, goldPath); + } + + _pathPaint.Color = oldColor; + _bitmaps[0]["ApolloGameplay_CubeMovements"] = new MapLayer {Layer = cubeMovementsBitmap, IsEnabled = false}; + }); + } + + private void DrawCubeMovements(SKCanvas c, UObject staticPath) + { + if (!staticPath.TryGetValue(out FStructFallback[] pathTravelers, "PathTravelers") || pathTravelers.Length < 1 || + !pathTravelers[0].TryGetValue(out FPackageIndex[] generatedSplinesArray, "GeneratedSplinesArray") || generatedSplinesArray.Length < 1 || + !pathTravelers[0].TryGetValue(out FStructFallback[] stepMetaData, "StepMetaData") || stepMetaData.Length < 1) + return; + + var bDone = false; + var path = new SKPath(); + for (var i = 0; i < generatedSplinesArray.Length; i++) + { + if (!stepMetaData[i].TryGetValue(out bool bSkipStep, "bSkipStep") || bSkipStep || + !Utils.TryGetPackageIndexExport(generatedSplinesArray[i], out UObject uObject) || + !uObject.TryGetValue(out FVector relativeLocation, "RelativeLocation")) continue; + + var vector = GetMapPosition(relativeLocation, _brRadius); + if (!bDone) + { + path.MoveTo(vector.X, vector.Y); + bDone = true; + } + else + { + path.LineTo(vector.X, vector.Y); + } + } + + c.DrawPath(path, _pathPaint); + } } } diff --git a/FModel/Views/MapViewer.xaml b/FModel/Views/MapViewer.xaml index 7c88543b..f7f9fd27 100644 --- a/FModel/Views/MapViewer.xaml +++ b/FModel/Views/MapViewer.xaml @@ -42,6 +42,8 @@ + From 619a7d018f11acb9b33a62d79e927b7d3ada192d Mon Sep 17 00:00:00 2001 From: GMatrixGames Date: Fri, 17 Sep 2021 10:48:27 -0400 Subject: [PATCH 56/58] Add another creative control option type. --- FModel/Creator/CreatorPackage.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/FModel/Creator/CreatorPackage.cs b/FModel/Creator/CreatorPackage.cs index cd4cb1df..0145853d 100644 --- a/FModel/Creator/CreatorPackage.cs +++ b/FModel/Creator/CreatorPackage.cs @@ -162,6 +162,7 @@ namespace FModel.Creator case "PlaylistUserOptionColorEnum": case "PlaylistUserOptionFloatEnum": case "PlaylistUserOptionFloatRange": + case "PlaylistUserTintedIconIntEnum": case "PlaylistUserOptionPrimaryAsset": case "PlaylistUserOptionCollisionProfileEnum": creator = new BaseUserControl(_object, _style); From 17a1b0b69bf86fd69437a9c4e522d11a65003451 Mon Sep 17 00:00:00 2001 From: iAmAsval Date: Sun, 19 Sep 2021 01:34:49 +0200 Subject: [PATCH 57/58] more precise cube movements --- FModel/ViewModels/MapViewerViewModel.cs | 51 +++++++++++++++++-------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/FModel/ViewModels/MapViewerViewModel.cs b/FModel/ViewModels/MapViewerViewModel.cs index cd945bed..0773e172 100644 --- a/FModel/ViewModels/MapViewerViewModel.cs +++ b/FModel/ViewModels/MapViewerViewModel.cs @@ -943,15 +943,15 @@ namespace FModel.ViewModels var objectPath = cubeMovementStaticPath.AssetPathName.Text.SubstringBeforeLast("."); var objectName = cubeMovementStaticPath.SubPathString.SubstringAfterLast("."); if (!Utils.TryLoadObject($"{objectPath}.{objectName}", out UObject staticPath)) - continue; - - DrawCubeMovements(c, staticPath); + return; + + DrawCubeMovements(c, staticPath, true); } if (Utils.TryLoadObject("/CorruptionGameplay/Levels/CubeMovement/Apollo_CM_Gold_Overlay.CM_Spline_Gold", out UObject goldPath)) { _pathPaint.Color = SKColors.Gold; - DrawCubeMovements(c, goldPath); + DrawCubeMovements(c, goldPath, false); } _pathPaint.Color = oldColor; @@ -959,30 +959,51 @@ namespace FModel.ViewModels }); } - private void DrawCubeMovements(SKCanvas c, UObject staticPath) + private void DrawCubeMovements(SKCanvas c, UObject staticPath, bool fixLocation) { if (!staticPath.TryGetValue(out FStructFallback[] pathTravelers, "PathTravelers") || pathTravelers.Length < 1 || !pathTravelers[0].TryGetValue(out FPackageIndex[] generatedSplinesArray, "GeneratedSplinesArray") || generatedSplinesArray.Length < 1 || !pathTravelers[0].TryGetValue(out FStructFallback[] stepMetaData, "StepMetaData") || stepMetaData.Length < 1) return; + UObject uObject; + var parentRelativeLocation = new FVector(); + if (fixLocation) + { + if (!pathTravelers[0].TryGetValue(out FPackageIndex pathTraveler, "PathTraveler") || + !Utils.TryGetPackageIndexExport(pathTraveler, out uObject) || + !uObject.TryGetValue(out FPackageIndex rootComponent, "RootComponent") || + !Utils.TryGetPackageIndexExport(rootComponent, out uObject) || + !uObject.TryGetValue(out parentRelativeLocation, "RelativeLocation")) + return; + } + var bDone = false; var path = new SKPath(); for (var i = 0; i < generatedSplinesArray.Length; i++) { if (!stepMetaData[i].TryGetValue(out bool bSkipStep, "bSkipStep") || bSkipStep || - !Utils.TryGetPackageIndexExport(generatedSplinesArray[i], out UObject uObject) || + !Utils.TryGetPackageIndexExport(generatedSplinesArray[i], out uObject) || !uObject.TryGetValue(out FVector relativeLocation, "RelativeLocation")) continue; - - var vector = GetMapPosition(relativeLocation, _brRadius); - if (!bDone) + + if (!uObject.TryGetValue(out FStructFallback splineCurves, "SplineCurves") || + !splineCurves.TryGetValue(out FStructFallback positions, "Position") || + !positions.TryGetValue(out FStructFallback[] positionPoints, "Points")) continue; + + for (var j = 0; j < positionPoints.Length; j++) { - path.MoveTo(vector.X, vector.Y); - bDone = true; - } - else - { - path.LineTo(vector.X, vector.Y); + if (!positionPoints[j].TryGetValue(out FVector position, "OutVal")) continue; + + var vector = GetMapPosition(parentRelativeLocation + relativeLocation + position, _brRadius); + if (!bDone) + { + path.MoveTo(vector.X, vector.Y); + bDone = true; + } + else + { + path.LineTo(vector.X, vector.Y); + } } } From f2f6fc01d2219b702965f63da792ed9a4a52bdeb Mon Sep 17 00:00:00 2001 From: iAmAsval Date: Sun, 19 Sep 2021 22:35:04 +0200 Subject: [PATCH 58/58] FModel v4.0.2 --- CUE4Parse | 2 +- FModel/ViewModels/MapViewerViewModel.cs | 22 ++++++++++------------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index 4736f823..6d911668 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 4736f8231f61631ffbc5afbd2b4a1281b8651be5 +Subproject commit 6d911668e730b3f4c1eab0b3f7e9a99bc3dde943 diff --git a/FModel/ViewModels/MapViewerViewModel.cs b/FModel/ViewModels/MapViewerViewModel.cs index 0773e172..301835fe 100644 --- a/FModel/ViewModels/MapViewerViewModel.cs +++ b/FModel/ViewModels/MapViewerViewModel.cs @@ -931,11 +931,11 @@ namespace FModel.ViewModels _fillPaint.StrokeWidth = 5; var cubeMovementsBitmap = new SKBitmap(_widthHeight, _widthHeight, SKColorType.Rgba8888, SKAlphaType.Premul); using var c = new SKCanvas(cubeMovementsBitmap); - + if (!Utils.TryLoadObject("/CorruptionGameplay/Levels/CorruptionGameplay_ApolloTerrain_Overlay.BP_CubeMovementGradient_2", out UObject overlay) || !overlay.TryGetValue(out FSoftObjectPath[] cubeMovementStaticPaths, "cubeMovementStaticPaths") || cubeMovementStaticPaths.Length < 1) return; - + var oldColor = _pathPaint.Color; _pathPaint.Color = SKColors.Purple; foreach (var cubeMovementStaticPath in cubeMovementStaticPaths) @@ -947,7 +947,7 @@ namespace FModel.ViewModels DrawCubeMovements(c, staticPath, true); } - + if (Utils.TryLoadObject("/CorruptionGameplay/Levels/CubeMovement/Apollo_CM_Gold_Overlay.CM_Spline_Gold", out UObject goldPath)) { _pathPaint.Color = SKColors.Gold; @@ -962,8 +962,7 @@ namespace FModel.ViewModels private void DrawCubeMovements(SKCanvas c, UObject staticPath, bool fixLocation) { if (!staticPath.TryGetValue(out FStructFallback[] pathTravelers, "PathTravelers") || pathTravelers.Length < 1 || - !pathTravelers[0].TryGetValue(out FPackageIndex[] generatedSplinesArray, "GeneratedSplinesArray") || generatedSplinesArray.Length < 1 || - !pathTravelers[0].TryGetValue(out FStructFallback[] stepMetaData, "StepMetaData") || stepMetaData.Length < 1) + !pathTravelers[0].TryGetValue(out FPackageIndex[] generatedSplinesArray, "GeneratedSplinesArray") || generatedSplinesArray.Length < 1) return; UObject uObject; @@ -980,21 +979,20 @@ namespace FModel.ViewModels var bDone = false; var path = new SKPath(); - for (var i = 0; i < generatedSplinesArray.Length; i++) + foreach (var generatedSpline in generatedSplinesArray) { - if (!stepMetaData[i].TryGetValue(out bool bSkipStep, "bSkipStep") || bSkipStep || - !Utils.TryGetPackageIndexExport(generatedSplinesArray[i], out uObject) || + if (!Utils.TryGetPackageIndexExport(generatedSpline, out uObject) || !uObject.TryGetValue(out FVector relativeLocation, "RelativeLocation")) continue; if (!uObject.TryGetValue(out FStructFallback splineCurves, "SplineCurves") || !splineCurves.TryGetValue(out FStructFallback positions, "Position") || !positions.TryGetValue(out FStructFallback[] positionPoints, "Points")) continue; - for (var j = 0; j < positionPoints.Length; j++) + foreach (var positionPoint in positionPoints) { - if (!positionPoints[j].TryGetValue(out FVector position, "OutVal")) continue; + if (!positionPoint.TryGetValue(out FVector point, "OutVal")) continue; - var vector = GetMapPosition(parentRelativeLocation + relativeLocation + position, _brRadius); + var vector = GetMapPosition(parentRelativeLocation + relativeLocation + point, _brRadius); if (!bDone) { path.MoveTo(vector.X, vector.Y); @@ -1006,7 +1004,7 @@ namespace FModel.ViewModels } } } - + c.DrawPath(path, _pathPaint); } }