mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-15 13:14:17 +01:00
Add some functionality to allow an IMC group to add apply to all variants.
This commit is contained in:
parent
137b752196
commit
05d010a281
10 changed files with 117 additions and 46 deletions
|
|
@ -51,7 +51,7 @@ public readonly struct ImcCache : IDisposable
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!_imcFiles.TryGetValue(path, out var file))
|
if (!_imcFiles.TryGetValue(path, out var file))
|
||||||
file = new ImcFile(manager, manip);
|
file = new ImcFile(manager, manip.Identifier);
|
||||||
|
|
||||||
_imcManipulations[idx] = (manip, file);
|
_imcManipulations[idx] = (manip, file);
|
||||||
if (!manip.Apply(file))
|
if (!manip.Apply(file))
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ public partial class TexToolsMeta
|
||||||
var manip = new ImcManipulation(metaFileInfo.PrimaryType, metaFileInfo.SecondaryType, metaFileInfo.PrimaryId,
|
var manip = new ImcManipulation(metaFileInfo.PrimaryType, metaFileInfo.SecondaryType, metaFileInfo.PrimaryId,
|
||||||
metaFileInfo.SecondaryId, i, metaFileInfo.EquipSlot,
|
metaFileInfo.SecondaryId, i, metaFileInfo.EquipSlot,
|
||||||
new ImcEntry());
|
new ImcEntry());
|
||||||
var def = new ImcFile(_metaFileManager, manip);
|
var def = new ImcFile(_metaFileManager, manip.Identifier);
|
||||||
var partIdx = ImcFile.PartIndex(manip.EquipSlot); // Gets turned to unknown for things without equip, and unknown turns to 0.
|
var partIdx = ImcFile.PartIndex(manip.EquipSlot); // Gets turned to unknown for things without equip, and unknown turns to 0.
|
||||||
foreach (var value in values)
|
foreach (var value in values)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ public partial class TexToolsMeta
|
||||||
{
|
{
|
||||||
case MetaManipulation.Type.Imc:
|
case MetaManipulation.Type.Imc:
|
||||||
var allManips = manips.ToList();
|
var allManips = manips.ToList();
|
||||||
var baseFile = new ImcFile(manager, allManips[0].Imc);
|
var baseFile = new ImcFile(manager, allManips[0].Imc.Identifier);
|
||||||
foreach (var manip in allManips)
|
foreach (var manip in allManips)
|
||||||
manip.Imc.Apply(baseFile);
|
manip.Imc.Apply(baseFile);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,12 @@ namespace Penumbra.Meta.Files;
|
||||||
|
|
||||||
public class ImcException : Exception
|
public class ImcException : Exception
|
||||||
{
|
{
|
||||||
public readonly ImcManipulation Manipulation;
|
public readonly ImcIdentifier Identifier;
|
||||||
public readonly string GamePath;
|
public readonly string GamePath;
|
||||||
|
|
||||||
public ImcException(ImcManipulation manip, Utf8GamePath path)
|
public ImcException(ImcIdentifier identifier, Utf8GamePath path)
|
||||||
{
|
{
|
||||||
Manipulation = manip;
|
Identifier = identifier;
|
||||||
GamePath = path.ToString();
|
GamePath = path.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -22,7 +22,7 @@ public class ImcException : Exception
|
||||||
=> "Could not obtain default Imc File.\n"
|
=> "Could not obtain default Imc File.\n"
|
||||||
+ " Either the default file does not exist (possibly for offhand files from TexTools) or the installation is corrupted.\n"
|
+ " Either the default file does not exist (possibly for offhand files from TexTools) or the installation is corrupted.\n"
|
||||||
+ $" Game Path: {GamePath}\n"
|
+ $" Game Path: {GamePath}\n"
|
||||||
+ $" Manipulation: {Manipulation}";
|
+ $" Manipulation: {Identifier}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe class ImcFile : MetaBaseFile
|
public unsafe class ImcFile : MetaBaseFile
|
||||||
|
|
@ -142,13 +142,14 @@ public unsafe class ImcFile : MetaBaseFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImcFile(MetaFileManager manager, ImcManipulation manip)
|
public ImcFile(MetaFileManager manager, ImcIdentifier identifier)
|
||||||
: base(manager, 0)
|
: base(manager, 0)
|
||||||
{
|
{
|
||||||
Path = manip.GamePath();
|
var path = identifier.GamePathString();
|
||||||
var file = manager.GameData.GetFile(Path.ToString());
|
Path = Utf8GamePath.FromString(path, out var p) ? p : Utf8GamePath.Empty;
|
||||||
|
var file = manager.GameData.GetFile(path);
|
||||||
if (file == null)
|
if (file == null)
|
||||||
throw new ImcException(manip, Path);
|
throw new ImcException(identifier, Path);
|
||||||
|
|
||||||
fixed (byte* ptr = file.Data)
|
fixed (byte* ptr = file.Data)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,32 @@ using Penumbra.Meta.Manipulations;
|
||||||
|
|
||||||
namespace Penumbra.Meta;
|
namespace Penumbra.Meta;
|
||||||
|
|
||||||
public class ImcChecker(MetaFileManager metaFileManager)
|
public class ImcChecker
|
||||||
{
|
{
|
||||||
|
private static readonly Dictionary<ImcIdentifier, int> VariantCounts = [];
|
||||||
|
private static MetaFileManager? _dataManager;
|
||||||
|
|
||||||
|
|
||||||
|
public static int GetVariantCount(ImcIdentifier identifier)
|
||||||
|
{
|
||||||
|
if (VariantCounts.TryGetValue(identifier, out var count))
|
||||||
|
return count;
|
||||||
|
|
||||||
|
count = GetFile(identifier)?.Count ?? 0;
|
||||||
|
VariantCounts[identifier] = count;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
public readonly record struct CachedEntry(ImcEntry Entry, bool FileExists, bool VariantExists);
|
public readonly record struct CachedEntry(ImcEntry Entry, bool FileExists, bool VariantExists);
|
||||||
|
|
||||||
private readonly Dictionary<ImcIdentifier, CachedEntry> _cachedDefaultEntries = new();
|
private readonly Dictionary<ImcIdentifier, CachedEntry> _cachedDefaultEntries = new();
|
||||||
|
private readonly MetaFileManager _metaFileManager;
|
||||||
|
|
||||||
|
public ImcChecker(MetaFileManager metaFileManager)
|
||||||
|
{
|
||||||
|
_metaFileManager = metaFileManager;
|
||||||
|
_dataManager = metaFileManager;
|
||||||
|
}
|
||||||
|
|
||||||
public CachedEntry GetDefaultEntry(ImcIdentifier identifier, bool storeCache)
|
public CachedEntry GetDefaultEntry(ImcIdentifier identifier, bool storeCache)
|
||||||
{
|
{
|
||||||
|
|
@ -17,7 +38,7 @@ public class ImcChecker(MetaFileManager metaFileManager)
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var e = ImcFile.GetDefault(metaFileManager, identifier.GamePath(), identifier.EquipSlot, identifier.Variant, out var entryExists);
|
var e = ImcFile.GetDefault(_metaFileManager, identifier.GamePath(), identifier.EquipSlot, identifier.Variant, out var entryExists);
|
||||||
entry = new CachedEntry(e, true, entryExists);
|
entry = new CachedEntry(e, true, entryExists);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
|
|
@ -33,4 +54,19 @@ public class ImcChecker(MetaFileManager metaFileManager)
|
||||||
public CachedEntry GetDefaultEntry(ImcManipulation imcManip, bool storeCache)
|
public CachedEntry GetDefaultEntry(ImcManipulation imcManip, bool storeCache)
|
||||||
=> GetDefaultEntry(new ImcIdentifier(imcManip.PrimaryId, imcManip.Variant, imcManip.ObjectType, imcManip.SecondaryId.Id,
|
=> GetDefaultEntry(new ImcIdentifier(imcManip.PrimaryId, imcManip.Variant, imcManip.ObjectType, imcManip.SecondaryId.Id,
|
||||||
imcManip.EquipSlot, imcManip.BodySlot), storeCache);
|
imcManip.EquipSlot, imcManip.BodySlot), storeCache);
|
||||||
|
|
||||||
|
private static ImcFile? GetFile(ImcIdentifier identifier)
|
||||||
|
{
|
||||||
|
if (_dataManager == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return new ImcFile(_dataManager, identifier);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,16 @@ public readonly record struct ImcIdentifier(
|
||||||
=> new(ObjectType, BodySlot, PrimaryId, SecondaryId.Id, Variant.Id, EquipSlot, entry);
|
=> new(ObjectType, BodySlot, PrimaryId, SecondaryId.Id, Variant.Id, EquipSlot, entry);
|
||||||
|
|
||||||
public void AddChangedItems(ObjectIdentification identifier, IDictionary<string, object?> changedItems)
|
public void AddChangedItems(ObjectIdentification identifier, IDictionary<string, object?> changedItems)
|
||||||
|
=> AddChangedItems(identifier, changedItems, false);
|
||||||
|
|
||||||
|
public void AddChangedItems(ObjectIdentification identifier, IDictionary<string, object?> changedItems, bool allVariants)
|
||||||
{
|
{
|
||||||
var path = ObjectType switch
|
var path = ObjectType switch
|
||||||
{
|
{
|
||||||
ObjectType.Equipment or ObjectType.Accessory => GamePaths.Equipment.Mtrl.Path(PrimaryId, GenderRace.MidlanderMale, EquipSlot,
|
ObjectType.Equipment when allVariants => GamePaths.Equipment.Mdl.Path(PrimaryId, GenderRace.MidlanderMale, EquipSlot),
|
||||||
Variant,
|
ObjectType.Equipment => GamePaths.Equipment.Mtrl.Path(PrimaryId, GenderRace.MidlanderMale, EquipSlot, Variant, "a"),
|
||||||
"a"),
|
ObjectType.Accessory when allVariants => GamePaths.Accessory.Mdl.Path(PrimaryId, GenderRace.MidlanderMale, EquipSlot),
|
||||||
|
ObjectType.Accessory => GamePaths.Accessory.Mtrl.Path(PrimaryId, GenderRace.MidlanderMale, EquipSlot, Variant, "a"),
|
||||||
ObjectType.Weapon => GamePaths.Weapon.Mtrl.Path(PrimaryId, SecondaryId.Id, Variant, "a"),
|
ObjectType.Weapon => GamePaths.Weapon.Mtrl.Path(PrimaryId, SecondaryId.Id, Variant, "a"),
|
||||||
ObjectType.DemiHuman => GamePaths.DemiHuman.Mtrl.Path(PrimaryId, SecondaryId.Id, EquipSlot, Variant,
|
ObjectType.DemiHuman => GamePaths.DemiHuman.Mtrl.Path(PrimaryId, SecondaryId.Id, EquipSlot, Variant,
|
||||||
"a"),
|
"a"),
|
||||||
|
|
@ -49,24 +53,19 @@ public readonly record struct ImcIdentifier(
|
||||||
identifier.Identify(changedItems, path);
|
identifier.Identify(changedItems, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Utf8GamePath GamePath()
|
public string GamePathString()
|
||||||
|
=> ObjectType switch
|
||||||
{
|
{
|
||||||
return ObjectType switch
|
ObjectType.Accessory => GamePaths.Accessory.Imc.Path(PrimaryId),
|
||||||
{
|
ObjectType.Equipment => GamePaths.Equipment.Imc.Path(PrimaryId),
|
||||||
ObjectType.Accessory => Utf8GamePath.FromString(GamePaths.Accessory.Imc.Path(PrimaryId), out var p) ? p : Utf8GamePath.Empty,
|
ObjectType.DemiHuman => GamePaths.DemiHuman.Imc.Path(PrimaryId, SecondaryId.Id),
|
||||||
ObjectType.Equipment => Utf8GamePath.FromString(GamePaths.Equipment.Imc.Path(PrimaryId), out var p) ? p : Utf8GamePath.Empty,
|
ObjectType.Monster => GamePaths.Monster.Imc.Path(PrimaryId, SecondaryId.Id),
|
||||||
ObjectType.DemiHuman => Utf8GamePath.FromString(GamePaths.DemiHuman.Imc.Path(PrimaryId, SecondaryId.Id), out var p)
|
ObjectType.Weapon => GamePaths.Weapon.Imc.Path(PrimaryId, SecondaryId.Id),
|
||||||
? p
|
_ => string.Empty,
|
||||||
: Utf8GamePath.Empty,
|
|
||||||
ObjectType.Monster => Utf8GamePath.FromString(GamePaths.Monster.Imc.Path(PrimaryId, SecondaryId.Id), out var p)
|
|
||||||
? p
|
|
||||||
: Utf8GamePath.Empty,
|
|
||||||
ObjectType.Weapon => Utf8GamePath.FromString(GamePaths.Weapon.Imc.Path(PrimaryId, SecondaryId.Id), out var p)
|
|
||||||
? p
|
|
||||||
: Utf8GamePath.Empty,
|
|
||||||
_ => throw new NotImplementedException(),
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
public Utf8GamePath GamePath()
|
||||||
|
=> Utf8GamePath.FromString(GamePathString(), out var p) ? p : Utf8GamePath.Empty;
|
||||||
|
|
||||||
public MetaIndex FileIndex()
|
public MetaIndex FileIndex()
|
||||||
=> (MetaIndex)(-1);
|
=> (MetaIndex)(-1);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using OtterGui.Classes;
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
using Penumbra.GameData.Data;
|
using Penumbra.GameData.Data;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
using Penumbra.Meta;
|
||||||
using Penumbra.Meta.Manipulations;
|
using Penumbra.Meta.Manipulations;
|
||||||
using Penumbra.Mods.Settings;
|
using Penumbra.Mods.Settings;
|
||||||
using Penumbra.Mods.SubMods;
|
using Penumbra.Mods.SubMods;
|
||||||
|
|
@ -31,6 +32,8 @@ public class ImcModGroup(Mod mod) : IModGroup
|
||||||
|
|
||||||
public ImcIdentifier Identifier;
|
public ImcIdentifier Identifier;
|
||||||
public ImcEntry DefaultEntry;
|
public ImcEntry DefaultEntry;
|
||||||
|
public bool AllVariants;
|
||||||
|
|
||||||
|
|
||||||
public FullPath? FindBestMatch(Utf8GamePath gamePath)
|
public FullPath? FindBestMatch(Utf8GamePath gamePath)
|
||||||
=> null;
|
=> null;
|
||||||
|
|
@ -39,7 +42,7 @@ public class ImcModGroup(Mod mod) : IModGroup
|
||||||
|
|
||||||
public bool CanBeDisabled
|
public bool CanBeDisabled
|
||||||
{
|
{
|
||||||
get => OptionData.Any(m => m.IsDisableSubMod);
|
get => _canBeDisabled;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_canBeDisabled = value;
|
_canBeDisabled = value;
|
||||||
|
|
@ -92,8 +95,8 @@ public class ImcModGroup(Mod mod) : IModGroup
|
||||||
public IModGroupEditDrawer EditDrawer(ModGroupEditDrawer editDrawer)
|
public IModGroupEditDrawer EditDrawer(ModGroupEditDrawer editDrawer)
|
||||||
=> new ImcModGroupEditDrawer(editDrawer, this);
|
=> new ImcModGroupEditDrawer(editDrawer, this);
|
||||||
|
|
||||||
public ImcManipulation GetManip(ushort mask)
|
public ImcManipulation GetManip(ushort mask, Variant variant)
|
||||||
=> new(Identifier.ObjectType, Identifier.BodySlot, Identifier.PrimaryId, Identifier.SecondaryId.Id, Identifier.Variant.Id,
|
=> new(Identifier.ObjectType, Identifier.BodySlot, Identifier.PrimaryId, Identifier.SecondaryId.Id, variant.Id,
|
||||||
Identifier.EquipSlot, DefaultEntry with { AttributeMask = mask });
|
Identifier.EquipSlot, DefaultEntry with { AttributeMask = mask });
|
||||||
|
|
||||||
public void AddData(Setting setting, Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
public void AddData(Setting setting, Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
||||||
|
|
@ -102,12 +105,23 @@ public class ImcModGroup(Mod mod) : IModGroup
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var mask = GetCurrentMask(setting);
|
var mask = GetCurrentMask(setting);
|
||||||
var imc = GetManip(mask);
|
if (AllVariants)
|
||||||
manipulations.Add(imc);
|
{
|
||||||
|
var count = ImcChecker.GetVariantCount(Identifier);
|
||||||
|
if (count == 0)
|
||||||
|
manipulations.Add(GetManip(mask, Identifier.Variant));
|
||||||
|
else
|
||||||
|
for (var i = 0; i <= count; ++i)
|
||||||
|
manipulations.Add(GetManip(mask, (Variant)i));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
manipulations.Add(GetManip(mask, Identifier.Variant));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddChangedItems(ObjectIdentification identifier, IDictionary<string, object?> changedItems)
|
public void AddChangedItems(ObjectIdentification identifier, IDictionary<string, object?> changedItems)
|
||||||
=> Identifier.AddChangedItems(identifier, changedItems);
|
=> Identifier.AddChangedItems(identifier, changedItems, AllVariants);
|
||||||
|
|
||||||
public Setting FixSetting(Setting setting)
|
public Setting FixSetting(Setting setting)
|
||||||
=> new(setting.Value & ((1ul << OptionData.Count) - 1));
|
=> new(setting.Value & ((1ul << OptionData.Count) - 1));
|
||||||
|
|
@ -120,6 +134,8 @@ public class ImcModGroup(Mod mod) : IModGroup
|
||||||
jObj.WriteTo(jWriter);
|
jObj.WriteTo(jWriter);
|
||||||
jWriter.WritePropertyName(nameof(DefaultEntry));
|
jWriter.WritePropertyName(nameof(DefaultEntry));
|
||||||
serializer.Serialize(jWriter, DefaultEntry);
|
serializer.Serialize(jWriter, DefaultEntry);
|
||||||
|
jWriter.WritePropertyName(nameof(AllVariants));
|
||||||
|
jWriter.WriteValue(AllVariants);
|
||||||
jWriter.WritePropertyName("Options");
|
jWriter.WritePropertyName("Options");
|
||||||
jWriter.WriteStartArray();
|
jWriter.WriteStartArray();
|
||||||
foreach (var option in OptionData)
|
foreach (var option in OptionData)
|
||||||
|
|
@ -156,6 +172,7 @@ public class ImcModGroup(Mod mod) : IModGroup
|
||||||
Description = json[nameof(Description)]?.ToObject<string>() ?? string.Empty,
|
Description = json[nameof(Description)]?.ToObject<string>() ?? string.Empty,
|
||||||
Priority = json[nameof(Priority)]?.ToObject<ModPriority>() ?? ModPriority.Default,
|
Priority = json[nameof(Priority)]?.ToObject<ModPriority>() ?? ModPriority.Default,
|
||||||
DefaultEntry = json[nameof(DefaultEntry)]?.ToObject<ImcEntry>() ?? new ImcEntry(),
|
DefaultEntry = json[nameof(DefaultEntry)]?.ToObject<ImcEntry>() ?? new ImcEntry(),
|
||||||
|
AllVariants = json[nameof(AllVariants)]?.ToObject<bool>() ?? false,
|
||||||
};
|
};
|
||||||
if (ret.Name.Length == 0)
|
if (ret.Name.Length == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -210,7 +227,7 @@ public class ImcModGroup(Mod mod) : IModGroup
|
||||||
if (idx >= 0)
|
if (idx >= 0)
|
||||||
return setting.HasFlag(idx);
|
return setting.HasFlag(idx);
|
||||||
|
|
||||||
Penumbra.Log.Warning($"A IMC Group should be able to be disabled, but does not contain a disable option.");
|
Penumbra.Log.Warning("A IMC Group should be able to be disabled, but does not contain a disable option.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ public static class EquipmentSwap
|
||||||
|
|
||||||
var (imcFileFrom, variants, affectedItems) = GetVariants(manager, identifier, slotFrom, idFrom, idTo, variantFrom);
|
var (imcFileFrom, variants, affectedItems) = GetVariants(manager, identifier, slotFrom, idFrom, idTo, variantFrom);
|
||||||
var imcManip = new ImcManipulation(slotTo, variantTo.Id, idTo.Id, default);
|
var imcManip = new ImcManipulation(slotTo, variantTo.Id, idTo.Id, default);
|
||||||
var imcFileTo = new ImcFile(manager, imcManip);
|
var imcFileTo = new ImcFile(manager, imcManip.Identifier);
|
||||||
var skipFemale = false;
|
var skipFemale = false;
|
||||||
var skipMale = false;
|
var skipMale = false;
|
||||||
var mtrlVariantTo = manips(imcManip.Copy(imcFileTo.GetEntry(ImcFile.PartIndex(slotTo), variantTo.Id))).Imc.Entry.MaterialId;
|
var mtrlVariantTo = manips(imcManip.Copy(imcFileTo.GetEntry(ImcFile.PartIndex(slotTo), variantTo.Id))).Imc.Entry.MaterialId;
|
||||||
|
|
@ -121,7 +121,7 @@ public static class EquipmentSwap
|
||||||
{
|
{
|
||||||
(var imcFileFrom, var variants, affectedItems) = GetVariants(manager, identifier, slot, idFrom, idTo, variantFrom);
|
(var imcFileFrom, var variants, affectedItems) = GetVariants(manager, identifier, slot, idFrom, idTo, variantFrom);
|
||||||
var imcManip = new ImcManipulation(slot, variantTo.Id, idTo, default);
|
var imcManip = new ImcManipulation(slot, variantTo.Id, idTo, default);
|
||||||
var imcFileTo = new ImcFile(manager, imcManip);
|
var imcFileTo = new ImcFile(manager, imcManip.Identifier);
|
||||||
|
|
||||||
var isAccessory = slot.IsAccessory();
|
var isAccessory = slot.IsAccessory();
|
||||||
var estType = slot switch
|
var estType = slot switch
|
||||||
|
|
@ -250,7 +250,7 @@ public static class EquipmentSwap
|
||||||
PrimaryId idFrom, PrimaryId idTo, Variant variantFrom)
|
PrimaryId idFrom, PrimaryId idTo, Variant variantFrom)
|
||||||
{
|
{
|
||||||
var entry = new ImcManipulation(slotFrom, variantFrom.Id, idFrom, default);
|
var entry = new ImcManipulation(slotFrom, variantFrom.Id, idFrom, default);
|
||||||
var imc = new ImcFile(manager, entry);
|
var imc = new ImcFile(manager, entry.Identifier);
|
||||||
EquipItem[] items;
|
EquipItem[] items;
|
||||||
Variant[] variants;
|
Variant[] variants;
|
||||||
if (idFrom == idTo)
|
if (idFrom == idTo)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using OtterGui.Classes;
|
||||||
using OtterGui.Filesystem;
|
using OtterGui.Filesystem;
|
||||||
using OtterGui.Services;
|
using OtterGui.Services;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
using Penumbra.Meta;
|
||||||
using Penumbra.Meta.Manipulations;
|
using Penumbra.Meta.Manipulations;
|
||||||
using Penumbra.Mods.Groups;
|
using Penumbra.Mods.Groups;
|
||||||
using Penumbra.Mods.Settings;
|
using Penumbra.Mods.Settings;
|
||||||
|
|
@ -14,7 +15,8 @@ public sealed class ImcModGroupEditor(CommunicatorService communicator, SaveServ
|
||||||
: ModOptionEditor<ImcModGroup, ImcSubMod>(communicator, saveService, config), IService
|
: ModOptionEditor<ImcModGroup, ImcSubMod>(communicator, saveService, config), IService
|
||||||
{
|
{
|
||||||
/// <summary> Add a new, empty imc group with the given manipulation data. </summary>
|
/// <summary> Add a new, empty imc group with the given manipulation data. </summary>
|
||||||
public ImcModGroup? AddModGroup(Mod mod, string newName, ImcIdentifier identifier, ImcEntry defaultEntry, SaveType saveType = SaveType.ImmediateSync)
|
public ImcModGroup? AddModGroup(Mod mod, string newName, ImcIdentifier identifier, ImcEntry defaultEntry,
|
||||||
|
SaveType saveType = SaveType.ImmediateSync)
|
||||||
{
|
{
|
||||||
if (!ModGroupEditor.VerifyFileName(mod, null, newName, true))
|
if (!ModGroupEditor.VerifyFileName(mod, null, newName, true))
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -78,6 +80,16 @@ public sealed class ImcModGroupEditor(CommunicatorService communicator, SaveServ
|
||||||
Communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionMetaChanged, option.Mod, option.Group, option, null, -1);
|
Communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionMetaChanged, option.Mod, option.Group, option, null, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ChangeAllVariants(ImcModGroup group, bool allVariants, SaveType saveType = SaveType.Queue)
|
||||||
|
{
|
||||||
|
if (group.AllVariants == allVariants)
|
||||||
|
return;
|
||||||
|
|
||||||
|
group.AllVariants = allVariants;
|
||||||
|
SaveService.Save(saveType, new ModSaveGroup(group, Config.ReplaceNonAsciiOnImport));
|
||||||
|
Communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionMetaChanged, group.Mod, group, null, null, -1);
|
||||||
|
}
|
||||||
|
|
||||||
public void ChangeCanBeDisabled(ImcModGroup group, bool canBeDisabled, SaveType saveType = SaveType.Queue)
|
public void ChangeCanBeDisabled(ImcModGroup group, bool canBeDisabled, SaveType saveType = SaveType.Queue)
|
||||||
{
|
{
|
||||||
if (group.CanBeDisabled == canBeDisabled)
|
if (group.CanBeDisabled == canBeDisabled)
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,13 @@ public readonly struct ImcModGroupEditDrawer(ModGroupEditDrawer editor, ImcModGr
|
||||||
var entry = group.DefaultEntry;
|
var entry = group.DefaultEntry;
|
||||||
var changes = false;
|
var changes = false;
|
||||||
|
|
||||||
ImUtf8.TextFramed(identifier.ToString(), 0, editor.AvailableWidth, borderColor: ImGui.GetColorU32(ImGuiCol.Border));
|
var width = editor.AvailableWidth.X - ImUtf8.ItemInnerSpacing.X - ImUtf8.CalcTextSize("All Variants"u8).X;
|
||||||
|
ImUtf8.TextFramed(identifier.ToString(), 0, new Vector2(width, 0), borderColor: ImGui.GetColorU32(ImGuiCol.Border));
|
||||||
|
ImUtf8.SameLineInner();
|
||||||
|
var allVariants = group.AllVariants;
|
||||||
|
if (ImUtf8.Checkbox("All Variants"u8, ref allVariants))
|
||||||
|
editor.ModManager.OptionEditor.ImcEditor.ChangeAllVariants(group, allVariants);
|
||||||
|
ImUtf8.HoverTooltip("Make this group overwrite all corresponding variants for this identifier, not just the one specified."u8);
|
||||||
|
|
||||||
using (ImUtf8.Group())
|
using (ImUtf8.Group())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue