mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-15 05:04:15 +01:00
Remove TryGetValue(MetaManipulation) from MetaDictionary.
This commit is contained in:
parent
5ca9e63a2a
commit
0445ed0ef9
11 changed files with 182 additions and 183 deletions
|
|
@ -2,6 +2,7 @@ using Penumbra.GameData.Enums;
|
|||
using Penumbra.GameData.Structs;
|
||||
using Penumbra.Interop.Services;
|
||||
using Penumbra.Interop.Structs;
|
||||
using Penumbra.Meta.Manipulations;
|
||||
using Penumbra.String.Functions;
|
||||
|
||||
namespace Penumbra.Meta.Files;
|
||||
|
|
@ -126,4 +127,7 @@ public sealed unsafe class ExpandedEqdpFile : MetaBaseFile
|
|||
|
||||
public static EqdpEntry GetDefault(MetaFileManager manager, GenderRace raceCode, bool accessory, PrimaryId primaryId)
|
||||
=> GetDefault(manager, CharacterUtility.ReverseIndices[(int)CharacterUtilityData.EqdpIdx(raceCode, accessory)], primaryId);
|
||||
|
||||
public static EqdpEntry GetDefault(MetaFileManager manager, EqdpIdentifier identifier)
|
||||
=> GetDefault(manager, CharacterUtility.ReverseIndices[(int)identifier.FileIndex()], identifier.SetId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using Penumbra.GameData.Structs;
|
||||
using Penumbra.Interop.Services;
|
||||
using Penumbra.Interop.Structs;
|
||||
using Penumbra.Meta.Manipulations;
|
||||
using Penumbra.String.Functions;
|
||||
|
||||
namespace Penumbra.Meta.Files;
|
||||
|
|
@ -164,6 +165,9 @@ public sealed class ExpandedGmpFile : ExpandedEqpGmpBase, IEnumerable<GmpEntry>
|
|||
public static GmpEntry GetDefault(MetaFileManager manager, PrimaryId primaryIdx)
|
||||
=> new() { Value = GetDefaultInternal(manager, InternalIndex, primaryIdx, GmpEntry.Default.Value) };
|
||||
|
||||
public static GmpEntry GetDefault(MetaFileManager manager, GmpIdentifier identifier)
|
||||
=> new() { Value = GetDefaultInternal(manager, InternalIndex, identifier.SetId, GmpEntry.Default.Value) };
|
||||
|
||||
public void Reset(IEnumerable<PrimaryId> entries)
|
||||
{
|
||||
foreach (var entry in entries)
|
||||
|
|
|
|||
|
|
@ -184,4 +184,7 @@ public sealed unsafe class EstFile : MetaBaseFile
|
|||
|
||||
public static EstEntry GetDefault(MetaFileManager manager, EstType estType, GenderRace genderRace, PrimaryId primaryId)
|
||||
=> GetDefault(manager, (MetaIndex)estType, genderRace, primaryId);
|
||||
|
||||
public static EstEntry GetDefault(MetaFileManager manager, EstIdentifier identifier)
|
||||
=> GetDefault(manager, identifier.FileIndex(), identifier.GenderRace, identifier.SetId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,9 @@ public unsafe class ImcFile : MetaBaseFile
|
|||
return ptr == null ? new ImcEntry() : *ptr;
|
||||
}
|
||||
|
||||
public ImcEntry GetEntry(EquipSlot slot, Variant variantIdx)
|
||||
=> GetEntry(PartIndex(slot), variantIdx);
|
||||
|
||||
public ImcEntry GetEntry(int partIdx, Variant variantIdx, out bool exists)
|
||||
{
|
||||
var ptr = VariantPtr(Data, partIdx, variantIdx);
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ public readonly record struct EqdpIdentifier(PrimaryId SetId, EquipSlot Slot, Ge
|
|||
}
|
||||
}
|
||||
|
||||
public readonly record struct EqdpEntryInternal(bool Model, bool Material)
|
||||
public readonly record struct EqdpEntryInternal(bool Material, bool Model)
|
||||
{
|
||||
private EqdpEntryInternal((bool, bool) val)
|
||||
: this(val.Item1, val.Item2)
|
||||
|
|
@ -81,7 +81,6 @@ public readonly record struct EqdpEntryInternal(bool Model, bool Material)
|
|||
: this(entry.ToBits(slot))
|
||||
{ }
|
||||
|
||||
|
||||
public EqdpEntry ToEntry(EquipSlot slot)
|
||||
=> Eqdp.FromSlotAndBits(slot, Model, Material);
|
||||
=> Eqdp.FromSlotAndBits(slot, Material, Model);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,19 @@ public sealed class MetaDictionary : IEnumerable<MetaManipulation>
|
|||
IEnumerator IEnumerable.GetEnumerator()
|
||||
=> GetEnumerator();
|
||||
|
||||
public bool Add(IMetaIdentifier identifier, object entry)
|
||||
=> identifier switch
|
||||
{
|
||||
EqdpIdentifier eqdpIdentifier => entry is EqdpEntryInternal e && Add(eqdpIdentifier, e),
|
||||
EqpIdentifier eqpIdentifier => entry is EqpEntryInternal e && Add(eqpIdentifier, e),
|
||||
EstIdentifier estIdentifier => entry is EstEntry e && Add(estIdentifier, e),
|
||||
GlobalEqpManipulation globalEqpManipulation => Add(globalEqpManipulation),
|
||||
GmpIdentifier gmpIdentifier => entry is GmpEntry e && Add(gmpIdentifier, e),
|
||||
ImcIdentifier imcIdentifier => entry is ImcEntry e && Add(imcIdentifier, e),
|
||||
RspIdentifier rspIdentifier => entry is RspEntry e && Add(rspIdentifier, e),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
public bool Add(MetaManipulation manip)
|
||||
{
|
||||
var ret = manip.ManipulationType switch
|
||||
|
|
@ -146,71 +159,23 @@ public sealed class MetaDictionary : IEnumerable<MetaManipulation>
|
|||
TryAdd(identifier);
|
||||
}
|
||||
|
||||
public bool TryGetValue(MetaManipulation identifier, out MetaManipulation oldValue)
|
||||
{
|
||||
switch (identifier.ManipulationType)
|
||||
{
|
||||
case MetaManipulation.Type.Imc:
|
||||
if (_imc.TryGetValue(identifier.Imc.Identifier, out var oldImc))
|
||||
{
|
||||
oldValue = new MetaManipulation(new ImcManipulation(identifier.Imc.Identifier, oldImc));
|
||||
return true;
|
||||
}
|
||||
public bool TryGetValue(EstIdentifier identifier, out EstEntry value)
|
||||
=> _est.TryGetValue(identifier, out value);
|
||||
|
||||
break;
|
||||
case MetaManipulation.Type.Eqdp:
|
||||
if (_eqp.TryGetValue(identifier.Eqp.Identifier, out var oldEqdp))
|
||||
{
|
||||
oldValue = new MetaManipulation(new EqpManipulation(identifier.Eqp.Identifier, oldEqdp.ToEntry(identifier.Eqp.Slot)));
|
||||
return true;
|
||||
}
|
||||
public bool TryGetValue(EqpIdentifier identifier, out EqpEntryInternal value)
|
||||
=> _eqp.TryGetValue(identifier, out value);
|
||||
|
||||
break;
|
||||
case MetaManipulation.Type.Eqp:
|
||||
if (_eqdp.TryGetValue(identifier.Eqdp.Identifier, out var oldEqp))
|
||||
{
|
||||
oldValue = new MetaManipulation(new EqdpManipulation(identifier.Eqdp.Identifier, oldEqp.ToEntry(identifier.Eqdp.Slot)));
|
||||
return true;
|
||||
}
|
||||
public bool TryGetValue(EqdpIdentifier identifier, out EqdpEntryInternal value)
|
||||
=> _eqdp.TryGetValue(identifier, out value);
|
||||
|
||||
break;
|
||||
case MetaManipulation.Type.Est:
|
||||
if (_est.TryGetValue(identifier.Est.Identifier, out var oldEst))
|
||||
{
|
||||
oldValue = new MetaManipulation(new EstManipulation(identifier.Est.Identifier, oldEst));
|
||||
return true;
|
||||
}
|
||||
public bool TryGetValue(GmpIdentifier identifier, out GmpEntry value)
|
||||
=> _gmp.TryGetValue(identifier, out value);
|
||||
|
||||
break;
|
||||
case MetaManipulation.Type.Gmp:
|
||||
if (_gmp.TryGetValue(identifier.Gmp.Identifier, out var oldGmp))
|
||||
{
|
||||
oldValue = new MetaManipulation(new GmpManipulation(identifier.Gmp.Identifier, oldGmp));
|
||||
return true;
|
||||
}
|
||||
public bool TryGetValue(RspIdentifier identifier, out RspEntry value)
|
||||
=> _rsp.TryGetValue(identifier, out value);
|
||||
|
||||
break;
|
||||
case MetaManipulation.Type.Rsp:
|
||||
if (_rsp.TryGetValue(identifier.Rsp.Identifier, out var oldRsp))
|
||||
{
|
||||
oldValue = new MetaManipulation(new RspManipulation(identifier.Rsp.Identifier, oldRsp));
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
case MetaManipulation.Type.GlobalEqp:
|
||||
if (_globalEqp.TryGetValue(identifier.GlobalEqp, out var oldGlobalEqp))
|
||||
{
|
||||
oldValue = new MetaManipulation(oldGlobalEqp);
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
oldValue = default;
|
||||
return false;
|
||||
}
|
||||
public bool TryGetValue(ImcIdentifier identifier, out ImcEntry value)
|
||||
=> _imc.TryGetValue(identifier, out value);
|
||||
|
||||
public void SetTo(MetaDictionary other)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.GameData.Data;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Files;
|
||||
|
|
@ -16,32 +16,19 @@ public static class EquipmentSwap
|
|||
private static EquipSlot[] ConvertSlots(EquipSlot slot, bool rFinger, bool lFinger)
|
||||
{
|
||||
if (slot != EquipSlot.RFinger)
|
||||
return new[]
|
||||
{
|
||||
slot,
|
||||
};
|
||||
return [slot];
|
||||
|
||||
return rFinger
|
||||
? lFinger
|
||||
? new[]
|
||||
{
|
||||
EquipSlot.RFinger,
|
||||
EquipSlot.LFinger,
|
||||
}
|
||||
: new[]
|
||||
{
|
||||
EquipSlot.RFinger,
|
||||
}
|
||||
? [EquipSlot.RFinger, EquipSlot.LFinger]
|
||||
: [EquipSlot.RFinger]
|
||||
: lFinger
|
||||
? new[]
|
||||
{
|
||||
EquipSlot.LFinger,
|
||||
}
|
||||
: Array.Empty<EquipSlot>();
|
||||
? [EquipSlot.LFinger]
|
||||
: [];
|
||||
}
|
||||
|
||||
public static EquipItem[] CreateTypeSwap(MetaFileManager manager, ObjectIdentification identifier, List<Swap> swaps,
|
||||
Func<Utf8GamePath, FullPath> redirections, Func<MetaManipulation, MetaManipulation> manips,
|
||||
Func<Utf8GamePath, FullPath> redirections, MetaDictionary manips,
|
||||
EquipSlot slotFrom, EquipItem itemFrom, EquipSlot slotTo, EquipItem itemTo)
|
||||
{
|
||||
LookupItem(itemFrom, out var actualSlotFrom, out var idFrom, out var variantFrom);
|
||||
|
|
@ -50,11 +37,14 @@ public static class EquipmentSwap
|
|||
throw new ItemSwap.InvalidItemTypeException();
|
||||
|
||||
var (imcFileFrom, variants, affectedItems) = GetVariants(manager, identifier, slotFrom, idFrom, idTo, variantFrom);
|
||||
var imcManip = new ImcManipulation(slotTo, variantTo.Id, idTo.Id, default);
|
||||
var imcFileTo = new ImcFile(manager, imcManip.Identifier);
|
||||
var imcIdentifierTo = new ImcIdentifier(slotTo, idTo, variantTo);
|
||||
var imcFileTo = new ImcFile(manager, imcIdentifierTo);
|
||||
var imcEntry = manips.TryGetValue(imcIdentifierTo, out var entry)
|
||||
? entry
|
||||
: imcFileTo.GetEntry(imcIdentifierTo.EquipSlot, imcIdentifierTo.Variant);
|
||||
var mtrlVariantTo = imcEntry.MaterialId;
|
||||
var skipFemale = false;
|
||||
var skipMale = false;
|
||||
var mtrlVariantTo = manips(imcManip.Copy(imcFileTo.GetEntry(ImcFile.PartIndex(slotTo), variantTo.Id))).Imc.Entry.MaterialId;
|
||||
foreach (var gr in Enum.GetValues<GenderRace>())
|
||||
{
|
||||
switch (gr.Split().Item1)
|
||||
|
|
@ -99,7 +89,7 @@ public static class EquipmentSwap
|
|||
}
|
||||
|
||||
public static EquipItem[] CreateItemSwap(MetaFileManager manager, ObjectIdentification identifier, List<Swap> swaps,
|
||||
Func<Utf8GamePath, FullPath> redirections, Func<MetaManipulation, MetaManipulation> manips, EquipItem itemFrom,
|
||||
Func<Utf8GamePath, FullPath> redirections, MetaDictionary manips, EquipItem itemFrom,
|
||||
EquipItem itemTo, bool rFinger = true, bool lFinger = true)
|
||||
{
|
||||
// Check actual ids, variants and slots. We only support using the same slot.
|
||||
|
|
@ -120,8 +110,12 @@ public static class EquipmentSwap
|
|||
foreach (var slot in ConvertSlots(slotFrom, rFinger, lFinger))
|
||||
{
|
||||
(var imcFileFrom, var variants, affectedItems) = GetVariants(manager, identifier, slot, idFrom, idTo, variantFrom);
|
||||
var imcManip = new ImcManipulation(slot, variantTo.Id, idTo, default);
|
||||
var imcFileTo = new ImcFile(manager, imcManip.Identifier);
|
||||
var imcIdentifierTo = new ImcIdentifier(slotTo, idTo, variantTo);
|
||||
var imcFileTo = new ImcFile(manager, imcIdentifierTo);
|
||||
var imcEntry = manips.TryGetValue(imcIdentifierTo, out var entry)
|
||||
? entry
|
||||
: imcFileTo.GetEntry(imcIdentifierTo.EquipSlot, imcIdentifierTo.Variant);
|
||||
var mtrlVariantTo = imcEntry.MaterialId;
|
||||
|
||||
var isAccessory = slot.IsAccessory();
|
||||
var estType = slot switch
|
||||
|
|
@ -133,7 +127,6 @@ public static class EquipmentSwap
|
|||
|
||||
var skipFemale = false;
|
||||
var skipMale = false;
|
||||
var mtrlVariantTo = manips(imcManip.Copy(imcFileTo.GetEntry(ImcFile.PartIndex(slot), variantTo))).Imc.Entry.MaterialId;
|
||||
foreach (var gr in Enum.GetValues<GenderRace>())
|
||||
{
|
||||
switch (gr.Split().Item1)
|
||||
|
|
@ -154,7 +147,7 @@ public static class EquipmentSwap
|
|||
if (eqdp != null)
|
||||
swaps.Add(eqdp);
|
||||
|
||||
var ownMdl = eqdp?.SwapApplied.Eqdp.Entry.ToBits(slot).Item2 ?? false;
|
||||
var ownMdl = eqdp?.SwapToModdedEntry.Model ?? false;
|
||||
var est = ItemSwap.CreateEst(manager, redirections, manips, estType, gr, idFrom, idTo, ownMdl);
|
||||
if (est != null)
|
||||
swaps.Add(est);
|
||||
|
|
@ -184,22 +177,22 @@ public static class EquipmentSwap
|
|||
return affectedItems;
|
||||
}
|
||||
|
||||
public static MetaSwap? CreateEqdp(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections,
|
||||
Func<MetaManipulation, MetaManipulation> manips, EquipSlot slot, GenderRace gr, PrimaryId idFrom,
|
||||
PrimaryId idTo, byte mtrlTo)
|
||||
public static MetaSwap<EqdpIdentifier, EqdpEntryInternal>? CreateEqdp(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections,
|
||||
MetaDictionary manips, EquipSlot slot, GenderRace gr, PrimaryId idFrom, PrimaryId idTo, byte mtrlTo)
|
||||
=> CreateEqdp(manager, redirections, manips, slot, slot, gr, idFrom, idTo, mtrlTo);
|
||||
|
||||
public static MetaSwap? CreateEqdp(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections,
|
||||
Func<MetaManipulation, MetaManipulation> manips, EquipSlot slotFrom, EquipSlot slotTo, GenderRace gr, PrimaryId idFrom,
|
||||
public static MetaSwap<EqdpIdentifier, EqdpEntryInternal>? CreateEqdp(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections,
|
||||
MetaDictionary manips, EquipSlot slotFrom, EquipSlot slotTo, GenderRace gr, PrimaryId idFrom,
|
||||
PrimaryId idTo, byte mtrlTo)
|
||||
{
|
||||
var (gender, race) = gr.Split();
|
||||
var eqdpFrom = new EqdpManipulation(ExpandedEqdpFile.GetDefault(manager, gr, slotFrom.IsAccessory(), idFrom), slotFrom, gender,
|
||||
race, idFrom);
|
||||
var eqdpTo = new EqdpManipulation(ExpandedEqdpFile.GetDefault(manager, gr, slotTo.IsAccessory(), idTo), slotTo, gender, race,
|
||||
idTo);
|
||||
var meta = new MetaSwap(manips, eqdpFrom, eqdpTo);
|
||||
var (ownMtrl, ownMdl) = meta.SwapApplied.Eqdp.Entry.ToBits(slotFrom);
|
||||
var eqdpFromIdentifier = new EqdpIdentifier(idFrom, slotFrom, gr);
|
||||
var eqdpToIdentifier = new EqdpIdentifier(idFrom, slotFrom, gr);
|
||||
var eqdpFromDefault = new EqdpEntryInternal(ExpandedEqdpFile.GetDefault(manager, eqdpFromIdentifier), slotFrom);
|
||||
var eqdpToDefault = new EqdpEntryInternal(ExpandedEqdpFile.GetDefault(manager, eqdpToIdentifier), slotTo);
|
||||
var meta = new MetaSwap<EqdpIdentifier, EqdpEntryInternal>(i => manips.TryGetValue(i, out var e) ? e : null, eqdpFromIdentifier,
|
||||
eqdpFromDefault, eqdpToIdentifier,
|
||||
eqdpToDefault);
|
||||
var (ownMtrl, ownMdl) = meta.SwapToModdedEntry;
|
||||
if (ownMdl)
|
||||
{
|
||||
var mdl = CreateMdl(manager, redirections, slotFrom, slotTo, gr, idFrom, idTo, mtrlTo);
|
||||
|
|
@ -270,38 +263,39 @@ public static class EquipmentSwap
|
|||
return (imc, variants, items);
|
||||
}
|
||||
|
||||
public static MetaSwap? CreateGmp(MetaFileManager manager, Func<MetaManipulation, MetaManipulation> manips, EquipSlot slot, PrimaryId idFrom,
|
||||
PrimaryId idTo)
|
||||
public static MetaSwap<GmpIdentifier, GmpEntry>? CreateGmp(MetaFileManager manager, MetaDictionary manips,
|
||||
EquipSlot slot, PrimaryId idFrom, PrimaryId idTo)
|
||||
{
|
||||
if (slot is not EquipSlot.Head)
|
||||
return null;
|
||||
|
||||
var manipFrom = new GmpManipulation(ExpandedGmpFile.GetDefault(manager, idFrom), idFrom);
|
||||
var manipTo = new GmpManipulation(ExpandedGmpFile.GetDefault(manager, idTo), idTo);
|
||||
return new MetaSwap(manips, manipFrom, manipTo);
|
||||
var manipFromIdentifier = new GmpIdentifier(idFrom);
|
||||
var manipToIdentifier = new GmpIdentifier(idTo);
|
||||
var manipFromDefault = ExpandedGmpFile.GetDefault(manager, manipFromIdentifier);
|
||||
var manipToDefault = ExpandedGmpFile.GetDefault(manager, manipToIdentifier);
|
||||
return new MetaSwap<GmpIdentifier, GmpEntry>(i => manips.TryGetValue(i, out var e) ? e : null, manipFromIdentifier, manipFromDefault, manipToIdentifier, manipToDefault);
|
||||
}
|
||||
|
||||
public static MetaSwap CreateImc(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections,
|
||||
Func<MetaManipulation, MetaManipulation> manips, EquipSlot slot,
|
||||
PrimaryId idFrom, PrimaryId idTo, Variant variantFrom, Variant variantTo, ImcFile imcFileFrom, ImcFile imcFileTo)
|
||||
public static MetaSwap<ImcIdentifier, ImcEntry> CreateImc(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections,
|
||||
MetaDictionary manips, EquipSlot slot, PrimaryId idFrom, PrimaryId idTo, Variant variantFrom, Variant variantTo,
|
||||
ImcFile imcFileFrom, ImcFile imcFileTo)
|
||||
=> CreateImc(manager, redirections, manips, slot, slot, idFrom, idTo, variantFrom, variantTo, imcFileFrom, imcFileTo);
|
||||
|
||||
public static MetaSwap CreateImc(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections,
|
||||
Func<MetaManipulation, MetaManipulation> manips,
|
||||
EquipSlot slotFrom, EquipSlot slotTo, PrimaryId idFrom, PrimaryId idTo,
|
||||
public static MetaSwap<ImcIdentifier, ImcEntry> CreateImc(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections,
|
||||
MetaDictionary manips, EquipSlot slotFrom, EquipSlot slotTo, PrimaryId idFrom, PrimaryId idTo,
|
||||
Variant variantFrom, Variant variantTo, ImcFile imcFileFrom, ImcFile imcFileTo)
|
||||
{
|
||||
var entryFrom = imcFileFrom.GetEntry(ImcFile.PartIndex(slotFrom), variantFrom);
|
||||
var entryTo = imcFileTo.GetEntry(ImcFile.PartIndex(slotTo), variantTo);
|
||||
var manipulationFrom = new ImcManipulation(slotFrom, variantFrom.Id, idFrom, entryFrom);
|
||||
var manipulationTo = new ImcManipulation(slotTo, variantTo.Id, idTo, entryTo);
|
||||
var imc = new MetaSwap(manips, manipulationFrom, manipulationTo);
|
||||
var manipFromIdentifier = new ImcIdentifier(slotFrom, idFrom, variantFrom);
|
||||
var manipToIdentifier = new ImcIdentifier(slotTo, idTo, variantTo);
|
||||
var manipFromDefault = imcFileFrom.GetEntry(ImcFile.PartIndex(slotFrom), variantFrom);
|
||||
var manipToDefault = imcFileTo.GetEntry(ImcFile.PartIndex(slotTo), variantTo);
|
||||
var imc = new MetaSwap<ImcIdentifier, ImcEntry>(i => manips.TryGetValue(i, out var e) ? e : null, manipFromIdentifier, manipFromDefault, manipToIdentifier, manipToDefault);
|
||||
|
||||
var decal = CreateDecal(manager, redirections, imc.SwapToModded.Imc.Entry.DecalId);
|
||||
var decal = CreateDecal(manager, redirections, imc.SwapToModdedEntry.DecalId);
|
||||
if (decal != null)
|
||||
imc.ChildSwaps.Add(decal);
|
||||
|
||||
var avfx = CreateAvfx(manager, redirections, idFrom, idTo, imc.SwapToModded.Imc.Entry.VfxId);
|
||||
var avfx = CreateAvfx(manager, redirections, idFrom, idTo, imc.SwapToModdedEntry.VfxId);
|
||||
if (avfx != null)
|
||||
imc.ChildSwaps.Add(avfx);
|
||||
|
||||
|
|
@ -322,7 +316,8 @@ public static class EquipmentSwap
|
|||
|
||||
|
||||
// Example: Abyssos Helm / Body
|
||||
public static FileSwap? CreateAvfx(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, PrimaryId idFrom, PrimaryId idTo, byte vfxId)
|
||||
public static FileSwap? CreateAvfx(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, PrimaryId idFrom, PrimaryId idTo,
|
||||
byte vfxId)
|
||||
{
|
||||
if (vfxId == 0)
|
||||
return null;
|
||||
|
|
@ -340,17 +335,18 @@ public static class EquipmentSwap
|
|||
return avfx;
|
||||
}
|
||||
|
||||
public static MetaSwap? CreateEqp(MetaFileManager manager, Func<MetaManipulation, MetaManipulation> manips, EquipSlot slot, PrimaryId idFrom,
|
||||
PrimaryId idTo)
|
||||
public static MetaSwap<EqpIdentifier, EqpEntryInternal>? CreateEqp(MetaFileManager manager, MetaDictionary manips,
|
||||
EquipSlot slot, PrimaryId idFrom, PrimaryId idTo)
|
||||
{
|
||||
if (slot.IsAccessory())
|
||||
return null;
|
||||
|
||||
var eqpValueFrom = ExpandedEqpFile.GetDefault(manager, idFrom);
|
||||
var eqpValueTo = ExpandedEqpFile.GetDefault(manager, idTo);
|
||||
var eqpFrom = new EqpManipulation(eqpValueFrom, slot, idFrom);
|
||||
var eqpTo = new EqpManipulation(eqpValueTo, slot, idFrom);
|
||||
return new MetaSwap(manips, eqpFrom, eqpTo);
|
||||
var manipFromIdentifier = new EqpIdentifier(idFrom, slot);
|
||||
var manipToIdentifier = new EqpIdentifier(idTo, slot);
|
||||
var manipFromDefault = new EqpEntryInternal(ExpandedEqpFile.GetDefault(manager, idFrom), slot);
|
||||
var manipToDefault = new EqpEntryInternal(ExpandedEqpFile.GetDefault(manager, idTo), slot);
|
||||
return new MetaSwap<EqpIdentifier, EqpEntryInternal>(i => manips.TryGetValue(i, out var e) ? e : null, manipFromIdentifier,
|
||||
manipFromDefault, manipToIdentifier, manipToDefault);
|
||||
}
|
||||
|
||||
public static FileSwap? CreateMtrl(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, EquipSlot slot, PrimaryId idFrom,
|
||||
|
|
@ -397,7 +393,8 @@ public static class EquipmentSwap
|
|||
return mtrl;
|
||||
}
|
||||
|
||||
public static FileSwap CreateTex(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, char prefix, PrimaryId idFrom, PrimaryId idTo,
|
||||
public static FileSwap CreateTex(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, char prefix, PrimaryId idFrom,
|
||||
PrimaryId idTo,
|
||||
ref MtrlFile.Texture texture, ref bool dataWasChanged)
|
||||
=> CreateTex(manager, redirections, prefix, EquipSlot.Unknown, EquipSlot.Unknown, idFrom, idTo, ref texture, ref dataWasChanged);
|
||||
|
||||
|
|
|
|||
|
|
@ -147,24 +147,23 @@ public static class ItemSwap
|
|||
return FileSwap.CreateSwap(manager, ResourceType.Sklb, redirections, sklbPath, sklbPath);
|
||||
}
|
||||
|
||||
/// <remarks> metaChanges is not manipulated, but IReadOnlySet does not support TryGetValue. </remarks>
|
||||
public static MetaSwap? CreateEst(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections,
|
||||
Func<MetaManipulation, MetaManipulation> manips, EstType type,
|
||||
GenderRace genderRace, PrimaryId idFrom, PrimaryId idTo, bool ownMdl)
|
||||
public static MetaSwap<EstIdentifier, EstEntry>? CreateEst(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections,
|
||||
MetaDictionary manips, EstType type, GenderRace genderRace, PrimaryId idFrom, PrimaryId idTo, bool ownMdl)
|
||||
{
|
||||
if (type == 0)
|
||||
return null;
|
||||
|
||||
var (gender, race) = genderRace.Split();
|
||||
var fromDefault = new EstManipulation(gender, race, type, idFrom, EstFile.GetDefault(manager, type, genderRace, idFrom));
|
||||
var toDefault = new EstManipulation(gender, race, type, idTo, EstFile.GetDefault(manager, type, genderRace, idTo));
|
||||
var est = new MetaSwap(manips, fromDefault, toDefault);
|
||||
var manipFromIdentifier = new EstIdentifier(idFrom, type, genderRace);
|
||||
var manipToIdentifier = new EstIdentifier(idTo, type, genderRace);
|
||||
var manipFromDefault = EstFile.GetDefault(manager, manipFromIdentifier);
|
||||
var manipToDefault = EstFile.GetDefault(manager, manipToIdentifier);
|
||||
var est = new MetaSwap<EstIdentifier, EstEntry>(i => manips.TryGetValue(i, out var e) ? e : null, manipFromIdentifier, manipFromDefault, manipToIdentifier, manipToDefault);
|
||||
|
||||
if (ownMdl && est.SwapApplied.Est.Entry.Value >= 2)
|
||||
if (ownMdl && est.SwapToModdedEntry.Value >= 2)
|
||||
{
|
||||
var phyb = CreatePhyb(manager, redirections, type, genderRace, est.SwapApplied.Est.Entry);
|
||||
var phyb = CreatePhyb(manager, redirections, type, genderRace, est.SwapToModdedEntry);
|
||||
est.ChildSwaps.Add(phyb);
|
||||
var sklb = CreateSklb(manager, redirections, type, genderRace, est.SwapApplied.Est.Entry);
|
||||
var sklb = CreateSklb(manager, redirections, type, genderRace, est.SwapToModdedEntry);
|
||||
est.ChildSwaps.Add(sklb);
|
||||
}
|
||||
else if (est.SwapAppliedIsDefault)
|
||||
|
|
|
|||
|
|
@ -74,9 +74,9 @@ public class ItemSwapContainer
|
|||
}
|
||||
|
||||
break;
|
||||
case MetaSwap meta:
|
||||
case IMetaSwap meta:
|
||||
if (!meta.SwapAppliedIsDefault)
|
||||
convertedManips.Add(meta.SwapApplied);
|
||||
convertedManips.Add(meta.SwapFromIdentifier, meta.SwapToModdedEntry);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -116,17 +116,10 @@ public class ItemSwapContainer
|
|||
? p => collection.ResolvePath(p) ?? new FullPath(p)
|
||||
: p => ModRedirections.TryGetValue(p, out var path) ? path : new FullPath(p);
|
||||
|
||||
private Func<MetaManipulation, MetaManipulation> MetaResolver(ModCollection? collection)
|
||||
{
|
||||
if (collection?.MetaCache?.Manipulations is { } cache)
|
||||
{
|
||||
MetaDictionary dict = [.. cache];
|
||||
return m => dict.TryGetValue(m, out var a) ? a : m;
|
||||
}
|
||||
|
||||
var set = _appliedModData.Manipulations;
|
||||
return m => set.TryGetValue(m, out var a) ? a : m;
|
||||
}
|
||||
private MetaDictionary MetaResolver(ModCollection? collection)
|
||||
=> collection?.MetaCache?.Manipulations is { } cache
|
||||
? [.. cache]
|
||||
: _appliedModData.Manipulations;
|
||||
|
||||
public EquipItem[] LoadEquipment(EquipItem from, EquipItem to, ModCollection? collection = null, bool useRightRing = true,
|
||||
bool useLeftRing = true)
|
||||
|
|
@ -161,8 +154,8 @@ public class ItemSwapContainer
|
|||
_ => (EstType)0,
|
||||
};
|
||||
|
||||
var metaResolver = MetaResolver(collection);
|
||||
var est = ItemSwap.CreateEst(manager, pathResolver, metaResolver, type, race, from, to, true);
|
||||
var estResolver = MetaResolver(collection);
|
||||
var est = ItemSwap.CreateEst(manager, pathResolver, estResolver, type, race, from, to, true);
|
||||
|
||||
Swaps.Add(mdl);
|
||||
if (est != null)
|
||||
|
|
|
|||
|
|
@ -1,58 +1,91 @@
|
|||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.GameData.Files;
|
||||
using Penumbra.Meta.Manipulations;
|
||||
using Penumbra.String.Classes;
|
||||
using Penumbra.Meta;
|
||||
using static Penumbra.Mods.ItemSwap.ItemSwap;
|
||||
using Penumbra.Services;
|
||||
|
||||
namespace Penumbra.Mods.ItemSwap;
|
||||
|
||||
public class Swap
|
||||
{
|
||||
/// <summary> Any further swaps belonging specifically to this tree of changes. </summary>
|
||||
public readonly List<Swap> ChildSwaps = new();
|
||||
public readonly List<Swap> ChildSwaps = [];
|
||||
|
||||
public IEnumerable<Swap> WithChildren()
|
||||
=> ChildSwaps.SelectMany(c => c.WithChildren()).Prepend(this);
|
||||
}
|
||||
|
||||
public sealed class MetaSwap : Swap
|
||||
public interface IMetaSwap
|
||||
{
|
||||
public IMetaIdentifier SwapFromIdentifier { get; }
|
||||
public IMetaIdentifier SwapToIdentifier { get; }
|
||||
|
||||
public object SwapFromDefaultEntry { get; }
|
||||
public object SwapToDefaultEntry { get; }
|
||||
public object SwapToModdedEntry { get; }
|
||||
|
||||
public bool SwapToIsDefault { get; }
|
||||
public bool SwapAppliedIsDefault { get; }
|
||||
}
|
||||
|
||||
public sealed class MetaSwap<TIdentifier, TEntry> : Swap, IMetaSwap
|
||||
where TIdentifier : unmanaged, IMetaIdentifier
|
||||
where TEntry : unmanaged, IEquatable<TEntry>
|
||||
{
|
||||
public TIdentifier SwapFromIdentifier;
|
||||
public TIdentifier SwapToIdentifier;
|
||||
|
||||
/// <summary> The default value of a specific meta manipulation that needs to be redirected. </summary>
|
||||
public MetaManipulation SwapFrom;
|
||||
public TEntry SwapFromDefaultEntry;
|
||||
|
||||
/// <summary> The default value of the same Meta entry of the redirected item. </summary>
|
||||
public MetaManipulation SwapToDefault;
|
||||
public TEntry SwapToDefaultEntry;
|
||||
|
||||
/// <summary> The modded value of the same Meta entry of the redirected item, or the same as SwapToDefault if unmodded. </summary>
|
||||
public MetaManipulation SwapToModded;
|
||||
public TEntry SwapToModdedEntry;
|
||||
|
||||
/// <summary> The modded value applied to the specific meta manipulation target before redirection. </summary>
|
||||
public MetaManipulation SwapApplied;
|
||||
|
||||
/// <summary> Whether SwapToModded equals SwapToDefault. </summary>
|
||||
public bool SwapToIsDefault;
|
||||
/// <summary> Whether SwapToModdedEntry equals SwapToDefaultEntry. </summary>
|
||||
public bool SwapToIsDefault { get; }
|
||||
|
||||
/// <summary> Whether the applied meta manipulation does not change anything against the default. </summary>
|
||||
public bool SwapAppliedIsDefault;
|
||||
public bool SwapAppliedIsDefault { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new MetaSwap from the original meta identifier and the target meta identifier.
|
||||
/// </summary>
|
||||
/// <param name="manipulations">A function that converts the given manipulation to the modded one.</param>
|
||||
/// <param name="manipFrom">The original meta identifier with its default value.</param>
|
||||
/// <param name="manipTo">The target meta identifier with its default value.</param>
|
||||
public MetaSwap(Func<MetaManipulation, MetaManipulation> manipulations, MetaManipulation manipFrom, MetaManipulation manipTo)
|
||||
/// <param name="manipulations">A function that obtains a modded meta entry if it exists. </param>
|
||||
/// <param name="manipFromIdentifier"> The original meta identifier. </param>
|
||||
/// <param name="manipFromEntry"> The default value for the original meta identifier. </param>
|
||||
/// <param name="manipToIdentifier"> The target meta identifier. </param>
|
||||
/// <param name="manipToEntry"> The default value for the target meta identifier. </param>
|
||||
public MetaSwap(Func<TIdentifier, TEntry?> manipulations, TIdentifier manipFromIdentifier, TEntry manipFromEntry,
|
||||
TIdentifier manipToIdentifier, TEntry manipToEntry)
|
||||
{
|
||||
SwapFrom = manipFrom;
|
||||
SwapToDefault = manipTo;
|
||||
SwapFromIdentifier = manipFromIdentifier;
|
||||
SwapToIdentifier = manipToIdentifier;
|
||||
SwapFromDefaultEntry = manipFromEntry;
|
||||
SwapToDefaultEntry = manipToEntry;
|
||||
|
||||
SwapToModded = manipulations(manipTo);
|
||||
SwapToIsDefault = manipTo.EntryEquals(SwapToModded);
|
||||
SwapApplied = SwapFrom.WithEntryOf(SwapToModded);
|
||||
SwapAppliedIsDefault = SwapApplied.EntryEquals(SwapFrom);
|
||||
SwapToModdedEntry = manipulations(SwapToIdentifier) ?? SwapToDefaultEntry;
|
||||
SwapToIsDefault = SwapToModdedEntry.Equals(SwapToDefaultEntry);
|
||||
SwapAppliedIsDefault = SwapToModdedEntry.Equals(SwapFromDefaultEntry);
|
||||
}
|
||||
|
||||
IMetaIdentifier IMetaSwap.SwapFromIdentifier
|
||||
=> SwapFromIdentifier;
|
||||
|
||||
IMetaIdentifier IMetaSwap.SwapToIdentifier
|
||||
=> SwapToIdentifier;
|
||||
|
||||
object IMetaSwap.SwapFromDefaultEntry
|
||||
=> SwapFromDefaultEntry;
|
||||
|
||||
object IMetaSwap.SwapToDefaultEntry
|
||||
=> SwapToDefaultEntry;
|
||||
|
||||
object IMetaSwap.SwapToModdedEntry
|
||||
=> SwapToModdedEntry;
|
||||
}
|
||||
|
||||
public sealed class FileSwap : Swap
|
||||
|
|
@ -113,8 +146,7 @@ public sealed class FileSwap : Swap
|
|||
/// <param name="swap">A full swap container with the actual file in memory.</param>
|
||||
/// <returns>True if everything could be read correctly, false otherwise.</returns>
|
||||
public static FileSwap CreateSwap(MetaFileManager manager, ResourceType type, Func<Utf8GamePath, FullPath> redirections,
|
||||
string swapFromRequest, string swapToRequest,
|
||||
string? swapFromPreChange = null)
|
||||
string swapFromRequest, string swapToRequest, string? swapFromPreChange = null)
|
||||
{
|
||||
var swap = new FileSwap
|
||||
{
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ public class ItemSwapTab : IDisposable, ITab
|
|||
{
|
||||
return swap switch
|
||||
{
|
||||
MetaSwap meta => $"{meta.SwapFrom}: {meta.SwapFrom.EntryToString()} -> {meta.SwapApplied.EntryToString()}",
|
||||
IMetaSwap meta => $"{meta.SwapFromIdentifier}: {meta.SwapFromDefaultEntry} -> {meta.SwapToModdedEntry}",
|
||||
FileSwap file =>
|
||||
$"{file.Type}: {file.SwapFromRequestPath} -> {file.SwapToModded.FullName}{(file.DataWasChanged ? " (EDITED)" : string.Empty)}",
|
||||
_ => string.Empty,
|
||||
|
|
@ -410,7 +410,7 @@ public class ItemSwapTab : IDisposable, ITab
|
|||
|
||||
private ImRaii.IEndObject DrawTab(SwapType newTab)
|
||||
{
|
||||
using var tab = ImRaii.TabItem(newTab is SwapType.BetweenSlots ? "Between Slots" : newTab.ToString());
|
||||
var tab = ImRaii.TabItem(newTab is SwapType.BetweenSlots ? "Between Slots" : newTab.ToString());
|
||||
if (tab)
|
||||
{
|
||||
_dirty |= _lastTab != newTab;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue