mirror of
https://github.com/4sval/FModel.git
synced 2026-09-25 10:39:14 -05:00
UE6 / The Finals / Rogue Company fixes + UGeometryCollection preview/export + UEFormat v10
Co-authored-by: Asval <asval.contactme@gmail.com>
This commit is contained in:
Submodule CUE4Parse updated: c99a1d6dfc...83200c61e6
@@ -32,6 +32,7 @@ public class BaseIcon : UCreator
|
||||
// rarity
|
||||
if (Object.TryGetValue(out FPackageIndex series, "Series")) GetSeries(series);
|
||||
else if (Object.TryGetValue(out FStructFallback componentContainer, "ComponentContainer")) GetSeries(componentContainer);
|
||||
else if (Object.TryGetValue(out EFortRarity hackRarity, "HackRarity")) GetRarity(hackRarity);
|
||||
else GetRarity(Object.GetOrDefault("Rarity", EFortRarity.Uncommon)); // default is uncommon
|
||||
|
||||
if (Object.TryGetValue(out FInstancedStruct[] dataList, "DataList"))
|
||||
@@ -48,7 +49,7 @@ public class BaseIcon : UCreator
|
||||
Preview = preview;
|
||||
else if (Object.TryGetValue(out FPackageIndex itemDefinition, "HeroDefinition", "WeaponDefinition"))
|
||||
Preview = Utils.GetBitmap(itemDefinition);
|
||||
else if (Object.TryGetValue(out FSoftObjectPath largePreview, "LargePreviewImage", "EntryListIcon", "SmallPreviewImage", "BundleImage", "ItemDisplayAsset", "LargeIcon", "ToastIcon", "SmallIcon"))
|
||||
else if (Object.TryGetValue(out FSoftObjectPath largePreview, "LargePreviewImage", "EntryListIcon", "SmallPreviewImage", "BundleImage", "ItemDisplayAsset", "LargeIcon", "ToastIcon", "SmallIcon", "CartridgeIcon", "EffectIcon"))
|
||||
Preview = Utils.GetBitmap(largePreview);
|
||||
else if (Object.TryGetValue(out string s, "LargePreviewImage") && !string.IsNullOrEmpty(s))
|
||||
Preview = Utils.GetBitmap(s);
|
||||
@@ -66,9 +67,9 @@ public class BaseIcon : UCreator
|
||||
}
|
||||
|
||||
// text
|
||||
if (Object.TryGetValue(out FText displayName, "DisplayName", "ItemName", "BundleName", "DefaultHeaderText", "UIDisplayName", "EntryName", "EventCalloutTitle"))
|
||||
if (Object.TryGetValue(out FText displayName, "DisplayName", "ItemName", "BundleName", "DefaultHeaderText", "UIDisplayName", "EntryName", "EventCalloutTitle", "KeyName", "HackDisplayName"))
|
||||
DisplayName = displayName.Text;
|
||||
if (Object.TryGetValue(out FText description, "Description", "ItemDescription", "SetDescription", "BundleDescription", "GeneralDescription", "DefaultBodyText", "UIDescription", "UIDisplayDescription", "EntryDescription", "EventCalloutDescription"))
|
||||
if (Object.TryGetValue(out FText description, "Description", "ItemDescription", "SetDescription", "BundleDescription", "GeneralDescription", "DefaultBodyText", "UIDescription", "UIDisplayDescription", "EntryDescription", "EventCalloutDescription", "KeyDescription", "HackDescription"))
|
||||
Description = description.Text;
|
||||
else if (Object.TryGetValue(out FText[] descriptions, "Description"))
|
||||
Description = string.Join('\n', descriptions.Select(x => x.Text));
|
||||
|
||||
@@ -65,6 +65,7 @@ public class CreatorPackage : IDisposable
|
||||
case "AthenaEmojiItemDefinition":
|
||||
case "AthenaItemWrapDefinition":
|
||||
case "AthenaToyItemDefinition":
|
||||
case "FortHackData":
|
||||
case "FortHeroType":
|
||||
case "FortTokenType":
|
||||
case "FortAbilityKit":
|
||||
@@ -72,7 +73,9 @@ public class CreatorPackage : IDisposable
|
||||
case "FortMissionInfo":
|
||||
case "RewardGraphToken":
|
||||
case "JunoKnowledgeBundle":
|
||||
case "FortHackDataMinimal":
|
||||
case "FortBannerTokenType":
|
||||
case "FortHackKeyCoreData":
|
||||
case "FortVariantTokenType":
|
||||
case "FortDecoItemDefinition":
|
||||
case "FortStatItemDefinition":
|
||||
@@ -88,6 +91,7 @@ public class CreatorPackage : IDisposable
|
||||
case "SparksBassItemDefinition":
|
||||
case "FortGadgetItemDefinition":
|
||||
case "AthenaCharmItemDefinition":
|
||||
case "FortHackKeyItemDefinition":
|
||||
case "FortPlaysetItemDefinition":
|
||||
case "FortGiftBoxItemDefinition":
|
||||
case "FortOutpostItemDefinition":
|
||||
@@ -124,6 +128,7 @@ public class CreatorPackage : IDisposable
|
||||
case "JunoRecipeBundleItemDefinition":
|
||||
case "FortHomebaseNodeItemDefinition":
|
||||
case "FortNeverPersistItemDefinition":
|
||||
case "FortHackCartridgeItemDefinition":
|
||||
case "FortPlayerAugmentItemDefinition":
|
||||
case "FortSmartBuildingItemDefinition":
|
||||
case "FortGiftBoxUnlockItemDefinition":
|
||||
|
||||
@@ -69,6 +69,7 @@ using CUE4Parse.UE4.Wwise;
|
||||
using CUE4Parse.Utils;
|
||||
using CUE4Parse_Conversion.Exporters;
|
||||
using CUE4Parse_Conversion.Sounds;
|
||||
using CUE4Parse.UE4.Assets.Exports.GeometryCollection;
|
||||
using EpicManifestParser;
|
||||
using EpicManifestParser.UE;
|
||||
using FModel.Creator;
|
||||
@@ -1561,6 +1562,7 @@ public class CUE4ParseViewModel : ViewModel
|
||||
// }:
|
||||
case UPaperSprite when isNone && UserSettings.Default.PreviewMaterials:
|
||||
case UStaticMesh when isNone && UserSettings.Default.PreviewStaticMeshes:
|
||||
case UGeometryCollection when isNone && UserSettings.Default.PreviewStaticMeshes:
|
||||
case USkeletalMesh when isNone && UserSettings.Default.PreviewSkeletalMeshes:
|
||||
case USkeleton when isNone && UserSettings.Default.SaveSkeletonAsMesh:
|
||||
case UMaterialInstance when isNone && UserSettings.Default.PreviewMaterials && !ModelIsOverwritingMaterial &&
|
||||
@@ -1587,6 +1589,7 @@ public class CUE4ParseViewModel : ViewModel
|
||||
return true;
|
||||
}
|
||||
case UStaticMesh when HasFlag(bulk, EBulkType.Meshes):
|
||||
case UGeometryCollection when HasFlag(bulk, EBulkType.Meshes):
|
||||
case USkeletalMesh when HasFlag(bulk, EBulkType.Meshes):
|
||||
case USkeleton when UserSettings.Default.SaveSkeletonAsMesh && HasFlag(bulk, EBulkType.Meshes):
|
||||
// case UMaterialInterface when HasFlag(bulk, EBulkType.Materials):
|
||||
|
||||
@@ -219,7 +219,7 @@ public class GameFileViewModel(GameFile asset) : ViewModel
|
||||
USkeletalMesh => (EAssetCategory.SkeletalMesh, EBulkType.Meshes),
|
||||
UCustomizableObject => (EAssetCategory.CustomizableObject, EBulkType.None),
|
||||
UNaniteDisplacedMesh => (EAssetCategory.NaniteDisplacedMesh, EBulkType.None),
|
||||
UGeometryCollection => (EAssetCategory.GeometryCollection, EBulkType.None),
|
||||
UGeometryCollection => (EAssetCategory.GeometryCollection, EBulkType.Meshes),
|
||||
|
||||
UTexture => (EAssetCategory.Texture, EBulkType.Textures),
|
||||
|
||||
|
||||
@@ -196,8 +196,8 @@ public class GameSelectorViewModel : ViewModel
|
||||
.OrderBy(value => ((int)value & 0xFF) == 0);
|
||||
private IEnumerable<DirectorySettings> EnumerateDetectedGames()
|
||||
{
|
||||
yield return GetUnrealEngineGame("Fortnite", "\\FortniteGame\\Content\\Paks", EGame.GAME_UE5_8);
|
||||
yield return DirectorySettings.Default("Fortnite [LIVE]", Constants._FN_LIVE_TRIGGER, ue: EGame.GAME_UE5_8);
|
||||
yield return GetUnrealEngineGame("Fortnite", "\\FortniteGame\\Content\\Paks", EGame.GAME_UE6_0);
|
||||
yield return DirectorySettings.Default("Fortnite [LIVE]", Constants._FN_LIVE_TRIGGER, ue: EGame.GAME_UE6_0);
|
||||
yield return GetUnrealEngineGame("Pewee", "\\RogueCompany\\Content\\Paks", EGame.GAME_RogueCompany);
|
||||
yield return GetUnrealEngineGame("Rosemallow", "\\Indiana\\Content\\Paks", EGame.GAME_UE4_21);
|
||||
yield return GetUnrealEngineGame("Catnip", "\\OakGame\\Content\\Paks", EGame.GAME_Borderlands3);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using CUE4Parse_Conversion.Dto;
|
||||
using CUE4Parse.UE4.Assets.Exports.GeometryCollection;
|
||||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
using CUE4Parse.UE4.Assets.Exports.StaticMesh;
|
||||
using CUE4Parse.UE4.Assets.Exports.Texture;
|
||||
@@ -143,6 +144,12 @@ public class StaticModel : UModel<MeshVertex>
|
||||
}
|
||||
}
|
||||
|
||||
public StaticModel(UGeometryCollection export, StaticMeshDto staticMesh, Transform transform = null)
|
||||
: base(export, staticMesh.LODs[LodLevel], export.Materials, staticMesh.LODs[LodLevel].Vertices, staticMesh.LODs.Count, transform)
|
||||
{
|
||||
Box = staticMesh.Bounds * Constants.SCALE_DOWN_RATIO;
|
||||
}
|
||||
|
||||
public override void RenderCollision(Shader shader)
|
||||
{
|
||||
base.RenderCollision(shader);
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Numerics;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using CUE4Parse_Conversion.Animations;
|
||||
using CUE4Parse_Conversion.Dto;
|
||||
using CUE4Parse_Conversion.Meshes;
|
||||
using CUE4Parse_Conversion.Options;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
@@ -29,6 +30,7 @@ using FModel.Views.Snooper.Lights;
|
||||
using FModel.Views.Snooper.Models;
|
||||
using FModel.Views.Snooper.Shading;
|
||||
using OpenTK.Windowing.GraphicsLibraryFramework;
|
||||
using Serilog;
|
||||
|
||||
namespace FModel.Views.Snooper;
|
||||
|
||||
@@ -88,6 +90,9 @@ public class Renderer : IDisposable
|
||||
case UStaticMesh when export.Value is UStaticMesh st:
|
||||
LoadStaticMesh(st, UserSettings.Default.NaniteMeshExportFormat);
|
||||
break;
|
||||
case UGeometryCollection when export.Value is UGeometryCollection gc:
|
||||
LoadStaticMesh(gc, UserSettings.Default.NaniteMeshExportFormat);
|
||||
break;
|
||||
case USkeletalMesh when export.Value is USkeletalMesh sk:
|
||||
LoadSkeletalMesh(sk);
|
||||
break;
|
||||
@@ -132,7 +137,7 @@ public class Renderer : IDisposable
|
||||
{
|
||||
// do nothing, selected model has the correct skeleton for this animation
|
||||
}
|
||||
else */if (animBase.Skeleton.TryLoad(out USkeleton skeleton))
|
||||
else */if (animBase.Skeleton?.TryLoad(out USkeleton skeleton) == true)
|
||||
{
|
||||
LoadSkeleton(skeleton);
|
||||
}
|
||||
@@ -144,7 +149,7 @@ public class Renderer : IDisposable
|
||||
}
|
||||
private void Animate(UObject anim, FGuid guid)
|
||||
{
|
||||
if (anim is not UAnimSequenceBase animBase || !animBase.Skeleton.TryLoad(out USkeleton skeleton) ||
|
||||
if (anim is not UAnimSequenceBase animBase || animBase.Skeleton == null || !animBase.Skeleton.TryLoad(out USkeleton skeleton) ||
|
||||
!Options.TryGetModel(guid, out var m) || m is not SkeletalModel model)
|
||||
return;
|
||||
|
||||
@@ -361,6 +366,31 @@ public class Renderer : IDisposable
|
||||
Options.SelectModel(guid);
|
||||
}
|
||||
|
||||
private void LoadStaticMesh(UGeometryCollection original, ENaniteMeshFormat naniteFormat = ENaniteMeshFormat.NoNanite)
|
||||
{
|
||||
var guid = new FGuid((uint) original.GetFullName().GetHashCode());
|
||||
if (Options.TryGetModel(guid, out var model))
|
||||
{
|
||||
model.AddInstance(Transform.Identity);
|
||||
Application.Current.Dispatcher.Invoke(() => model.SetupInstances());
|
||||
return;
|
||||
}
|
||||
|
||||
StaticMeshDto mesh;
|
||||
try
|
||||
{
|
||||
mesh = new StaticMeshDto(original, naniteFormat);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, "Failed to convert geometry collection");
|
||||
return;
|
||||
}
|
||||
|
||||
Options.Models[guid] = new StaticModel(original, mesh);
|
||||
Options.SelectModel(guid);
|
||||
}
|
||||
|
||||
private void LoadSkeletalMesh(USkeletalMesh original)
|
||||
{
|
||||
var guid = new FGuid((uint) original.GetFullName().GetHashCode());
|
||||
|
||||
Reference in New Issue
Block a user