added the fucking update mode

This commit is contained in:
Asval 2019-11-11 17:10:39 +01:00
parent 6edaf437ad
commit 5ac94fa91d
15 changed files with 747 additions and 21 deletions

View File

@ -94,6 +94,94 @@
<setting name="FAutoSaveImg" serializeAs="String">
<value>False</value>
</setting>
<setting name="FUM_AssetsType" serializeAs="String">
<value>{
"[BR] Cosmetics": {
"Path": "/FortniteGame/Content/Athena/Items/Cosmetics/",
"isChecked": "True"
},
"[BR] Cosmetics Variants": {
"Path": "/FortniteGame/Content/Athena/Items/CosmeticVariantTokens/",
"isChecked": "True"
},
"[BR] Banners": {
"Path": "/FortniteGame/Content/Athena/Items/BannerToken/",
"isChecked": "True"
},
"[BR] Challenges": {
"Path": "/FortniteGame/Content/Athena/Items/ChallengeBundles/",
"isChecked": "True"
},
"[BR] Consumables": {
"Path": "/FortniteGame/Content/Athena/Items/Consumables/",
"isChecked": "False"
},
"[BR] Traps": {
"Path": "/FortniteGame/Content/Athena/Items/Traps/",
"isChecked": "False"
},
"[BR] Weapons": {
"Path": "/FortniteGame/Content/Athena/Items/Weapons/",
"isChecked": "True"
},
"[BR] 2D Assets": {
"Path": "/FortniteGame/Content/2dAssets/",
"isChecked": "True"
},
"[BR] Featured Images": {
"Path": "/FortniteGame/Content/UI/Foundation/Textures/BattleRoyale/FeaturedItems/",
"isChecked": "False"
},
"[STW] Heroes": {
"Path": "/FortniteGame/Content/Heroes/",
"isChecked": "False"
},
"[STW] Defenders": {
"Path": "/FortniteGame/Content/Items/Defenders/",
"isChecked": "False"
},
"[STW] Schematics": {
"Path": "/FortniteGame/Content/Items/Schematics/",
"isChecked": "False"
},
"[STW] Traps": {
"Path": "/FortniteGame/Content/Items/Traps/",
"isChecked": "False"
},
"[STW] Weapons": {
"Path": "/FortniteGame/Content/Items/Weapons/",
"isChecked": "False"
},
"[STW] Ingredients": {
"Path": "/FortniteGame/Content/Items/Ingredients/",
"isChecked": "False"
},
"[STW] Persistent Resources": {
"Path": "/FortniteGame/Content/Items/PersistentResources/",
"isChecked": "False"
},
"[STW] CardPacks": {
"Path": "/FortniteGame/Content/Items/CardPacks/",
"isChecked": "False"
},
"Tokens": {
"Path": "/FortniteGame/Content/Items/Tokens/",
"isChecked": "False"
},
"Icons": {
"Path": "/FortniteGame/Content/UI/Foundation/Textures/Icons/",
"isChecked": "False"
},
"Additional Banners": {
"Path": "/FortniteGame/Content/UI/Foundation/Textures/Banner/",
"isChecked": "False"
},
"Additional Loading Screens": {
"Path": "/FortniteGame/Content/UI/Foundation/Textures/LoadingScreens/",
"isChecked": "False"
}
}</value>
</setting>
</FModel.Properties.Settings>
</userSettings>
<runtime>

View File

@ -152,6 +152,9 @@
<Compile Include="Forms\FModel_Settings.xaml.cs">
<DependentUpon>FModel_Settings.xaml</DependentUpon>
</Compile>
<Compile Include="Forms\FModel_UpdateMode.xaml.cs">
<DependentUpon>FModel_UpdateMode.xaml</DependentUpon>
</Compile>
<Compile Include="Forms\HexViewer\BaseByte.cs" />
<Compile Include="Forms\HexViewer\Core\BookMark.cs" />
<Compile Include="Forms\HexViewer\Core\Bytes\ByteConverters.cs" />
@ -417,6 +420,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Forms\FModel_UpdateMode.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Forms\HexViewer\BrushesDictionary.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>

View File

@ -44,7 +44,7 @@
<MenuItem x:Name="MI_BackupPAKs" Header="Backup PAKs" Click="MI_BackupPAKs_Click" IsEnabled="False"/>
<Separator/>
<MenuItem x:Name="MI_DifferenceMode" Header="Difference Mode" IsCheckable="True" Checked="MI_Change_Header" Unchecked="MI_Change_Header"/>
<MenuItem x:Name="MI_UpdateMode" Header="Lazy Mode" IsCheckable="True" Checked="MI_Change_Header" Unchecked="MI_Change_Header" IsEnabled="False"/>
<MenuItem x:Name="MI_UpdateMode" Header="Update Mode" IsCheckable="True" Checked="MI_Change_Header" Unchecked="MI_Change_Header" IsEnabled="False"/>
<Separator/>
<MenuItem x:Name="MI_Settings" Header="Settings" InputGestureText="F1" Command="{x:Static commands:FModel_Commands.OpenSettings}">
<MenuItem.Icon>

View File

@ -155,7 +155,8 @@ namespace FModel
//LOAD AND EXTRACT DIFF
if (MI_DifferenceMode.IsChecked && MI_UpdateMode.IsChecked)
{
//not done yet
await PAKsLoader.LoadDifference();
await AssetsLoader.ExtractUpdateMode();
}
}
private void MI_ReloadAESs_Click(object sender, RoutedEventArgs e)
@ -250,10 +251,21 @@ namespace FModel
{
MI_LoadAllPAKs.Header = "Load And Extract Difference";
MI_UpdateMode.IsEnabled = true;
MI_Auto_Save_Images.IsChecked = true; //auto save images
if (MI_DifferenceMode.IsChecked && MI_UpdateMode.IsChecked)
{
if (!FormsUtility.IsWindowOpen<Window>("Update Mode"))
{
new FModel_UpdateMode().Show();
}
else { FormsUtility.GetOpenedWindow<Window>("Update Mode").Focus(); }
}
}
if (!MI_UpdateMode.IsChecked)
{
MI_LoadAllPAKs.Header = "Load Difference";
MI_Auto_Save_Images.IsChecked = false;
}
//BOTH

View File

@ -7,7 +7,7 @@
mc:Ignorable="d"
Title="Search"
Height="700"
Width="1000"
Width="1100"
Style="{StaticResource {x:Type Window}}"
WindowStartupLocation="CenterScreen"
Icon="/FModel;component/Logo.ico"
@ -38,12 +38,13 @@
<Separator/>
<MenuItem x:Name="RC_Properties" Header="Properties" Click="RC_Properties_Click">
<MenuItem.Icon>
<Image Source="/FModel;component/Resources/StatusAnnotations_Information_16xLG_color.png" Width="16" Height="16"/>
<Image Source="/FModel;component/Resources/info_16x.png" Width="16" Height="16"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
<Button x:Name="GoTo_Button" Content="Go To Selected Asset" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" Width="120" Click="GoTo_Button_Click"/>
<Button x:Name="GoTo_Button" Content="Go To Selected Asset" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" Width="120" Click="GoTo_Button_Click" Margin="10,0,0,0"/>
<Label x:Name="FoundNumber_Label" Content="Found 0 asset" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,10,0" Padding="0"/>
</Grid>
</Window>

View File

@ -9,6 +9,7 @@ using System.IO;
using FModel.Methods.Assets;
using FProp = FModel.Properties.Settings;
using System;
using System.Globalization;
namespace FModel.Forms
{
@ -57,26 +58,34 @@ namespace FModel.Forms
}
}
private static async Task PopulateDataGrid()
private async Task PopulateDataGrid()
{
Dictionary<string, string> IfExistChecker = new Dictionary<string, string>();
int i = 0;
await Task.Run(() =>
{
if (!string.IsNullOrEmpty(FWindow.FCurrentPAK))
{
FillList(PAKEntries.PAKToDisplay[FWindow.FCurrentPAK], IfExistChecker);
FPakEntry[] ohyeah = PAKEntries.PAKToDisplay[FWindow.FCurrentPAK];
FillList(ohyeah, IfExistChecker);
i = ohyeah.Length;
}
else
{
foreach (FPakEntry[] PAKsFileInfos in PAKEntries.PAKToDisplay.Values)
{
FillList(PAKsFileInfos, IfExistChecker);
i += PAKsFileInfos.Length;
}
}
}).ContinueWith(TheTask =>
{
TasksUtility.TaskCompleted(TheTask.Exception);
});
//max = million
FoundNumber_Label.Content = $"Found {i.ToString("# ### ###", new NumberFormatInfo{ NumberGroupSeparator = " " }).Trim()} assets";
}
private static void FillList(FPakEntry[] EntryArray, Dictionary<string, string> ExistChecker)

View File

@ -57,7 +57,7 @@
<ComboBoxItem Content="Flat"/>
<ComboBoxItem Content="Minimalist"/>
</ComboBox>
<Border BorderThickness="1" Background="#FF252D36" HorizontalAlignment="Right" Height="164" Margin="398,0,0,0" Width="164" VerticalAlignment="Top">
<Border BorderThickness="1" BorderBrush="#7F748198" Background="#FF252D36" HorizontalAlignment="Right" Height="164" Margin="398,0,0,0" Width="164" VerticalAlignment="Top">
<Image x:Name="ImageBox_RarityPreview" Source="/FModel;component/Resources/Template_D_N.png" UseLayoutRounding="True"/>
</Border>
@ -94,7 +94,7 @@
<Slider x:Name="OpacityBanner_Slider" Style="{StaticResource Horizontal_Slider}" Thumb.DragCompleted="UpdateChallengeCustomTheme" HorizontalAlignment="Left" Margin="57,112,0,0" VerticalAlignment="Top" Maximum="255" Width="242" Background="#FF333C46" BorderBrush="#7F748198" Foreground="{x:Null}" IsEnabled="False"/>
<CheckBox x:Name="bCustomChallenge" Content="Custom Theme" HorizontalAlignment="Left" Margin="6,59,0,0" VerticalAlignment="Top" Checked="EnableDisableCustomTheme" Unchecked="EnableDisableCustomTheme"/>
<Border BorderThickness="1" Background="#FF252D36" HorizontalAlignment="Right" Height="105" Width="258" VerticalAlignment="Top" Margin="0,3,0,0">
<Border BorderThickness="1" BorderBrush="#7F748198" Background="#FF252D36" HorizontalAlignment="Right" Height="105" Width="258" VerticalAlignment="Top" Margin="0,3,0,0">
<Image x:Name="ImageBox_ChallengePreview" Source="/FModel;component/Resources/Template_Challenge.png" UseLayoutRounding="True"/>
</Border>
<Button x:Name="OpenChallengeTheme_Button" Content="Open Image" HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="258" Click="OpenChallengeTheme_Button_Click" Margin="0,0,0,3"/>

View File

@ -1,7 +1,6 @@
using FModel.Methods.MessageBox;
using System.Windows;
using System;
using FProp = FModel.Properties.Settings;
using System.Windows.Controls;
using System.ComponentModel;
using System.Reflection;
@ -17,9 +16,7 @@ using Ookii.Dialogs.Wpf;
using System.Globalization;
using FModel.Methods.Assets.IconCreator;
using ColorPickerWPF;
using Newtonsoft.Json;
using System.Collections.Generic;
using FModel.Methods.PAKs;
using FProp = FModel.Properties.Settings;
namespace FModel.Forms
{

View File

@ -0,0 +1,71 @@
<Window x:Class="FModel.Forms.FModel_UpdateMode"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:FModel.Forms"
mc:Ignorable="d"
Title="Update Mode" Height="315" Width="700" UseLayoutRounding="True"
Style="{StaticResource {x:Type Window}}" WindowStartupLocation="CenterScreen" Icon="/FModel;component/Logo.ico" ResizeMode="CanMinimize" Loaded="Window_Loaded">
<Grid>
<ListBox x:Name="AssetsListBox" HorizontalAlignment="Left" Height="225" Margin="10,10,0,0" VerticalAlignment="Top" Width="250" ItemsSource="{Binding Assets}" SelectionChanged="AssetsListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}"/>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem x:Name="RC_Properties" Header="Properties" Click="RC_Properties_Click">
<MenuItem.Icon>
<Image Width="16" Height="16" Source="/FModel;component/Resources/info_16x.png"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
<Label Content="Name:" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="265,10,0,0"/>
<TextBox x:Name="NameTextBox" Height="19" Margin="307,13,10,0" TextWrapping="NoWrap" VerticalAlignment="Top" Foreground="#FFEFEFEF"/>
<Label Content="Path:" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="265,35,0,0"/>
<TextBox x:Name="PathTextBox" Text="/FortniteGame/Content/Athena/..." Height="19" Margin="307,38,10,0" TextWrapping="NoWrap" VerticalAlignment="Top" Foreground="#FFEFEFEF"/>
<Button x:Name="Button_AddAssetType" Content="Add" HorizontalAlignment="Right" Margin="0,62,10,0" VerticalAlignment="Top" Width="80" Height="19" Click="Button_AddAssetType_Click"/>
<Button x:Name="Button_RemoveAssetType" Content="Remove Selected" HorizontalAlignment="Right" Margin="0,62,95,0" VerticalAlignment="Top" Width="110" Height="19" IsEnabled="False" Click="Button_RemoveAssetType_Click"/>
<Border BorderThickness="1" BorderBrush="#7F748198" Background="#FF252D36" HorizontalAlignment="Left" Height="144" Margin="265,91,0,0" Width="411" VerticalAlignment="Top">
<Image x:Name="ImageBox_RarityPreview" Source="/FModel;component/Resources/Template_D_N.png" UseLayoutRounding="True" HorizontalAlignment="Right" Height="140" Width="140" Margin="0,0,1,0"/>
</Border>
<Label Content="Language:" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="265,91,0,0"/>
<ComboBox x:Name="ComboBox_Language" HorizontalAlignment="Left" Margin="324,94,0,0" VerticalAlignment="Top" Width="202" BorderBrush="#7F748198" Background="#FF333C46">
<ComboBoxItem Content="English"/>
<ComboBoxItem Content="French"/>
<ComboBoxItem Content="German"/>
<ComboBoxItem Content="Italian"/>
<ComboBoxItem Content="Spanish"/>
<ComboBoxItem Content="Spanish (LA)"/>
<ComboBoxItem Content="Arabic"/>
<ComboBoxItem Content="Japanese"/>
<ComboBoxItem Content="Korean"/>
<ComboBoxItem Content="Polish"/>
<ComboBoxItem Content="Portuguese (Brazil)"/>
<ComboBoxItem Content="Russian"/>
<ComboBoxItem Content="Turkish"/>
<ComboBoxItem Content="Chinese (S)"/>
<ComboBoxItem Content="Traditional Chinese"/>
</ComboBox>
<Label Content="Rarity Design:" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="265,116,0,0"/>
<ComboBox x:Name="ComboBox_Design" HorizontalAlignment="Left" Margin="341,119,0,0" VerticalAlignment="Top" Width="185" BorderBrush="#7F748198" Background="#FF333C46" IsReadOnly="True" SelectionChanged="UpdateImageBox">
<ComboBoxItem Content="Default"/>
<ComboBoxItem Content="Flat"/>
<ComboBoxItem Content="Minimalist"/>
</ComboBox>
<CheckBox x:Name="bFeaturedIcon" Content="Shop Item Icon" HorizontalAlignment="Left" Margin="438,143,0,0" VerticalAlignment="Top" Checked="UpdateImageBox" Unchecked="UpdateImageBox"/>
<CheckBox x:Name="bWatermarkIcon" Content="Watermark" HorizontalAlignment="Left" Margin="271,188,0,0" VerticalAlignment="Top" Checked="EnableDisableWatermark" Unchecked="EnableDisableWatermark"/>
<Button x:Name="OpenFile_Button" Content="+" HorizontalAlignment="Left" Margin="352,184,0,0" VerticalAlignment="Top" Width="19" IsEnabled="False" Click="OpenFile_Button_Click"/>
<Label x:Name="Watermark_Label" Content="File Name: " MaxWidth="240" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="376,183,0,0"/>
<Label Content="Opacity:" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="265,205,0,0"/>
<Slider x:Name="Opacity_Slider" Style="{StaticResource Horizontal_Slider}" Thumb.DragCompleted="UpdateImageWithWatermark" HorizontalAlignment="Left" Margin="330,208,0,0" VerticalAlignment="Top" Maximum="255" Width="196" Background="#FF333C46" BorderBrush="#7F748198" Foreground="{x:Null}" IsEnabled="False"/>
<Button Content="OK" HorizontalAlignment="Right" Margin="0,0,10,10" VerticalAlignment="Bottom" Width="80" Click="Button_Click"/>
</Grid>
</Window>

View File

@ -0,0 +1,351 @@
using FModel.Methods;
using FModel.Methods.Assets;
using FModel.Methods.MessageBox;
using FModel.Methods.Utilities;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using FProp = FModel.Properties.Settings;
namespace FModel.Forms
{
/// <summary>
/// Logique d'interaction pour FModel_UpdateMode.xaml
/// </summary>
public partial class FModel_UpdateMode : Window
{
#region CLASS
public class AssetProperties : INotifyPropertyChanged
{
public string Name { get; set; }
public string Path { get; set; }
//Provide change-notification for IsChecked
[JsonIgnore]
private bool _fIsChecked = false;
public bool IsChecked
{
get { return _fIsChecked; }
set
{
_fIsChecked = value;
this.OnPropertyChanged("IsChecked");
}
}
//Provide change-notification for IsSelected
[JsonIgnore]
private bool _fIsSelected = false;
public bool IsSelected
{
get { return _fIsSelected; }
set
{
_fIsSelected = value;
this.OnPropertyChanged("IsSelected");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string strPropertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(strPropertyName));
}
}
#endregion
#region ENUMS
enum LIndexes
{
[Description("English")]
English = 0,
[Description("French")]
French = 1,
[Description("German")]
German = 2,
[Description("Italian")]
Italian = 3,
[Description("Spanish")]
Spanish = 4,
[Description("Spanish (LA)")]
Spanish_LA = 5,
[Description("Arabic")]
Arabic = 6,
[Description("Japanese")]
Japanese = 7,
[Description("Korean")]
Korean = 8,
[Description("Polish")]
Polish = 9,
[Description("Portuguese (Brazil)")]
Portuguese_Brazil = 10,
[Description("Russian")]
Russian = 11,
[Description("Turkish")]
Turkish = 12,
[Description("Chinese (S)")]
Chinese_S = 13,
[Description("Traditional Chinese")]
Traditional_Chinese = 14
}
enum RIndexes
{
[Description("Default")]
Default = 0,
[Description("Flat")]
Flat = 1,
[Description("Minimalist")]
Minimalist = 2
}
public static T GetEnumValueFromDescription<T>(string description)
{
var type = typeof(T);
if (!type.IsEnum) { throw new ArgumentException(); }
FieldInfo[] fields = type.GetFields();
var field = fields
.SelectMany(f => f.GetCustomAttributes(
typeof(DescriptionAttribute), false), (
f, a) => new { Field = f, Att = a })
.Where(a => ((DescriptionAttribute)a.Att)
.Description == description).SingleOrDefault();
return field == null ? default(T) : (T)field.Field.GetRawConstantValue();
}
#endregion
public ObservableCollection<AssetProperties> Assets { get; set; }
public static Dictionary<string, Dictionary<string, string>> AssetsEntriesDict { get; set; }
public FModel_UpdateMode()
{
InitializeComponent();
}
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
FoldersUtility.CheckWatermark();
ComboBox_Language.SelectedIndex = (int)GetEnumValueFromDescription<LIndexes>(FProp.Default.FLanguage);
ComboBox_Design.SelectedIndex = (int)GetEnumValueFromDescription<RIndexes>(FProp.Default.FRarity_Design);
bFeaturedIcon.IsChecked = FProp.Default.FIsFeatured;
bWatermarkIcon.IsChecked = FProp.Default.FUseWatermark;
Watermark_Label.Content += Path.GetFileName(FProp.Default.FWatermarkFilePath);
Opacity_Slider.Value = FProp.Default.FWatermarkOpacity;
AssetsEntriesDict = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(FProp.Default.FUM_AssetsType);
Assets = new ObservableCollection<AssetProperties>();
foreach (KeyValuePair<string, Dictionary<string, string>> a in AssetsEntriesDict)
{
Assets.Add(new AssetProperties
{
Name = a.Key,
Path = a.Value["Path"],
IsChecked = bool.Parse(a.Value["isChecked"])
});
}
DataContext = this;
await UpdateImageWithWatermark();
}
private async void UpdateImageBox(object sender, RoutedEventArgs e)
{
await UpdateImageWithWatermark();
}
private async void UpdateImageWithWatermark(object sender, RoutedEventArgs e)
{
await UpdateImageWithWatermark();
}
private async Task UpdateImageWithWatermark()
{
bool watermarkEnabled = (bool)bWatermarkIcon.IsChecked;
bool isFeatured = (bool)bFeaturedIcon.IsChecked;
string rarityDesign = ((ComboBoxItem)ComboBox_Design.SelectedItem).Content.ToString();
int opacity = Convert.ToInt32(Opacity_Slider.Value);
double scale = FProp.Default.FWatermarkScale;
await Task.Run(() =>
{
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext drawingContext = drawingVisual.RenderOpen())
{
//INITIALIZATION
drawingContext.DrawRectangle(Brushes.Transparent, null, new Rect(new Point(0, 0), new Size(515, 515)));
BitmapImage source = null;
switch (rarityDesign)
{
case "Default":
source = new BitmapImage(new Uri(isFeatured ? "pack://application:,,,/Resources/Template_D_F.png" : "pack://application:,,,/Resources/Template_D_N.png"));
break;
case "Flat":
source = new BitmapImage(new Uri(isFeatured ? "pack://application:,,,/Resources/Template_F_F.png" : "pack://application:,,,/Resources/Template_F_N.png"));
break;
case "Minimalist":
source = new BitmapImage(new Uri(isFeatured ? "pack://application:,,,/Resources/Template_M_F.png" : "pack://application:,,,/Resources/Template_M_N.png"));
break;
}
drawingContext.DrawImage(source, new Rect(new Point(0, 0), new Size(515, 515)));
if (!string.IsNullOrEmpty(FProp.Default.FWatermarkFilePath) && watermarkEnabled)
{
using (StreamReader image = new StreamReader(FProp.Default.FWatermarkFilePath))
{
if (image != null)
{
BitmapImage bmp = new BitmapImage();
bmp.BeginInit();
bmp.CacheOption = BitmapCacheOption.OnLoad;
bmp.StreamSource = image.BaseStream;
bmp.EndInit();
drawingContext.DrawImage(ImagesUtility.CreateTransparency(bmp, opacity), new Rect(FProp.Default.FWatermarkXPos, FProp.Default.FWatermarkYPos, scale, scale));
}
}
}
}
if (drawingVisual != null)
{
RenderTargetBitmap RTB = new RenderTargetBitmap(515, 515, 96, 96, PixelFormats.Pbgra32);
RTB.Render(drawingVisual);
RTB.Freeze(); //We freeze to apply the RTB to our imagesource from the UI Thread
FWindow.FMain.Dispatcher.InvokeAsync(() =>
{
ImageBox_RarityPreview.Source = BitmapFrame.Create(RTB); //thread safe and fast af
});
}
}).ContinueWith(TheTask =>
{
TasksUtility.TaskCompleted(TheTask.Exception);
});
}
private async void EnableDisableWatermark(object sender, RoutedEventArgs e)
{
OpenFile_Button.IsEnabled = (bool)bWatermarkIcon.IsChecked;
Opacity_Slider.IsEnabled = (bool)bWatermarkIcon.IsChecked;
await UpdateImageWithWatermark();
}
private async void OpenFile_Button_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog openFiledialog = new Microsoft.Win32.OpenFileDialog();
openFiledialog.Title = "Choose your watermark";
openFiledialog.Multiselect = false;
openFiledialog.Filter = "PNG Files (*.png)|*.png|All Files (*.*)|*.*";
if (openFiledialog.ShowDialog() == true)
{
Watermark_Label.Content = "File Name: " + Path.GetFileName(openFiledialog.FileName);
FProp.Default.FWatermarkFilePath = openFiledialog.FileName;
FProp.Default.Save();
await UpdateImageWithWatermark();
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
AssetsEntriesDict = new Dictionary<string, Dictionary<string, string>>();
foreach (AssetProperties a in Assets)
{
AssetsEntriesDict[a.Name] = new Dictionary<string, string>();
AssetsEntriesDict[a.Name]["Path"] = a.Path;
AssetsEntriesDict[a.Name]["isChecked"] = a.IsChecked.ToString();
}
if (AssetEntries.AssetEntriesDict != null && !string.Equals(FProp.Default.FLanguage, ((ComboBoxItem)ComboBox_Language.SelectedItem).Content.ToString()))
{
AssetTranslations.SetAssetTranslation(((ComboBoxItem)ComboBox_Language.SelectedItem).Content.ToString());
}
FProp.Default.FLanguage = ((ComboBoxItem)ComboBox_Language.SelectedItem).Content.ToString();
FProp.Default.FRarity_Design = ((ComboBoxItem)ComboBox_Design.SelectedItem).Content.ToString();
FProp.Default.FIsFeatured = (bool)bFeaturedIcon.IsChecked;
FProp.Default.FUseWatermark = (bool)bWatermarkIcon.IsChecked;
FProp.Default.FWatermarkOpacity = Convert.ToInt32(Opacity_Slider.Value);
FProp.Default.FUM_AssetsType = JsonConvert.SerializeObject(AssetsEntriesDict, Formatting.Indented);
FProp.Default.Save();
Close();
}
private void AssetsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count > 0) { ((ListBox)sender).ScrollIntoView(e.AddedItems[0]); }
Button_RemoveAssetType.IsEnabled = AssetsListBox.SelectedIndex >= 0;
}
private void Button_RemoveAssetType_Click(object sender, RoutedEventArgs e)
{
if (AssetsListBox.Items.Count > 0 && AssetsListBox.SelectedItems.Count > 0)
{
Assets.Remove(AssetsListBox.SelectedItem as AssetProperties);
}
}
private void Button_AddAssetType_Click(object sender, RoutedEventArgs e)
{
string path = PathTextBox.Text.Trim();
if (!path.StartsWith("/"))
path = path.Insert(0, "/");
if (!path.EndsWith("/"))
path += "/";
Assets.Add(new AssetProperties
{
Name = NameTextBox.Text,
Path = path,
IsSelected = true
});
}
private void RC_Properties_Click(object sender, RoutedEventArgs e)
{
if (AssetsListBox.SelectedIndex >= 0)
{
AssetProperties a = AssetsListBox.SelectedItem as AssetProperties;
string infos = GetAssetInfos(a);
if (DarkMessageBox.ShowYesNo(infos, a.Name, "Copy Properties", "OK") == MessageBoxResult.Yes)
{
Clipboard.SetText(infos);
new UpdateMyConsole(a.Name, CColors.Blue).Append();
new UpdateMyConsole("'s properties successfully copied", CColors.White, true).Append();
}
}
}
private static string GetAssetInfos(AssetProperties a)
{
StringBuilder sb = new StringBuilder();
sb.Append(
"\n- Name:\t\t" + a.Name +
"\n- Path:\t\t" + a.Path +
"\n- Checked:\t" + a.IsChecked +
"\n- Selected:\tTrue" +
"\n"
);
return sb.ToString();
}
}
}

View File

@ -9,7 +9,6 @@ using System.Threading.Tasks;
using System.Linq;
using System.IO;
using System.Windows.Media;
using FProp = FModel.Properties.Settings;
namespace FModel.Methods.Assets
{
@ -56,7 +55,6 @@ namespace FModel.Methods.Assets
FWindow.FMain.Button_Extract.IsEnabled = true;
FWindow.FMain.Button_Stop.IsEnabled = false;
}
public static async Task ExtractFoldersAndSub(string path)
{
new UpdateMyProcessEvents("", "").Update();
@ -127,8 +125,70 @@ namespace FModel.Methods.Assets
FWindow.FMain.Button_Extract.IsEnabled = true;
FWindow.FMain.Button_Stop.IsEnabled = false;
}
public static async Task ExtractUpdateMode()
{
new UpdateMyProcessEvents("", "").Update();
FWindow.FMain.MI_UpdateMode.IsEnabled = true;
FWindow.FMain.Button_Extract.IsEnabled = false;
FWindow.FMain.Button_Stop.IsEnabled = true;
FWindow.FMain.AssetPropertiesBox_Main.Text = string.Empty;
FWindow.FMain.AssetPropertiesBox_Main.SyntaxHighlighting = ResourceLoader.LoadHighlightingDefinition("Json.xshd");
FWindow.FMain.ImageBox_Main.Source = null;
private static void LoadAsset(string assetPath)
List<IEnumerable<string>> assetList = new List<IEnumerable<string>>();
foreach (FPakEntry[] PAKsFileInfos in PAKEntries.PAKToDisplay.Values)
{
IEnumerable<string> files = PAKsFileInfos
.Where(x => Forms.FModel_UpdateMode.AssetsEntriesDict.Any(c => bool.Parse(c.Value["isChecked"]) && x.Name.StartsWith(c.Value["Path"])))
.Select(x => x.Name);
if (files != null) { assetList.Add(files); }
}
TasksUtility.CancellableTaskTokenSource = new CancellationTokenSource();
CancellationToken cToken = TasksUtility.CancellableTaskTokenSource.Token;
await Task.Run(() =>
{
isRunning = true;
foreach (IEnumerable<string> filesFromOnePak in assetList)
{
foreach (string asset in filesFromOnePak.OrderBy(s => s))
{
cToken.ThrowIfCancellationRequested(); //if clicked on 'Stop' it breaks at the following item
string target;
if (asset.EndsWith(".uexp") || asset.EndsWith(".ubulk")) { continue; }
else if (!asset.EndsWith(".uasset"))
{
target = asset; //ini uproject locres etc
}
else
{
target = asset.Substring(0, asset.LastIndexOf(".")); //uassets
}
FWindow.FMain.Dispatcher.InvokeAsync(() => //ui thread because if not, FCurrentAsset isn't updated in time to Auto Save a JSON Data for example
{
FWindow.FCurrentAsset = Path.GetFileName(target);
});
LoadAsset(target);
}
}
}, cToken).ContinueWith(TheTask =>
{
TasksUtility.TaskCompleted(TheTask.Exception);
TasksUtility.CancellableTaskTokenSource.Dispose();
isRunning = false;
});
FWindow.FMain.MI_Auto_Save_Images.IsChecked = false;
FWindow.FMain.Button_Extract.IsEnabled = true;
FWindow.FMain.Button_Stop.IsEnabled = false;
new UpdateMyProcessEvents("All assets have been extracted successfully", "Success").Update();
}
public static void LoadAsset(string assetPath)
{
PakReader.PakReader reader = AssetsUtility.GetPakReader(assetPath);
if (reader != null)

View File

@ -127,7 +127,7 @@ namespace FModel.Methods.PAKs
catch (Exception ex)
{
if (string.Equals(ex.Message, "The AES key is invalid")) { UIHelper.DisplayError(); }
else { UIHelper.DisplayEmergencyError(ex); return; }
else { new UpdateMyConsole(ex.Message, CColors.Red, true).Append(); return; }
break;
}
@ -171,7 +171,7 @@ namespace FModel.Methods.PAKs
catch (Exception ex)
{
if (string.Equals(ex.Message, "The AES key is invalid")) { UIHelper.DisplayError(Path.GetFileNameWithoutExtension(Pak.ThePAKPath), AESFromManager); }
else { UIHelper.DisplayEmergencyError(ex); return; }
else { new UpdateMyConsole(ex.Message, CColors.Red, true).Append(); return; }
continue;
}
@ -290,9 +290,9 @@ namespace FModel.Methods.PAKs
FWindow.FMain.ViewModel = srt;
});
new UpdateMyProcessEvents("All PAK files have been compared successfully", "Success").Update();
await FWindow.FMain.Dispatcher.InvokeAsync(() =>
{
new UpdateMyProcessEvents("All PAK files have been compared successfully", "Success").Update();
FWindow.FMain.TreeView_Main.IsEnabled = true;
FWindow.FMain.MI_LoadAllPAKs.IsEnabled = true;
FWindow.FMain.MI_BackupPAKs.IsEnabled = true;

View File

@ -358,5 +358,47 @@ namespace FModel.Properties {
this["FAutoSaveImg"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("{\r\n \"[BR] Cosmetics\": {\r\n \"Path\": \"/FortniteGame/Content/Athena/Items/Cosmeti" +
"cs/\",\r\n \"isChecked\": \"True\"\r\n },\r\n \"[BR] Cosmetics Variants\": {\r\n \"Path\"" +
": \"/FortniteGame/Content/Athena/Items/CosmeticVariantTokens/\",\r\n \"isChecked\":" +
" \"True\"\r\n },\r\n \"[BR] Banners\": {\r\n \"Path\": \"/FortniteGame/Content/Athena/It" +
"ems/BannerToken/\",\r\n \"isChecked\": \"True\"\r\n },\r\n \"[BR] Challenges\": {\r\n \"" +
"Path\": \"/FortniteGame/Content/Athena/Items/ChallengeBundles/\",\r\n \"isChecked\":" +
" \"True\"\r\n },\r\n \"[BR] Consumables\": {\r\n \"Path\": \"/FortniteGame/Content/Athen" +
"a/Items/Consumables/\",\r\n \"isChecked\": \"False\"\r\n },\r\n \"[BR] Traps\": {\r\n \"" +
"Path\": \"/FortniteGame/Content/Athena/Items/Traps/\",\r\n \"isChecked\": \"False\"\r\n " +
" },\r\n \"[BR] Weapons\": {\r\n \"Path\": \"/FortniteGame/Content/Athena/Items/Weapon" +
"s/\",\r\n \"isChecked\": \"True\"\r\n },\r\n \"[BR] 2D Assets\": {\r\n \"Path\": \"/Fortni" +
"teGame/Content/2dAssets/\",\r\n \"isChecked\": \"True\"\r\n },\r\n \"[BR] Featured Imag" +
"es\": {\r\n \"Path\": \"/FortniteGame/Content/UI/Foundation/Textures/BattleRoyale/F" +
"eaturedItems/\",\r\n \"isChecked\": \"False\"\r\n },\r\n \"[STW] Heroes\": {\r\n \"Path\"" +
": \"/FortniteGame/Content/Heroes/\",\r\n \"isChecked\": \"False\"\r\n },\r\n \"[STW] Def" +
"enders\": {\r\n \"Path\": \"/FortniteGame/Content/Items/Defenders/\",\r\n \"isChecke" +
"d\": \"False\"\r\n },\r\n \"[STW] Schematics\": {\r\n \"Path\": \"/FortniteGame/Content/I" +
"tems/Schematics/\",\r\n \"isChecked\": \"False\"\r\n },\r\n \"[STW] Traps\": {\r\n \"Pat" +
"h\": \"/FortniteGame/Content/Items/Traps/\",\r\n \"isChecked\": \"False\"\r\n },\r\n \"[S" +
"TW] Weapons\": {\r\n \"Path\": \"/FortniteGame/Content/Items/Weapons/\",\r\n \"isChe" +
"cked\": \"False\"\r\n },\r\n \"[STW] Ingredients\": {\r\n \"Path\": \"/FortniteGame/Conte" +
"nt/Items/Ingredients/\",\r\n \"isChecked\": \"False\"\r\n },\r\n \"[STW] Persistent Res" +
"ources\": {\r\n \"Path\": \"/FortniteGame/Content/Items/PersistentResources/\",\r\n " +
" \"isChecked\": \"False\"\r\n },\r\n \"[STW] CardPacks\": {\r\n \"Path\": \"/FortniteGame/" +
"Content/Items/CardPacks/\",\r\n \"isChecked\": \"False\"\r\n },\r\n \"Tokens\": {\r\n \"" +
"Path\": \"/FortniteGame/Content/Items/Tokens/\",\r\n \"isChecked\": \"False\"\r\n },\r\n " +
" \"Icons\": {\r\n \"Path\": \"/FortniteGame/Content/UI/Foundation/Textures/Icons/\",\r" +
"\n \"isChecked\": \"False\"\r\n },\r\n \"Additional Banners\": {\r\n \"Path\": \"/Fortni" +
"teGame/Content/UI/Foundation/Textures/Banner/\",\r\n \"isChecked\": \"False\"\r\n },\r" +
"\n \"Additional Loading Screens\": {\r\n \"Path\": \"/FortniteGame/Content/UI/Founda" +
"tion/Textures/LoadingScreens/\",\r\n \"isChecked\": \"False\"\r\n }\r\n}")]
public string FUM_AssetsType {
get {
return ((string)(this["FUM_AssetsType"]));
}
set {
this["FUM_AssetsType"] = value;
}
}
}
}

View File

@ -86,5 +86,93 @@
<Setting Name="FAutoSaveImg" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="FUM_AssetsType" Type="System.String" Scope="User">
<Value Profile="(Default)">{
"[BR] Cosmetics": {
"Path": "/FortniteGame/Content/Athena/Items/Cosmetics/",
"isChecked": "True"
},
"[BR] Cosmetics Variants": {
"Path": "/FortniteGame/Content/Athena/Items/CosmeticVariantTokens/",
"isChecked": "True"
},
"[BR] Banners": {
"Path": "/FortniteGame/Content/Athena/Items/BannerToken/",
"isChecked": "True"
},
"[BR] Challenges": {
"Path": "/FortniteGame/Content/Athena/Items/ChallengeBundles/",
"isChecked": "True"
},
"[BR] Consumables": {
"Path": "/FortniteGame/Content/Athena/Items/Consumables/",
"isChecked": "False"
},
"[BR] Traps": {
"Path": "/FortniteGame/Content/Athena/Items/Traps/",
"isChecked": "False"
},
"[BR] Weapons": {
"Path": "/FortniteGame/Content/Athena/Items/Weapons/",
"isChecked": "True"
},
"[BR] 2D Assets": {
"Path": "/FortniteGame/Content/2dAssets/",
"isChecked": "True"
},
"[BR] Featured Images": {
"Path": "/FortniteGame/Content/UI/Foundation/Textures/BattleRoyale/FeaturedItems/",
"isChecked": "False"
},
"[STW] Heroes": {
"Path": "/FortniteGame/Content/Heroes/",
"isChecked": "False"
},
"[STW] Defenders": {
"Path": "/FortniteGame/Content/Items/Defenders/",
"isChecked": "False"
},
"[STW] Schematics": {
"Path": "/FortniteGame/Content/Items/Schematics/",
"isChecked": "False"
},
"[STW] Traps": {
"Path": "/FortniteGame/Content/Items/Traps/",
"isChecked": "False"
},
"[STW] Weapons": {
"Path": "/FortniteGame/Content/Items/Weapons/",
"isChecked": "False"
},
"[STW] Ingredients": {
"Path": "/FortniteGame/Content/Items/Ingredients/",
"isChecked": "False"
},
"[STW] Persistent Resources": {
"Path": "/FortniteGame/Content/Items/PersistentResources/",
"isChecked": "False"
},
"[STW] CardPacks": {
"Path": "/FortniteGame/Content/Items/CardPacks/",
"isChecked": "False"
},
"Tokens": {
"Path": "/FortniteGame/Content/Items/Tokens/",
"isChecked": "False"
},
"Icons": {
"Path": "/FortniteGame/Content/UI/Foundation/Textures/Icons/",
"isChecked": "False"
},
"Additional Banners": {
"Path": "/FortniteGame/Content/UI/Foundation/Textures/Banner/",
"isChecked": "False"
},
"Additional Loading Screens": {
"Path": "/FortniteGame/Content/UI/Foundation/Textures/LoadingScreens/",
"isChecked": "False"
}
}</Value>
</Setting>
</Settings>
</SettingsFile>

View File

@ -70,10 +70,10 @@
## How To Use
To run this program, you'll need [.NET Framework 4.7.1](https://dotnet.microsoft.com/download/dotnet-framework/net471) or newer installed on your computer. Once it's done, you can download the latest release [here](https://github.com/iAmAsval/FModel/releases/latest/download/FModel.zip).
To run this program, you'll need [.NET Framework 4.7.2](https://dotnet.microsoft.com/download/dotnet-framework/net472) or newer installed on your computer. Once it's done, you can download the latest release [here](https://github.com/iAmAsval/FModel/releases/latest/download/FModel.zip).
1. Extract `FModel.exe` and `libSkiaSharp.dll` somewhere - __double click on FModel.exe__
2. You're now asked to set the path to your Fortnite .PAK files - __click on Load and then on Settings__
2. The path to your Fortnite .PAK files should be automatically detected but you can still set it manually - __click on Load and then on Settings__
3. You'll need the AES key in order to read the files - __click on AES Manager and enter the key under Static Key__
4. You can now load one or all .PAK files
5. Navigate through the tree to find the Asset you want