diff --git a/ForzaModelTool/App.xaml b/ForzaModelTool/App.xaml
index 26b8e30..9fa8fef 100644
--- a/ForzaModelTool/App.xaml
+++ b/ForzaModelTool/App.xaml
@@ -4,6 +4,10 @@
xmlns:local="clr-namespace:ForzaModelTool"
StartupUri="MainWindow.xaml">
-
+
+
+
+
+
diff --git a/ForzaModelTool/ForzaModelTool.csproj b/ForzaModelTool/ForzaModelTool.csproj
index adc5be6..af8d3c0 100644
--- a/ForzaModelTool/ForzaModelTool.csproj
+++ b/ForzaModelTool/ForzaModelTool.csproj
@@ -2,11 +2,12 @@
WinExe
- net5.0-windows
+ net7.0-windows
true
true
app.manifest
stare.ico
+ 2.0.0
diff --git a/ForzaModelTool/MainWindow.xaml b/ForzaModelTool/MainWindow.xaml
index bb6049d..21ab568 100644
--- a/ForzaModelTool/MainWindow.xaml
+++ b/ForzaModelTool/MainWindow.xaml
@@ -4,15 +4,24 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" WindowStartupLocation="CenterScreen"
- Title="Forza Model Replacer" Height="450" Width="350" ResizeMode="NoResize" WindowStyle="None" AllowsTransparency="True" Background="Transparent" MouseDown="MainWindow_MouseDown">
+ Title="Forza Model Replacer" Height="500" Width="350" ResizeMode="NoResize" WindowStyle="None" AllowsTransparency="True" Background="Transparent" MouseDown="MainWindow_MouseDown">
-
-
+
+
+
+
+
+
+
+
+
+
-
+
@@ -21,10 +30,11 @@
-
-
-
+
+
@@ -32,35 +42,34 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/ForzaModelTool/MainWindow.xaml.cs b/ForzaModelTool/MainWindow.xaml.cs
index 9dea3cf..589b162 100644
--- a/ForzaModelTool/MainWindow.xaml.cs
+++ b/ForzaModelTool/MainWindow.xaml.cs
@@ -3,8 +3,7 @@
using System.Windows.Input;
using System.Windows.Forms;
using System.IO;
-using System.IO.Compression;
-using System.Text;
+using System.Diagnostics;
namespace ForzaModelTool
{
@@ -34,14 +33,13 @@ private void MinButton_Click(object sender, RoutedEventArgs e)
WindowState = WindowState.Minimized;
}
#endregion
- string GamePath;
- string[] DonorCar;
- string[] TargetCar;
- string GamePathMedia = "\\media\\cars";
- readonly string tempPath = System.IO.Path.GetTempPath();
+
+ public static bool validPath;
+ public static string GamePath;
+ public static string rawPath = $"{"C:\\Users\\"}{Environment.UserName}{"\\Documents\\Forza Model Tool\\"}";
//click on path button > select game path, if wrong throws error message, if correct move on
- private void BTN_Path_Click(object sender, RoutedEventArgs e)
+ public void BTN_Path_Click(object sender, RoutedEventArgs e)
{
//Pop-up to select Folder, yoinked from YT
FolderBrowserDialog dialog = new();
@@ -51,325 +49,31 @@ private void BTN_Path_Click(object sender, RoutedEventArgs e)
//if game path includes ForzaHorizon5.exe or not
if (File.Exists(GamePath + "\\ForzaHorizon5.exe"))
{
- TXT_GamePath.Text = new FileInfo(GamePath).DirectoryName;
+ validPath = true;
+ TXT_GamePath.Text = new FileInfo(GamePath).FullName;
TXT_NoPath.Visibility = Visibility.Hidden;
- BTN_Swapper.IsEnabled = true;
BTN_Path.IsEnabled = false;
- BTN_Zip.IsEnabled = true;
- BTN_CLR.IsEnabled = true;
- CarLists();
}
else
{
System.Windows.MessageBox.Show("Path is wrong or not selected.", "Error", MessageBoxButton.OK, (MessageBoxImage)MessageBoxIcon.Error);
+ validPath = false;
TXT_NoPath.Visibility = Visibility.Visible;
- BTN_Swapper.IsEnabled = false;
- BTN_Zip.IsEnabled = false;
- BTN_CLR.IsEnabled = false;
- }
- }
-
- //fill car lists
- private void CarLists()
- {
- // scrap car zips from GamePath + \media\cars
- DonorCar = Directory.GetFiles(GamePath + GamePathMedia);
- foreach (string donoCar in DonorCar)
- {
- // removes path + file extension so it looks cleaner
- LST_DonorCar.Items.Add(Path.GetFileNameWithoutExtension(donoCar));
- }
- TargetCar = Directory.GetFiles(GamePath + GamePathMedia);
- foreach (string targCar in TargetCar)
- {
- LST_TargetCar.Items.Add(Path.GetFileNameWithoutExtension(targCar));
- }
- }
- //looks in GamePath + CarName.zip from list for .modelbin, lists all in new dropdown list
- private void ModelLists(string models)
- {
- using (ZipArchive archive = ZipFile.OpenRead($"{GamePath}{GamePathMedia}{"\\"}{models}{".zip"}"))
- {
- foreach (ZipArchiveEntry entry in archive.Entries)
- {
- if (models == (string)LST_DonorCar.SelectedItem)
- {
- if (entry.FullName.EndsWith(".modelbin")) LST_DonorModel.Items.Add(entry);
- }
- else if (models == (string)LST_TargetCar.SelectedItem)
- {
- if (entry.FullName.EndsWith(".modelbin")) LST_TargetModel.Items.Add(entry);
- }
- }
- }
- }
-
- //checks if item from dropdown list is not null, clears list and runs ModelLists method to populate list again
- private void LST_DonorCar_SelectionChanged(object sender, EventArgs e)
- {
- if (LST_DonorCar.SelectedItem != null)
- {
- LST_DonorModel.Items.Clear();
- ModelLists((string)LST_DonorCar.SelectedItem);
- }
- }
- private void LST_TargetCar_SelectionChanged(object sender, EventArgs e)
- {
- if (LST_TargetCar.SelectedItem != null)
- {
- LST_TargetModel.Items.Clear();
- ModelLists((string)LST_TargetCar.SelectedItem);
}
}
- private void BTN_Swapper_Click(object sender, RoutedEventArgs e)
+ // view switching (from szaamerik)
+ private void CategoryButton_Click(object sender, RoutedEventArgs e)
{
- // if dono + target models are selected disable buttons and run Swapper()
- if (LST_DonorModel.SelectedItem != null && LST_TargetModel.SelectedItem != null)
- {
- if (!Directory.Exists(tempPath + "Forza Model Tool"))
- {
- Directory.CreateDirectory(tempPath + "Forza Model Tool");
- }
- LST_DonorCar.IsEnabled = false;
- LST_DonorModel.IsEnabled = false;
- LST_TargetCar.IsEnabled = false;
- LST_TargetModel.IsEnabled = false;
- BTN_Swapper.IsEnabled = false;
- BTN_Zip.IsEnabled = false;
- BTN_CLR.IsEnabled = false;
- Swapper();
- LST_DonorCar.IsEnabled = true;
- LST_DonorModel.IsEnabled = true;
- LST_TargetCar.IsEnabled = true;
- LST_TargetModel.IsEnabled = true;
- BTN_Swapper.IsEnabled = true;
- BTN_Zip.IsEnabled = true;
- BTN_CLR.IsEnabled = true;
- }
- else if (LST_DonorModel.SelectedItem == null && LST_TargetModel.SelectedItem != null)
- {
- System.Windows.MessageBox.Show("No Donator Model selected.", "Error", MessageBoxButton.OK, (MessageBoxImage)MessageBoxIcon.Error);
- }
- else if (LST_DonorModel.SelectedItem != null && LST_TargetModel.SelectedItem == null)
- {
- System.Windows.MessageBox.Show("No Target Model selected.", "Error", MessageBoxButton.OK, (MessageBoxImage)MessageBoxIcon.Error);
- }
- else System.Windows.MessageBox.Show("No Models selected.", "Error", MessageBoxButton.OK, (MessageBoxImage)MessageBoxIcon.Error);
+ DisplayFrame.Source = new Uri((string)((System.Windows.Controls.Button)sender).Tag, UriKind.Relative);
}
- private void BTN_Zip_Click(object sender, RoutedEventArgs e)
+ // check/create base folders
+ public static void FolderCheck()
{
- //Import + Export strings to make things easier
- string GamePath2 = $"{GamePath}{"\\media\\Stripped\\MediaOverride\\RC0\\"}{"Cars"}";
- string tempPath2 = tempPath + @"Forza Model Tool\";
-
- //
- if (Directory.Exists($"{tempPath2}{"Export\\"}"))
- {
- string ExportPath = $"{tempPath2}{"Export\\"}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}";
- //if zip does not exist
- if (!File.Exists($"{ExportPath}{".zip"}"))
- {
- if (!Directory.Exists(ExportPath))
- System.Windows.MessageBox.Show($"{"The folder \""}{LST_TargetCar.SelectedItem}{"\" is missing. \nPlease swap a model first before trying to create the zip."}", "Missing Folder", MessageBoxButton.OK, MessageBoxImage.Error);
- else
- {
- //create zip of target model(s) with name of target car
- ZipFile.CreateFromDirectory(ExportPath, $"{ExportPath}{".zip"}");
-
- //if target car zip in '\media\Stripped\MediaOverride\RC0\Cars' does not exist
- if (!File.Exists($"{GamePath2}{"\\"}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".zip"}"))
- {
- //move said zip to '\media\Stripped\MediaOverride\RC0\Cars'
- File.Move($"{ExportPath}{".zip"}", $"{GamePath2}{"\\"}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".zip"}");
- System.Windows.MessageBox.Show($"{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".zip"}" + " was successfully created!", ":)");
- }
- else
- {
- //throws "error" popup that the target car zip already exists in that directory, user can overwrite said zip by pressing yes button
- MessageBoxResult result;
- result = System.Windows.MessageBox.Show($"{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".zip"}" + " already exists. Do you want to overwrite it?", "Warning", MessageBoxButton.YesNo, MessageBoxImage.Warning);
- if (result == MessageBoxResult.Yes)
- {
- //move + overwrite created target zip to '\media\Stripped\MediaOverride\RC0\Cars'
- File.Move($"{ExportPath}{".zip"}", $"{GamePath2}{"\\"}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".zip"}", true);
- System.Windows.MessageBox.Show($"{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".zip"}" + " was successfully created!", ":)");
- }
- //if no, target car zip inside export folder gets deleted
- else
- {
- File.Delete($"{ExportPath}{".zip"}");
- System.Windows.MessageBox.Show($"{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".zip"}" + " was not created.", ":(");
- }
- }
- }
- }
- }
- else System.Windows.MessageBox.Show("You need to swap a model first before you can create a zip!", "Missing Folder/Model", MessageBoxButton.OK, MessageBoxImage.Error);
- }
-
- private void Swapper()
- {
- //Import + Export strings to make things easier
- string tempPath2 = tempPath + @"Forza Model Tool\";
- string ExportPath = $"{tempPath2}{"Export\\"}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}";
- string ImportPath = $"{tempPath2}{"Import\\"}{Path.GetFileNameWithoutExtension(LST_DonorCar.SelectedItem.ToString())}";
-
- //check if donor car folder inside 'temp\forza model tool\import' does not exist
- if (!Directory.Exists(ImportPath))
- {
- //Extract selected dono car zip to new Folder inside 'temp\forza model tool\import'
- ZipFile.ExtractToDirectory($"{GamePath}{GamePathMedia}{"\\"}{LST_DonorCar.SelectedItem}{".zip"}", ImportPath);
- }
- //check if temp car folder inside 'temp\forza model tool\export' + folder structure of target model does not exist
- if (!Directory.Exists($"{ExportPath}{"\\"}{Path.GetDirectoryName(LST_TargetModel.SelectedItem.ToString())}"))
- {
- //Create necessary folder structure inside selected Target car folder (folder of car name + folders like "scene", "exterior", etc.)
- Directory.CreateDirectory($"{ExportPath}{"\\"}{Path.GetDirectoryName(LST_TargetModel.SelectedItem.ToString())}");
- }
-
- //copy + overwrite selected donor model to selected target model path (folders are being "constructed"[combined])
- File.Copy(Path.Combine(ImportPath, LST_DonorModel.SelectedItem.ToString()), Path.Combine(ExportPath, LST_TargetModel.SelectedItem.ToString()), true);
-
- CarbinSwap();
- }
-
- private void CarbinSwap()
- {
- //Import + Export strings to make things easier
- string tempPath2 = tempPath + @"Forza Model Tool\";
- string ExportPath = $"{tempPath2}{"Export\\"}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}";
- string ImportPath = $"{tempPath2}{"Import\\"}";
- string DonorCarbin = $"{ImportPath}{Path.GetFileNameWithoutExtension(LST_DonorCar.SelectedItem.ToString())}{"\\"}{Path.GetFileNameWithoutExtension(LST_DonorCar.SelectedItem.ToString())}{".carbin"}";
- string TargetCarbin = $"{ExportPath}{"\\"}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".carbin"}";
-
- if (!Directory.Exists($"{ImportPath}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}"))
- {
- ZipFile.ExtractToDirectory($"{GamePath}{GamePathMedia}{"\\"}{LST_TargetCar.SelectedItem}{".zip"}", $"{ImportPath}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}");
- }
- if (!File.Exists(TargetCarbin))
- {
- File.Copy($"{ImportPath}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{"\\"}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".carbin"}", TargetCarbin);
- }
-
- // searches for first byte of 'pattern' inside 'src', if first byte found try to match 'pattern'
- int Search(byte[] src, byte[] pattern, int startOfIndex)
- {
- int maxFirstCharSlot = src.Length - pattern.Length + 1;
- for (int i = startOfIndex; i < maxFirstCharSlot; i++)
- {
- if (src[i] != pattern[0]) // compare only first byte
- continue;
-
- // found a match on first byte, now try to match rest of the pattern
- for (int j = pattern.Length - 1; j >= 1; j--)
- {
- if (src[i + j] != pattern[j]) break;
- if (j == 1) return i;
- }
- }
- return 69;
- }
-
- byte[] PatternFF = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
- byte[] DonoFileBytes = File.ReadAllBytes(DonorCarbin);
- byte[] DonoSearchBytes = Encoding.ASCII.GetBytes(Path.GetFileName(LST_DonorModel.SelectedItem.ToString().ToLower()));
- int DonoStartPosition = Search(DonoFileBytes, DonoSearchBytes, 0);
- int DonoEndPosition = Search(DonoFileBytes, PatternFF, DonoStartPosition);
-
- byte[] TargFileBytes = File.ReadAllBytes(TargetCarbin);
- byte[] TargSearchBytes = Encoding.ASCII.GetBytes(Path.GetFileName(LST_TargetModel.SelectedItem.ToString().ToLower()));
- int TargStartPosition = Search(TargFileBytes, TargSearchBytes, 0);
- int TargEndPosition = Search(TargFileBytes, PatternFF, TargStartPosition);
-
- // read carbin from target car, dump everything till selected target model texture entry into temp.dat
- using (FileStream targCarb = File.OpenRead(TargetCarbin))
- using (FileStream writeStream = File.OpenWrite(tempPath2 + "temp.dat"))
- {
- // create a buffer to hold the bytes
- byte[] buffer = new byte[1024];
- int bytesRead;
-
- // while beginning of selected target model texture entry is bigger than current position read + write into file
- while (TargStartPosition + Path.GetFileName(LST_TargetModel.SelectedItem.ToString()).Length + 70 > targCarb.Position)
- {
- bytesRead = targCarb.Read(buffer, 0, 1);
- writeStream.Write(buffer, 0, bytesRead);
- }
- targCarb.Flush();
- targCarb.Close();
- }
-
- // read carbin from dono car, dump selected model texture entry into temp.dat
- using (FileStream donoCarb = File.OpenRead(DonorCarbin))
- using (FileStream writeStream = File.OpenWrite(tempPath2 + "temp.dat"))
- {
- byte[] buffer = new Byte[1024];
- int bytesRead;
- int yeppers = 0;
-
- // seek inside carbin to beginning of needed texture entry. seek inside temp.dat to end of the file
- donoCarb.Seek(DonoStartPosition + Path.GetFileName(LST_DonorModel.SelectedItem.ToString()).Length + 70, SeekOrigin.Begin);
- // seek to end of temp.dat
- writeStream.Seek(TargStartPosition + Path.GetFileName(LST_TargetModel.SelectedItem.ToString()).Length + 70, SeekOrigin.Begin);
- // while selected texture entry is bigger than 'yeppers' read and write into file. yeppers = 0 and gets increased by 1 after each read + write
- while (DonoEndPosition - (DonoStartPosition + Path.GetFileName(LST_DonorModel.SelectedItem.ToString()).Length + 70) > yeppers)
- {
- bytesRead = donoCarb.Read(buffer, 0, 1);
- writeStream.Write(buffer, 0, bytesRead);
- yeppers++;
- }
- writeStream.Flush();
- writeStream.Close();
- }
-
- // read target car carbin, dump rest of the file
- using (FileStream targCarb = File.OpenRead(TargetCarbin))
- using (FileStream writeStream = File.Open(tempPath2 + "temp.dat", FileMode.Open))
- {
- byte[] buffer = new byte[1024];
- int bytesRead;
-
- // seek to end of
- targCarb.Seek(TargEndPosition, SeekOrigin.Begin);
- // seek to end of temp.dat again
- writeStream.Seek(TargStartPosition + Path.GetFileName(LST_TargetModel.SelectedItem.ToString()).Length + 70 + DonoEndPosition - (DonoStartPosition + Path.GetFileName(LST_DonorModel.SelectedItem.ToString()).Length + 70), SeekOrigin.Begin);
- while ((bytesRead = targCarb.Read(buffer, 0, 1024)) > 0)
- {
- writeStream.Write(buffer, 0, bytesRead);
- }
- targCarb.Flush();
- targCarb.Close();
- }
-
- // delete target carbin, rename "temp.dat" to target carbin and move to its location
- File.Delete(TargetCarbin);
- File.Copy(tempPath2 + "temp.dat", TargetCarbin);
- File.Delete(tempPath2 + "temp.dat");
-
- System.Windows.MessageBox.Show($"{"Successfully swapped \""}{Path.GetFileName(LST_DonorModel.SelectedItem.ToString())}{"\" from \""}{Path.GetFileNameWithoutExtension(LST_DonorCar.SelectedItem.ToString())}" +
- $"{"\" to \""}{Path.GetFileName(LST_TargetModel.SelectedItem.ToString())}{"\" from \""}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{"\"."}", "Swap successful!");
- }
-
- private void BTN_CLR_Click(object sender, RoutedEventArgs e)
- {
- string tempPath2 = tempPath + @"Forza Model Tool\";
- string ExportPath = $"{tempPath2}{"Export\\"}";
- string ImportPath = $"{tempPath2}{"Import\\"}";
-
- // if Export folder exists remove both Export and Import folders
- if (Directory.Exists($"{ExportPath}"))
- {
- MessageBoxResult result;
- result = System.Windows.MessageBox.Show("This will delete all created folders + files inside \"" + tempPath + "Forza Model Tool\" \nAre you sure you want to proceed?", "Warning", MessageBoxButton.YesNo, MessageBoxImage.Warning);
- if (result == MessageBoxResult.Yes)
- {
- Directory.Delete(ImportPath, true);
- Directory.Delete(ExportPath, true);
- }
- }
- else System.Windows.MessageBox.Show("There is nothing to delete.");
+ Directory.CreateDirectory(System.IO.Path.Combine(rawPath));
+ Directory.CreateDirectory(System.IO.Path.Combine(rawPath + "Model Swap"));
+ Directory.CreateDirectory(System.IO.Path.Combine(rawPath + "Wheel Swap"));
}
}
}
diff --git a/ForzaModelTool/Themes/ButtonTheme.xaml b/ForzaModelTool/Themes/ButtonTheme.xaml
new file mode 100644
index 0000000..e12928e
--- /dev/null
+++ b/ForzaModelTool/Themes/ButtonTheme.xaml
@@ -0,0 +1,12 @@
+
+
+
\ No newline at end of file
diff --git a/ForzaModelTool/Views/ModelSwapView.xaml b/ForzaModelTool/Views/ModelSwapView.xaml
new file mode 100644
index 0000000..9017ff9
--- /dev/null
+++ b/ForzaModelTool/Views/ModelSwapView.xaml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ForzaModelTool/Views/ModelSwapView.xaml.cs b/ForzaModelTool/Views/ModelSwapView.xaml.cs
new file mode 100644
index 0000000..42be33d
--- /dev/null
+++ b/ForzaModelTool/Views/ModelSwapView.xaml.cs
@@ -0,0 +1,351 @@
+using System;
+using System.IO.Compression;
+using System.IO;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Diagnostics;
+
+namespace ForzaModelTool.Views
+{
+ public partial class ModelSwapView : UserControl
+ {
+ public ModelSwapView()
+ {
+ InitializeComponent();
+ }
+
+ string GamePath;
+ string[] Cars;
+ string GamePathMedia = "\\media\\cars";
+ readonly string rawPath = MainWindow.rawPath;
+
+ #region Clickable Things
+ public void SelectableOn()
+ {
+ LST_DonorCar.IsEnabled = true;
+ LST_DonorModel.IsEnabled = true;
+ LST_TargetCar.IsEnabled = true;
+ LST_TargetModel.IsEnabled = true;
+ BTN_Swapper.IsEnabled = true;
+ BTN_Zip.IsEnabled = true;
+ BTN_CLR.IsEnabled = true;
+ }
+
+ public void SelectableOff()
+ {
+ LST_DonorCar.IsEnabled = false;
+ LST_DonorModel.IsEnabled = false;
+ LST_TargetCar.IsEnabled = false;
+ LST_TargetModel.IsEnabled = false;
+ BTN_Swapper.IsEnabled = false;
+ BTN_Zip.IsEnabled = false;
+ BTN_CLR.IsEnabled = false;
+ }
+ #endregion
+
+ // if lists are empty, fill car lists
+ public void CarLists()
+ {
+ GamePath = MainWindow.GamePath;
+ // scrap car zips from GamePath + \media\cars
+ if (LST_DonorCar.Items.IsEmpty)
+ {
+ Cars = Directory.GetFiles(GamePath + GamePathMedia);
+ foreach (string car in Cars)
+ {
+ // removes path + file extension so it looks cleaner
+ LST_DonorCar.Items.Add(Path.GetFileNameWithoutExtension(car));
+ LST_TargetCar.Items.Add(Path.GetFileNameWithoutExtension(car));
+ }
+ }
+ }
+
+ //looks in GamePath + CarName.zip from list for .modelbin, lists all in new dropdown list
+ private void ModelLists(string models)
+ {
+ using (ZipArchive archive = ZipFile.OpenRead($"{GamePath}{GamePathMedia}{"\\"}{models}{".zip"}"))
+ {
+ foreach (ZipArchiveEntry entry in archive.Entries)
+ {
+ if (models == (string)LST_DonorCar.SelectedItem)
+ {
+ if (entry.FullName.EndsWith(".modelbin")) LST_DonorModel.Items.Add(entry);
+ }
+ else if (models == (string)LST_TargetCar.SelectedItem)
+ {
+ if (entry.FullName.EndsWith(".modelbin")) LST_TargetModel.Items.Add(entry);
+ }
+ }
+ }
+ }
+
+ //checks if item from dropdown list is not null, clears list and runs ModelLists method to populate list again
+ private void LST_DonorCar_SelectionChanged(object sender, EventArgs e)
+ {
+ if (LST_DonorCar.SelectedItem != null)
+ {
+ LST_DonorModel.Items.Clear();
+ ModelLists((string)LST_DonorCar.SelectedItem);
+ }
+ }
+ private void LST_TargetCar_SelectionChanged(object sender, EventArgs e)
+ {
+ if (LST_TargetCar.SelectedItem != null)
+ {
+ LST_TargetModel.Items.Clear();
+ ModelLists((string)LST_TargetCar.SelectedItem);
+ }
+ }
+
+ // call CarList() to make the combobox actually work (idfk why i have to do this all of a sudden, its so fucking retarded)
+ private void LST_TargetCar_Opened(object sender, EventArgs e)
+ {
+ if (MainWindow.validPath)
+ {
+ SelectableOn();
+ CarLists();
+ }
+ }
+
+ private void LST_DonorCar_Opened(object sender, EventArgs e)
+ {
+ if (MainWindow.validPath)
+ {
+ SelectableOn();
+ CarLists();
+ }
+ }
+
+ private void BTN_Swapper_Click(object sender, RoutedEventArgs e)
+ {
+ // if dono + target models are selected disable buttons and run Swapper()
+ if (LST_DonorModel.SelectedItem != null && LST_TargetModel.SelectedItem != null)
+ {
+ MainWindow.FolderCheck();
+ SelectableOff();
+ Swapper();
+ SelectableOn();
+ }
+ else if (LST_DonorModel.SelectedItem == null && LST_TargetModel.SelectedItem != null)
+ {
+ System.Windows.MessageBox.Show("No Donator Model selected.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ else if (LST_DonorModel.SelectedItem != null && LST_TargetModel.SelectedItem == null)
+ {
+ System.Windows.MessageBox.Show("No Target Model selected.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ else System.Windows.MessageBox.Show("No Models selected.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+
+ private void BTN_Zip_Click(object sender, RoutedEventArgs e)
+ {
+ //Import + Export strings to make things easier
+ string GamePath2 = $"{GamePath}{"\\media\\Stripped\\MediaOverride\\RC0\\"}{"Cars"}";
+
+ //
+ if (Directory.Exists($"{rawPath}{"Model Swap\\Export\\"}"))
+ {
+ string ExportPath = $"{rawPath}{"Model Swap\\Export\\"}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}";
+ //if zip does not exist
+ if (!File.Exists($"{ExportPath}{".zip"}"))
+ {
+ if (!Directory.Exists(ExportPath))
+ System.Windows.MessageBox.Show($"{"The folder \""}{LST_TargetCar.SelectedItem}{"\" is missing. \nPlease swap a model first before trying to create the zip."}", "Missing Folder", MessageBoxButton.OK, MessageBoxImage.Error);
+ else
+ {
+ //create zip of target model(s) with name of target car
+ ZipFile.CreateFromDirectory(ExportPath, $"{ExportPath}{".zip"}");
+
+ //if target car zip in '\media\Stripped\MediaOverride\RC0\Cars' does not exist
+ if (!File.Exists($"{GamePath2}{"\\"}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".zip"}"))
+ {
+ //move said zip to '\media\Stripped\MediaOverride\RC0\Cars'
+ File.Move($"{ExportPath}{".zip"}", $"{GamePath2}{"\\"}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".zip"}");
+ System.Windows.MessageBox.Show($"{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".zip"}" + " was successfully created!", ":)");
+ }
+ else
+ {
+ //throws "error" popup that the target car zip already exists in that directory, user can overwrite said zip by pressing yes button
+ MessageBoxResult result;
+ result = System.Windows.MessageBox.Show($"{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".zip"}" + " already exists. Do you want to overwrite it?", "Warning", MessageBoxButton.YesNo, MessageBoxImage.Warning);
+ if (result == MessageBoxResult.Yes)
+ {
+ //move + overwrite created target zip to '\media\Stripped\MediaOverride\RC0\Cars'
+ File.Move($"{ExportPath}{".zip"}", $"{GamePath2}{"\\"}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".zip"}", true);
+ System.Windows.MessageBox.Show($"{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".zip"}" + " was successfully created!", ":)");
+ }
+ //if no, target car zip inside export folder gets deleted
+ else
+ {
+ File.Delete($"{ExportPath}{".zip"}");
+ System.Windows.MessageBox.Show($"{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".zip"}" + " was not created.", ":(");
+ }
+ }
+ }
+ }
+ }
+ else System.Windows.MessageBox.Show("You need to swap a model first before you can create a zip!", "Missing Folder/Model", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+
+ private void Swapper()
+ {
+ //Import + Export strings to make things easier
+ string ExportPath = $"{rawPath}{"Model Swap\\Export\\"}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}";
+ string ImportPath = $"{rawPath}{"Model Swap\\Import\\"}{Path.GetFileNameWithoutExtension(LST_DonorCar.SelectedItem.ToString())}";
+
+ //check if donor car folder inside 'temp\forza model tool\import' does not exist
+ if (!Directory.Exists(ImportPath))
+ {
+ //Extract selected dono car zip to new Folder inside 'temp\forza model tool\import'
+ ZipFile.ExtractToDirectory($"{GamePath}{GamePathMedia}{"\\"}{LST_DonorCar.SelectedItem}{".zip"}", ImportPath);
+ }
+ //check if temp car folder inside 'temp\forza model tool\export' + folder structure of target model does not exist
+ if (!Directory.Exists($"{ExportPath}{"\\"}{Path.GetDirectoryName(LST_TargetModel.SelectedItem.ToString())}"))
+ {
+ //Create necessary folder structure inside selected Target car folder (folder of car name + folders like "scene", "exterior", etc.)
+ Directory.CreateDirectory($"{ExportPath}{"\\"}{Path.GetDirectoryName(LST_TargetModel.SelectedItem.ToString())}");
+ }
+
+ //copy + overwrite selected donor model to selected target model path (folders are being "constructed"[combined])
+ File.Copy(Path.Combine(ImportPath, LST_DonorModel.SelectedItem.ToString()), Path.Combine(ExportPath, LST_TargetModel.SelectedItem.ToString()), true);
+
+ CarbinSwap();
+ }
+
+ private void CarbinSwap()
+ {
+ //Import + Export strings to make things easier
+ string ExportPath = $"{rawPath}{"Model Swap\\Export\\"}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}";
+ string ImportPath = $"{rawPath}{"Model Swap\\Import\\"}";
+ string DonorCarbin = $"{ImportPath}{Path.GetFileNameWithoutExtension(LST_DonorCar.SelectedItem.ToString())}{"\\"}{Path.GetFileNameWithoutExtension(LST_DonorCar.SelectedItem.ToString())}{".carbin"}";
+ string TargetCarbin = $"{ExportPath}{"\\"}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".carbin"}";
+
+ if (!Directory.Exists($"{ImportPath}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}"))
+ {
+ ZipFile.ExtractToDirectory($"{GamePath}{GamePathMedia}{"\\"}{LST_TargetCar.SelectedItem}{".zip"}", $"{ImportPath}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}");
+ }
+ if (!File.Exists(TargetCarbin))
+ {
+ File.Copy($"{ImportPath}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{"\\"}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{".carbin"}", TargetCarbin);
+ }
+
+ // searches for first byte of 'pattern' inside 'src', if first byte found try to match 'pattern'
+ int Search(byte[] src, byte[] pattern, int startOfIndex)
+ {
+ int maxFirstCharSlot = src.Length - pattern.Length + 1;
+ for (int i = startOfIndex; i < maxFirstCharSlot; i++)
+ {
+ if (src[i] != pattern[0]) // compare only first byte
+ continue;
+
+ // found a match on first byte, now try to match rest of the pattern
+ for (int j = pattern.Length - 1; j >= 1; j--)
+ {
+ if (src[i + j] != pattern[j]) break;
+ if (j == 1) return i;
+ }
+ }
+ return 69;
+ }
+
+ byte[] PatternFF = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ byte[] DonoFileBytes = File.ReadAllBytes(DonorCarbin);
+ byte[] DonoSearchBytes = Encoding.ASCII.GetBytes(Path.GetFileName(LST_DonorModel.SelectedItem.ToString().ToLower()));
+ int DonoStartPosition = Search(DonoFileBytes, DonoSearchBytes, 0);
+ int DonoEndPosition = Search(DonoFileBytes, PatternFF, DonoStartPosition);
+
+ byte[] TargFileBytes = File.ReadAllBytes(TargetCarbin);
+ byte[] TargSearchBytes = Encoding.ASCII.GetBytes(Path.GetFileName(LST_TargetModel.SelectedItem.ToString().ToLower()));
+ int TargStartPosition = Search(TargFileBytes, TargSearchBytes, 0);
+ int TargEndPosition = Search(TargFileBytes, PatternFF, TargStartPosition);
+
+ // read carbin from target car, dump everything till selected target model texture entry into temp.dat
+ using (FileStream targCarb = File.OpenRead(TargetCarbin))
+ using (FileStream writeStream = File.OpenWrite(rawPath + "Model Swap\\temp.dat"))
+ {
+ // create a buffer to hold the bytes
+ byte[] buffer = new byte[1024];
+ int bytesRead;
+
+ // while beginning of selected target model texture entry is bigger than current position read + write into file
+ while (TargStartPosition + Path.GetFileName(LST_TargetModel.SelectedItem.ToString()).Length + 70 > targCarb.Position)
+ {
+ bytesRead = targCarb.Read(buffer, 0, 1);
+ writeStream.Write(buffer, 0, bytesRead);
+ }
+ targCarb.Flush();
+ targCarb.Close();
+ }
+
+ // read carbin from dono car, dump selected model texture entry into temp.dat
+ using (FileStream donoCarb = File.OpenRead(DonorCarbin))
+ using (FileStream writeStream = File.OpenWrite(rawPath + "Model Swap\\temp.dat"))
+ {
+ byte[] buffer = new Byte[1024];
+ int bytesRead;
+ int yeppers = 0;
+
+ // seek inside carbin to beginning of needed texture entry. seek inside temp.dat to end of the file
+ donoCarb.Seek(DonoStartPosition + Path.GetFileName(LST_DonorModel.SelectedItem.ToString()).Length + 70, SeekOrigin.Begin);
+ // seek to end of temp.dat
+ writeStream.Seek(TargStartPosition + Path.GetFileName(LST_TargetModel.SelectedItem.ToString()).Length + 70, SeekOrigin.Begin);
+ // while selected texture entry is bigger than 'yeppers' read and write into file. yeppers = 0 and gets increased by 1 after each read + write
+ while (DonoEndPosition - (DonoStartPosition + Path.GetFileName(LST_DonorModel.SelectedItem.ToString()).Length + 70) > yeppers)
+ {
+ bytesRead = donoCarb.Read(buffer, 0, 1);
+ writeStream.Write(buffer, 0, bytesRead);
+ yeppers++;
+ }
+ writeStream.Flush();
+ writeStream.Close();
+ }
+
+ // read target car carbin, dump rest of the file
+ using (FileStream targCarb = File.OpenRead(TargetCarbin))
+ using (FileStream writeStream = File.Open(rawPath + "Model Swap\\temp.dat", FileMode.Open))
+ {
+ byte[] buffer = new byte[1024];
+ int bytesRead;
+
+ // seek to end of
+ targCarb.Seek(TargEndPosition, SeekOrigin.Begin);
+ // seek to end of temp.dat again
+ writeStream.Seek(TargStartPosition + Path.GetFileName(LST_TargetModel.SelectedItem.ToString()).Length + 70 + DonoEndPosition - (DonoStartPosition + Path.GetFileName(LST_DonorModel.SelectedItem.ToString()).Length + 70), SeekOrigin.Begin);
+ while ((bytesRead = targCarb.Read(buffer, 0, 1024)) > 0)
+ {
+ writeStream.Write(buffer, 0, bytesRead);
+ }
+ targCarb.Flush();
+ targCarb.Close();
+ }
+
+ // delete target carbin, rename "temp.dat" to target carbin and move to its location
+ File.Delete(TargetCarbin);
+ File.Copy(rawPath + "Model Swap\\temp.dat", TargetCarbin);
+ File.Delete(rawPath + "Model Swap\\temp.dat");
+
+ System.Windows.MessageBox.Show($"{"Successfully swapped \""}{Path.GetFileName(LST_DonorModel.SelectedItem.ToString())}{"\" from \""}{Path.GetFileNameWithoutExtension(LST_DonorCar.SelectedItem.ToString())}" +
+ $"{"\" to \""}{Path.GetFileName(LST_TargetModel.SelectedItem.ToString())}{"\" from \""}{Path.GetFileNameWithoutExtension(LST_TargetCar.SelectedItem.ToString())}{"\"."}", "Swap successful!");
+ }
+
+ private void BTN_CLR_Click(object sender, RoutedEventArgs e)
+ {
+ string ModelSwapPath = $"{rawPath}{"Model Swap\\"}";
+ string WheelSwapPath = $"{rawPath}{"Wheel Swap\\"}";
+
+ // if Export folder exists remove both Export and Import folders
+ if (Directory.Exists(ModelSwapPath))
+ {
+ MessageBoxResult result;
+ result = System.Windows.MessageBox.Show("This will delete all created folders + files inside \"" + this.rawPath + " \nAre you sure you want to proceed?", "Warning", MessageBoxButton.YesNo, MessageBoxImage.Warning);
+ if (result == MessageBoxResult.Yes)
+ {
+ Directory.Delete(ModelSwapPath, true);
+ Directory.Delete(WheelSwapPath, true);
+ }
+ }
+ else System.Windows.MessageBox.Show("There is nothing to delete.");
+ }
+ }
+}
diff --git a/ForzaModelTool/Views/WheelSwapView.xaml b/ForzaModelTool/Views/WheelSwapView.xaml
new file mode 100644
index 0000000..49cfcea
--- /dev/null
+++ b/ForzaModelTool/Views/WheelSwapView.xaml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Enabling this will create a new zip of the wheels which can be added to the game instead of replacing existing ones. If you don't have access to the gamedb this will be useless to you.
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ForzaModelTool/Views/WheelSwapView.xaml.cs b/ForzaModelTool/Views/WheelSwapView.xaml.cs
new file mode 100644
index 0000000..c59de02
--- /dev/null
+++ b/ForzaModelTool/Views/WheelSwapView.xaml.cs
@@ -0,0 +1,322 @@
+using System;
+using System.IO.Compression;
+using System.IO;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Diagnostics;
+using System.Diagnostics.Eventing.Reader;
+
+namespace ForzaModelTool.Views
+{
+ public partial class WheelSwapView : UserControl
+ {
+ public WheelSwapView()
+ {
+ InitializeComponent();
+ }
+
+ string GamePath;
+ string[] Cars;
+ string[] Wheels;
+ string GamePathMediaC = "\\media\\cars";
+ string GamePathMediaT = "\\media\\cars\\_library";
+ string GamePathMediaW = "\\media\\cars\\_library\\scene\\wheels";
+ readonly string rawPath = MainWindow.rawPath;
+
+ #region Clickable Things
+ public void SelectableOn()
+ {
+ LST_DonorWheel.IsEnabled = true;
+ LST_TargetWheel.IsEnabled = true;
+ LST_WheelVar.IsEnabled = true;
+ BTN_Swapper.IsEnabled = true;
+ }
+
+ public void SelectableOff()
+ {
+ LST_DonorWheel.IsEnabled = false;
+ LST_TargetWheel.IsEnabled = false;
+ LST_WheelVar.IsEnabled = false;
+ BTN_Swapper.IsEnabled = false;
+ }
+ #endregion
+
+ #region Lists + Checkbox
+ private void LST_DonorWheel_Opened(object sender, EventArgs e)
+ {
+ if (MainWindow.validPath)
+ {
+ SelectableOn();
+ CarList();
+ }
+ }
+
+ private void LST_DonorWheel_SelectionChanged(object sender, EventArgs e)
+ {
+ if (LST_DonorWheel.SelectedItem != null)
+ {
+ LST_WheelVar.Items.Clear();
+ WheelVariant((string)LST_DonorWheel.SelectedItem);
+ }
+ }
+
+ private void CBOX_Addon_Clicked(object sender, RoutedEventArgs e)
+ {
+ if (CBOX_Addon.IsChecked == true)
+ {
+ if (LST_TargetWheel.Items != null)
+ LST_TargetWheel.Items.Clear();
+ LST_TargetWheel.IsEnabled = false;
+ }
+ else
+ LST_TargetWheel.IsEnabled = true;
+ }
+
+ private void LST_TargetWheel_Opened(object sender, EventArgs e)
+ {
+ if (MainWindow.validPath)
+ {
+ SelectableOn();
+ WheelList();
+ }
+ }
+ #endregion
+
+ // if list empty, fill car list
+ public void CarList()
+ {
+ GamePath = MainWindow.GamePath;
+ // scrap car zips from GamePath + \media\cars
+ if (LST_DonorWheel.Items.IsEmpty)
+ {
+ Cars = Directory.GetFiles(GamePath + GamePathMediaC);
+ foreach (string car in Cars)
+ LST_DonorWheel.Items.Add(Path.GetFileNameWithoutExtension(car));
+ }
+ }
+
+ // if list empty, fill wheel list (aftermarket wheels)
+ public void WheelList()
+ {
+ GamePath = MainWindow.GamePath;
+ if (LST_TargetWheel.Items.IsEmpty)
+ {
+ Wheels = Directory.GetFiles(GamePath + GamePathMediaW);
+ foreach (string wheel in Wheels)
+ LST_TargetWheel.Items.Add(Path.GetFileNameWithoutExtension(wheel));
+ }
+ }
+
+ // populate wheel variant list (some cars have wheels with different depths aka variants)
+ private void WheelVariant(string car)
+ {
+ using (ZipArchive archive = ZipFile.OpenRead($"{GamePath}{GamePathMediaC}{"\\"}{car}{".zip"}"))
+ foreach (ZipArchiveEntry entry in archive.Entries)
+ if (car == (string)LST_DonorWheel.SelectedItem)
+ if (entry.FullName.Contains("_wheel", StringComparison.OrdinalIgnoreCase) && !entry.FullName.Contains(".swatchbin"))
+ LST_WheelVar.Items.Add(entry.Name);
+ LST_WheelVar.SelectedIndex = 0;
+ }
+
+ private void BTN_Swapper_Click(object sender, RoutedEventArgs e)
+ {
+ // if dono + target models are selected disable buttons and run Swapper()
+ if (LST_DonorWheel.SelectedItem != null && LST_WheelVar.SelectedItem != null && LST_TargetWheel.SelectedItem != null)
+ {
+ MainWindow.FolderCheck();
+ SelectableOff();
+ Swapper(false);
+ SelectableOn();
+ }
+ else if (LST_DonorWheel.SelectedItem != null && LST_WheelVar.SelectedItem != null && LST_TargetWheel.SelectedItem == null)
+ {
+ if (CBOX_Addon.IsChecked == true)
+ {
+ MainWindow.FolderCheck();
+ SelectableOff();
+ Swapper(true);
+ SelectableOn();
+ }
+ else
+ MessageBox.Show("No Target Wheel selected.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ else if (LST_DonorWheel.SelectedItem == null && LST_WheelVar.SelectedItem != null && LST_TargetWheel.SelectedItem != null)
+ MessageBox.Show("No Car Wheel selected.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
+ else if (LST_DonorWheel.SelectedItem != null && LST_WheelVar.SelectedItem == null && LST_TargetWheel.SelectedItem != null)
+ MessageBox.Show("No Car Wheel Variant selected.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
+ else
+ MessageBox.Show("No Wheels selected.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+
+ private void Swapper(bool bChecked)
+ {
+ string ExportCPath = $"{rawPath}{"Wheel Swap\\"}{Path.GetFileNameWithoutExtension(LST_DonorWheel.SelectedItem.ToString())}";
+ string TexturePath = "\\Textures\\AO";
+ string GamePathMediaOW = GamePath + "\\media\\stripped\\mediaoverride\\rc0\\cars\\_library\\scene\\wheels";
+ string[] textureZips = { "\\Textures.zip", "\\Textures_pri_44.zip", "\\Textures_pri_45.zip", "\\Textures_pri_301.zip" };
+ bool foundTexture = false;
+ bool textureError = false;
+
+ // if add-on checkbox checked, create wheel zip with car name, else create wheel zip of selected car wheel renamed to target wheel
+ if (bChecked)
+ {
+ if (!Directory.Exists(ExportCPath))
+ Directory.CreateDirectory($"{ExportCPath}{"\\"}{Path.GetDirectoryName(LST_DonorWheel.SelectedItem.ToString())}{TexturePath}");
+
+ using (ZipArchive archive = ZipFile.OpenRead($"{GamePath}{GamePathMediaC}{"\\"}{LST_DonorWheel.SelectedItem}{".zip"}"))
+ foreach (ZipArchiveEntry entry in archive.Entries)
+ if (entry.FullName.Contains(LST_WheelVar.SelectedItem.ToString(), StringComparison.OrdinalIgnoreCase))
+ archive.GetEntry(entry.FullName).ExtractToFile($"{ExportCPath}{"\\"}{LST_DonorWheel.SelectedItem}{"_wheelLF.modelbin"}", true);
+
+ while (foundTexture == false && textureError == false)
+ {
+ using (ZipArchive archive = ZipFile.OpenRead($"{GamePath}{GamePathMediaC}{"\\"}{LST_DonorWheel.SelectedItem}{".zip"}"))
+ foreach (ZipArchiveEntry entry in archive.Entries)
+ if (entry.FullName.Contains("_wheellf_ao", StringComparison.OrdinalIgnoreCase))
+ {
+ archive.GetEntry(entry.FullName).ExtractToFile($"{ExportCPath}{"\\"}{TexturePath}{"\\"}{entry.Name}", true);
+ foundTexture = true;
+ break;
+ }
+
+ foreach (string zip in textureZips)
+ {
+ if (File.Exists(GamePath + GamePathMediaT + zip))
+ {
+ using (ZipArchive archive = ZipFile.OpenRead($"{GamePath}{GamePathMediaT}{zip}"))
+ {
+ foreach (ZipArchiveEntry entry in archive.Entries)
+ if (entry.FullName.Contains(LST_DonorWheel.SelectedItem.ToString() + "_wheellf_ao", StringComparison.OrdinalIgnoreCase))
+ {
+ archive.GetEntry(entry.FullName).ExtractToFile($"{ExportCPath}{"\\"}{TexturePath}{"\\"}{entry.Name}", true);
+ foundTexture = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!foundTexture)
+ {
+ MessageBox.Show("Texture was not found.", "Missing Texture", MessageBoxButton.OK, MessageBoxImage.Error);
+ textureError = true;
+ }
+ }
+
+ // if texture file found, create + move zip to \media\Stripped\MediaOverride\RC0\Cars\_library\scene\wheels
+ if (foundTexture)
+ {
+ if (!Directory.Exists(GamePathMediaOW))
+ Directory.CreateDirectory(GamePathMediaOW);
+
+ if (!File.Exists($"{ExportCPath}{".zip"}"))
+ {
+ ZipFile.CreateFromDirectory(ExportCPath, $"{GamePathMediaOW}{"\\"}{LST_DonorWheel.SelectedItem}{".zip"}");
+ MessageBox.Show($"{Path.GetFileNameWithoutExtension(LST_DonorWheel.SelectedItem.ToString())}{".zip"}" + " was successfully created!", ":)");
+ }
+ else
+ {
+ //throws "error" popup that the target car zip already exists in that directory, user can overwrite said zip by pressing yes button
+ MessageBoxResult result;
+ result = MessageBox.Show($"{Path.GetFileNameWithoutExtension(LST_DonorWheel.SelectedItem.ToString())}{".zip"}" + " already exists. Do you want to overwrite it?", "Warning", MessageBoxButton.YesNo, MessageBoxImage.Warning);
+ if (result == MessageBoxResult.Yes)
+ {
+ //move + overwrite created target zip to '\media\Stripped\MediaOverride\RC0\Cars\_library\scene\wheels'
+ File.Move($"{ExportCPath}{".zip"}", $"{GamePathMediaOW}{"\\"}{LST_DonorWheel.SelectedItem}{".zip"}", true);
+ MessageBox.Show($"{Path.GetFileNameWithoutExtension(LST_DonorWheel.SelectedItem.ToString())}{".zip"}" + " was successfully created!", ":)");
+ }
+ //if no, target car zip inside export folder gets deleted
+ else
+ {
+ File.Delete($"{ExportCPath}{".zip"}");
+ MessageBox.Show($"{Path.GetFileNameWithoutExtension(LST_DonorWheel.SelectedItem.ToString())}{".zip"}" + " was not created.", ":(");
+ }
+ }
+ }
+ // delete leftover folders/files
+ if (Directory.Exists(ExportCPath))
+ Directory.Delete(ExportCPath, true);
+ }
+ else
+ {
+ string ExportWPath = $"{rawPath}{"Wheel Swap\\"}{Path.GetFileNameWithoutExtension(LST_TargetWheel.SelectedItem.ToString())}";
+
+ if (!Directory.Exists(ExportWPath))
+ Directory.CreateDirectory($"{ExportWPath}{"\\"}{Path.GetDirectoryName(LST_TargetWheel.SelectedItem.ToString())}{TexturePath}");
+
+ using (ZipArchive archive = ZipFile.OpenRead($"{GamePath}{GamePathMediaC}{"\\"}{LST_DonorWheel.SelectedItem}{".zip"}"))
+ foreach (ZipArchiveEntry entry in archive.Entries)
+ if (entry.FullName.Contains(LST_WheelVar.SelectedItem.ToString(), StringComparison.OrdinalIgnoreCase))
+ archive.GetEntry(entry.FullName).ExtractToFile($"{ExportWPath}{"\\"}{LST_TargetWheel.SelectedItem}{"_wheelLF.modelbin"}", true);
+
+ while (foundTexture == false && textureError == false)
+ {
+ using (ZipArchive archive = ZipFile.OpenRead($"{GamePath}{GamePathMediaC}{"\\"}{LST_DonorWheel.SelectedItem}{".zip"}"))
+ foreach (ZipArchiveEntry entry in archive.Entries)
+ if (entry.FullName.Contains("_wheellf_ao", StringComparison.OrdinalIgnoreCase))
+ {
+ archive.GetEntry(entry.FullName).ExtractToFile($"{ExportWPath}{"\\"}{TexturePath}{"\\"}{entry.Name}", true);
+ foundTexture = true;
+ break;
+ }
+
+ foreach (string zip in textureZips)
+ {
+ if (File.Exists(GamePath + GamePathMediaT + zip))
+ {
+ using (ZipArchive archive = ZipFile.OpenRead($"{GamePath}{GamePathMediaT}{zip}"))
+ {
+ foreach (ZipArchiveEntry entry in archive.Entries)
+ if (entry.FullName.Contains(LST_DonorWheel.SelectedItem.ToString() + "_wheellf_ao", StringComparison.OrdinalIgnoreCase))
+ {
+ archive.GetEntry(entry.FullName).ExtractToFile($"{ExportWPath}{"\\"}{TexturePath}{"\\"}{LST_TargetWheel.SelectedItem}{"_wheelLF_AO.swatchbin"}", true);
+ foundTexture = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!foundTexture)
+ {
+ MessageBox.Show("Texture was not found.", "Missing Texture", MessageBoxButton.OK, MessageBoxImage.Error);
+ textureError = true;
+ }
+
+ // if texture file found, create + move zip to \media\Stripped\MediaOverride\RC0\Cars\_library\scene\wheels
+ if (foundTexture)
+ {
+ if (!Directory.Exists(GamePathMediaOW))
+ Directory.CreateDirectory(GamePathMediaOW);
+
+ if (!File.Exists($"{ExportWPath}{".zip"}"))
+ {
+ ZipFile.CreateFromDirectory(ExportWPath, $"{GamePathMediaOW}{"\\"}{LST_TargetWheel.SelectedItem}{".zip"}");
+ MessageBox.Show($"{Path.GetFileNameWithoutExtension(LST_TargetWheel.SelectedItem.ToString())}{".zip"}" + " was successfully created!", ":)");
+ }
+ else
+ {
+ //throws "error" popup that the target car zip already exists in that directory, user can overwrite said zip by pressing yes button
+ MessageBoxResult result;
+ result = MessageBox.Show($"{Path.GetFileNameWithoutExtension(LST_TargetWheel.SelectedItem.ToString())}{".zip"}" + " already exists. Do you want to overwrite it?", "Warning", MessageBoxButton.YesNo, MessageBoxImage.Warning);
+ if (result == MessageBoxResult.Yes)
+ {
+ //move + overwrite created target zip to '\media\Stripped\MediaOverride\RC0\Cars\_library\scene\wheels'
+ File.Move($"{ExportWPath}{".zip"}", $"{GamePathMediaOW}{"\\"}{LST_TargetWheel.SelectedItem}{".zip"}", true);
+ MessageBox.Show($"{Path.GetFileNameWithoutExtension(LST_TargetWheel.SelectedItem.ToString())}{".zip"}" + " was successfully created!", ":)");
+ }
+ //if no, target car zip inside export folder gets deleted
+ else
+ {
+ File.Delete($"{ExportCPath}{".zip"}");
+ MessageBox.Show($"{Path.GetFileNameWithoutExtension(LST_TargetWheel.SelectedItem.ToString())}{".zip"}" + " was not created.", ":(");
+ }
+ }
+ }
+ // delete leftover folders/files
+ if (Directory.Exists(ExportCPath))
+ Directory.Delete(ExportCPath, true);
+ }
+ }
+ }
+ }
+}