diff --git a/FFXIV_TexTools/FFXIV_TexTools.csproj b/FFXIV_TexTools/FFXIV_TexTools.csproj
index d1d580f8..33ffabe6 100644
--- a/FFXIV_TexTools/FFXIV_TexTools.csproj
+++ b/FFXIV_TexTools/FFXIV_TexTools.csproj
@@ -23,9 +23,9 @@
FFXIV_TexTools
Copyright © 2024
- 3.0.6.1
- 3.0.6.1
- 3.0.6.1
+ 3.0.6.2
+ 3.0.6.2
+ 3.0.6.2
9.0
true
@@ -156,6 +156,10 @@
XivStringRaces.Designer.cs
Designer
+
+ ResXFileCodeGenerator
+ XivStrings.Designer.cs
+
@@ -198,6 +202,11 @@
True
UIStrings.resx
+
+ True
+ True
+ XivStrings.resx
+
Code
diff --git a/FFXIV_TexTools/Helpers/ModpackUpgraderWrapper.cs b/FFXIV_TexTools/Helpers/ModpackUpgraderWrapper.cs
index 7d2bcc70..bb4f41bb 100644
--- a/FFXIV_TexTools/Helpers/ModpackUpgraderWrapper.cs
+++ b/FFXIV_TexTools/Helpers/ModpackUpgraderWrapper.cs
@@ -22,58 +22,73 @@ public static async Task UpgradeModpackPrompted(bool includePartials = true)
InitialDirectory = Path.GetFullPath(Settings.Default.ModPack_Directory),
};
+ ofd.Multiselect = true;
if (ofd.ShowDialog() != System.Windows.Forms.DialogResult.OK)
{
return;
}
- var path = ofd.FileName;
+
+ var paths = ofd.FileNames;
await mw.LockUi("Upgrading Modpack", "Please Wait...\n\nIf this takes more than 3-5 minutes, please close TexTools and retry with \nOptions => Settings => 'Compress Upgrade Textures' turned off.");
try
{
+ var i = 1;
+ foreach (var path in paths)
+ {
+ if(paths.Length > 1)
+ {
+ mw._lockProgressController.SetMessage("Updating Mod #" + i + "/" + paths.Length);
+ }
- var data = await xivModdingFramework.Mods.ModpackUpgrader.UpgradeModpack(path, includePartials);
+ var data = await xivModdingFramework.Mods.ModpackUpgrader.UpgradeModpack(path, includePartials);
- if(!data.AnyChanges)
- {
- FlexibleMessageBox.Show(ViewHelpers.GetWin32Window(MainWindow.GetMainWindow()),
- "The upgrader found nothing to upgrade in the modpack.\n\nThis typically means the mod either does not need to be upgraded, must be manually upgraded, or was already upgraded, possibly by another tool (Ex. Penumbra).",
- "No Upgrade Needed",
- MessageBoxButtons.OK, MessageBoxIcon.Information);
- return;
- }
+ if (!data.AnyChanges && paths.Length == 1)
+ {
+ FlexibleMessageBox.Show(ViewHelpers.GetWin32Window(MainWindow.GetMainWindow()),
+ "The upgrader found nothing to upgrade in the modpack.\n\nThis typically means the mod either does not need to be upgraded, must be manually upgraded, or was already upgraded, possibly by another tool (Ex. Penumbra).",
+ "No Upgrade Needed",
+ MessageBoxButtons.OK, MessageBoxIcon.Information);
+ return;
+ }
- var ext = Path.GetExtension(path);
+ var ext = Path.GetExtension(path);
- var name = Path.GetFileNameWithoutExtension(path);
- if (ext == ".json")
- {
- name = IOUtil.MakePathSafe(data.Data.MetaPage.Name, false);
- }
+ var name = Path.GetFileNameWithoutExtension(path);
+ if (ext == ".json")
+ {
+ name = IOUtil.MakePathSafe(data.Data.MetaPage.Name, false);
+ }
- if (ext != ".ttmp2" && ext != ".pmp")
- {
- ext = ".pmp";
- }
+ if (ext != ".ttmp2" && ext != ".pmp")
+ {
+ ext = ".pmp";
+ }
- // Final Save location
- var dir = Path.GetDirectoryName(path);
- var fName = name + "_dt" + ext;
- var sfd = new SaveFileDialog()
- {
- FileName = fName,
- Filter = ViewHelpers.ModpackFileFilter,
- InitialDirectory = dir,
- };
- if (sfd.ShowDialog() != System.Windows.Forms.DialogResult.OK)
- {
- return;
+ // Final Save location
+ var dir = Path.GetDirectoryName(path);
+ var fName = name + "_dt" + ext;
+ var newPath = Path.GetFullPath(Path.Combine(dir, fName));
+ if (paths.Length == 1)
+ {
+ var sfd = new SaveFileDialog()
+ {
+ FileName = fName,
+ Filter = ViewHelpers.ModpackFileFilter,
+ InitialDirectory = dir,
+ };
+ if (sfd.ShowDialog() != System.Windows.Forms.DialogResult.OK)
+ {
+ return;
+ }
+ newPath = sfd.FileName;
+ }
+
+ await data.Data.WriteModpack(newPath, true);
}
- var newPath = sfd.FileName;
- await data.Data.WriteModpack(newPath, true);
}
catch (Exception ex)
{
diff --git a/FFXIV_TexTools/MainWindow.xaml b/FFXIV_TexTools/MainWindow.xaml
index 10d1104a..1dc6d4da 100644
--- a/FFXIV_TexTools/MainWindow.xaml
+++ b/FFXIV_TexTools/MainWindow.xaml
@@ -110,8 +110,8 @@
diff --git a/FFXIV_TexTools/MainWindow.xaml.cs b/FFXIV_TexTools/MainWindow.xaml.cs
index ec6c697c..f9604238 100644
--- a/FFXIV_TexTools/MainWindow.xaml.cs
+++ b/FFXIV_TexTools/MainWindow.xaml.cs
@@ -240,7 +240,7 @@ public bool IsUiLocked
public IProgress LockProgress { get { return _lockProgress; } }
- private ProgressDialogController _lockProgressController ;
+ internal ProgressDialogController _lockProgressController ;
///
/// Fired when the old tree is about to be discarded.
diff --git a/FFXIV_TexTools/Models/PenumbraUpgradeStatus.cs b/FFXIV_TexTools/Models/PenumbraUpgradeStatus.cs
index 6055bf28..cf458823 100644
--- a/FFXIV_TexTools/Models/PenumbraUpgradeStatus.cs
+++ b/FFXIV_TexTools/Models/PenumbraUpgradeStatus.cs
@@ -11,10 +11,11 @@
using System.Diagnostics;
using xivModdingFramework.Mods;
using xivModdingFramework.Exd.FileTypes;
+using FFXIV_TexTools.Views.Upgrades;
namespace FFXIV_TexTools.Models
{
- public class PenumbraUpgradeStatus
+ public class PenumbraUpgradeStatus : ICloneable
{
[JsonConverter(typeof(StringEnumConverter))]
public enum EUpgradeResult
@@ -28,7 +29,7 @@ public enum EUpgradeResult
public Dictionary Upgrades = new Dictionary();
- public async Task ProcessMod(string baseDir, string targetDir, string mod)
+ public async Task ProcessMod(string baseDir, string targetDir, string mod, bool compress = true)
{
var source = Path.GetFullPath(Path.Combine(baseDir, mod));
var target = Path.GetFullPath(Path.Combine(targetDir, mod));
@@ -42,8 +43,19 @@ public async Task ProcessMod(string baseDir, string targetDir, s
var res = EUpgradeResult.Failure;
try
{
- var s = await ModpackUpgrader.UpgradeModpack(source, target);
- res = s ? EUpgradeResult.Success : EUpgradeResult.Unchanged;
+ var result = await ModpackUpgrader.UpgradeModpack(source, target, false);
+
+ if (!result)
+ {
+ // If we did nothing, just direct copy the mod, rather than doing the more expensive
+ // PMP write.
+ IOUtil.CopyFolder(source, target);
+ }
+
+ res = result ? EUpgradeResult.Success : EUpgradeResult.Unchanged;
+
+
+
} catch (Exception ex)
{
if (Directory.Exists(target))
@@ -74,13 +86,26 @@ public async Task ProcessMod(string baseDir, string targetDir, s
Trace.WriteLine(ex);
}
- await IOUtil.CompressWindowsDirectory(target);
+ if (compress)
+ {
+ await IOUtil.CompressWindowsDirectory(target);
+ }
- if (Upgrades.ContainsKey(mod))
+ lock (PenumbraLibraryUpgradeWindow._ResultsLock)
{
- Upgrades[mod] = res;
+ if (Upgrades.ContainsKey(mod))
+ {
+ Upgrades[mod] = res;
+ }
}
return res;
}
+
+ public object Clone()
+ {
+ var cl = (PenumbraUpgradeStatus) MemberwiseClone();
+ cl.Upgrades = new Dictionary(Upgrades);
+ return cl;
+ }
}
}
diff --git a/FFXIV_TexTools/Resources/UIStrings.Designer.cs b/FFXIV_TexTools/Resources/UIStrings.Designer.cs
index 4de0624c..a820d4f2 100644
--- a/FFXIV_TexTools/Resources/UIStrings.Designer.cs
+++ b/FFXIV_TexTools/Resources/UIStrings.Designer.cs
@@ -1963,7 +1963,7 @@ public static string Import_Raw {
}
///
- /// Looks up a localized string similar to Import Raw File.
+ /// Looks up a localized string similar to Import File.
///
public static string Import_Raw_File {
get {
@@ -3616,7 +3616,7 @@ public static string Racial_Settings_Editor {
}
///
- /// Looks up a localized string similar to Raw File Operations.
+ /// Looks up a localized string similar to File Operations.
///
public static string Raw_File_Operations {
get {
diff --git a/FFXIV_TexTools/Resources/UIStrings.resx b/FFXIV_TexTools/Resources/UIStrings.resx
index ae1aa370..7ca15c7b 100644
--- a/FFXIV_TexTools/Resources/UIStrings.resx
+++ b/FFXIV_TexTools/Resources/UIStrings.resx
@@ -1004,7 +1004,7 @@ If you would like to enable this, first import a texture for the selected item.<
Import Raw File
- Raw File Operations
+ File Operations
Clean Up Modlist
@@ -1163,7 +1163,7 @@ If you would like to enable this, first import a texture for the selected item.<
Extract File
- Import Raw File
+ Import File
Destination Path:
diff --git a/FFXIV_TexTools/Resources/XivStrings.Designer.cs b/FFXIV_TexTools/Resources/XivStrings.Designer.cs
index c79df8be..c946a778 100644
--- a/FFXIV_TexTools/Resources/XivStrings.Designer.cs
+++ b/FFXIV_TexTools/Resources/XivStrings.Designer.cs
@@ -19,7 +19,7 @@ namespace FFXIV_TexTools.Resources {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class XivStrings {
@@ -60,6 +60,15 @@ internal XivStrings() {
}
}
+ ///
+ /// Looks up a localized string similar to Accessories.
+ ///
+ internal static string Accessories {
+ get {
+ return ResourceManager.GetString("Accessories", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Accessory.
///
@@ -123,6 +132,15 @@ internal static string AutodeskCollada {
}
}
+ ///
+ /// Looks up a localized string similar to Beneficial.
+ ///
+ internal static string Beneficial {
+ get {
+ return ResourceManager.GetString("Beneficial", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Bishop Autoturret.
///
@@ -222,6 +240,15 @@ internal static string DemiHuman {
}
}
+ ///
+ /// Looks up a localized string similar to Detrimental.
+ ///
+ internal static string Detrimental {
+ get {
+ return ResourceManager.GetString("Detrimental", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Diffuse.
///
@@ -852,6 +879,15 @@ internal static string Ornaments {
}
}
+ ///
+ /// Looks up a localized string similar to Other.
+ ///
+ internal static string Other {
+ get {
+ return ResourceManager.GetString("Other", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Outdoor Furniture.
///
@@ -1149,6 +1185,15 @@ internal static string Weapon {
}
}
+ ///
+ /// Looks up a localized string similar to Weapons.
+ ///
+ internal static string Weapons {
+ get {
+ return ResourceManager.GetString("Weapons", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Weather.
///
@@ -1166,26 +1211,5 @@ internal static string Wrists {
return ResourceManager.GetString("Wrists", resourceCulture);
}
}
- internal static string Beneficial
- {
- get
- {
- return ResourceManager.GetString("Beneficial", resourceCulture);
- }
- }
- internal static string Detrimental
- {
- get
- {
- return ResourceManager.GetString("Detrimental", resourceCulture);
- }
- }
- internal static string Other
- {
- get
- {
- return ResourceManager.GetString("Other", resourceCulture);
- }
- }
}
}
diff --git a/FFXIV_TexTools/Resources/XivStrings.resx b/FFXIV_TexTools/Resources/XivStrings.resx
index 254d6343..4ffc28f2 100644
--- a/FFXIV_TexTools/Resources/XivStrings.resx
+++ b/FFXIV_TexTools/Resources/XivStrings.resx
@@ -495,4 +495,10 @@
Other
+
+ Accessories
+
+
+ Weapons
+
\ No newline at end of file
diff --git a/FFXIV_TexTools/ViewModels/FullModelViewModel.cs b/FFXIV_TexTools/ViewModels/FullModelViewModel.cs
index 3025f5ba..15a3ae27 100644
--- a/FFXIV_TexTools/ViewModels/FullModelViewModel.cs
+++ b/FFXIV_TexTools/ViewModels/FullModelViewModel.cs
@@ -803,12 +803,13 @@ private async Task UpdateBodyTextures(TTModel ttModel, IItemModel item, Dictiona
.FirstOrDefault();
bTex.MaterialPath = newMaterial;
+ var tx = MainWindow.DefaultTransaction;
var mtrlPath = Mtrl.GetMtrlPath(tempMdlPath, newMaterial, mtrlVariant);
- var mtrl = await Mtrl.GetXivMtrl(mtrlPath);
+ var mtrl = await Mtrl.GetXivMtrl(mtrlPath, false, tx);
var colors = ModelTexture.GetCustomColors();
colors.InvertNormalGreen = false;
- var modelMaps = await ModelTexture.GetModelMaps(mtrl, false, colors, -1, MainWindow.UserTransaction);
+ var modelMaps = await ModelTexture.GetModelMaps(mtrl, false, colors, -1, tx);
// Reindex the material dictionary as materials may have sorted differently
ReIndexMaterialDictionary(ttModel, materialDictionary, modelMaps);
diff --git a/FFXIV_TexTools/Views/Controls/ItemSelectControl.xaml.cs b/FFXIV_TexTools/Views/Controls/ItemSelectControl.xaml.cs
index cd42c442..d1347358 100644
--- a/FFXIV_TexTools/Views/Controls/ItemSelectControl.xaml.cs
+++ b/FFXIV_TexTools/Views/Controls/ItemSelectControl.xaml.cs
@@ -278,6 +278,50 @@ private void BuildSetTree()
private void PreloadBaseCategories()
{
+ var weapons = new ItemTreeElement(null, null, XivStrings.Weapons);
+ CategoryElements.Add(weapons);
+
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Shield.GetNiceName()));
+
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Sword.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Axe.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Broadsword.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Gunblade.GetNiceName()));
+
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Staff.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Orrery.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Nouliths.GetNiceName()));
+
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Fists.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Lance.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Daggers.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Katana.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Scythe.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Twinfangs.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Bow.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Gun.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Glaives.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Wand.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Book.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Rapier.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Brush.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Cane.GetNiceName()));
+
+
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Saw.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.CrossPeinHammer.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.RaisingHammer.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.LapidaryHammer.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Needle.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.RoundKnife.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Alembic.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.CulinaryKnife.GetNiceName()));
+
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Pickaxe.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.Hatchet.GetNiceName()));
+ weapons.Children.Add(new ItemTreeElement(null, null, XivWeaponType.FishingRod.GetNiceName()));
+
+
var gear = new ItemTreeElement(null, null, XivStrings.Gear);
CategoryElements.Add(gear);
@@ -287,17 +331,6 @@ private void PreloadBaseCategories()
gear.Children.Add(new ItemTreeElement(null, null, XivStrings.Legs));
gear.Children.Add(new ItemTreeElement(null, null, XivStrings.Feet));
-
- gear.Children.Add(new ItemTreeElement(null, null, XivStrings.Main_Hand));
- gear.Children.Add(new ItemTreeElement(null, null, XivStrings.Off_Hand));
- gear.Children.Add(new ItemTreeElement(null, null, XivStrings.Dual_Wield));
- gear.Children.Add(new ItemTreeElement(null, null, XivStrings.Two_Handed));
-
- gear.Children.Add(new ItemTreeElement(null, null, XivStrings.Earring));
- gear.Children.Add(new ItemTreeElement(null, null, XivStrings.Neck));
- gear.Children.Add(new ItemTreeElement(null, null, XivStrings.Wrists));
- gear.Children.Add(new ItemTreeElement(null, null, XivStrings.Rings));
-
gear.Children.Add(new ItemTreeElement(null, null, XivStrings.Head_Body));
gear.Children.Add(new ItemTreeElement(null, null, XivStrings.Body_Hands));
gear.Children.Add(new ItemTreeElement(null, null, XivStrings.Body_Hands_Legs));
@@ -305,7 +338,15 @@ private void PreloadBaseCategories()
gear.Children.Add(new ItemTreeElement(null, null, XivStrings.Legs_Feet));
gear.Children.Add(new ItemTreeElement(null, null, XivStrings.All));
- gear.Children.Add(new ItemTreeElement(null, null, XivStrings.Food));
+ //gear.Children.Add(new ItemTreeElement(null, null, XivStrings.Food));
+
+
+ var accessories = new ItemTreeElement(null, null, XivStrings.Accessories);
+ CategoryElements.Add(accessories);
+ accessories.Children.Add(new ItemTreeElement(null, null, XivStrings.Earring));
+ accessories.Children.Add(new ItemTreeElement(null, null, XivStrings.Neck));
+ accessories.Children.Add(new ItemTreeElement(null, null, XivStrings.Wrists));
+ accessories.Children.Add(new ItemTreeElement(null, null, XivStrings.Rings));
}
private async Task> BuildCategoryTree()
diff --git a/FFXIV_TexTools/Views/Upgrades/PenumbraLibraryUpgradeWindow.xaml b/FFXIV_TexTools/Views/Upgrades/PenumbraLibraryUpgradeWindow.xaml
index c56daae3..2945b1ce 100644
--- a/FFXIV_TexTools/Views/Upgrades/PenumbraLibraryUpgradeWindow.xaml
+++ b/FFXIV_TexTools/Views/Upgrades/PenumbraLibraryUpgradeWindow.xaml
@@ -5,7 +5,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:FFXIV_TexTools.Views.Upgrades"
mc:Ignorable="d"
- Title="Penumbra Library Update Tool" Height="450" Width="800">
+ Title="Penumbra Library Update Tool" Height="600" Width="800">
@@ -32,12 +32,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FFXIV_TexTools/Views/Upgrades/PenumbraLibraryUpgradeWindow.xaml.cs b/FFXIV_TexTools/Views/Upgrades/PenumbraLibraryUpgradeWindow.xaml.cs
index fd3bcd8c..2e70a7e0 100644
--- a/FFXIV_TexTools/Views/Upgrades/PenumbraLibraryUpgradeWindow.xaml.cs
+++ b/FFXIV_TexTools/Views/Upgrades/PenumbraLibraryUpgradeWindow.xaml.cs
@@ -9,6 +9,7 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
+using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
@@ -119,6 +120,40 @@ public bool ContinuePauseEnabled
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ContinuePauseEnabled)));
}
}
+ private bool _UseCompression = true;
+ public bool UseCompression
+ {
+ get => _UseCompression;
+ set
+ {
+ _UseCompression = value;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(UseCompression)));
+ }
+ }
+
+ private int _ConcurrentMax = 3;
+ public int ConcurrentMax
+ {
+ get => _ConcurrentMax;
+ set
+ {
+ _ConcurrentMax = value;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ConcurrentMax)));
+ }
+ }
+
+ public static object _ResultsLock = new object();
+
+
+ public ObservableCollection> ConcurrentSource { get; set; } = new ObservableCollection>()
+ {
+ new KeyValuePair("Slow (Batch Size 1)", 1),
+ new KeyValuePair("Medium (Batch Size 3)", 3),
+ new KeyValuePair("Fast (Batch Size 5)", 5),
+ new KeyValuePair("Faster (Batch Size 10)", 10),
+ new KeyValuePair("Fastest (Batch Size 20)", 20),
+ };
+
PenumbraUpgradeStatus Results;
@@ -326,7 +361,10 @@ private void LoadOrCreateJson()
private void SaveJson()
{
if (Results == null || string.IsNullOrEmpty(DestinationPath)) return;
- File.WriteAllText(JsonPath, JsonConvert.SerializeObject(Results, Formatting.Indented));
+ lock (_ResultsLock)
+ {
+ File.WriteAllText(JsonPath, JsonConvert.SerializeObject((PenumbraUpgradeStatus)Results.Clone(), Formatting.Indented));
+ }
}
private void UpdateLists()
{
@@ -364,6 +402,47 @@ private void UpdateLists()
}
+ private async Task ProcessMods(List mods)
+ {
+ if (mods.Count == 0) return;
+
+ object _lock = new object();
+ var tasks = new List();
+ Dispatcher.Invoke(() =>
+ {
+ StatusText = "Processing Mod: " + mods[0] + " and " + (mods.Count-1) + " other mods...";
+ });
+
+ foreach (var mod in mods)
+ {
+ tasks.Add(Task.Run(async () =>
+ {
+ await Results.ProcessMod(PenumbraPath, DestinationPath, mod, UseCompression);
+ lock (_lock)
+ {
+ SaveJson();
+ }
+ }));
+ }
+ await Task.WhenAll(tasks);
+
+ }
+
+ private List GetNextMods(int count)
+ {
+ var ret = new HashSet();
+
+ int i = 0;
+ var nextMod = Results.Upgrades.FirstOrDefault(x => x.Value == PenumbraUpgradeStatus.EUpgradeResult.NotStarted);
+ while (i < count && !string.IsNullOrWhiteSpace(nextMod.Key))
+ {
+ Results.Upgrades[nextMod.Key] = EUpgradeResult.InProgress;
+ ret.Add(nextMod.Key);
+ i++;
+ nextMod = Results.Upgrades.FirstOrDefault(x => x.Value == PenumbraUpgradeStatus.EUpgradeResult.NotStarted);
+ }
+ return ret.ToList();
+ }
private bool _RequestStop = false;
private async Task Start()
@@ -373,22 +452,16 @@ private async Task Start()
_RequestStop = false;
ContinuePauseEnabled = true;
+
await Task.Run(async () =>
{
var workerState = XivCache.CacheWorkerEnabled;
await XivCache.SetCacheWorkerState(false);
- var nextMod = Results.Upgrades.FirstOrDefault(x => x.Value == PenumbraUpgradeStatus.EUpgradeResult.NotStarted);
- while (!string.IsNullOrWhiteSpace(nextMod.Key) && !_RequestStop)
+
+ var nextMods = GetNextMods(ConcurrentMax);
+ while (nextMods.Count > 0 && !_RequestStop)
{
- var mod = nextMod.Key;
- Dispatcher.Invoke(() =>
- {
- StatusText = "Processing Mod: " + mod;
- });
-
- var res = await Results.ProcessMod(PenumbraPath, DestinationPath, mod);
-
- SaveJson();
+ await ProcessMods(nextMods);
// Always clear the temp folder between actions.
try
@@ -409,15 +482,34 @@ await Task.Run(async () =>
{
UpdateLists();
});
- nextMod = Results.Upgrades.FirstOrDefault(x => x.Value == PenumbraUpgradeStatus.EUpgradeResult.NotStarted);
+ nextMods = GetNextMods(ConcurrentMax);
}
if (_RequestStop)
{
State = UpgradeState.Paused;
+ StatusText = "Update Paused";
ContinuePauseEnabled = true;
} else
{
+ // Copy any final files from the old Library.
+
+ StatusText = "Copying lingering library files...";
+ try
+ {
+ //Copy all the files & Replaces any files with the same name
+ foreach (string newPath in Directory.GetFiles(PenumbraPath, "*.*", SearchOption.TopDirectoryOnly))
+ {
+ var path = IOUtil.MakeLongPath(newPath);
+ File.Copy(path, newPath.Replace(PenumbraPath, DestinationPath), true);
+ }
+ }
+ catch
+ {
+ // No-Op.
+ }
+
+
StatusText = "Complete! :D";
State = UpgradeState.Completed;
}
@@ -429,6 +521,7 @@ private async Task Stop()
{
if (Results == null) return;
_RequestStop = true;
+ StatusText = "Pausing when current mods are done processing...";
ContinuePauseEnabled = false;
}
diff --git a/lib/xivModdingFramework b/lib/xivModdingFramework
index 3df03dbc..42129891 160000
--- a/lib/xivModdingFramework
+++ b/lib/xivModdingFramework
@@ -1 +1 @@
-Subproject commit 3df03dbc0a05ebc34f721055f52227cfa4d01c4f
+Subproject commit 42129891f4b706f070b6574d1b7c17981981211c