diff --git a/FModel/Creator/Bases/BaseGCosmetic.cs b/FModel/Creator/Bases/BaseGCosmetic.cs new file mode 100644 index 00000000..18b4a211 --- /dev/null +++ b/FModel/Creator/Bases/BaseGCosmetic.cs @@ -0,0 +1,71 @@ +using FModel.Creator.Rarities; +using FModel.Creator.Texts; +using PakReader.Parsers.Class; +using PakReader.Parsers.PropertyTagData; +using SkiaSharp; +using System; +using System.Windows; + +namespace FModel.Creator.Bases +{ + public class BaseGCosmetic : IBase + { + public SKBitmap FallbackImage; + public SKBitmap IconImage; + public SKColor[] RarityBackgroundColors; + public SKColor[] RarityBorderColor; + public string DisplayName; + public string Description; + public int Width = 512; // keep it 512 (or a multiple of 512) if you don't want blurry icons + public int Height = 512; + public int Margin = 2; + + public BaseGCosmetic(string exportType) + { + FallbackImage = SKBitmap.Decode(Application.GetResourceStream(new Uri("pack://application:,,,/Resources/T_Placeholder_Item_Image.png")).Stream); + IconImage = FallbackImage; + RarityBackgroundColors = new SKColor[2] { SKColor.Parse("FFFFFF"), SKColor.Parse("636363") }; + RarityBorderColor = new SKColor[2] { SKColor.Parse("D0D0D0"), SKColor.Parse("FFFFFF") }; + DisplayName = ""; + Description = ""; + Width = exportType switch + { + "GCosmeticCard" => 1024, + _ => 512 + }; + Height = exportType switch + { + "GCosmeticCard" => 200, + _ => 512 + }; + } + + public BaseGCosmetic(IUExport export, string exportType) : this(exportType) + { + // rarity + Rarity.GetInGameRarity(this, export.GetExport("Rarity")); + + // image + if (export.GetExport("IconTexture") is SoftObjectProperty previewImage) + this.IconImage = Utils.GetSoftObjectTexture(previewImage); + else if (export.GetExport("IconTexture") is ObjectProperty iconTexture) + this.IconImage = Utils.GetObjectTexture(iconTexture); + + // text + if (export.GetExport("DisplayName", "Title") is TextProperty displayName) + DisplayName = Text.GetTextPropertyBase(displayName); + if (export.GetExport("Description") is TextProperty description) + Description = Text.GetTextPropertyBase(description); + } + + SKBitmap IBase.FallbackImage => FallbackImage; + SKBitmap IBase.IconImage => IconImage; + SKColor[] IBase.RarityBackgroundColors => RarityBackgroundColors; + SKColor[] IBase.RarityBorderColor => RarityBorderColor; + string IBase.DisplayName => DisplayName; + string IBase.Description => Description; + int IBase.Width => Width; + int IBase.Height => Height; + int IBase.Margin => Margin; + } +} diff --git a/FModel/Creator/Bases/BaseIcon.cs b/FModel/Creator/Bases/BaseIcon.cs index f5b62c5f..b5d620cd 100644 --- a/FModel/Creator/Bases/BaseIcon.cs +++ b/FModel/Creator/Bases/BaseIcon.cs @@ -12,7 +12,7 @@ using System.Windows; namespace FModel.Creator.Bases { - public class BaseIcon + public class BaseIcon : IBase { public SKBitmap FallbackImage; public SKBitmap IconImage; @@ -126,5 +126,15 @@ namespace FModel.Creator.Bases AdditionalSize = 48 * Stats.Count; } + + SKBitmap IBase.FallbackImage => FallbackImage; + SKBitmap IBase.IconImage => IconImage; + SKColor[] IBase.RarityBackgroundColors => RarityBackgroundColors; + SKColor[] IBase.RarityBorderColor => RarityBorderColor; + string IBase.DisplayName => DisplayName; + string IBase.Description => Description; + int IBase.Width => Size; + int IBase.Height => Size + AdditionalSize; + int IBase.Margin => Margin; } } diff --git a/FModel/Creator/Bases/IBase.cs b/FModel/Creator/Bases/IBase.cs new file mode 100644 index 00000000..367d6faf --- /dev/null +++ b/FModel/Creator/Bases/IBase.cs @@ -0,0 +1,17 @@ +using SkiaSharp; + +namespace FModel.Creator.Bases +{ + interface IBase + { + SKBitmap FallbackImage { get; } + SKBitmap IconImage { get; } + SKColor[] RarityBackgroundColors { get; } + SKColor[] RarityBorderColor { get; } + string DisplayName { get; } + string Description { get; } + int Width { get; } + int Height { get; } + int Margin { get; } + } +} diff --git a/FModel/Creator/Creator.cs b/FModel/Creator/Creator.cs index 8a3c7e97..e80c1b79 100644 --- a/FModel/Creator/Creator.cs +++ b/FModel/Creator/Creator.cs @@ -25,7 +25,7 @@ namespace FModel.Creator string assetFolder = d.Parent.Name; if (Text.TypeFaces.NeedReload(false)) Text.TypeFaces = new Typefaces(); // when opening bundle creator settings without loading paks first - int index = Globals.Game.ActualGame == EGame.Valorant ? 1 : 0; + int index = Globals.Game.ActualGame == EGame.Valorant || Globals.Game.ActualGame == EGame.Spellbreak ? 1 : 0; string exportType = exportTypes.Length > index ? exportTypes[index].String : string.Empty; switch (exportType) { @@ -290,6 +290,43 @@ namespace FModel.Creator // } // return false; // } + case "GAccolade": + case "GCosmeticSkin": + case "GCosmeticCard": + case "GCosmeticTitle": + case "GCosmeticBadge": + case "GCosmeticEmote": + case "GCosmeticTriumph": + case "GCosmeticRunTrail": + case "GCosmeticArtifact": + case "GCosmeticDropTrail": + { + BaseGCosmetic icon = new BaseGCosmetic(exports[index], exportType); + using (var ret = new SKBitmap(icon.Width, icon.Height, SKColorType.Rgba8888, SKAlphaType.Premul)) + using (var c = new SKCanvas(ret)) + { + if ((EIconDesign)Properties.Settings.Default.AssetsIconDesign != EIconDesign.NoBackground) + { + Rarity.DrawRarity(c, icon); + } + + LargeSmallImage.DrawPreviewImage(c, icon); + + if ((EIconDesign)Properties.Settings.Default.AssetsIconDesign != EIconDesign.NoBackground) + { + if ((EIconDesign)Properties.Settings.Default.AssetsIconDesign != EIconDesign.NoText) + { + Text.DrawBackground(c, icon); + Text.DrawDisplayName(c, icon); + Text.DrawDescription(c, icon); + } + } + + Watermark.DrawWatermark(c); // watermark should only be applied on icons with width = 512 + ImageBoxVm.imageBoxViewModel.Set(ret, assetName); + } + return true; + } } return false; } diff --git a/FModel/Creator/Icons/LargeSmallImage.cs b/FModel/Creator/Icons/LargeSmallImage.cs index c46df618..79feee8d 100644 --- a/FModel/Creator/Icons/LargeSmallImage.cs +++ b/FModel/Creator/Icons/LargeSmallImage.cs @@ -54,8 +54,8 @@ namespace FModel.Creator.Icons return false; } - public static void DrawPreviewImage(SKCanvas c, BaseIcon icon) => - c.DrawBitmap(icon.IconImage ?? icon.FallbackImage, new SKRect(icon.Margin, icon.Margin, icon.Size - icon.Margin, icon.Size - icon.Margin), + public static void DrawPreviewImage(SKCanvas c, IBase icon) => + c.DrawBitmap(icon.IconImage ?? icon.FallbackImage, new SKRect(icon.Margin, icon.Margin, icon.Width - icon.Margin, icon.Height - icon.Margin), new SKPaint { FilterQuality = SKFilterQuality.High, IsAntialias = true }); } } diff --git a/FModel/Creator/Rarities/Rarity.cs b/FModel/Creator/Rarities/Rarity.cs index 1af83fa2..540725c2 100644 --- a/FModel/Creator/Rarities/Rarity.cs +++ b/FModel/Creator/Rarities/Rarity.cs @@ -66,6 +66,27 @@ namespace FModel.Creator.Rarities else GetHardCodedRarity(icon, e); } + public static void GetInGameRarity(BaseGCosmetic icon, EnumProperty e) + { + PakPackage p = Utils.GetPropertyPakPackage("/Game/UI/UIKit/DT_RarityColors"); + if (p.HasExport() && !p.Equals(default)) + { + var d = p.GetExport(); + if (d != null) + { + if (e != null && d.TryGetValue(e?.Value.String["EXRarity::".Length..], out object r) && r is UObject rarity && + rarity.GetExport("Colors") is ArrayProperty colors && + colors.Value[0] is StructProperty s1 && s1.Value is FLinearColor color1 && + colors.Value[1] is StructProperty s2 && s2.Value is FLinearColor color2 && + colors.Value[2] is StructProperty s3 && s3.Value is FLinearColor color3) + { + icon.RarityBackgroundColors = new SKColor[2] { SKColor.Parse(color1.Hex), SKColor.Parse(color3.Hex) }; + icon.RarityBorderColor = new SKColor[2] { SKColor.Parse(color2.Hex), SKColor.Parse(color1.Hex) }; + } + } + } + } + public static void GetHardCodedRarity(BaseIcon icon, EnumProperty e) { switch (e?.Value.String) @@ -103,17 +124,17 @@ namespace FModel.Creator.Rarities } } - public static void DrawRarity(SKCanvas c, BaseIcon icon) + public static void DrawRarity(SKCanvas c, IBase icon) { // border - c.DrawRect(new SKRect(0, 0, icon.Size, icon.Size), + c.DrawRect(new SKRect(0, 0, icon.Width, icon.Height), new SKPaint { IsAntialias = true, FilterQuality = SKFilterQuality.High, Shader = SKShader.CreateLinearGradient( - new SKPoint(icon.Size / 2, icon.Size), - new SKPoint(icon.Size, icon.Size / 4), + new SKPoint(icon.Width / 2, icon.Height), + new SKPoint(icon.Width, icon.Height / 4), icon.RarityBorderColor, SKShaderTileMode.Clamp) }); @@ -122,12 +143,12 @@ namespace FModel.Creator.Rarities { case EIconDesign.Flat: { - if (icon.RarityBackgroundImage != null) - c.DrawBitmap(icon.RarityBackgroundImage, new SKRect(icon.Margin, icon.Margin, icon.Size - icon.Margin, icon.Size - icon.Margin), + if (icon is BaseIcon i && i.RarityBackgroundImage != null) + c.DrawBitmap(i.RarityBackgroundImage, new SKRect(icon.Margin, icon.Margin, icon.Width - icon.Margin, icon.Height - icon.Margin), new SKPaint { FilterQuality = SKFilterQuality.High, IsAntialias = true }); else { - c.DrawRect(new SKRect(icon.Margin, icon.Margin, icon.Size - icon.Margin, icon.Size - icon.Margin), + c.DrawRect(new SKRect(icon.Margin, icon.Margin, icon.Width - icon.Margin, icon.Height - icon.Margin), new SKPaint { IsAntialias = true, @@ -143,16 +164,16 @@ namespace FModel.Creator.Rarities }; var pathTop = new SKPath { FillType = SKPathFillType.EvenOdd }; pathTop.MoveTo(icon.Margin, icon.Margin); - pathTop.LineTo(icon.Margin + (icon.Size / 17 * 10), icon.Margin); - pathTop.LineTo(icon.Margin, icon.Margin + (icon.Size / 17)); + pathTop.LineTo(icon.Margin + (icon.Width / 17 * 10), icon.Margin); + pathTop.LineTo(icon.Margin, icon.Margin + (icon.Height / 17)); pathTop.Close(); c.DrawPath(pathTop, paint); var pathBottom = new SKPath { FillType = SKPathFillType.EvenOdd }; - pathBottom.MoveTo(icon.Margin, icon.Size - icon.Margin); - pathBottom.LineTo(icon.Margin, icon.Size - icon.Margin - (icon.Size / 17 * 2.5f)); - pathBottom.LineTo(icon.Size - icon.Margin, icon.Size - icon.Margin - (icon.Size / 17 * 4.5f)); - pathBottom.LineTo(icon.Size - icon.Margin, icon.Size - icon.Margin); + pathBottom.MoveTo(icon.Margin, icon.Height - icon.Margin); + pathBottom.LineTo(icon.Margin, icon.Height - icon.Margin - (icon.Height / 17 * 2.5f)); + pathBottom.LineTo(icon.Width - icon.Margin, icon.Height - icon.Margin - (icon.Height / 17 * 4.5f)); + pathBottom.LineTo(icon.Width - icon.Margin, icon.Height - icon.Margin); pathBottom.Close(); c.DrawPath(pathBottom, paint); } @@ -160,18 +181,18 @@ namespace FModel.Creator.Rarities } default: { - if (icon.RarityBackgroundImage != null) - c.DrawBitmap(icon.RarityBackgroundImage, new SKRect(icon.Margin, icon.Margin, icon.Size - icon.Margin, icon.Size - icon.Margin), + if (icon is BaseIcon i && i.RarityBackgroundImage != null) + c.DrawBitmap(i.RarityBackgroundImage, new SKRect(icon.Margin, icon.Margin, icon.Width - icon.Margin, icon.Height - icon.Margin), new SKPaint { FilterQuality = SKFilterQuality.High, IsAntialias = true }); else - c.DrawRect(new SKRect(icon.Margin, icon.Margin, icon.Size - icon.Margin, icon.Size - icon.Margin), + c.DrawRect(new SKRect(icon.Margin, icon.Margin, icon.Width - icon.Margin, icon.Height - icon.Margin), new SKPaint { IsAntialias = true, FilterQuality = SKFilterQuality.High, Shader = SKShader.CreateRadialGradient( - new SKPoint(icon.Size / 2, icon.Size / 2), - icon.Size / 5 * 4, + new SKPoint(icon.Width / 2, icon.Height / 2), + icon.Width / 5 * 4, icon.RarityBackgroundColors, SKShaderTileMode.Clamp) }); diff --git a/FModel/Creator/Texts/Helper.cs b/FModel/Creator/Texts/Helper.cs index aeabd6d5..cf3da354 100644 --- a/FModel/Creator/Texts/Helper.cs +++ b/FModel/Creator/Texts/Helper.cs @@ -14,8 +14,8 @@ namespace FModel.Creator.Texts public float Width { get; set; } } - public static void DrawCenteredMultilineText(SKCanvas canvas, string text, int maxLineCount, BaseIcon icon, ETextSide side, SKRect area, SKPaint paint) - => DrawCenteredMultilineText(canvas, text, maxLineCount, icon.Size, icon.Margin, side, area, paint); + public static void DrawCenteredMultilineText(SKCanvas canvas, string text, int maxLineCount, IBase icon, ETextSide side, SKRect area, SKPaint paint) + => DrawCenteredMultilineText(canvas, text, maxLineCount, icon.Width, icon.Margin, side, area, paint); public static void DrawCenteredMultilineText(SKCanvas canvas, string text, int maxLineCount, int size, int margin, ETextSide side, SKRect area, SKPaint paint) { float lineHeight = paint.TextSize * 1.2f; diff --git a/FModel/Creator/Texts/Text.cs b/FModel/Creator/Texts/Text.cs index e8c0dea2..d38be445 100644 --- a/FModel/Creator/Texts/Text.cs +++ b/FModel/Creator/Texts/Text.cs @@ -87,17 +87,17 @@ namespace FModel.Creator.Texts return string.Empty; } - public static void DrawBackground(SKCanvas c, BaseIcon icon) + public static void DrawBackground(SKCanvas c, IBase icon) { switch ((EIconDesign)Properties.Settings.Default.AssetsIconDesign) { case EIconDesign.Flat: { var pathBottom = new SKPath { FillType = SKPathFillType.EvenOdd }; - pathBottom.MoveTo(icon.Margin, icon.Size - icon.Margin); - pathBottom.LineTo(icon.Margin, icon.Size - icon.Margin - (icon.Size / 17 * 2.5f)); - pathBottom.LineTo(icon.Size - icon.Margin, icon.Size - icon.Margin - (icon.Size / 17 * 4.5f)); - pathBottom.LineTo(icon.Size - icon.Margin, icon.Size - icon.Margin); + pathBottom.MoveTo(icon.Margin, icon.Height - icon.Margin); + pathBottom.LineTo(icon.Margin, icon.Height - icon.Margin - (icon.Height / 17 * 2.5f)); + pathBottom.LineTo(icon.Width - icon.Margin, icon.Height - icon.Margin - (icon.Height / 17 * 4.5f)); + pathBottom.LineTo(icon.Width - icon.Margin, icon.Height - icon.Margin); pathBottom.Close(); c.DrawPath(pathBottom, new SKPaint { @@ -110,7 +110,7 @@ namespace FModel.Creator.Texts default: { c.DrawRect( - new SKRect(icon.Margin, _STARTER_TEXT_POSITION, icon.Size - icon.Margin, icon.Size - icon.Margin), + new SKRect(icon.Margin, _STARTER_TEXT_POSITION, icon.Width - icon.Margin, icon.Height - icon.Margin), new SKPaint { IsAntialias = true, @@ -122,12 +122,12 @@ namespace FModel.Creator.Texts } } - public static void DrawDisplayName(SKCanvas c, BaseIcon icon) + public static void DrawDisplayName(SKCanvas c, IBase icon) { _NAME_TEXT_SIZE = 45; string text = icon.DisplayName; SKTextAlign side = SKTextAlign.Center; - int x = icon.Size / 2; + int x = icon.Width / 2; int y = _STARTER_TEXT_POSITION + _NAME_TEXT_SIZE; switch ((EIconDesign)Properties.Settings.Default.AssetsIconDesign) { @@ -141,7 +141,7 @@ namespace FModel.Creator.Texts { _NAME_TEXT_SIZE = 47; side = SKTextAlign.Right; - x = icon.Size - icon.Margin * 2; + x = icon.Width - icon.Margin * 2; break; } } @@ -157,7 +157,7 @@ namespace FModel.Creator.Texts }; // resize if too long - while (namePaint.MeasureText(text) > (icon.Size - (icon.Margin * 2))) + while (namePaint.MeasureText(text) > (icon.Width - (icon.Margin * 2))) { namePaint.TextSize = _NAME_TEXT_SIZE -= 2; } @@ -165,7 +165,7 @@ namespace FModel.Creator.Texts c.DrawText(text, x, y, namePaint); } - public static void DrawDescription(SKCanvas c, BaseIcon icon) + public static void DrawDescription(SKCanvas c, IBase icon) { int maxLine = 4; _BOTTOM_TEXT_SIZE = 15; @@ -198,7 +198,7 @@ namespace FModel.Creator.Texts // wrap if too long Helper.DrawCenteredMultilineText(c, text, maxLine, icon, side, - new SKRect(icon.Margin, _STARTER_TEXT_POSITION + _NAME_TEXT_SIZE, icon.Size - icon.Margin, icon.Size - _BOTTOM_TEXT_SIZE), + new SKRect(icon.Margin, _STARTER_TEXT_POSITION + _NAME_TEXT_SIZE, icon.Width - icon.Margin, icon.Height - _BOTTOM_TEXT_SIZE), descriptionPaint); } diff --git a/FModel/Creator/Texts/Typefaces.cs b/FModel/Creator/Texts/Typefaces.cs index ef67c089..e80056e0 100644 --- a/FModel/Creator/Texts/Typefaces.cs +++ b/FModel/Creator/Texts/Typefaces.cs @@ -49,6 +49,13 @@ namespace FModel.Creator.Texts private const string _DINNEXT_LTARABIC_LIGHT = "UI/Fonts/FinalFonts/LOCFonts/DIN_Next_Arabic/DINNextLTArabic-Light"; private const string _NOTOSANS_CJK_LIGHT = "UI/Fonts/FinalFonts/LOCFonts/CJK/NotoSansCJK-Light"; // chinese, japanese, korean private const string _DINNEXT_W1G_BOLD = "UI/Fonts/FinalFonts/DINNextW1G-Bold"; + + private const string _SPELLBREAK_BASE_PATH = "/Game/UI/Fonts/"; + private const string _MONTSERRAT_SEMIBOLD = "Montserrat-Semibold"; + private const string _MONTSERRAT_SEMIBOLD_ITALIC = "Montserrat-SemiBoldItalic"; + private const string _NANUM_GOTHIC = "NanumGothic"; + private const string _QUADRAT_BOLD = "Quadrat_Bold"; + private const string _SEGOE_BOLD_ITALIC = "Segoe_Bold_Italic"; #pragma warning restore IDE0051 public SKTypeface DefaultTypeface; // used as default font for all untranslated strings (item source, ...) @@ -143,6 +150,18 @@ namespace FModel.Creator.Texts BundleDefaultTypeface = SKTypeface.FromStream(t[2].AsStream()); else BundleDefaultTypeface = DefaultTypeface; } + else if (Globals.Game.ActualGame == EGame.Spellbreak) + { + ArraySegment[] t = Utils.GetPropertyArraySegmentByte(_SPELLBREAK_BASE_PATH + _QUADRAT_BOLD); + if (t != null && t.Length == 3 && t[2].Array != null) + DisplayNameTypeface = SKTypeface.FromStream(t[2].AsStream()); + else DisplayNameTypeface = DefaultTypeface; + + t = Utils.GetPropertyArraySegmentByte(_SPELLBREAK_BASE_PATH + _MONTSERRAT_SEMIBOLD); + if (t != null && t.Length == 3 && t[2].Array != null) + DescriptionTypeface = SKTypeface.FromStream(t[2].AsStream()); + else DescriptionTypeface = DefaultTypeface; + } } public bool NeedReload(bool forceReload) => forceReload ? diff --git a/FModel/Creator/Utils.cs b/FModel/Creator/Utils.cs index c38e2cd6..f7677170 100644 --- a/FModel/Creator/Utils.cs +++ b/FModel/Creator/Utils.cs @@ -64,6 +64,10 @@ namespace FModel.Creator s += "_1024"; else if (s.Equals("/Game/UI/Foundation/Textures/BattleRoyale/BattlePass/T-BattlePass-Season14-Tile") || s.Equals("/Game/UI/Foundation/Textures/BattleRoyale/BattlePass/T-BattlePassWithLevels-Season14-Tile")) s += "_1"; + else if (s.Equals("/Game/UI/Textures/assets/cosmetics/skins/headshot/Skin_Headshot_WolfsBlood_UIT")) + s = "/Game/UI/Textures/assets/cosmetics/skins/headshot/Skin_Headshot_Wolfsblood_UIT"; + else if (s.Equals("/Game/UI/Textures/assets/cosmetics/skins/headshot/Skin_Headshot_Timeweaver_UIT")) + s = "/Game/UI/Textures/assets/cosmetics/skins/headshot/Skin_Headshot_TimeWeaver_UIT"; } PakPackage p = GetPropertyPakPackage(s); diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index a17d4c40..35ffdad2 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -89,6 +89,7 @@ + @@ -129,18 +130,18 @@ - + - + - + @@ -202,6 +203,7 @@ + diff --git a/FModel/MainWindow.xaml b/FModel/MainWindow.xaml index 0b5f7e10..cf767f61 100644 --- a/FModel/MainWindow.xaml +++ b/FModel/MainWindow.xaml @@ -71,6 +71,11 @@ + + + + + diff --git a/FModel/PakReader/Parsers/Class/UAkAudioEvent.cs b/FModel/PakReader/Parsers/Class/UAkAudioEvent.cs new file mode 100644 index 00000000..17d4393b --- /dev/null +++ b/FModel/PakReader/Parsers/Class/UAkAudioEvent.cs @@ -0,0 +1,29 @@ +using System.Collections; +using System.Collections.Generic; + +namespace PakReader.Parsers.Class +{ + public sealed class UAkAudioEvent : IUExport + { + readonly Dictionary Map; + + internal UAkAudioEvent(PackageReader reader) + { + _ = new UObject(reader, true); + Map = new Dictionary(1) + { + { "MaxAttenuationRadius", reader.ReadFloat() } + }; + } + + public object this[string key] => Map[key]; + public IEnumerable Keys => Map.Keys; + public IEnumerable Values => Map.Values; + public int Count => Map.Count; + public bool ContainsKey(string key) => Map.ContainsKey(key); + public IEnumerator> GetEnumerator() => Map.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => Map.GetEnumerator(); + + public bool TryGetValue(string key, out object value) => Map.TryGetValue(key, out value); + } +} diff --git a/FModel/PakReader/Parsers/Class/UObject.cs b/FModel/PakReader/Parsers/Class/UObject.cs index 9998551d..e8a9dcfa 100644 --- a/FModel/PakReader/Parsers/Class/UObject.cs +++ b/FModel/PakReader/Parsers/Class/UObject.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Collections.Generic; using System.Linq; @@ -74,20 +73,5 @@ namespace PakReader.Parsers.Class return false; } public bool TryGetValue(string key, out object value) => Dict.TryGetValue(key, out value); - - public T Deserialize() - { - var ret = ReflectionHelper.NewInstance(); - var map = ReflectionHelper.GetActionMap(); - foreach (var kv in Dict) - { - (var baseType, var typeGetter) = ReflectionHelper.GetPropertyInfo(kv.Value.GetType()); - if (map.TryGetValue((kv.Key.ToLowerInvariant(), baseType), out Action setter)) - { - setter(ret, typeGetter(kv.Value)); - } - } - return ret; - } } } diff --git a/FModel/PakReader/Parsers/Objects/FPakEntry.cs b/FModel/PakReader/Parsers/Objects/FPakEntry.cs index 14dd7dd9..63a98c83 100644 --- a/FModel/PakReader/Parsers/Objects/FPakEntry.cs +++ b/FModel/PakReader/Parsers/Objects/FPakEntry.cs @@ -32,7 +32,7 @@ namespace PakReader.Parsers.Objects PakFileName = pakName; string name = caseSensitive ? reader.ReadFString() : reader.ReadFString().ToLowerInvariant(); - Name = name.StartsWith("/") ? name.Substring(1) : name; + Name = name.StartsWith("/") ? name[1..] : name; var StartOffset = reader.BaseStream.Position; @@ -229,16 +229,16 @@ namespace PakReader.Parsers.Objects public FPakEntry Uexp = null; public FPakEntry Ubulk = null; - public bool IsUE4Package() => Name.Substring(Name.LastIndexOf(".")).Equals(".uasset"); - public bool IsLocres() => Name.Substring(Name.LastIndexOf(".")).Equals(".locres"); - public bool IsUE4Map() => Name.Substring(Name.LastIndexOf(".")).Equals(".umap"); - public bool IsUE4Font() => Name.Substring(Name.LastIndexOf(".")).Equals(".ufont"); + public bool IsUE4Package() => Name[Name.LastIndexOf(".")..].Equals(".uasset"); + public bool IsLocres() => Name[Name.LastIndexOf(".")..].Equals(".locres"); + public bool IsUE4Map() => Name[Name.LastIndexOf(".")..].Equals(".umap"); + public bool IsUE4Font() => Name[Name.LastIndexOf(".")..].Equals(".ufont"); public bool HasUexp() => Uexp != null; public bool HasUbulk() => Ubulk != null; public bool IsCompressed() => UncompressedSize != Size || CompressionMethodIndex != (int)ECompressionFlags.COMPRESS_None; - public string GetExtension() => Name.Substring(Name.LastIndexOf(".")); + public string GetExtension() => Name[Name.LastIndexOf(".")..]; public string GetPathWithoutFile() { int stop = Name.LastIndexOf("/"); diff --git a/FModel/PakReader/Parsers/OodleStream.cs b/FModel/PakReader/Parsers/OodleStream.cs index b7e345bf..497bc89c 100644 --- a/FModel/PakReader/Parsers/OodleStream.cs +++ b/FModel/PakReader/Parsers/OodleStream.cs @@ -75,7 +75,7 @@ namespace PakReader.Parsers public override bool CanRead => throw new NotImplementedException(); public override bool CanSeek => throw new NotImplementedException(); public override bool CanWrite => throw new NotImplementedException(); - public override long Length => throw new NotImplementedException(); + public override long Length => _baseStream.Length; public override long Position { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } } } diff --git a/FModel/PakReader/Parsers/PackageReader.cs b/FModel/PakReader/Parsers/PackageReader.cs index 8da12dce..60453e97 100644 --- a/FModel/PakReader/Parsers/PackageReader.cs +++ b/FModel/PakReader/Parsers/PackageReader.cs @@ -57,6 +57,7 @@ namespace PakReader.Parsers "FontFace" => new UFontFace(this, ubulk), "SoundWave" => new USoundWave(this, ubulk, ExportMap.Sum(e => e.SerialSize) + PackageFileSummary.TotalHeaderSize), "StringTable" => new UStringTable(this), + "AkAudioEvent" => new UAkAudioEvent(this), _ => new UObject(this), }; diff --git a/FModel/Properties/Resources.Designer.cs b/FModel/Properties/Resources.Designer.cs index be14d3e9..084bda2b 100644 --- a/FModel/Properties/Resources.Designer.cs +++ b/FModel/Properties/Resources.Designer.cs @@ -2184,6 +2184,16 @@ namespace FModel.Properties { } } + /// + /// Recherche une ressource localisée de type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap rotate_3d { + get { + object obj = ResourceManager.GetObject("rotate_3d", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Recherche une chaîne localisée semblable à Russian. /// diff --git a/FModel/Properties/Resources.resx b/FModel/Properties/Resources.resx index 213e9591..82ca3043 100644 --- a/FModel/Properties/Resources.resx +++ b/FModel/Properties/Resources.resx @@ -1081,4 +1081,7 @@ It's now the most used free software to leak on Fortnite. Skip this Version + + ..\Resources\rotate-3d.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/FModel/Resources/rotate-3d.png b/FModel/Resources/rotate-3d.png new file mode 100644 index 00000000..6420ca48 Binary files /dev/null and b/FModel/Resources/rotate-3d.png differ diff --git a/FModel/Utils/Assets.cs b/FModel/Utils/Assets.cs index 59f50fb5..6b3e8a36 100644 --- a/FModel/Utils/Assets.cs +++ b/FModel/Utils/Assets.cs @@ -342,9 +342,9 @@ namespace FModel.Utils public static void Filter(string filter, string item, out bool bSearch) { if (filter.StartsWith("!=")) - bSearch = item.IndexOf(filter.Substring(2), StringComparison.CurrentCultureIgnoreCase) < 0; + bSearch = item.IndexOf(filter[2..], StringComparison.CurrentCultureIgnoreCase) < 0; else if (filter.StartsWith("==")) - bSearch = item.IndexOf(filter.Substring(2), StringComparison.CurrentCulture) >= 0; + bSearch = item.IndexOf(filter[2..], StringComparison.CurrentCulture) >= 0; else bSearch = item.IndexOf(filter, StringComparison.CurrentCultureIgnoreCase) >= 0; } @@ -367,7 +367,7 @@ namespace FModel.Utils if (data[i] == null) continue; - string basePath = Properties.Settings.Default.OutputPath + "\\Exports\\" + mount.Substring(1); + string basePath = Properties.Settings.Default.OutputPath + "\\Exports\\" + mount[1..]; string fullPath = basePath + Path.ChangeExtension(entry.Name, ext[i]); string name = Path.GetFileName(fullPath); Directory.CreateDirectory(basePath + entry.GetPathWithoutFile()); @@ -394,7 +394,7 @@ namespace FModel.Utils { if (Globals.CachedPakFiles.TryGetValue(entry.PakFileName, out var r)) { - string basePath = Properties.Settings.Default.OutputPath + "\\Exports\\" + r.MountPoint.Substring(1); + string basePath = Properties.Settings.Default.OutputPath + "\\Exports\\" + r.MountPoint[1..]; string fullPath = basePath + entry.Name; string name = Path.GetFileName(fullPath); Directory.CreateDirectory(basePath + entry.GetPathWithoutFile()); @@ -440,7 +440,7 @@ namespace FModel.Utils { if (Globals.CachedPakFiles.TryGetValue(entry.PakFileName, out var r)) { - string toCopy = r.MountPoint.Substring(1); + string toCopy = r.MountPoint[1..]; if (mode == ECopy.Path) toCopy += entry.Name; else if (mode == ECopy.PathNoExt) diff --git a/FModel/Utils/SevenZipHelper.cs b/FModel/Utils/SevenZipHelper.cs index 8ad31393..48b0da45 100644 --- a/FModel/Utils/SevenZipHelper.cs +++ b/FModel/Utils/SevenZipHelper.cs @@ -80,7 +80,7 @@ namespace FModel.Utils lzmaEncoder.Code(input, output, -1, -1, prg); } - public static void Decompress(Stream input, Stream output, Action? onProgress = null) + public static void Decompress(Stream input, Stream output, Action onProgress = null) { var decoder = new Decoder();