mirror of
https://github.com/4sval/FModel.git
synced 2026-09-13 20:16:38 -05:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
3
.github/workflows/main.yml
vendored
3
.github/workflows/main.yml
vendored
@@ -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:
|
||||
|
||||
Submodule CUE4Parse updated: 36d50f3b25...4736f8231f
@@ -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";
|
||||
|
||||
@@ -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<T>(FPackageIndex packageIndex, out T export) where T : UObject
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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,18 @@ 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 _brCubeMovements;
|
||||
public bool BrCubeMovements
|
||||
{
|
||||
get => _brCubeMovements;
|
||||
set => SetProperty(ref _brCubeMovements, value, "ApolloGameplay_CubeMovements");
|
||||
}
|
||||
|
||||
private bool _prLandmarks;
|
||||
@@ -228,8 +234,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 +287,11 @@ namespace FModel.ViewModels
|
||||
case "ApolloGameplay_Fireflies":
|
||||
await LoadFireflies();
|
||||
break;
|
||||
case "ApolloGameplay_Inks":
|
||||
await LoadInks();
|
||||
case "ApolloGameplay_CorruptionZones":
|
||||
await LoadCorruptionZones();
|
||||
break;
|
||||
case "ApolloGameplay_CubeMovements":
|
||||
await LoadCubeMovements();
|
||||
break;
|
||||
case "PapayaGameplay_CannonballGame":
|
||||
await LoadCannonballGame();
|
||||
@@ -387,7 +402,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 +827,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 +861,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 +888,105 @@ 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};
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// FortniteGame/Plugins/GameFeatures/CorruptionGameplay/Content/CorruptionGameplay_LevelOverlay.uasset
|
||||
/// too lazy to filters
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,11 @@
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.MapViewer}}}" IsEnabled="{Binding IsReady}" />
|
||||
<CheckBox Content="Fireflies" Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" IsChecked="{Binding MapViewer.BrFireflies}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.MapViewer}}}" IsEnabled="{Binding IsReady}" />
|
||||
<!-- <CheckBox Content="Inks" Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" IsChecked="{Binding MapViewer.BrInks}" -->
|
||||
<!-- DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.MapViewer}}}" IsEnabled="{Binding IsReady}" /> -->
|
||||
<CheckBox Content="Corruption Zones" Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" IsChecked="{Binding MapViewer.BrCorruptionZones}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.MapViewer}}}" IsEnabled="{Binding IsReady}"
|
||||
ToolTip="Saving the image with Corruption Zones enabled will smooth these ugly sharp edges"/>
|
||||
<CheckBox Content="Cube Movements" Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" IsChecked="{Binding MapViewer.BrCubeMovements}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.MapViewer}}}" IsEnabled="{Binding IsReady}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="PrTemplate">
|
||||
|
||||
Reference in New Issue
Block a user