mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
Add design migration for inverted gloss and specular, and a backup before doing that.
This commit is contained in:
parent
d7074c5791
commit
5cd224b164
5 changed files with 91 additions and 14 deletions
|
|
@ -143,10 +143,10 @@ public class Configuration : IPluginConfiguration, ISavable
|
|||
|
||||
public static class Constants
|
||||
{
|
||||
public const int CurrentVersion = 6;
|
||||
public const int CurrentVersion = 7;
|
||||
|
||||
public static readonly ISortMode<Design>[] ValidSortModes =
|
||||
{
|
||||
[
|
||||
ISortMode<Design>.FoldersFirst,
|
||||
ISortMode<Design>.Lexicographical,
|
||||
new DesignFileSystem.CreationDate(),
|
||||
|
|
@ -159,7 +159,7 @@ public class Configuration : IPluginConfiguration, ISavable
|
|||
ISortMode<Design>.InverseFoldersLast,
|
||||
ISortMode<Design>.InternalOrder,
|
||||
ISortMode<Design>.InverseInternalOrder,
|
||||
};
|
||||
];
|
||||
}
|
||||
|
||||
/// <summary> Convert SortMode Types to their name. </summary>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using Newtonsoft.Json;
|
|||
using Newtonsoft.Json.Linq;
|
||||
using OtterGui.Classes;
|
||||
using Penumbra.GameData.Structs;
|
||||
using Notification = OtterGui.Classes.Notification;
|
||||
|
||||
namespace Glamourer.Designs;
|
||||
|
||||
|
|
@ -34,7 +35,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
|
|||
}
|
||||
|
||||
// Metadata
|
||||
public new const int FileVersion = 1;
|
||||
public new const int FileVersion = 2;
|
||||
|
||||
public Guid Identifier { get; internal init; }
|
||||
public DateTimeOffset CreationDate { get; internal init; }
|
||||
|
|
@ -143,17 +144,81 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
|
|||
|
||||
#region Deserialization
|
||||
|
||||
public static Design LoadDesign(CustomizeService customizations, ItemManager items, DesignLinkLoader linkLoader, JObject json)
|
||||
public static Design LoadDesign(SaveService saveService, CustomizeService customizations, ItemManager items, DesignLinkLoader linkLoader, JObject json)
|
||||
{
|
||||
var version = json["FileVersion"]?.ToObject<int>() ?? 0;
|
||||
return version switch
|
||||
{
|
||||
FileVersion => LoadDesignV1(customizations, items, linkLoader, json),
|
||||
1 => LoadDesignV1(saveService, customizations, items, linkLoader, json),
|
||||
FileVersion => LoadDesignV2(customizations, items, linkLoader, json),
|
||||
_ => throw new Exception("The design to be loaded has no valid Version."),
|
||||
};
|
||||
}
|
||||
|
||||
private static Design LoadDesignV1(CustomizeService customizations, ItemManager items, DesignLinkLoader linkLoader, JObject json)
|
||||
/// <summary> The values for gloss and specular strength were switched. Swap them for all appropriate designs. </summary>
|
||||
private static Design LoadDesignV1(SaveService saveService, CustomizeService customizations, ItemManager items, DesignLinkLoader linkLoader, JObject json)
|
||||
{
|
||||
var design = LoadDesignV2(customizations, items, linkLoader, json);
|
||||
var materialDesignData = design.GetMaterialDataRef();
|
||||
if (materialDesignData.Values.Count == 0)
|
||||
return design;
|
||||
|
||||
var materialData = materialDesignData.Clone();
|
||||
// Guesstimate whether to migrate material rows:
|
||||
// Update 1.3.0.10 released at that time, so any design last updated before that can be migrated.
|
||||
if (design.LastEdit <= new DateTime(2024, 8, 7, 16, 0, 0, DateTimeKind.Utc))
|
||||
{
|
||||
Migrate("because it was saved the wrong way around before 1.3.0.10, and this design was not changed since that release.");
|
||||
}
|
||||
else
|
||||
{
|
||||
var hasNegativeGloss = false;
|
||||
var hasNonPositiveGloss = false;
|
||||
var specularLarger = 0;
|
||||
foreach (var (key, value) in materialData.GetValues(MaterialValueIndex.Min(), MaterialValueIndex.Max()))
|
||||
{
|
||||
hasNegativeGloss |= value.Value.GlossStrength < 0;
|
||||
hasNonPositiveGloss |= value.Value.GlossStrength <= 0;
|
||||
if (value.Value.SpecularStrength > value.Value.GlossStrength)
|
||||
++specularLarger;
|
||||
}
|
||||
|
||||
// If there is any negative gloss, this is wrong and can be migrated.
|
||||
if (hasNegativeGloss)
|
||||
Migrate("because it had a negative Gloss value, which is not supported and thus probably outdated.");
|
||||
// If there is any non-positive Gloss and some specular values that are larger, it is probably wrong and can be migrated.
|
||||
else if (hasNonPositiveGloss && specularLarger > 0)
|
||||
Migrate("because it had a zero Gloss value, and at least one Specular Strength larger than the Gloss, which is unusual.");
|
||||
// If most of the specular strengths are larger, it is probably wrong and can be migrated.
|
||||
else if (specularLarger > materialData.Values.Count / 2)
|
||||
Migrate("because most of its Specular Strength values were larger than the Gloss values, which is unusual.");
|
||||
}
|
||||
|
||||
return design;
|
||||
|
||||
void Migrate(string reason)
|
||||
{
|
||||
materialDesignData.Clear();
|
||||
foreach (var (key, value) in materialData.GetValues(MaterialValueIndex.Min(), MaterialValueIndex.Max()))
|
||||
{
|
||||
var gloss = Math.Clamp(value.Value.SpecularStrength, 0, (float)Half.MaxValue);
|
||||
var specularStrength = Math.Clamp(value.Value.GlossStrength, 0, (float)Half.MaxValue);
|
||||
var colorRow = value.Value with
|
||||
{
|
||||
GlossStrength = gloss,
|
||||
SpecularStrength = specularStrength,
|
||||
};
|
||||
materialDesignData.AddOrUpdateValue(MaterialValueIndex.FromKey(key), value with { Value = colorRow });
|
||||
}
|
||||
|
||||
Glamourer.Messager.AddMessage(new Notification(
|
||||
$"Swapped Gloss and Specular Strength in {materialDesignData.Values.Count} Rows in design {design.Incognito} {reason}",
|
||||
NotificationType.Info));
|
||||
saveService.Save(SaveType.ImmediateSync,design);
|
||||
}
|
||||
}
|
||||
|
||||
private static Design LoadDesignV2(CustomizeService customizations, ItemManager items, DesignLinkLoader linkLoader, JObject json)
|
||||
{
|
||||
var creationDate = json["CreationDate"]?.ToObject<DateTimeOffset>() ?? throw new ArgumentNullException("CreationDate");
|
||||
|
||||
|
|
@ -183,7 +248,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
|
|||
|
||||
static string[] ParseTags(JObject json)
|
||||
{
|
||||
var tags = json["Tags"]?.ToObject<string[]>() ?? Array.Empty<string>();
|
||||
var tags = json["Tags"]?.ToObject<string[]>() ?? [];
|
||||
return tags.OrderBy(t => t).Distinct().ToArray();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ using Penumbra.GameData.Structs;
|
|||
namespace Glamourer.Designs;
|
||||
|
||||
public class DesignConverter(
|
||||
SaveService saveService,
|
||||
ItemManager _items,
|
||||
DesignManager _designs,
|
||||
CustomizeService _customize,
|
||||
|
|
@ -69,7 +70,7 @@ public class DesignConverter(
|
|||
try
|
||||
{
|
||||
var ret = jObject["Identifier"] != null
|
||||
? Design.LoadDesign(_customize, _items, _linkLoader, jObject)
|
||||
? Design.LoadDesign(saveService, _customize, _items, _linkLoader, jObject)
|
||||
: DesignBase.LoadDesignBase(_customize, _items, jObject);
|
||||
|
||||
if (!customize)
|
||||
|
|
@ -100,7 +101,7 @@ public class DesignConverter(
|
|||
case (byte)'{':
|
||||
var jObj1 = JObject.Parse(Encoding.UTF8.GetString(bytes));
|
||||
ret = jObj1["Identifier"] != null
|
||||
? Design.LoadDesign(_customize, _items, _linkLoader, jObj1)
|
||||
? Design.LoadDesign(saveService, _customize, _items, _linkLoader, jObj1)
|
||||
: DesignBase.LoadDesignBase(_customize, _items, jObj1);
|
||||
break;
|
||||
case 1:
|
||||
|
|
@ -115,7 +116,7 @@ public class DesignConverter(
|
|||
var jObj2 = JObject.Parse(decompressed);
|
||||
Debug.Assert(version == 3);
|
||||
ret = jObj2["Identifier"] != null
|
||||
? Design.LoadDesign(_customize, _items, _linkLoader, jObj2)
|
||||
? Design.LoadDesign(saveService, _customize, _items, _linkLoader, jObj2)
|
||||
: DesignBase.LoadDesignBase(_customize, _items, jObj2);
|
||||
break;
|
||||
}
|
||||
|
|
@ -126,7 +127,7 @@ public class DesignConverter(
|
|||
var jObj2 = JObject.Parse(decompressed);
|
||||
Debug.Assert(version == 5);
|
||||
ret = jObj2["Identifier"] != null
|
||||
? Design.LoadDesign(_customize, _items, _linkLoader, jObj2)
|
||||
? Design.LoadDesign(saveService, _customize, _items, _linkLoader, jObj2)
|
||||
: DesignBase.LoadDesignBase(_customize, _items, jObj2);
|
||||
break;
|
||||
}
|
||||
|
|
@ -136,7 +137,7 @@ public class DesignConverter(
|
|||
var jObj2 = JObject.Parse(decompressed);
|
||||
Debug.Assert(version == 6);
|
||||
ret = jObj2["Identifier"] != null
|
||||
? Design.LoadDesign(_customize, _items, _linkLoader, jObj2)
|
||||
? Design.LoadDesign(saveService, _customize, _items, _linkLoader, jObj2)
|
||||
: DesignBase.LoadDesignBase(_customize, _items, jObj2);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public sealed class DesignManager : DesignEditor
|
|||
{
|
||||
var text = File.ReadAllText(f.FullName);
|
||||
var data = JObject.Parse(text);
|
||||
var design = Design.LoadDesign(Customizations, Items, linkLoader, data);
|
||||
var design = Design.LoadDesign(SaveService, Customizations, Items, linkLoader, data);
|
||||
designs.Value!.Add((design, f.FullName));
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
|||
|
|
@ -23,9 +23,20 @@ public class ConfigMigrationService(SaveService saveService, FixedDesignMigrator
|
|||
MigrateV2To4();
|
||||
MigrateV4To5();
|
||||
MigrateV5To6();
|
||||
MigrateV6To7();
|
||||
AddColors(config, true);
|
||||
}
|
||||
|
||||
private void MigrateV6To7()
|
||||
{
|
||||
if (_config.Version > 6)
|
||||
return;
|
||||
|
||||
// Do not actually change anything in the config, just create a backup before designs are migrated.
|
||||
backupService.CreateMigrationBackup("pre_gloss_specular_migration");
|
||||
_config.Version = 7;
|
||||
}
|
||||
|
||||
private void MigrateV5To6()
|
||||
{
|
||||
if (_config.Version > 5)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue