mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Add option to apply only attributes from IMC group.
This commit is contained in:
parent
ac1ea124d9
commit
00fbb2686b
8 changed files with 63 additions and 40 deletions
|
|
@ -6,9 +6,9 @@ namespace Penumbra.Meta;
|
|||
|
||||
public class ImcChecker
|
||||
{
|
||||
private static readonly Dictionary<ImcIdentifier, int> VariantCounts = [];
|
||||
private static MetaFileManager? _dataManager;
|
||||
|
||||
private static readonly Dictionary<ImcIdentifier, int> VariantCounts = [];
|
||||
private static MetaFileManager? _dataManager;
|
||||
private static readonly ConcurrentDictionary<ImcIdentifier, CachedEntry> GlobalCachedDefaultEntries = [];
|
||||
|
||||
public static int GetVariantCount(ImcIdentifier identifier)
|
||||
{
|
||||
|
|
@ -26,23 +26,20 @@ public class ImcChecker
|
|||
|
||||
public readonly record struct CachedEntry(ImcEntry Entry, bool FileExists, bool VariantExists);
|
||||
|
||||
private readonly Dictionary<ImcIdentifier, CachedEntry> _cachedDefaultEntries = new();
|
||||
private readonly MetaFileManager _metaFileManager;
|
||||
|
||||
public ImcChecker(MetaFileManager metaFileManager)
|
||||
{
|
||||
_metaFileManager = metaFileManager;
|
||||
_dataManager = metaFileManager;
|
||||
}
|
||||
=> _dataManager = metaFileManager;
|
||||
|
||||
public CachedEntry GetDefaultEntry(ImcIdentifier identifier, bool storeCache)
|
||||
public static CachedEntry GetDefaultEntry(ImcIdentifier identifier, bool storeCache)
|
||||
{
|
||||
if (_cachedDefaultEntries.TryGetValue(identifier, out var entry))
|
||||
if (GlobalCachedDefaultEntries.TryGetValue(identifier, out var entry))
|
||||
return entry;
|
||||
|
||||
if (_dataManager == null)
|
||||
return new CachedEntry(default, false, false);
|
||||
|
||||
try
|
||||
{
|
||||
var e = ImcFile.GetDefault(_metaFileManager, identifier.GamePath(), identifier.EquipSlot, identifier.Variant, out var entryExists);
|
||||
var e = ImcFile.GetDefault(_dataManager, identifier.GamePath(), identifier.EquipSlot, identifier.Variant, out var entryExists);
|
||||
entry = new CachedEntry(e, true, entryExists);
|
||||
}
|
||||
catch (Exception)
|
||||
|
|
@ -51,7 +48,7 @@ public class ImcChecker
|
|||
}
|
||||
|
||||
if (storeCache)
|
||||
_cachedDefaultEntries.Add(identifier, entry);
|
||||
GlobalCachedDefaultEntries.TryAdd(identifier, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ namespace Penumbra.Mods.Editor;
|
|||
|
||||
public class ModMetaEditor(
|
||||
ModGroupEditor groupEditor,
|
||||
MetaFileManager metaFileManager,
|
||||
ImcChecker imcChecker) : MetaDictionary, IService
|
||||
MetaFileManager metaFileManager) : MetaDictionary, IService
|
||||
{
|
||||
public sealed class OtherOptionData : HashSet<string>
|
||||
{
|
||||
|
|
@ -67,14 +66,14 @@ public class ModMetaEditor(
|
|||
Changes = false;
|
||||
}
|
||||
|
||||
public static bool DeleteDefaultValues(MetaFileManager metaFileManager, ImcChecker imcChecker, MetaDictionary dict)
|
||||
public static bool DeleteDefaultValues(MetaFileManager metaFileManager, MetaDictionary dict)
|
||||
{
|
||||
var clone = dict.Clone();
|
||||
dict.Clear();
|
||||
var count = 0;
|
||||
foreach (var (key, value) in clone.Imc)
|
||||
{
|
||||
var defaultEntry = imcChecker.GetDefaultEntry(key, false);
|
||||
var defaultEntry = ImcChecker.GetDefaultEntry(key, false);
|
||||
if (!defaultEntry.Entry.Equals(value))
|
||||
{
|
||||
dict.TryAdd(key, value);
|
||||
|
|
@ -164,7 +163,7 @@ public class ModMetaEditor(
|
|||
}
|
||||
|
||||
public void DeleteDefaultValues()
|
||||
=> Changes = DeleteDefaultValues(metaFileManager, imcChecker, this);
|
||||
=> Changes = DeleteDefaultValues(metaFileManager, this);
|
||||
|
||||
public void Apply(IModDataContainer container)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ public class ImcModGroup(Mod mod) : IModGroup
|
|||
public ImcIdentifier Identifier;
|
||||
public ImcEntry DefaultEntry;
|
||||
public bool AllVariants;
|
||||
public bool OnlyAttributes;
|
||||
|
||||
|
||||
public FullPath? FindBestMatch(Utf8GamePath gamePath)
|
||||
|
|
@ -97,28 +98,36 @@ public class ImcModGroup(Mod mod) : IModGroup
|
|||
public IModGroupEditDrawer EditDrawer(ModGroupEditDrawer editDrawer)
|
||||
=> new ImcModGroupEditDrawer(editDrawer, this);
|
||||
|
||||
public ImcEntry GetEntry(ushort mask)
|
||||
=> DefaultEntry with { AttributeMask = mask };
|
||||
private ImcEntry GetEntry(Variant variant, ushort mask)
|
||||
{
|
||||
if (!OnlyAttributes)
|
||||
return DefaultEntry with { AttributeMask = mask };
|
||||
|
||||
var defaultEntry = ImcChecker.GetDefaultEntry(Identifier with { Variant = variant }, true);
|
||||
if (defaultEntry.VariantExists)
|
||||
return defaultEntry.Entry with { AttributeMask = mask };
|
||||
|
||||
return DefaultEntry with { AttributeMask = mask };
|
||||
}
|
||||
|
||||
public void AddData(Setting setting, Dictionary<Utf8GamePath, FullPath> redirections, MetaDictionary manipulations)
|
||||
{
|
||||
if (IsDisabled(setting))
|
||||
return;
|
||||
|
||||
var mask = GetCurrentMask(setting);
|
||||
var entry = GetEntry(mask);
|
||||
var mask = GetCurrentMask(setting);
|
||||
if (AllVariants)
|
||||
{
|
||||
var count = ImcChecker.GetVariantCount(Identifier);
|
||||
if (count == 0)
|
||||
manipulations.TryAdd(Identifier, entry);
|
||||
manipulations.TryAdd(Identifier, GetEntry(Identifier.Variant, mask));
|
||||
else
|
||||
for (var i = 0; i <= count; ++i)
|
||||
manipulations.TryAdd(Identifier with { Variant = (Variant)i }, entry);
|
||||
manipulations.TryAdd(Identifier with { Variant = (Variant)i }, GetEntry((Variant)i, mask));
|
||||
}
|
||||
else
|
||||
{
|
||||
manipulations.TryAdd(Identifier, entry);
|
||||
manipulations.TryAdd(Identifier, GetEntry(Identifier.Variant, mask));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -138,6 +147,8 @@ public class ImcModGroup(Mod mod) : IModGroup
|
|||
serializer.Serialize(jWriter, DefaultEntry);
|
||||
jWriter.WritePropertyName(nameof(AllVariants));
|
||||
jWriter.WriteValue(AllVariants);
|
||||
jWriter.WritePropertyName(nameof(OnlyAttributes));
|
||||
jWriter.WriteValue(OnlyAttributes);
|
||||
jWriter.WritePropertyName("Options");
|
||||
jWriter.WriteStartArray();
|
||||
foreach (var option in OptionData)
|
||||
|
|
@ -170,8 +181,9 @@ public class ImcModGroup(Mod mod) : IModGroup
|
|||
var identifier = ImcIdentifier.FromJson(json[nameof(Identifier)] as JObject);
|
||||
var ret = new ImcModGroup(mod)
|
||||
{
|
||||
DefaultEntry = json[nameof(DefaultEntry)]?.ToObject<ImcEntry>() ?? new ImcEntry(),
|
||||
AllVariants = json[nameof(AllVariants)]?.ToObject<bool>() ?? false,
|
||||
DefaultEntry = json[nameof(DefaultEntry)]?.ToObject<ImcEntry>() ?? new ImcEntry(),
|
||||
AllVariants = json[nameof(AllVariants)]?.ToObject<bool>() ?? false,
|
||||
OnlyAttributes = json[nameof(OnlyAttributes)]?.ToObject<bool>() ?? false,
|
||||
};
|
||||
if (!ModSaveGroup.ReadJsonBase(json, ret))
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -89,6 +89,16 @@ public sealed class ImcModGroupEditor(CommunicatorService communicator, SaveServ
|
|||
Communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionMetaChanged, group.Mod, group, null, null, -1);
|
||||
}
|
||||
|
||||
public void ChangeOnlyAttributes(ImcModGroup group, bool onlyAttributes, SaveType saveType = SaveType.Queue)
|
||||
{
|
||||
if (group.OnlyAttributes == onlyAttributes)
|
||||
return;
|
||||
|
||||
group.OnlyAttributes = onlyAttributes;
|
||||
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)
|
||||
{
|
||||
if (group.CanBeDisabled == canBeDisabled)
|
||||
|
|
|
|||
|
|
@ -25,8 +25,7 @@ public partial class ModCreator(
|
|||
Configuration config,
|
||||
ModDataEditor dataEditor,
|
||||
MetaFileManager metaFileManager,
|
||||
GamePathParser gamePathParser,
|
||||
ImcChecker imcChecker) : IService
|
||||
GamePathParser gamePathParser) : IService
|
||||
{
|
||||
public readonly Configuration Config = config;
|
||||
|
||||
|
|
@ -86,7 +85,7 @@ public partial class ModCreator(
|
|||
{
|
||||
foreach (var container in mod.AllDataContainers)
|
||||
{
|
||||
if (ModMetaEditor.DeleteDefaultValues(metaFileManager, imcChecker, container.Manipulations))
|
||||
if (ModMetaEditor.DeleteDefaultValues(metaFileManager, container.Manipulations))
|
||||
saveService.ImmediateSaveSync(new ModSaveGroup(container, Config.ReplaceNonAsciiOnImport));
|
||||
}
|
||||
}
|
||||
|
|
@ -235,7 +234,7 @@ public partial class ModCreator(
|
|||
DeleteDeleteList(deleteList, delete);
|
||||
var changes = oldSize < option.Manipulations.Count;
|
||||
if (deleteDefault && !Config.KeepDefaultMetaChanges)
|
||||
changes |= ModMetaEditor.DeleteDefaultValues(metaFileManager, imcChecker, option.Manipulations);
|
||||
changes |= ModMetaEditor.DeleteDefaultValues(metaFileManager, option.Manipulations);
|
||||
|
||||
return (changes, deleteList);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public sealed class ImcMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile
|
|||
}
|
||||
|
||||
private void UpdateEntry()
|
||||
=> (Entry, _fileExists, _) = MetaFiles.ImcChecker.GetDefaultEntry(Identifier, true);
|
||||
=> (Entry, _fileExists, _) = ImcChecker.GetDefaultEntry(Identifier, true);
|
||||
|
||||
protected override void DrawNew()
|
||||
{
|
||||
|
|
@ -54,7 +54,7 @@ public sealed class ImcMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile
|
|||
DrawMetaButtons(identifier, entry);
|
||||
DrawIdentifier(identifier);
|
||||
|
||||
var defaultEntry = MetaFiles.ImcChecker.GetDefaultEntry(identifier, true).Entry;
|
||||
var defaultEntry = ImcChecker.GetDefaultEntry(identifier, true).Entry;
|
||||
if (DrawEntry(defaultEntry, ref entry, true))
|
||||
Editor.Changes |= Editor.Update(identifier, entry);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,13 +24,11 @@ public class AddGroupDrawer : IUiService
|
|||
private bool _imcFileExists;
|
||||
private bool _entryExists;
|
||||
private bool _entryInvalid;
|
||||
private readonly ImcChecker _imcChecker;
|
||||
private readonly ModManager _modManager;
|
||||
|
||||
public AddGroupDrawer(ModManager modManager, ImcChecker imcChecker)
|
||||
public AddGroupDrawer(ModManager modManager)
|
||||
{
|
||||
_modManager = modManager;
|
||||
_imcChecker = imcChecker;
|
||||
UpdateEntry();
|
||||
}
|
||||
|
||||
|
|
@ -142,7 +140,7 @@ public class AddGroupDrawer : IUiService
|
|||
|
||||
private void UpdateEntry()
|
||||
{
|
||||
(_defaultEntry, _imcFileExists, _entryExists) = _imcChecker.GetDefaultEntry(_imcIdentifier, false);
|
||||
(_defaultEntry, _imcFileExists, _entryExists) = ImcChecker.GetDefaultEntry(_imcIdentifier, false);
|
||||
_entryInvalid = !_imcIdentifier.Validate() || _defaultEntry.MaterialId == 0 || !_entryExists;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using OtterGui.Text;
|
|||
using OtterGui.Text.Widget;
|
||||
using OtterGuiInternal.Utility;
|
||||
using Penumbra.GameData.Structs;
|
||||
using Penumbra.Meta;
|
||||
using Penumbra.Mods.Groups;
|
||||
using Penumbra.Mods.Manager.OptionEditor;
|
||||
using Penumbra.Mods.SubMods;
|
||||
|
|
@ -18,18 +19,25 @@ public readonly struct ImcModGroupEditDrawer(ModGroupEditDrawer editor, ImcModGr
|
|||
public void Draw()
|
||||
{
|
||||
var identifier = group.Identifier;
|
||||
var defaultEntry = editor.ImcChecker.GetDefaultEntry(identifier, true).Entry;
|
||||
var defaultEntry = ImcChecker.GetDefaultEntry(identifier, true).Entry;
|
||||
var entry = group.DefaultEntry;
|
||||
var changes = false;
|
||||
|
||||
var width = editor.AvailableWidth.X - ImUtf8.ItemInnerSpacing.X - ImUtf8.CalcTextSize("All Variants"u8).X;
|
||||
var width = editor.AvailableWidth.X - 3 * ImUtf8.ItemInnerSpacing.X - ImUtf8.ItemSpacing.X - ImUtf8.CalcTextSize("All Variants"u8).X - ImUtf8.CalcTextSize("Only Attributes"u8).X - 2 * ImUtf8.FrameHeight;
|
||||
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);
|
||||
|
||||
ImGui.SameLine();
|
||||
var onlyAttributes = group.OnlyAttributes;
|
||||
if (ImUtf8.Checkbox("Only Attributes"u8, ref onlyAttributes))
|
||||
editor.ModManager.OptionEditor.ImcEditor.ChangeOnlyAttributes(group, onlyAttributes);
|
||||
ImUtf8.HoverTooltip("Only overwrite the attribute flags and take all the other values from the game's default entry instead of the one configured here.\n\nMainly useful if used with All Variants to keep the material IDs for each variant."u8);
|
||||
|
||||
using (ImUtf8.Group())
|
||||
{
|
||||
ImUtf8.TextFrameAligned("Material ID"u8);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue