mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Update Mod Merger for other group types.
This commit is contained in:
parent
535694e9c8
commit
4c0e6d2a67
2 changed files with 139 additions and 48 deletions
|
|
@ -6,6 +6,7 @@ using OtterGui.Extensions;
|
||||||
using OtterGui.Services;
|
using OtterGui.Services;
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
using Penumbra.Communication;
|
using Penumbra.Communication;
|
||||||
|
using Penumbra.Mods.Groups;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
using Penumbra.Mods.Manager.OptionEditor;
|
using Penumbra.Mods.Manager.OptionEditor;
|
||||||
using Penumbra.Mods.SubMods;
|
using Penumbra.Mods.SubMods;
|
||||||
|
|
@ -44,13 +45,13 @@ public class ModMerger : IDisposable, IService
|
||||||
public ModMerger(ModManager mods, ModGroupEditor editor, ModSelection selection, DuplicateManager duplicates,
|
public ModMerger(ModManager mods, ModGroupEditor editor, ModSelection selection, DuplicateManager duplicates,
|
||||||
CommunicatorService communicator, ModCreator creator, Configuration config)
|
CommunicatorService communicator, ModCreator creator, Configuration config)
|
||||||
{
|
{
|
||||||
_editor = editor;
|
_editor = editor;
|
||||||
_selection = selection;
|
_selection = selection;
|
||||||
_duplicates = duplicates;
|
_duplicates = duplicates;
|
||||||
_communicator = communicator;
|
_communicator = communicator;
|
||||||
_creator = creator;
|
_creator = creator;
|
||||||
_config = config;
|
_config = config;
|
||||||
_mods = mods;
|
_mods = mods;
|
||||||
_selection.Subscribe(OnSelectionChange, ModSelection.Priority.ModMerger);
|
_selection.Subscribe(OnSelectionChange, ModSelection.Priority.ModMerger);
|
||||||
_communicator.ModPathChanged.Subscribe(OnModPathChange, ModPathChanged.Priority.ModMerger);
|
_communicator.ModPathChanged.Subscribe(OnModPathChange, ModPathChanged.Priority.ModMerger);
|
||||||
}
|
}
|
||||||
|
|
@ -99,26 +100,117 @@ public class ModMerger : IDisposable, IService
|
||||||
|
|
||||||
foreach (var originalGroup in MergeFromMod!.Groups)
|
foreach (var originalGroup in MergeFromMod!.Groups)
|
||||||
{
|
{
|
||||||
var (group, groupIdx, groupCreated) = _editor.FindOrAddModGroup(MergeToMod!, originalGroup.Type, originalGroup.Name);
|
switch (originalGroup.Type)
|
||||||
if (groupCreated)
|
|
||||||
_createdGroups.Add(groupIdx);
|
|
||||||
if (group == null)
|
|
||||||
throw new Exception(
|
|
||||||
$"The merged group {originalGroup.Name} already existed, but had a different type than the original group of type {originalGroup.Type}.");
|
|
||||||
|
|
||||||
foreach (var originalOption in originalGroup.DataContainers)
|
|
||||||
{
|
{
|
||||||
var (option, _, optionCreated) = _editor.FindOrAddOption(group, originalOption.GetName());
|
case GroupType.Single:
|
||||||
if (optionCreated)
|
case GroupType.Multi:
|
||||||
{
|
{
|
||||||
_createdOptions.Add(option!);
|
var (group, groupIdx, groupCreated) = _editor.FindOrAddModGroup(MergeToMod!, originalGroup.Type, originalGroup.Name);
|
||||||
// #TODO DataContainer <> Option.
|
if (group is null)
|
||||||
MergeIntoOption([originalOption], (IModDataContainer)option!, false);
|
throw new Exception(
|
||||||
|
$"The merged group {originalGroup.Name} already existed, but had a different type than the original group of type {originalGroup.Type}.");
|
||||||
|
|
||||||
|
if (groupCreated)
|
||||||
|
{
|
||||||
|
_createdGroups.Add(groupIdx);
|
||||||
|
group.Description = originalGroup.Description;
|
||||||
|
group.Image = originalGroup.Image;
|
||||||
|
group.DefaultSettings = originalGroup.DefaultSettings;
|
||||||
|
group.Page = originalGroup.Page;
|
||||||
|
group.Priority = originalGroup.Priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var originalOption in originalGroup.Options)
|
||||||
|
{
|
||||||
|
var (option, _, optionCreated) = _editor.FindOrAddOption(group, originalOption.Name);
|
||||||
|
if (optionCreated)
|
||||||
|
{
|
||||||
|
_createdOptions.Add(option!);
|
||||||
|
MergeIntoOption([(IModDataContainer)originalOption], (IModDataContainer)option!, false);
|
||||||
|
option!.Description = originalOption.Description;
|
||||||
|
if (option is MultiSubMod multiOption)
|
||||||
|
multiOption.Priority = ((MultiSubMod)originalOption).Priority;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception(
|
||||||
|
$"Could not merge {MergeFromMod!.Name} into {MergeToMod!.Name}: The option {option!.FullName} already existed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
case GroupType.Imc when originalGroup is ImcModGroup imc:
|
||||||
{
|
{
|
||||||
throw new Exception(
|
var group = _editor.ImcEditor.AddModGroup(MergeToMod!, imc.Name, imc.Identifier, imc.DefaultEntry);
|
||||||
$"Could not merge {MergeFromMod!.Name} into {MergeToMod!.Name}: The option {option!.FullName} already existed.");
|
if (group is null)
|
||||||
|
throw new Exception(
|
||||||
|
$"The merged group {originalGroup.Name} already existed, but groups of type {originalGroup.Type} can not be merged.");
|
||||||
|
|
||||||
|
group.AllVariants = imc.AllVariants;
|
||||||
|
group.OnlyAttributes = imc.OnlyAttributes;
|
||||||
|
group.Description = imc.Description;
|
||||||
|
group.Image = imc.Image;
|
||||||
|
group.DefaultSettings = imc.DefaultSettings;
|
||||||
|
group.Page = imc.Page;
|
||||||
|
group.Priority = imc.Priority;
|
||||||
|
foreach (var originalOption in imc.OptionData)
|
||||||
|
{
|
||||||
|
if (originalOption.IsDisableSubMod)
|
||||||
|
{
|
||||||
|
_editor.ImcEditor.ChangeCanBeDisabled(group, true);
|
||||||
|
var disable = group.OptionData.First(s => s.IsDisableSubMod);
|
||||||
|
disable.Description = originalOption.Description;
|
||||||
|
disable.Name = originalOption.Name;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newOption = _editor.ImcEditor.AddOption(group, originalOption.Name);
|
||||||
|
if (newOption is null)
|
||||||
|
throw new Exception(
|
||||||
|
$"Could not merge {MergeFromMod!.Name} into {MergeToMod!.Name}: Unknown error when creating IMC option {originalOption.FullName}.");
|
||||||
|
|
||||||
|
newOption.Description = originalOption.Description;
|
||||||
|
newOption.AttributeMask = originalOption.AttributeMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroupType.Combining when originalGroup is CombiningModGroup combining:
|
||||||
|
{
|
||||||
|
var group = _editor.CombiningEditor.AddModGroup(MergeToMod!, combining.Name);
|
||||||
|
if (group is null)
|
||||||
|
throw new Exception(
|
||||||
|
$"The merged group {originalGroup.Name} already existed, but groups of type {originalGroup.Type} can not be merged.");
|
||||||
|
|
||||||
|
group.Description = combining.Description;
|
||||||
|
group.Image = combining.Image;
|
||||||
|
group.DefaultSettings = combining.DefaultSettings;
|
||||||
|
group.Page = combining.Page;
|
||||||
|
group.Priority = combining.Priority;
|
||||||
|
foreach (var originalOption in combining.OptionData)
|
||||||
|
{
|
||||||
|
var option = _editor.CombiningEditor.AddOption(group, originalOption.Name);
|
||||||
|
if (option is null)
|
||||||
|
throw new Exception(
|
||||||
|
$"Could not merge {MergeFromMod!.Name} into {MergeToMod!.Name}: Unknown error when creating combining option {originalOption.FullName}.");
|
||||||
|
|
||||||
|
option.Description = originalOption.Description;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group.Data.Count != combining.Data.Count)
|
||||||
|
throw new Exception(
|
||||||
|
$"Could not merge {MergeFromMod!.Name} into {MergeToMod!.Name}: Unknown error caused data container counts in combining group {originalGroup.Name} to differ.");
|
||||||
|
|
||||||
|
foreach (var (originalContainer, container) in combining.Data.Zip(group.Data))
|
||||||
|
{
|
||||||
|
container.Name = originalContainer.Name;
|
||||||
|
MergeIntoOption([originalContainer], container, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -151,7 +243,6 @@ public class ModMerger : IDisposable, IService
|
||||||
if (!dir.Exists)
|
if (!dir.Exists)
|
||||||
_createdDirectories.Add(dir.FullName);
|
_createdDirectories.Add(dir.FullName);
|
||||||
CopyFiles(dir);
|
CopyFiles(dir);
|
||||||
// #TODO DataContainer <> Option.
|
|
||||||
MergeIntoOption(MergeFromMod!.AllDataContainers.Reverse(), (IModDataContainer)option!, true);
|
MergeIntoOption(MergeFromMod!.AllDataContainers.Reverse(), (IModDataContainer)option!, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ public abstract class ModOptionEditor<TGroup, TOption>(
|
||||||
where TOption : class, IModOption
|
where TOption : class, IModOption
|
||||||
{
|
{
|
||||||
protected readonly CommunicatorService Communicator = communicator;
|
protected readonly CommunicatorService Communicator = communicator;
|
||||||
protected readonly SaveService SaveService = saveService;
|
protected readonly SaveService SaveService = saveService;
|
||||||
protected readonly Configuration Config = config;
|
protected readonly Configuration Config = config;
|
||||||
|
|
||||||
/// <summary> Add a new, empty option group of the given type and name. </summary>
|
/// <summary> Add a new, empty option group of the given type and name. </summary>
|
||||||
public TGroup? AddModGroup(Mod mod, string newName, SaveType saveType = SaveType.ImmediateSync)
|
public TGroup? AddModGroup(Mod mod, string newName, SaveType saveType = SaveType.ImmediateSync)
|
||||||
|
|
@ -25,7 +25,7 @@ public abstract class ModOptionEditor<TGroup, TOption>(
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var maxPriority = mod.Groups.Count == 0 ? ModPriority.Default : mod.Groups.Max(o => o.Priority) + 1;
|
var maxPriority = mod.Groups.Count == 0 ? ModPriority.Default : mod.Groups.Max(o => o.Priority) + 1;
|
||||||
var group = CreateGroup(mod, newName, maxPriority);
|
var group = CreateGroup(mod, newName, maxPriority);
|
||||||
mod.Groups.Add(group);
|
mod.Groups.Add(group);
|
||||||
SaveService.Save(saveType, new ModSaveGroup(group, Config.ReplaceNonAsciiOnImport));
|
SaveService.Save(saveType, new ModSaveGroup(group, Config.ReplaceNonAsciiOnImport));
|
||||||
Communicator.ModOptionChanged.Invoke(ModOptionChangeType.GroupAdded, mod, group, null, null, -1);
|
Communicator.ModOptionChanged.Invoke(ModOptionChangeType.GroupAdded, mod, group, null, null, -1);
|
||||||
|
|
@ -92,8 +92,8 @@ public abstract class ModOptionEditor<TGroup, TOption>(
|
||||||
/// <summary> Delete the given option from the given group. </summary>
|
/// <summary> Delete the given option from the given group. </summary>
|
||||||
public void DeleteOption(TOption option)
|
public void DeleteOption(TOption option)
|
||||||
{
|
{
|
||||||
var mod = option.Mod;
|
var mod = option.Mod;
|
||||||
var group = option.Group;
|
var group = option.Group;
|
||||||
var optionIdx = option.GetIndex();
|
var optionIdx = option.GetIndex();
|
||||||
Communicator.ModOptionChanged.Invoke(ModOptionChangeType.PrepareChange, mod, group, option, null, -1);
|
Communicator.ModOptionChanged.Invoke(ModOptionChangeType.PrepareChange, mod, group, option, null, -1);
|
||||||
RemoveOption((TGroup)group, optionIdx);
|
RemoveOption((TGroup)group, optionIdx);
|
||||||
|
|
@ -104,7 +104,7 @@ public abstract class ModOptionEditor<TGroup, TOption>(
|
||||||
/// <summary> Move an option inside the given option group. </summary>
|
/// <summary> Move an option inside the given option group. </summary>
|
||||||
public void MoveOption(TOption option, int optionIdxTo)
|
public void MoveOption(TOption option, int optionIdxTo)
|
||||||
{
|
{
|
||||||
var idx = option.GetIndex();
|
var idx = option.GetIndex();
|
||||||
var group = (TGroup)option.Group;
|
var group = (TGroup)option.Group;
|
||||||
if (!MoveOption(group, idx, optionIdxTo))
|
if (!MoveOption(group, idx, optionIdxTo))
|
||||||
return;
|
return;
|
||||||
|
|
@ -113,10 +113,10 @@ public abstract class ModOptionEditor<TGroup, TOption>(
|
||||||
Communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionMoved, group.Mod, group, option, null, idx);
|
Communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionMoved, group.Mod, group, option, null, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract TGroup CreateGroup(Mod mod, string newName, ModPriority priority, SaveType saveType = SaveType.ImmediateSync);
|
protected abstract TGroup CreateGroup(Mod mod, string newName, ModPriority priority, SaveType saveType = SaveType.ImmediateSync);
|
||||||
protected abstract TOption? CloneOption(TGroup group, IModOption option);
|
protected abstract TOption? CloneOption(TGroup group, IModOption option);
|
||||||
protected abstract void RemoveOption(TGroup group, int optionIndex);
|
protected abstract void RemoveOption(TGroup group, int optionIndex);
|
||||||
protected abstract bool MoveOption(TGroup group, int optionIdxFrom, int optionIdxTo);
|
protected abstract bool MoveOption(TGroup group, int optionIdxFrom, int optionIdxTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ModOptionChangeTypeExtension
|
public static class ModOptionChangeTypeExtension
|
||||||
|
|
@ -132,22 +132,22 @@ public static class ModOptionChangeTypeExtension
|
||||||
{
|
{
|
||||||
(requiresSaving, requiresReloading, wasPrepared) = type switch
|
(requiresSaving, requiresReloading, wasPrepared) = type switch
|
||||||
{
|
{
|
||||||
ModOptionChangeType.GroupRenamed => (true, false, false),
|
ModOptionChangeType.GroupRenamed => (true, false, false),
|
||||||
ModOptionChangeType.GroupAdded => (true, false, false),
|
ModOptionChangeType.GroupAdded => (true, false, false),
|
||||||
ModOptionChangeType.GroupDeleted => (true, true, false),
|
ModOptionChangeType.GroupDeleted => (true, true, false),
|
||||||
ModOptionChangeType.GroupMoved => (true, false, false),
|
ModOptionChangeType.GroupMoved => (true, false, false),
|
||||||
ModOptionChangeType.GroupTypeChanged => (true, true, true),
|
ModOptionChangeType.GroupTypeChanged => (true, true, true),
|
||||||
ModOptionChangeType.PriorityChanged => (true, true, true),
|
ModOptionChangeType.PriorityChanged => (true, true, true),
|
||||||
ModOptionChangeType.OptionAdded => (true, true, true),
|
ModOptionChangeType.OptionAdded => (true, true, true),
|
||||||
ModOptionChangeType.OptionDeleted => (true, true, false),
|
ModOptionChangeType.OptionDeleted => (true, true, false),
|
||||||
ModOptionChangeType.OptionMoved => (true, false, false),
|
ModOptionChangeType.OptionMoved => (true, false, false),
|
||||||
ModOptionChangeType.OptionFilesChanged => (false, true, false),
|
ModOptionChangeType.OptionFilesChanged => (false, true, false),
|
||||||
ModOptionChangeType.OptionFilesAdded => (false, true, true),
|
ModOptionChangeType.OptionFilesAdded => (false, true, true),
|
||||||
ModOptionChangeType.OptionSwapsChanged => (false, true, false),
|
ModOptionChangeType.OptionSwapsChanged => (false, true, false),
|
||||||
ModOptionChangeType.OptionMetaChanged => (false, true, false),
|
ModOptionChangeType.OptionMetaChanged => (false, true, false),
|
||||||
ModOptionChangeType.DisplayChange => (false, false, false),
|
ModOptionChangeType.DisplayChange => (false, false, false),
|
||||||
ModOptionChangeType.DefaultOptionChanged => (true, false, false),
|
ModOptionChangeType.DefaultOptionChanged => (true, false, false),
|
||||||
_ => (false, false, false),
|
_ => (false, false, false),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue