mirror of
https://github.com/xivdev/Penumbra.git
synced 2026-02-23 08:17:59 +01:00
Update with workable prototype.
This commit is contained in:
parent
e77fa18c61
commit
795fa7336e
9 changed files with 168 additions and 116 deletions
2
OtterGui
2
OtterGui
|
|
@ -1 +1 @@
|
||||||
Subproject commit fd387218d2d2d237075cb35be6ca89eeb53e14e5
|
Subproject commit 055f169572223fd1b59389549c88b4c861c94608
|
||||||
|
|
@ -3,7 +3,6 @@ using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
using OtterGui.Filesystem;
|
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
using Penumbra.GameData.Data;
|
using Penumbra.GameData.Data;
|
||||||
using Penumbra.Meta.Manipulations;
|
using Penumbra.Meta.Manipulations;
|
||||||
|
|
@ -18,7 +17,6 @@ namespace Penumbra.Mods.Groups;
|
||||||
/// <summary> Groups that allow all available options to be selected at once. </summary>
|
/// <summary> Groups that allow all available options to be selected at once. </summary>
|
||||||
public sealed class CombiningModGroup : IModGroup
|
public sealed class CombiningModGroup : IModGroup
|
||||||
{
|
{
|
||||||
|
|
||||||
public GroupType Type
|
public GroupType Type
|
||||||
=> GroupType.Combining;
|
=> GroupType.Combining;
|
||||||
|
|
||||||
|
|
@ -60,33 +58,6 @@ public sealed class CombiningModGroup : IModGroup
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveOption(int index)
|
|
||||||
{
|
|
||||||
if(index < 0 || index >= OptionData.Count)
|
|
||||||
return;
|
|
||||||
|
|
||||||
OptionData.RemoveAt(index);
|
|
||||||
var list = new List<CombinedDataContainer>(Data.Count / 2);
|
|
||||||
var optionFlag = 1 << index;
|
|
||||||
list.AddRange(Data.Where((c, i) => (i & optionFlag) == 0));
|
|
||||||
Data = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MoveOption(int from, int to)
|
|
||||||
{
|
|
||||||
if (!OptionData.Move(ref from, ref to))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var list = new List<CombinedDataContainer>(Data.Count);
|
|
||||||
for (var i = 0ul; i < (ulong)Data.Count; ++i)
|
|
||||||
{
|
|
||||||
var actualIndex = (int) Functions.MoveBit(i, from, to);
|
|
||||||
list.Add(Data[actualIndex]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Data = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IModOption? AddOption(string name, string description = "")
|
public IModOption? AddOption(string name, string description = "")
|
||||||
{
|
{
|
||||||
var groupIdx = Mod.Groups.IndexOf(this);
|
var groupIdx = Mod.Groups.IndexOf(this);
|
||||||
|
|
@ -98,10 +69,9 @@ public sealed class CombiningModGroup : IModGroup
|
||||||
Name = name,
|
Name = name,
|
||||||
Description = description,
|
Description = description,
|
||||||
};
|
};
|
||||||
// Double available containers.
|
return OptionData.AddNewWithPowerSet(Data, subMod, () => new CombinedDataContainer(this), IModGroup.MaxCombiningOptions)
|
||||||
FillContainers(2 * Data.Count);
|
? subMod
|
||||||
OptionData.Add(subMod);
|
: null;
|
||||||
return subMod;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CombiningModGroup? Load(Mod mod, JObject json)
|
public static CombiningModGroup? Load(Mod mod, JObject json)
|
||||||
|
|
@ -148,7 +118,8 @@ public sealed class CombiningModGroup : IModGroup
|
||||||
Penumbra.Messager.NotificationMessage(
|
Penumbra.Messager.NotificationMessage(
|
||||||
$"Combining Group {ret.Name} in {mod.Name} has not enough data containers for its {ret.OptionData.Count} options, filling with empty containers.",
|
$"Combining Group {ret.Name} in {mod.Name} has not enough data containers for its {ret.OptionData.Count} options, filling with empty containers.",
|
||||||
NotificationType.Warning);
|
NotificationType.Warning);
|
||||||
ret.FillContainers(requiredContainers);
|
ret.Data.EnsureCapacity(requiredContainers);
|
||||||
|
ret.Data.AddRange(Enumerable.Repeat(0, requiredContainers - ret.Data.Count).Select(_ => new CombinedDataContainer(ret)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.DefaultSettings = ret.FixSetting(ret.DefaultSettings);
|
ret.DefaultSettings = ret.FixSetting(ret.DefaultSettings);
|
||||||
|
|
@ -222,14 +193,4 @@ public sealed class CombiningModGroup : IModGroup
|
||||||
Mod = mod;
|
Mod = mod;
|
||||||
Data = [];
|
Data = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
|
||||||
private void FillContainers(int requiredCount)
|
|
||||||
{
|
|
||||||
if (requiredCount <= Data.Count)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Data.EnsureCapacity(requiredCount);
|
|
||||||
Data.AddRange(Enumerable.Repeat(0, requiredCount - Data.Count).Select(_ => new CombinedDataContainer(this)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
using OtterGui;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
using OtterGui.Filesystem;
|
|
||||||
using OtterGui.Services;
|
using OtterGui.Services;
|
||||||
using Penumbra.Mods.Groups;
|
using Penumbra.Mods.Groups;
|
||||||
using Penumbra.Mods.Settings;
|
using Penumbra.Mods.Settings;
|
||||||
|
|
@ -19,54 +19,30 @@ public sealed class CombiningModGroupEditor(CommunicatorService communicator, Sa
|
||||||
};
|
};
|
||||||
|
|
||||||
protected override CombiningSubMod? CloneOption(CombiningModGroup group, IModOption option)
|
protected override CombiningSubMod? CloneOption(CombiningModGroup group, IModOption option)
|
||||||
{
|
=> throw new NotImplementedException();
|
||||||
if (group.OptionData.Count >= IModGroup.MaxCombiningOptions)
|
|
||||||
{
|
|
||||||
Penumbra.Log.Error(
|
|
||||||
$"Could not add option {option.Name} to {group.Name} for mod {group.Mod.Name}, "
|
|
||||||
+ $"since only up to {IModGroup.MaxCombiningOptions} options are supported in one group.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var newOption = new CombiningSubMod(group)
|
|
||||||
{
|
|
||||||
Name = option.Name,
|
|
||||||
Description = option.Description,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (option is IModDataContainer data)
|
|
||||||
{
|
|
||||||
SubMod.Clone(data, newOption);
|
|
||||||
if (option is MultiSubMod m)
|
|
||||||
newOption.Priority = m.Priority;
|
|
||||||
else
|
|
||||||
newOption.Priority = new ModPriority(group.OptionData.Max(o => o.Priority.Value) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
group.OptionData.Add(newOption);
|
|
||||||
return newOption;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void RemoveOption(CombiningModGroup group, int optionIndex)
|
protected override void RemoveOption(CombiningModGroup group, int optionIndex)
|
||||||
{
|
{
|
||||||
var optionFlag = 1 << optionIndex;
|
if (group.OptionData.RemoveWithPowerSet(group.Data, optionIndex))
|
||||||
for (var i = group.Data.Count - 1; i >= 0; --i)
|
group.DefaultSettings.RemoveBit(optionIndex);
|
||||||
{
|
|
||||||
group.Data.RemoveAll()
|
|
||||||
if ((i & optionFlag) == optionFlag)
|
|
||||||
group.Data.RemoveAt(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
group.OptionData.RemoveAt(optionIndex);
|
|
||||||
group.DefaultSettings = group.DefaultSettings.RemoveBit(optionIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool MoveOption(MultiModGroup group, int optionIdxFrom, int optionIdxTo)
|
protected override bool MoveOption(CombiningModGroup group, int optionIdxFrom, int optionIdxTo)
|
||||||
{
|
{
|
||||||
if (!group.OptionData.Move(ref optionIdxFrom, ref optionIdxTo))
|
if (!group.OptionData.MoveWithPowerSet(group.Data, ref optionIdxFrom, ref optionIdxTo))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
group.DefaultSettings = group.DefaultSettings.MoveBit(optionIdxFrom, optionIdxTo);
|
group.DefaultSettings.MoveBit(optionIdxFrom, optionIdxTo);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetDisplayName(CombinedDataContainer container, string name, SaveType saveType = SaveType.Queue)
|
||||||
|
{
|
||||||
|
if (container.Name == name)
|
||||||
|
return;
|
||||||
|
|
||||||
|
container.Name = name;
|
||||||
|
SaveService.Save(saveType, new ModSaveGroup(container.Group, Config.ReplaceNonAsciiOnImport));
|
||||||
|
Communicator.ModOptionChanged.Invoke(ModOptionChangeType.DisplayChange, container.Group.Mod, container.Group, null, null, -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,7 @@ public class ModGroupEditor(
|
||||||
case ImcSubMod i:
|
case ImcSubMod i:
|
||||||
ImcEditor.DeleteOption(i);
|
ImcEditor.DeleteOption(i);
|
||||||
return;
|
return;
|
||||||
case CombiningModGroup c:
|
case CombiningSubMod c:
|
||||||
CombiningEditor.DeleteOption(c);
|
CombiningEditor.DeleteOption(c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -259,7 +259,7 @@ public class ModGroupEditor(
|
||||||
GroupType.Single => SingleEditor.AddModGroup(mod, newName, saveType),
|
GroupType.Single => SingleEditor.AddModGroup(mod, newName, saveType),
|
||||||
GroupType.Multi => MultiEditor.AddModGroup(mod, newName, saveType),
|
GroupType.Multi => MultiEditor.AddModGroup(mod, newName, saveType),
|
||||||
GroupType.Imc => ImcEditor.AddModGroup(mod, newName, default, default, saveType),
|
GroupType.Imc => ImcEditor.AddModGroup(mod, newName, default, default, saveType),
|
||||||
GroupType.Combining => CombiningEditor.AddModGroup(mod, newName, default, default, saveType),
|
GroupType.Combining => CombiningEditor.AddModGroup(mod, newName, saveType),
|
||||||
_ => null,
|
_ => null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,13 +82,11 @@ public partial class ModCreator(
|
||||||
if (incorporateMetaChanges)
|
if (incorporateMetaChanges)
|
||||||
IncorporateAllMetaChanges(mod, true);
|
IncorporateAllMetaChanges(mod, true);
|
||||||
if (deleteDefaultMetaChanges && !Config.KeepDefaultMetaChanges)
|
if (deleteDefaultMetaChanges && !Config.KeepDefaultMetaChanges)
|
||||||
{
|
|
||||||
foreach (var container in mod.AllDataContainers)
|
foreach (var container in mod.AllDataContainers)
|
||||||
{
|
{
|
||||||
if (ModMetaEditor.DeleteDefaultValues(metaFileManager, container.Manipulations))
|
if (ModMetaEditor.DeleteDefaultValues(metaFileManager, container.Manipulations))
|
||||||
saveService.ImmediateSaveSync(new ModSaveGroup(container, Config.ReplaceNonAsciiOnImport));
|
saveService.ImmediateSaveSync(new ModSaveGroup(container, Config.ReplaceNonAsciiOnImport));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -186,7 +184,8 @@ public partial class ModCreator(
|
||||||
/// If .meta or .rgsp files are encountered, parse them and incorporate their meta changes into the mod.
|
/// If .meta or .rgsp files are encountered, parse them and incorporate their meta changes into the mod.
|
||||||
/// If delete is true, the files are deleted afterwards.
|
/// If delete is true, the files are deleted afterwards.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public (bool Changes, List<string> DeleteList) IncorporateMetaChanges(IModDataContainer option, DirectoryInfo basePath, bool delete, bool deleteDefault)
|
public (bool Changes, List<string> DeleteList) IncorporateMetaChanges(IModDataContainer option, DirectoryInfo basePath, bool delete,
|
||||||
|
bool deleteDefault)
|
||||||
{
|
{
|
||||||
var deleteList = new List<string>();
|
var deleteList = new List<string>();
|
||||||
var oldSize = option.Manipulations.Count;
|
var oldSize = option.Manipulations.Count;
|
||||||
|
|
@ -447,9 +446,10 @@ public partial class ModCreator(
|
||||||
var json = JObject.Parse(File.ReadAllText(file.FullName));
|
var json = JObject.Parse(File.ReadAllText(file.FullName));
|
||||||
switch (json[nameof(Type)]?.ToObject<GroupType>() ?? GroupType.Single)
|
switch (json[nameof(Type)]?.ToObject<GroupType>() ?? GroupType.Single)
|
||||||
{
|
{
|
||||||
case GroupType.Multi: return MultiModGroup.Load(mod, json);
|
case GroupType.Multi: return MultiModGroup.Load(mod, json);
|
||||||
case GroupType.Single: return SingleModGroup.Load(mod, json);
|
case GroupType.Single: return SingleModGroup.Load(mod, json);
|
||||||
case GroupType.Imc: return ImcModGroup.Load(mod, json);
|
case GroupType.Imc: return ImcModGroup.Load(mod, json);
|
||||||
|
case GroupType.Combining: return CombiningModGroup.Load(mod, json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ using Penumbra.Meta.Manipulations;
|
||||||
using Penumbra.Mods.Editor;
|
using Penumbra.Mods.Editor;
|
||||||
using Penumbra.Mods.Groups;
|
using Penumbra.Mods.Groups;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
using Swan.Formatters;
|
|
||||||
|
|
||||||
namespace Penumbra.Mods.SubMods;
|
namespace Penumbra.Mods.SubMods;
|
||||||
|
|
||||||
|
|
@ -15,7 +14,7 @@ public class CombinedDataContainer(IModGroup group) : IModDataContainer
|
||||||
|
|
||||||
public IModGroup Group { get; } = group;
|
public IModGroup Group { get; } = group;
|
||||||
|
|
||||||
public string Name { get; } = string.Empty;
|
public string Name { get; set; } = string.Empty;
|
||||||
public Dictionary<Utf8GamePath, FullPath> Files { get; set; } = [];
|
public Dictionary<Utf8GamePath, FullPath> Files { get; set; } = [];
|
||||||
public Dictionary<Utf8GamePath, FullPath> FileSwaps { get; set; } = [];
|
public Dictionary<Utf8GamePath, FullPath> FileSwaps { get; set; } = [];
|
||||||
public MetaDictionary Manipulations { get; set; } = new();
|
public MetaDictionary Manipulations { get; set; } = new();
|
||||||
|
|
@ -35,11 +34,12 @@ public class CombinedDataContainer(IModGroup group) : IModDataContainer
|
||||||
var sb = new StringBuilder(128);
|
var sb = new StringBuilder(128);
|
||||||
for (var i = 0; i < IModGroup.MaxCombiningOptions; ++i)
|
for (var i = 0; i < IModGroup.MaxCombiningOptions; ++i)
|
||||||
{
|
{
|
||||||
if ((index & 1) == 0)
|
if ((index & 1) != 0)
|
||||||
continue;
|
{
|
||||||
|
sb.Append(Group.Options[i].Name);
|
||||||
|
sb.Append(' ').Append('+').Append(' ');
|
||||||
|
}
|
||||||
|
|
||||||
sb.Append(Group.Options[i].Name);
|
|
||||||
sb.Append(' ').Append('+').Append(' ');
|
|
||||||
index >>= 1;
|
index >>= 1;
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -81,29 +81,40 @@ public static class SubMod
|
||||||
[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
|
||||||
public static void WriteModContainer(JsonWriter j, JsonSerializer serializer, IModDataContainer data, DirectoryInfo basePath)
|
public static void WriteModContainer(JsonWriter j, JsonSerializer serializer, IModDataContainer data, DirectoryInfo basePath)
|
||||||
{
|
{
|
||||||
j.WritePropertyName(nameof(data.Files));
|
if (data.Files.Count > 0)
|
||||||
j.WriteStartObject();
|
|
||||||
foreach (var (gamePath, file) in data.Files)
|
|
||||||
{
|
{
|
||||||
if (file.ToRelPath(basePath, out var relPath))
|
j.WritePropertyName(nameof(data.Files));
|
||||||
|
j.WriteStartObject();
|
||||||
|
foreach (var (gamePath, file) in data.Files)
|
||||||
|
{
|
||||||
|
if (file.ToRelPath(basePath, out var relPath))
|
||||||
|
{
|
||||||
|
j.WritePropertyName(gamePath.ToString());
|
||||||
|
j.WriteValue(relPath.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
j.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.FileSwaps.Count > 0)
|
||||||
|
{
|
||||||
|
j.WritePropertyName(nameof(data.FileSwaps));
|
||||||
|
j.WriteStartObject();
|
||||||
|
foreach (var (gamePath, file) in data.FileSwaps)
|
||||||
{
|
{
|
||||||
j.WritePropertyName(gamePath.ToString());
|
j.WritePropertyName(gamePath.ToString());
|
||||||
j.WriteValue(relPath.ToString());
|
j.WriteValue(file.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
j.WriteEndObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
j.WriteEndObject();
|
if (data.Manipulations.Count > 0)
|
||||||
j.WritePropertyName(nameof(data.FileSwaps));
|
|
||||||
j.WriteStartObject();
|
|
||||||
foreach (var (gamePath, file) in data.FileSwaps)
|
|
||||||
{
|
{
|
||||||
j.WritePropertyName(gamePath.ToString());
|
j.WritePropertyName(nameof(data.Manipulations));
|
||||||
j.WriteValue(file.ToString());
|
serializer.Serialize(j, data.Manipulations);
|
||||||
}
|
}
|
||||||
|
|
||||||
j.WriteEndObject();
|
|
||||||
j.WritePropertyName(nameof(data.Manipulations));
|
|
||||||
serializer.Serialize(j, data.Manipulations);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Write the data for a selectable mod option on a JsonWriter. </summary>
|
/// <summary> Write the data for a selectable mod option on a JsonWriter. </summary>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,10 @@
|
||||||
|
using Dalamud.Interface;
|
||||||
|
using ImGuiNET;
|
||||||
|
using OtterGui;
|
||||||
|
using OtterGui.Raii;
|
||||||
|
using OtterGui.Text;
|
||||||
using Penumbra.Mods.Groups;
|
using Penumbra.Mods.Groups;
|
||||||
|
using Penumbra.Mods.SubMods;
|
||||||
|
|
||||||
namespace Penumbra.UI.ModsTab.Groups;
|
namespace Penumbra.UI.ModsTab.Groups;
|
||||||
|
|
||||||
|
|
@ -6,6 +12,100 @@ public readonly struct CombiningModGroupEditDrawer(ModGroupEditDrawer editor, Co
|
||||||
{
|
{
|
||||||
public void Draw()
|
public void Draw()
|
||||||
{
|
{
|
||||||
|
foreach (var (option, optionIdx) in group.OptionData.WithIndex())
|
||||||
|
{
|
||||||
|
using var id = ImUtf8.PushId(optionIdx);
|
||||||
|
editor.DrawOptionPosition(group, option, optionIdx);
|
||||||
|
|
||||||
|
ImUtf8.SameLineInner();
|
||||||
|
editor.DrawOptionDefaultMultiBehaviour(group, option, optionIdx);
|
||||||
|
|
||||||
|
ImUtf8.SameLineInner();
|
||||||
|
editor.DrawOptionName(option);
|
||||||
|
|
||||||
|
ImUtf8.SameLineInner();
|
||||||
|
editor.DrawOptionDescription(option);
|
||||||
|
|
||||||
|
ImUtf8.SameLineInner();
|
||||||
|
editor.DrawOptionDelete(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawNewOption();
|
||||||
|
DrawContainerNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawNewOption()
|
||||||
|
{
|
||||||
|
var count = group.OptionData.Count;
|
||||||
|
if (count >= IModGroup.MaxCombiningOptions)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var name = editor.DrawNewOptionBase(group, count);
|
||||||
|
|
||||||
|
var validName = name.Length > 0;
|
||||||
|
if (ImUtf8.IconButton(FontAwesomeIcon.Plus, validName
|
||||||
|
? "Add a new option to this group."u8
|
||||||
|
: "Please enter a name for the new option."u8, default, !validName))
|
||||||
|
{
|
||||||
|
editor.ModManager.OptionEditor.CombiningEditor.AddOption(group, name);
|
||||||
|
editor.NewOptionName = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe void DrawContainerNames()
|
||||||
|
{
|
||||||
|
if (ImUtf8.ButtonEx("Edit Container Names"u8,
|
||||||
|
"Add optional names to separate data containers of the combining group.\nThose are just for easier identification while editing the mod, and are not generally displayed to the user."u8,
|
||||||
|
new Vector2(400 * ImUtf8.GlobalScale, 0)))
|
||||||
|
ImUtf8.OpenPopup("DataContainerNames"u8);
|
||||||
|
|
||||||
|
var sizeX = group.OptionData.Count * (ImGui.GetStyle().ItemInnerSpacing.X + ImGui.GetFrameHeight()) + 300 * ImUtf8.GlobalScale;
|
||||||
|
ImGui.SetNextWindowSize(new Vector2(sizeX, ImGui.GetFrameHeightWithSpacing() * Math.Min(16, group.Data.Count) + 200 * ImUtf8.GlobalScale));
|
||||||
|
using var popup = ImUtf8.Popup("DataContainerNames"u8);
|
||||||
|
if (!popup)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var option in group.OptionData)
|
||||||
|
{
|
||||||
|
ImUtf8.RotatedText(option.Name, true);
|
||||||
|
ImUtf8.SameLineInner();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.NewLine();
|
||||||
|
ImGui.Separator();
|
||||||
|
using var child = ImUtf8.Child("##Child"u8, ImGui.GetContentRegionAvail());
|
||||||
|
ImGuiClip.ClippedDraw(group.Data, DrawRow, ImGui.GetFrameHeightWithSpacing());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawRow(CombinedDataContainer container, int index)
|
||||||
|
{
|
||||||
|
using var id = ImUtf8.PushId(index);
|
||||||
|
using (ImRaii.Disabled())
|
||||||
|
{
|
||||||
|
for (var i = 0; i < group.OptionData.Count; ++i)
|
||||||
|
{
|
||||||
|
id.Push(i);
|
||||||
|
var check = (index & (1 << i)) != 0;
|
||||||
|
ImUtf8.Checkbox(""u8, ref check);
|
||||||
|
ImUtf8.SameLineInner();
|
||||||
|
id.Pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var name = editor.CombiningDisplayIndex == index ? editor.CombiningDisplayName ?? container.Name : container.Name;
|
||||||
|
if (ImUtf8.InputText("##Nothing"u8, ref name, "Optional Display Name..."u8))
|
||||||
|
{
|
||||||
|
editor.CombiningDisplayIndex = index;
|
||||||
|
editor.CombiningDisplayName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.IsItemDeactivatedAfterEdit())
|
||||||
|
editor.ModManager.OptionEditor.CombiningEditor.SetDisplayName(container, name);
|
||||||
|
|
||||||
|
if (ImGui.IsItemDeactivated())
|
||||||
|
{
|
||||||
|
editor.CombiningDisplayIndex = -1;
|
||||||
|
editor.CombiningDisplayName = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,9 @@ public sealed class ModGroupEditDrawer(
|
||||||
private IModOption? _dragDropOption;
|
private IModOption? _dragDropOption;
|
||||||
private bool _draggingAcross;
|
private bool _draggingAcross;
|
||||||
|
|
||||||
|
internal string? CombiningDisplayName;
|
||||||
|
internal int CombiningDisplayIndex;
|
||||||
|
|
||||||
public void Draw(Mod mod)
|
public void Draw(Mod mod)
|
||||||
{
|
{
|
||||||
PrepareStyle();
|
PrepareStyle();
|
||||||
|
|
@ -275,6 +278,7 @@ public sealed class ModGroupEditDrawer(
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal string DrawNewOptionBase(IModGroup group, int count)
|
internal string DrawNewOptionBase(IModGroup group, int count)
|
||||||
{
|
{
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
ImUtf8.Selectable($"Option #{count + 1}", false, size: OptionIdxSelectable);
|
ImUtf8.Selectable($"Option #{count + 1}", false, size: OptionIdxSelectable);
|
||||||
Target(group, count);
|
Target(group, count);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue