mirror of
https://github.com/4sval/FModel.git
synced 2026-08-22 09:24:32 -05:00
added battle pass icon generation
This commit is contained in:
@@ -70,6 +70,9 @@ namespace FModel.Creator.Bases
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (export.GetExport<TextProperty>("DisplayName", "DefaultHeaderText", "UIDisplayName") is TextProperty displayName)
|
||||
DisplayName = Text.GetTextPropertyBase(displayName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
267
FModel/Creator/Bases/BaseSeason.cs
Normal file
267
FModel/Creator/Bases/BaseSeason.cs
Normal file
@@ -0,0 +1,267 @@
|
||||
using FModel.Creator.Bundles;
|
||||
using FModel.Creator.Texts;
|
||||
using PakReader.Parsers.Class;
|
||||
using PakReader.Parsers.PropertyTagData;
|
||||
using SkiaSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FModel.Creator.Bases
|
||||
{
|
||||
public class BaseSeason
|
||||
{
|
||||
public string DisplayName;
|
||||
public string FolderName;
|
||||
public string Watermark;
|
||||
public Reward FirstWinReward;
|
||||
public Dictionary<int, List<Reward>> BookXpSchedule;
|
||||
public Header DisplayStyle;
|
||||
public int Width = 1024;
|
||||
public int HeaderHeight = 261; // height is the header basically
|
||||
public int AdditionalSize = 50; // must be increased depending on the number of quests to draw
|
||||
|
||||
public BaseSeason()
|
||||
{
|
||||
DisplayName = "";
|
||||
FolderName = "";
|
||||
Watermark = Properties.Settings.Default.ChallengeBannerWatermark;
|
||||
FirstWinReward = null;
|
||||
BookXpSchedule = new Dictionary<int, List<Reward>>();
|
||||
DisplayStyle = new Header();
|
||||
}
|
||||
|
||||
public BaseSeason(IUExport export, string assetFolder) : this()
|
||||
{
|
||||
if (export.GetExport<TextProperty>("DisplayName") is TextProperty displayName)
|
||||
DisplayName = Text.GetTextPropertyBase(displayName);
|
||||
|
||||
if (export.GetExport<StructProperty>("SeasonFirstWinRewards") is StructProperty s && s.Value is UObject seasonFirstWinRewards &&
|
||||
seasonFirstWinRewards.GetExport<ArrayProperty>("Rewards") is ArrayProperty rewards)
|
||||
{
|
||||
foreach (StructProperty reward in rewards.Value)
|
||||
{
|
||||
if (reward.Value is UObject o &&
|
||||
o.GetExport<SoftObjectProperty>("ItemDefinition") is SoftObjectProperty itemDefinition &&
|
||||
o.GetExport<IntProperty>("Quantity") is IntProperty quantity)
|
||||
{
|
||||
FirstWinReward = new Reward(quantity, itemDefinition.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (export.GetExport<StructProperty>("BookXpScheduleFree") is StructProperty r2 && r2.Value is UObject bookXpScheduleFree &&
|
||||
bookXpScheduleFree.GetExport<ArrayProperty>("Levels") is ArrayProperty levels2)
|
||||
{
|
||||
for (int i = 0; i < levels2.Value.Length; i++)
|
||||
{
|
||||
BookXpSchedule[i] = new List<Reward>(); // init list for all reward index and once
|
||||
if (levels2.Value[i] is StructProperty level && level.Value is UObject l &&
|
||||
l.GetExport<ArrayProperty>("Rewards") is ArrayProperty elRewards && elRewards.Value.Length > 0)
|
||||
{
|
||||
foreach (StructProperty reward in elRewards.Value)
|
||||
{
|
||||
if (reward.Value is UObject o &&
|
||||
o.GetExport<SoftObjectProperty>("ItemDefinition") is SoftObjectProperty itemDefinition &&
|
||||
//!itemDefinition.Value.AssetPathName.String.StartsWith("/Game/Athena/Items/ChallengeBundleSchedules/") &&
|
||||
o.GetExport<IntProperty>("Quantity") is IntProperty quantity)
|
||||
{
|
||||
BookXpSchedule[i].Add(new Reward(quantity, itemDefinition.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (export.GetExport<StructProperty>("BookXpSchedulePaid") is StructProperty r1 && r1.Value is UObject bookXpSchedulePaid &&
|
||||
bookXpSchedulePaid.GetExport<ArrayProperty>("Levels") is ArrayProperty levels1)
|
||||
{
|
||||
for (int i = 0; i < levels1.Value.Length; i++)
|
||||
{
|
||||
if (levels1.Value[i] is StructProperty level && level.Value is UObject l &&
|
||||
l.GetExport<ArrayProperty>("Rewards") is ArrayProperty elRewards && elRewards.Value.Length > 0)
|
||||
{
|
||||
foreach (StructProperty reward in elRewards.Value)
|
||||
{
|
||||
if (reward.Value is UObject o &&
|
||||
o.GetExport<SoftObjectProperty>("ItemDefinition") is SoftObjectProperty itemDefinition &&
|
||||
//!itemDefinition.Value.AssetPathName.String.StartsWith("/Game/Athena/Items/ChallengeBundleSchedules/") &&
|
||||
o.GetExport<IntProperty>("Quantity") is IntProperty quantity)
|
||||
{
|
||||
BookXpSchedule[i].Add(new Reward(quantity, itemDefinition.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FolderName = assetFolder;
|
||||
AdditionalSize += 100 * (BookXpSchedule.Count / 10);
|
||||
}
|
||||
|
||||
public void Draw(SKCanvas c)
|
||||
{
|
||||
DrawHeaderPaint(c);
|
||||
DrawHeaderText(c);
|
||||
|
||||
using SKPaint paint = new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
TextSize = 15,
|
||||
Color = SKColors.White,
|
||||
TextAlign = SKTextAlign.Center,
|
||||
Typeface = Text.TypeFaces.BottomDefaultTypeface
|
||||
};
|
||||
using SKPaint bg = new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
Color = SKColor.Parse("#0F5CAF"),
|
||||
};
|
||||
using SKPaint rarity = new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
Color = SKColors.White,
|
||||
};
|
||||
using SKPaint icon = new SKPaint
|
||||
{
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
IsAntialias = true
|
||||
};
|
||||
|
||||
int y = HeaderHeight + 50;
|
||||
int defaultSize = 80;
|
||||
int x = 20;
|
||||
foreach (var (index, reward) in BookXpSchedule)
|
||||
{
|
||||
if (index == 0)
|
||||
continue;
|
||||
|
||||
c.DrawText(index.ToString(), new SKPoint(x + (defaultSize / 2), y - 5), paint);
|
||||
|
||||
rarity.Color = reward[0].TheReward.RarityBackgroundColors[0];
|
||||
c.DrawRect(new SKRect(x, y, x + defaultSize, y + defaultSize), bg);
|
||||
c.DrawBitmap(reward[0].RewardIcon, new SKPoint(x, y), icon);
|
||||
var pathBottom = new SKPath { FillType = SKPathFillType.EvenOdd };
|
||||
pathBottom.MoveTo(x, y + defaultSize);
|
||||
pathBottom.LineTo(x, y + defaultSize - (defaultSize / 25 * 2.5f));
|
||||
pathBottom.LineTo(x + defaultSize, y + defaultSize - (defaultSize / 25 * 4.5f));
|
||||
pathBottom.LineTo(x + defaultSize, y + defaultSize);
|
||||
pathBottom.Close();
|
||||
c.DrawPath(pathBottom, rarity);
|
||||
|
||||
if (index != 1 && index % 10 == 0)
|
||||
{
|
||||
y += defaultSize + 20;
|
||||
x = 20;
|
||||
}
|
||||
else
|
||||
{
|
||||
x += defaultSize + 20;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawHeaderText(SKCanvas c)
|
||||
{
|
||||
using SKPaint paint = new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
Typeface = Text.TypeFaces.BundleDisplayNameTypeface,
|
||||
TextSize = 50,
|
||||
Color = SKColors.White,
|
||||
TextAlign = SKTextAlign.Left,
|
||||
};
|
||||
|
||||
string text = DisplayName.ToUpper();
|
||||
int x = 300;
|
||||
while (paint.MeasureText(text) > (Width - x))
|
||||
{
|
||||
paint.TextSize -= 2;
|
||||
}
|
||||
c.DrawText(text, x, 155, paint);
|
||||
|
||||
paint.Color = SKColors.White.WithAlpha(150);
|
||||
paint.TextAlign = SKTextAlign.Right;
|
||||
paint.TextSize = 23;
|
||||
c.DrawText(Watermark
|
||||
.Replace("{BundleName}", text)
|
||||
.Replace("{Date}", DateTime.Now.ToString("dd/MM/yyyy")),
|
||||
Width - 25, HeaderHeight - 40, paint);
|
||||
|
||||
paint.Typeface = Text.TypeFaces.BundleDefaultTypeface;
|
||||
paint.Color = DisplayStyle.SecondaryColor;
|
||||
paint.TextAlign = SKTextAlign.Left;
|
||||
paint.TextSize = 30;
|
||||
c.DrawText(FolderName.ToUpper(), x, 95, paint);
|
||||
}
|
||||
|
||||
private void DrawHeaderPaint(SKCanvas c)
|
||||
{
|
||||
c.DrawRect(new SKRect(0, 0, Width, HeaderHeight), new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
Color = DisplayStyle.PrimaryColor
|
||||
});
|
||||
|
||||
if (DisplayStyle.CustomBackground != null && DisplayStyle.CustomBackground.Height != DisplayStyle.CustomBackground.Width)
|
||||
{
|
||||
var bgPaint = new SKPaint { IsAntialias = true, FilterQuality = SKFilterQuality.High, BlendMode = SKBlendMode.Screen };
|
||||
if (Properties.Settings.Default.UseChallengeBanner) bgPaint.Color = SKColors.Transparent.WithAlpha((byte)Properties.Settings.Default.ChallengeBannerOpacity);
|
||||
c.DrawBitmap(DisplayStyle.CustomBackground, new SKRect(0, 0, 1024, 256), bgPaint);
|
||||
}
|
||||
else if (DisplayStyle.DisplayImage != null)
|
||||
{
|
||||
if (DisplayStyle.CustomBackground != null && DisplayStyle.CustomBackground.Height == DisplayStyle.CustomBackground.Width)
|
||||
c.DrawBitmap(DisplayStyle.CustomBackground, new SKRect(0, 0, HeaderHeight, HeaderHeight),
|
||||
new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
BlendMode = SKBlendMode.Screen,
|
||||
ImageFilter = SKImageFilter.CreateDropShadow(2.5F, 0, 20, 0, DisplayStyle.SecondaryColor.WithAlpha(25))
|
||||
});
|
||||
|
||||
c.DrawBitmap(DisplayStyle.DisplayImage, new SKRect(0, 0, HeaderHeight, HeaderHeight),
|
||||
new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
ImageFilter = SKImageFilter.CreateDropShadow(-2.5F, 0, 20, 0, DisplayStyle.SecondaryColor.WithAlpha(50))
|
||||
});
|
||||
}
|
||||
|
||||
c.DrawBitmap(FirstWinReward.TheReward.IconImage.Resize(HeaderHeight, HeaderHeight), new SKPoint(0, 0), new SKPaint
|
||||
{
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
IsAntialias = true
|
||||
});
|
||||
|
||||
SKPath pathTop = new SKPath { FillType = SKPathFillType.EvenOdd };
|
||||
pathTop.MoveTo(0, HeaderHeight);
|
||||
pathTop.LineTo(Width, HeaderHeight);
|
||||
pathTop.LineTo(Width, HeaderHeight - 19);
|
||||
pathTop.LineTo(Width / 2 + 7, HeaderHeight - 23);
|
||||
pathTop.LineTo(Width / 2 + 13, HeaderHeight - 7);
|
||||
pathTop.LineTo(0, HeaderHeight - 19);
|
||||
pathTop.Close();
|
||||
c.DrawPath(pathTop, new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
Color = DisplayStyle.SecondaryColor,
|
||||
ImageFilter = SKImageFilter.CreateDropShadow(-5, -5, 0, 0, DisplayStyle.AccentColor.WithAlpha(75))
|
||||
});
|
||||
|
||||
c.DrawRect(new SKRect(0, HeaderHeight, Width, HeaderHeight + AdditionalSize), new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
Color = DisplayStyle.PrimaryColor.WithAlpha(200) // default background is black, so i'm kinda lowering the brightness here and that's what i want
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using FModel.Creator.Bases;
|
||||
using PakReader.Pak;
|
||||
using PakReader.Parsers.Class;
|
||||
using PakReader.Parsers.Objects;
|
||||
using PakReader.Parsers.PropertyTagData;
|
||||
using SkiaSharp;
|
||||
using System;
|
||||
@@ -11,6 +12,7 @@ namespace FModel.Creator.Bundles
|
||||
{
|
||||
public int RewardQuantity;
|
||||
public SKBitmap RewardIcon;
|
||||
public BaseIcon TheReward;
|
||||
public string RewardFillColor;
|
||||
public string RewardBorderColor;
|
||||
public bool IsCountShifted;
|
||||
@@ -19,6 +21,7 @@ namespace FModel.Creator.Bundles
|
||||
{
|
||||
RewardQuantity = 0;
|
||||
RewardIcon = null;
|
||||
TheReward = null;
|
||||
RewardFillColor = "";
|
||||
RewardBorderColor = "";
|
||||
IsCountShifted = false;
|
||||
@@ -39,7 +42,8 @@ namespace FModel.Creator.Bundles
|
||||
{
|
||||
if (p.GetExport<UObject>() is UObject banner)
|
||||
{
|
||||
RewardIcon = new BaseIcon(banner, $"{parts[1]}.uasset", false).IconImage.Resize(64, 64);
|
||||
TheReward = new BaseIcon(banner, $"{parts[1]}.uasset", false);
|
||||
RewardIcon = TheReward.IconImage.Resize(64, 64);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,6 +51,21 @@ namespace FModel.Creator.Bundles
|
||||
}
|
||||
else GetReward(assetName);
|
||||
}
|
||||
public Reward(IntProperty quantity, FSoftObjectPath itemFullPath)
|
||||
{
|
||||
RewardQuantity = quantity.Value;
|
||||
PakPackage p = Utils.GetPropertyPakPackage(itemFullPath.AssetPathName.String);
|
||||
if (p.HasExport() && !p.Equals(default))
|
||||
{
|
||||
var d = p.GetExport<UObject>();
|
||||
if (d != null)
|
||||
{
|
||||
int i = itemFullPath.AssetPathName.String.LastIndexOf('/');
|
||||
TheReward = new BaseIcon(d, itemFullPath.AssetPathName.String[(i > 0 ? i : 0)..] + ".uasset", false);
|
||||
RewardIcon = TheReward.IconImage.Resize(80, 80);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Reward(IntProperty quantity, SoftObjectProperty itemDefinition) : this()
|
||||
{
|
||||
@@ -83,7 +102,8 @@ namespace FModel.Creator.Bundles
|
||||
break;
|
||||
default:
|
||||
IsCountShifted = false;
|
||||
RewardIcon = new BaseIcon(d, itemDefinition.Value.AssetPathName.String.Substring(s1, s2) + ".uasset", false).IconImage.Resize(64, 64);
|
||||
TheReward = new BaseIcon(d, itemDefinition.Value.AssetPathName.String.Substring(s1, s2) + ".uasset", false);
|
||||
RewardIcon = TheReward.IconImage.Resize(64, 64);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -123,7 +143,8 @@ namespace FModel.Creator.Bundles
|
||||
{
|
||||
int i = path.LastIndexOf('/');
|
||||
IsCountShifted = false;
|
||||
RewardIcon = new BaseIcon(d, path.Substring(i > 0 ? i : 0) + ".uasset", false).IconImage.Resize(64, 64);
|
||||
TheReward = new BaseIcon(d, path[(i > 0 ? i : 0)..] + ".uasset", false);
|
||||
RewardIcon = TheReward.IconImage.Resize(64, 64);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -142,6 +142,18 @@ namespace FModel.Creator
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case "AthenaSeasonItemDefinition":
|
||||
{
|
||||
BaseSeason icon = new BaseSeason(exports[index], assetFolder);
|
||||
using (var ret = new SKBitmap(icon.Width, icon.HeaderHeight + icon.AdditionalSize, SKColorType.Rgba8888, SKAlphaType.Opaque))
|
||||
using (var c = new SKCanvas(ret))
|
||||
{
|
||||
icon.Draw(c);
|
||||
|
||||
ImageBoxVm.imageBoxViewModel.Set(ret, assetName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case "FortMtxOfferData":
|
||||
{
|
||||
BaseOffer icon = new BaseOffer(exports[index]);
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||
<TextBox x:Name="GamesPath_TxtBox" Grid.Row="1" Grid.Column="2"
|
||||
TextWrapping="NoWrap" VerticalAlignment="Top" Foreground="#FFEFEFEF" Margin="5,3,5,0" TextChanged="OnTextChange"/>
|
||||
<Button Grid.Row="1" Grid.Column="3" Content="..." Height="20" Width="20" VerticalAlignment="Top" Margin="5,3,5,0" Click="OnInputClick"/>
|
||||
<Button x:Name="BrowsePath" Grid.Row="1" Grid.Column="3" Content="..." Height="20" Width="20" VerticalAlignment="Top" Margin="5,3,5,0" Click="OnInputClick"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
|
||||
@@ -141,6 +141,7 @@ namespace FModel.Windows.Launcher
|
||||
{
|
||||
if (e.Source is TextBox text)
|
||||
{
|
||||
BrowsePath.IsEnabled = text.Text != "donotedit-youcanteditanyway.manifest";
|
||||
text.IsReadOnly = text.Text == "donotedit-youcanteditanyway.manifest";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user