mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-15 05:04:15 +01:00
More cleanup on groups.
This commit is contained in:
parent
e40c4999b6
commit
297be487b5
14 changed files with 107 additions and 102 deletions
|
|
@ -1,5 +1,6 @@
|
|||
using OtterGui.Classes;
|
||||
using Penumbra.Api.Api;
|
||||
using Penumbra.Api.IpcSubscribers;
|
||||
|
||||
namespace Penumbra.Communication;
|
||||
|
||||
|
|
@ -15,7 +16,7 @@ public sealed class PreSettingsTabBarDraw() : EventWrapper<string, float, float,
|
|||
{
|
||||
public enum Priority
|
||||
{
|
||||
/// <seealso cref="PenumbraApi.PreSettingsTabBarDraw"/>
|
||||
/// <seealso cref="Api.IpcSubscribers.PreSettingsTabBarDraw"/>
|
||||
Default = 0,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,22 +16,22 @@ public interface IModGroup
|
|||
{
|
||||
public const int MaxMultiOptions = 63;
|
||||
|
||||
public Mod Mod { get; }
|
||||
public string Name { get; }
|
||||
public string Description { get; }
|
||||
public GroupType Type { get; }
|
||||
public ModPriority Priority { get; set; }
|
||||
public Setting DefaultSettings { get; set; }
|
||||
public Mod Mod { get; }
|
||||
public string Name { get; }
|
||||
public string Description { get; set; }
|
||||
public GroupType Type { get; }
|
||||
public ModPriority Priority { get; set; }
|
||||
public Setting DefaultSettings { get; set; }
|
||||
|
||||
public FullPath? FindBestMatch(Utf8GamePath gamePath);
|
||||
public int AddOption(Mod mod, string name, string description = "");
|
||||
public int AddOption(Mod mod, string name, string description = "");
|
||||
|
||||
public IReadOnlyList<IModOption> Options { get; }
|
||||
public IReadOnlyList<IModOption> Options { get; }
|
||||
public IReadOnlyList<IModDataContainer> DataContainers { get; }
|
||||
public bool IsOption { get; }
|
||||
public bool IsOption { get; }
|
||||
|
||||
public IModGroup Convert(GroupType type);
|
||||
public bool MoveOption(int optionIdxFrom, int optionIdxTo);
|
||||
public bool MoveOption(int optionIdxFrom, int optionIdxTo);
|
||||
|
||||
public int GetIndex();
|
||||
|
||||
|
|
@ -42,46 +42,5 @@ public interface IModGroup
|
|||
|
||||
public void WriteJson(JsonTextWriter jWriter, JsonSerializer serializer, DirectoryInfo? basePath = null);
|
||||
|
||||
public bool ChangeOptionDescription(int optionIndex, string newDescription)
|
||||
{
|
||||
if (optionIndex < 0 || optionIndex >= Options.Count)
|
||||
return false;
|
||||
|
||||
var option = Options[optionIndex];
|
||||
if (option.Description == newDescription)
|
||||
return false;
|
||||
|
||||
option.Description = newDescription;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool ChangeOptionName(int optionIndex, string newName)
|
||||
{
|
||||
if (optionIndex < 0 || optionIndex >= Options.Count)
|
||||
return false;
|
||||
|
||||
var option = Options[optionIndex];
|
||||
if (option.Name == newName)
|
||||
return false;
|
||||
|
||||
option.Name = newName;
|
||||
return true;
|
||||
}
|
||||
|
||||
public (int Redirections, int Swaps, int Manips) GetCounts();
|
||||
|
||||
public static (int Redirections, int Swaps, int Manips) GetCountsBase(IModGroup group)
|
||||
{
|
||||
var redirectionCount = 0;
|
||||
var swapCount = 0;
|
||||
var manipCount = 0;
|
||||
foreach (var option in group.DataContainers)
|
||||
{
|
||||
redirectionCount += option.Files.Count;
|
||||
swapCount += option.FileSwaps.Count;
|
||||
manipCount += option.Manipulations.Count;
|
||||
}
|
||||
|
||||
return (redirectionCount, swapCount, manipCount);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
42
Penumbra/Mods/Groups/ModGroup.cs
Normal file
42
Penumbra/Mods/Groups/ModGroup.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Mods.Settings;
|
||||
|
||||
namespace Penumbra.Mods.Groups;
|
||||
|
||||
public static class ModGroup
|
||||
{
|
||||
public static IModGroup Create(Mod mod, GroupType type, string name)
|
||||
{
|
||||
var maxPriority = mod.Groups.Count == 0 ? ModPriority.Default : mod.Groups.Max(o => o.Priority) + 1;
|
||||
return type switch
|
||||
{
|
||||
GroupType.Single => new SingleModGroup(mod)
|
||||
{
|
||||
Name = name,
|
||||
Priority = maxPriority,
|
||||
},
|
||||
GroupType.Multi => new MultiModGroup(mod)
|
||||
{
|
||||
Name = name,
|
||||
Priority = maxPriority,
|
||||
},
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public static (int Redirections, int Swaps, int Manips) GetCountsBase(IModGroup group)
|
||||
{
|
||||
var redirectionCount = 0;
|
||||
var swapCount = 0;
|
||||
var manipCount = 0;
|
||||
foreach (var option in group.DataContainers)
|
||||
{
|
||||
redirectionCount += option.Files.Count;
|
||||
swapCount += option.FileSwaps.Count;
|
||||
manipCount += option.Manipulations.Count;
|
||||
}
|
||||
|
||||
return (redirectionCount, swapCount, manipCount);
|
||||
}
|
||||
}
|
||||
|
|
@ -51,7 +51,7 @@ public readonly struct ModSaveGroup : ISavable
|
|||
if (_groupIdx >= 0)
|
||||
_group!.WriteJson(j, serializer);
|
||||
else
|
||||
SubModHelpers.WriteModContainer(j, serializer, _defaultMod!, _basePath);
|
||||
SubMod.WriteModContainer(j, serializer, _defaultMod!, _basePath);
|
||||
j.WriteEndObject();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,10 +141,10 @@ public sealed class MultiModGroup(Mod mod) : IModGroup, ITexToolsGroup
|
|||
foreach (var option in OptionData)
|
||||
{
|
||||
jWriter.WriteStartObject();
|
||||
SubModHelpers.WriteModOption(jWriter, option);
|
||||
SubMod.WriteModOption(jWriter, option);
|
||||
jWriter.WritePropertyName(nameof(option.Priority));
|
||||
jWriter.WriteValue(option.Priority.Value);
|
||||
SubModHelpers.WriteModContainer(jWriter, serializer, option, basePath ?? Mod.ModPath);
|
||||
SubMod.WriteModContainer(jWriter, serializer, option, basePath ?? Mod.ModPath);
|
||||
jWriter.WriteEndObject();
|
||||
}
|
||||
|
||||
|
|
@ -153,7 +153,7 @@ public sealed class MultiModGroup(Mod mod) : IModGroup, ITexToolsGroup
|
|||
}
|
||||
|
||||
public (int Redirections, int Swaps, int Manips) GetCounts()
|
||||
=> IModGroup.GetCountsBase(this);
|
||||
=> ModGroup.GetCountsBase(this);
|
||||
|
||||
public Setting FixSetting(Setting setting)
|
||||
=> new(setting.Value & (1ul << OptionData.Count) - 1);
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ public sealed class SingleModGroup(Mod mod) : IModGroup, ITexToolsGroup
|
|||
=> OptionData.Count == 0 ? Setting.Zero : new Setting(Math.Min(setting.Value, (ulong)(OptionData.Count - 1)));
|
||||
|
||||
public (int Redirections, int Swaps, int Manips) GetCounts()
|
||||
=> IModGroup.GetCountsBase(this);
|
||||
=> ModGroup.GetCountsBase(this);
|
||||
|
||||
public void WriteJson(JsonTextWriter jWriter, JsonSerializer serializer, DirectoryInfo? basePath = null)
|
||||
{
|
||||
|
|
@ -145,8 +145,8 @@ public sealed class SingleModGroup(Mod mod) : IModGroup, ITexToolsGroup
|
|||
foreach (var option in OptionData)
|
||||
{
|
||||
jWriter.WriteStartObject();
|
||||
SubModHelpers.WriteModOption(jWriter, option);
|
||||
SubModHelpers.WriteModContainer(jWriter, serializer, option, basePath ?? Mod.ModPath);
|
||||
SubMod.WriteModOption(jWriter, option);
|
||||
SubMod.WriteModContainer(jWriter, serializer, option, basePath ?? Mod.ModPath);
|
||||
jWriter.WriteEndObject();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ public class ModOptionEditor(CommunicatorService communicator, SaveService saveS
|
|||
return;
|
||||
|
||||
saveService.ImmediateDelete(new ModSaveGroup(mod, groupIdx, config.ReplaceNonAsciiOnImport));
|
||||
var _ = group switch
|
||||
_ = group switch
|
||||
{
|
||||
SingleModGroup s => s.Name = newName,
|
||||
MultiModGroup m => m.Name = newName,
|
||||
|
|
@ -85,21 +85,11 @@ public class ModOptionEditor(CommunicatorService communicator, SaveService saveS
|
|||
if (!VerifyFileName(mod, null, newName, true))
|
||||
return;
|
||||
|
||||
var maxPriority = mod.Groups.Count == 0 ? ModPriority.Default : mod.Groups.Max(o => o.Priority) + 1;
|
||||
|
||||
mod.Groups.Add(type == GroupType.Multi
|
||||
? new MultiModGroup(mod)
|
||||
{
|
||||
Name = newName,
|
||||
Priority = maxPriority,
|
||||
}
|
||||
: new SingleModGroup(mod)
|
||||
{
|
||||
Name = newName,
|
||||
Priority = maxPriority,
|
||||
});
|
||||
saveService.Save(saveType, new ModSaveGroup(mod, mod.Groups.Count - 1, config.ReplaceNonAsciiOnImport));
|
||||
communicator.ModOptionChanged.Invoke(ModOptionChangeType.GroupAdded, mod, mod.Groups.Count - 1, -1, -1);
|
||||
var idx = mod.Groups.Count;
|
||||
var group = ModGroup.Create(mod, type, newName);
|
||||
mod.Groups.Add(group);
|
||||
saveService.Save(saveType, new ModSaveGroup(mod, idx, config.ReplaceNonAsciiOnImport));
|
||||
communicator.ModOptionChanged.Invoke(ModOptionChangeType.GroupAdded, mod, idx, -1, -1);
|
||||
}
|
||||
|
||||
/// <summary> Add a new mod, empty option group of the given type and name if it does not exist already. </summary>
|
||||
|
|
@ -142,12 +132,7 @@ public class ModOptionEditor(CommunicatorService communicator, SaveService saveS
|
|||
if (group.Description == newDescription)
|
||||
return;
|
||||
|
||||
var _ = group switch
|
||||
{
|
||||
SingleModGroup s => s.Description = newDescription,
|
||||
MultiModGroup m => m.Description = newDescription,
|
||||
_ => newDescription,
|
||||
};
|
||||
group.Description = newDescription;
|
||||
saveService.QueueSave(new ModSaveGroup(mod, groupIdx, config.ReplaceNonAsciiOnImport));
|
||||
communicator.ModOptionChanged.Invoke(ModOptionChangeType.DisplayChange, mod, groupIdx, -1, -1);
|
||||
}
|
||||
|
|
@ -155,9 +140,11 @@ public class ModOptionEditor(CommunicatorService communicator, SaveService saveS
|
|||
/// <summary> Change the description of the given option. </summary>
|
||||
public void ChangeOptionDescription(Mod mod, int groupIdx, int optionIdx, string newDescription)
|
||||
{
|
||||
if (!mod.Groups[groupIdx].ChangeOptionDescription(optionIdx, newDescription))
|
||||
var option = mod.Groups[groupIdx].Options[optionIdx];
|
||||
if (option.Description == newDescription)
|
||||
return;
|
||||
|
||||
option.Description = newDescription;
|
||||
saveService.QueueSave(new ModSaveGroup(mod, groupIdx, config.ReplaceNonAsciiOnImport));
|
||||
communicator.ModOptionChanged.Invoke(ModOptionChangeType.DisplayChange, mod, groupIdx, optionIdx, -1);
|
||||
}
|
||||
|
|
@ -193,9 +180,12 @@ public class ModOptionEditor(CommunicatorService communicator, SaveService saveS
|
|||
/// <summary> Rename the given option. </summary>
|
||||
public void RenameOption(Mod mod, int groupIdx, int optionIdx, string newName)
|
||||
{
|
||||
if (!mod.Groups[groupIdx].ChangeOptionName(optionIdx, newName))
|
||||
var option = mod.Groups[groupIdx].Options[optionIdx];
|
||||
if (option.Name == newName)
|
||||
return;
|
||||
|
||||
option.Name = newName;
|
||||
|
||||
saveService.QueueSave(new ModSaveGroup(mod, groupIdx, config.ReplaceNonAsciiOnImport));
|
||||
communicator.ModOptionChanged.Invoke(ModOptionChangeType.DisplayChange, mod, groupIdx, optionIdx, -1);
|
||||
}
|
||||
|
|
@ -251,7 +241,7 @@ public class ModOptionEditor(CommunicatorService communicator, SaveService saveS
|
|||
Description = option.Description,
|
||||
};
|
||||
if (option is IModDataContainer data)
|
||||
SubModHelpers.Clone(data, newOption);
|
||||
SubMod.Clone(data, newOption);
|
||||
s.OptionData.Add(newOption);
|
||||
break;
|
||||
}
|
||||
|
|
@ -265,7 +255,7 @@ public class ModOptionEditor(CommunicatorService communicator, SaveService saveS
|
|||
Priority = option is MultiSubMod s ? s.Priority : ModPriority.Default,
|
||||
};
|
||||
if (option is IModDataContainer data)
|
||||
SubModHelpers.Clone(data, newOption);
|
||||
SubMod.Clone(data, newOption);
|
||||
m.OptionData.Add(newOption);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,17 +3,13 @@ using OtterGui.Widgets;
|
|||
|
||||
namespace Penumbra.Mods.Manager;
|
||||
|
||||
public class ModCombo : FilterComboCache<Mod>
|
||||
public class ModCombo(Func<IReadOnlyList<Mod>> generator) : FilterComboCache<Mod>(generator, MouseWheelType.None, Penumbra.Log)
|
||||
{
|
||||
protected override bool IsVisible(int globalIndex, LowerString filter)
|
||||
=> Items[globalIndex].Name.Contains(filter);
|
||||
|
||||
protected override string ToString(Mod obj)
|
||||
=> obj.Name.Text;
|
||||
|
||||
public ModCombo(Func<IReadOnlyList<Mod>> generator)
|
||||
: base(generator, MouseWheelType.None, Penumbra.Log)
|
||||
{ }
|
||||
}
|
||||
|
||||
public class ModStorage : IReadOnlyList<Mod>
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ public partial class ModCreator(
|
|||
try
|
||||
{
|
||||
var jObject = File.Exists(defaultFile) ? JObject.Parse(File.ReadAllText(defaultFile)) : new JObject();
|
||||
SubModHelpers.LoadDataContainer(jObject, mod.Default, mod.ModPath);
|
||||
SubMod.LoadDataContainer(jObject, mod.Default, mod.ModPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public class DefaultSubMod(IMod mod) : IModDataContainer
|
|||
=> null;
|
||||
|
||||
public void AddTo(Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
||||
=> SubModHelpers.AddContainerTo(this, redirections, manipulations);
|
||||
=> SubMod.AddContainerTo(this, redirections, manipulations);
|
||||
|
||||
public string GetName()
|
||||
=> FullName;
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ public class MultiSubMod(Mod mod, MultiModGroup group) : OptionSubMod<MultiModGr
|
|||
public MultiSubMod(Mod mod, MultiModGroup group, JToken json)
|
||||
: this(mod, group)
|
||||
{
|
||||
SubModHelpers.LoadOptionData(json, this);
|
||||
SubModHelpers.LoadDataContainer(json, this, mod.ModPath);
|
||||
SubMod.LoadOptionData(json, this);
|
||||
SubMod.LoadDataContainer(json, this, mod.ModPath);
|
||||
Priority = json[nameof(IModGroup.Priority)]?.ToObject<ModPriority>() ?? ModPriority.Default;
|
||||
}
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ public class MultiSubMod(Mod mod, MultiModGroup group) : OptionSubMod<MultiModGr
|
|||
Description = Description,
|
||||
Priority = Priority,
|
||||
};
|
||||
SubModHelpers.Clone(this, ret);
|
||||
SubMod.Clone(this, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ public class MultiSubMod(Mod mod, MultiModGroup group) : OptionSubMod<MultiModGr
|
|||
Name = Name,
|
||||
Description = Description,
|
||||
};
|
||||
SubModHelpers.Clone(this, ret);
|
||||
SubMod.Clone(this, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public abstract class OptionSubMod<T>(Mod mod, T group) : IModDataOption
|
|||
public HashSet<MetaManipulation> Manipulations { get; set; } = [];
|
||||
|
||||
public void AddDataTo(Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
||||
=> SubModHelpers.AddContainerTo(this, redirections, manipulations);
|
||||
=> SubMod.AddContainerTo(this, redirections, manipulations);
|
||||
|
||||
public string GetName()
|
||||
=> Name;
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ public class SingleSubMod(Mod mod, SingleModGroup singleGroup) : OptionSubMod<Si
|
|||
public SingleSubMod(Mod mod, SingleModGroup singleGroup, JToken json)
|
||||
: this(mod, singleGroup)
|
||||
{
|
||||
SubModHelpers.LoadOptionData(json, this);
|
||||
SubModHelpers.LoadDataContainer(json, this, mod.ModPath);
|
||||
SubMod.LoadOptionData(json, this);
|
||||
SubMod.LoadDataContainer(json, this, mod.ModPath);
|
||||
}
|
||||
|
||||
public SingleSubMod Clone(Mod mod, SingleModGroup group)
|
||||
|
|
@ -20,7 +20,7 @@ public class SingleSubMod(Mod mod, SingleModGroup singleGroup) : OptionSubMod<Si
|
|||
Name = Name,
|
||||
Description = Description,
|
||||
};
|
||||
SubModHelpers.Clone(this, ret);
|
||||
SubMod.Clone(this, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ public class SingleSubMod(Mod mod, SingleModGroup singleGroup) : OptionSubMod<Si
|
|||
Description = Description,
|
||||
Priority = priority,
|
||||
};
|
||||
SubModHelpers.Clone(this, ret);
|
||||
SubMod.Clone(this, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,29 @@
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Penumbra.Meta.Manipulations;
|
||||
using Penumbra.Mods.Groups;
|
||||
using Penumbra.String.Classes;
|
||||
|
||||
namespace Penumbra.Mods.SubMods;
|
||||
|
||||
public static class SubModHelpers
|
||||
public static class SubMod
|
||||
{
|
||||
public static IModOption Create(IModGroup group, string name, string description = "")
|
||||
=> group switch
|
||||
{
|
||||
SingleModGroup single => new SingleSubMod(group.Mod, single)
|
||||
{
|
||||
Name = name,
|
||||
Description = description,
|
||||
},
|
||||
MultiModGroup multi => new MultiSubMod(group.Mod, multi)
|
||||
{
|
||||
Name = name,
|
||||
Description = description,
|
||||
},
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(group)),
|
||||
};
|
||||
|
||||
/// <summary> Add all unique meta manipulations, file redirections and then file swaps from a ModDataContainer to the given sets. Skip any keys that are already contained. </summary>
|
||||
public static void AddContainerTo(IModDataContainer container, Dictionary<Utf8GamePath, FullPath> redirections,
|
||||
HashSet<MetaManipulation> manipulations)
|
||||
Loading…
Add table
Add a link
Reference in a new issue