Merge branch '4sval:dev' into dev

This commit is contained in:
Chompster86 2026-01-24 18:29:08 -05:00 committed by GitHub
commit 6cbd18fbe8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 65 additions and 9 deletions

@ -1 +1 @@
Subproject commit af1207f8a099062e48255db4e5cf45ba3c21311d
Subproject commit 32ddcc61539cb8f82a92c8dc2d769ec34375aa37

View File

@ -10,7 +10,9 @@ using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using AdonisUI.Controls;
using CUE4Parse;
using CUE4Parse.Compression;
using CUE4Parse.Encryption.Aes;
@ -20,6 +22,7 @@ using CUE4Parse.FileProvider.Vfs;
using CUE4Parse.GameTypes.Aion2.Objects;
using CUE4Parse.GameTypes.AshEchoes.FileProvider;
using CUE4Parse.GameTypes.KRD.Assets.Exports;
using CUE4Parse.GameTypes.SMG.UE4.Assets.Exports.Wwise;
using CUE4Parse.MappingsProvider;
using CUE4Parse.UE4.AssetRegistry;
using CUE4Parse.UE4.Assets;
@ -50,11 +53,14 @@ using CUE4Parse.UE4.Shaders;
using CUE4Parse.UE4.Versions;
using CUE4Parse.UE4.Wwise;
using CUE4Parse.Utils;
using CUE4Parse_Conversion;
using CUE4Parse_Conversion.Sounds;
using EpicManifestParser;
using EpicManifestParser.UE;
using EpicManifestParser.ZlibngDotNetDecompressor;
using FModel.Creator;
using FModel.Extensions;
using FModel.Framework;
@ -63,14 +69,21 @@ using FModel.Settings;
using FModel.Views;
using FModel.Views.Resources.Controls;
using FModel.Views.Snooper;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.Desktop;
using Serilog;
using SkiaSharp;
using Svg.Skia;
using UE4Config.Parsing;
using Application = System.Windows.Application;
using FGuid = CUE4Parse.UE4.Objects.Core.Misc.FGuid;
@ -296,7 +309,7 @@ public class CUE4ParseViewModel : ViewModel
}
Provider.Initialize();
_wwiseProviderLazy = new Lazy<WwiseProvider>(() => new WwiseProvider(Provider, UserSettings.Default.WwiseMaxBnkPrefetch));
_wwiseProviderLazy = new Lazy<WwiseProvider>(() => new WwiseProvider(Provider, UserSettings.Default.GameDirectory, UserSettings.Default.WwiseMaxBnkPrefetch));
_fmodProviderLazy = new Lazy<FModProvider>(() => new FModProvider(Provider, UserSettings.Default.GameDirectory));
_criWareProviderLazy = new Lazy<CriWareProvider>(() => new CriWareProvider(Provider, UserSettings.Default.GameDirectory));
Log.Information($"{Provider.Versions.Game} ({Provider.Versions.Platform}) | Archives: x{Provider.UnloadedVfs.Count} | AES: x{Provider.RequiredKeys.Count} | Loose Files: x{Provider.Files.Count}");
@ -1061,6 +1074,13 @@ public class CUE4ParseViewModel : ViewModel
TabControl.SelectedTab.AddImage(sourceFile.SubstringAfterLast('/'), false, bitmap, false, updateUi);
return false;
}
// The Dark Pictures Anthology: House of Ashes
case UExternalSource when (isNone || saveAudio) && pointer.Object.Value is UExternalSource externalSource:
{
var audioName = Path.GetFileNameWithoutExtension(externalSource.ExternalSourcePath);
SaveAndPlaySound(audioName, "wem", externalSource.Data?.WemFile ?? [], saveAudio);
return false;
}
case UAkAudioEvent when (isNone || saveAudio) && pointer.Object.Value is UAkAudioEvent audioEvent:
{
var extractedSounds = WwiseProvider.ExtractAudioEventSounds(audioEvent);

View File

@ -5,8 +5,10 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using CUE4Parse.FileProvider.Objects;
using CUE4Parse.GameTypes.FN.Assets.Exports.DataAssets;
using CUE4Parse.GameTypes.SMG.UE4.Assets.Exports.Wwise;
using CUE4Parse.UE4.Assets;
using CUE4Parse.UE4.Assets.Exports.Animation;
using CUE4Parse.UE4.Assets.Exports.BuildData;
@ -37,12 +39,17 @@ using CUE4Parse.UE4.Objects.RigVM;
using CUE4Parse.UE4.Objects.UObject;
using CUE4Parse.UE4.Objects.UObject.Editor;
using CUE4Parse.Utils;
using CUE4Parse_Conversion.Textures;
using FModel.Framework;
using FModel.Services;
using FModel.Settings;
using Serilog;
using SkiaSharp;
using Svg.Skia;
namespace FModel.ViewModels;
@ -200,7 +207,8 @@ public class GameFileViewModel(GameFile asset) : ViewModel
UCurveBase => EAssetCategory.CurveBase,
UWwiseAssetLibrary or USoundBase or UAkMediaAssetData or UAtomWaveBank or USoundAtomCue
or UAtomCueSheet or USoundAtomCueSheet or UFMODBank or UFMODEvent or UAkAudioType => EAssetCategory.Audio,
or UAtomCueSheet or USoundAtomCueSheet or UFMODBank or UFMODEvent or UAkAudioType
or UExternalSource or UExternalSourceBank => EAssetCategory.Audio,
UFileMediaSource => EAssetCategory.Video,
UFont or UFontFace => EAssetCategory.Font,

View File

@ -87,8 +87,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_7);
yield return DirectorySettings.Default("Fortnite [LIVE]", Constants._FN_LIVE_TRIGGER, ue: EGame.GAME_UE5_7);
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("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);

View File

@ -157,9 +157,10 @@
<MenuItem.IsEnabled>
<Binding Path="PlacementTarget.SelectedItems" RelativeSource="{RelativeSource AncestorType=ContextMenu}">
<Binding.Converter>
<converters:AnyItemMeetsConditionConverter>
<converters:AnyItemMeetsConditionConverter ConditionMode="Or">
<converters:AnyItemMeetsConditionConverter.Conditions>
<converters:ItemCategoryCondition Category="Texture" />
<converters:ItemCategoryCondition Category="ItemDefinitionBase" />
</converters:AnyItemMeetsConditionConverter.Conditions>
</converters:AnyItemMeetsConditionConverter>
</Binding.Converter>

View File

@ -14,18 +14,36 @@ public class AnyItemMeetsConditionConverter : IValueConverter
{
public Collection<IItemCondition> Conditions { get; } = [];
/// <summary>
/// Determines how multiple conditions are evaluated. Default is 'And'.
/// </summary>
public EConditionMode ConditionMode { get; set; } = EConditionMode.And;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is not IEnumerable items || Conditions.Count == 0)
return false;
return items.OfType<GameFileViewModel>().Any(item => Conditions.All(c => c.Matches(item)));
Func<GameFileViewModel, bool> predicate = ConditionMode switch
{
EConditionMode.And => item => Conditions.All(condition => condition.Matches(item)),
EConditionMode.Or => item => Conditions.Any(condition => condition.Matches(item)),
_ => throw new ArgumentOutOfRangeException()
};
return items.OfType<GameFileViewModel>().Any(predicate);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public enum EConditionMode
{
And,
Or
}
}
public interface IItemCondition
@ -39,7 +57,16 @@ public class ItemCategoryCondition : IItemCondition
public bool Matches(GameFileViewModel item)
{
return item != null && item.AssetCategory.IsOfCategory(Category);
if (item == null) return false;
// if the specified category is a base category, check if the item's category is derived from it
if (Category.IsBaseCategory())
{
return item.AssetCategory.IsOfCategory(Category);
}
// if the specified category is a targeted non-base category, check for exact match
return item.AssetCategory == Category;
}
}

View File

@ -598,7 +598,7 @@ public class Renderer : IDisposable
if (bSpline && model is SplineModel splineModel)
splineModel.AddComponent((USplineMeshComponent)staticMeshComp);
}
else if (m.TryConvert(out var mesh))
else if (m.TryConvert(out var mesh, UserSettings.Default.NaniteMeshExportFormat))
{
model = bSpline ? new SplineModel(m, mesh, (USplineMeshComponent)staticMeshComp, transform) : new StaticModel(m, mesh, transform);
model.IsTwoSided = actor.GetOrDefault("bMirrored", staticMeshComp.GetOrDefault("bDisallowMeshPaintPerInstance", model.IsTwoSided));