mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Merge branch 'master' into Exter-N/stockings-skin-slot
This commit is contained in:
commit
83a36ed4cb
5 changed files with 137 additions and 18 deletions
|
|
@ -30,7 +30,7 @@ public class ModPanelDescriptionTab(
|
||||||
ImGui.Dummy(ImGuiHelpers.ScaledVector2(2));
|
ImGui.Dummy(ImGuiHelpers.ScaledVector2(2));
|
||||||
|
|
||||||
ImGui.Dummy(ImGuiHelpers.ScaledVector2(2));
|
ImGui.Dummy(ImGuiHelpers.ScaledVector2(2));
|
||||||
var (predefinedTagsEnabled, predefinedTagButtonOffset) = predefinedTagsConfig.Count > 0
|
var (predefinedTagsEnabled, predefinedTagButtonOffset) = predefinedTagsConfig.Enabled
|
||||||
? (true, ImGui.GetFrameHeight() + ImGui.GetStyle().WindowPadding.X + (ImGui.GetScrollMaxY() > 0 ? ImGui.GetStyle().ScrollbarSize : 0))
|
? (true, ImGui.GetFrameHeight() + ImGui.GetStyle().WindowPadding.X + (ImGui.GetScrollMaxY() > 0 ? ImGui.GetStyle().ScrollbarSize : 0))
|
||||||
: (false, 0);
|
: (false, 0);
|
||||||
var tagIdx = _localTags.Draw("Local Tags: ",
|
var tagIdx = _localTags.Draw("Local Tags: ",
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ public class ModPanelEditTab(
|
||||||
FeatureChecker.DrawFeatureFlagInput(modManager.DataEditor, _mod, UiHelpers.InputTextWidth.X);
|
FeatureChecker.DrawFeatureFlagInput(modManager.DataEditor, _mod, UiHelpers.InputTextWidth.X);
|
||||||
|
|
||||||
UiHelpers.DefaultLineSpace();
|
UiHelpers.DefaultLineSpace();
|
||||||
var sharedTagsEnabled = predefinedTagManager.Count > 0;
|
var sharedTagsEnabled = predefinedTagManager.Enabled;
|
||||||
var sharedTagButtonOffset = sharedTagsEnabled ? ImGui.GetFrameHeight() + ImGui.GetStyle().FramePadding.X : 0;
|
var sharedTagButtonOffset = sharedTagsEnabled ? ImGui.GetFrameHeight() + ImGui.GetStyle().FramePadding.X : 0;
|
||||||
var tagIdx = _modTags.Draw("Mod Tags: ", "Edit tags by clicking them, or add new tags. Empty tags are removed.", _mod.ModTags,
|
var tagIdx = _modTags.Draw("Mod Tags: ", "Edit tags by clicking them, or add new tags. Empty tags are removed.", _mod.ModTags,
|
||||||
out var editedTag, rightEndOffset: sharedTagButtonOffset);
|
out var editedTag, rightEndOffset: sharedTagButtonOffset);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using OtterGui.Extensions;
|
using OtterGui.Extensions;
|
||||||
|
using OtterGui.Filesystem;
|
||||||
using OtterGui.Raii;
|
using OtterGui.Raii;
|
||||||
using OtterGui.Services;
|
using OtterGui.Services;
|
||||||
using OtterGui.Text;
|
using OtterGui.Text;
|
||||||
|
|
@ -10,7 +11,7 @@ using Penumbra.Mods.Manager;
|
||||||
|
|
||||||
namespace Penumbra.UI.ModsTab;
|
namespace Penumbra.UI.ModsTab;
|
||||||
|
|
||||||
public class MultiModPanel(ModFileSystemSelector selector, ModDataEditor editor) : IUiService
|
public class MultiModPanel(ModFileSystemSelector selector, ModDataEditor editor, PredefinedTagManager tagManager) : IUiService
|
||||||
{
|
{
|
||||||
public void Draw()
|
public void Draw()
|
||||||
{
|
{
|
||||||
|
|
@ -97,7 +98,12 @@ public class MultiModPanel(ModFileSystemSelector selector, ModDataEditor editor)
|
||||||
var width = ImGuiHelpers.ScaledVector2(150, 0);
|
var width = ImGuiHelpers.ScaledVector2(150, 0);
|
||||||
ImUtf8.TextFrameAligned("Multi Tagger:"u8);
|
ImUtf8.TextFrameAligned("Multi Tagger:"u8);
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X - 2 * (width.X + ImGui.GetStyle().ItemSpacing.X));
|
|
||||||
|
var predefinedTagsEnabled = tagManager.Enabled;
|
||||||
|
var inputWidth = predefinedTagsEnabled
|
||||||
|
? ImGui.GetContentRegionAvail().X - 2 * width.X - 3 * ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetFrameHeight()
|
||||||
|
: ImGui.GetContentRegionAvail().X - 2 * (width.X + ImGui.GetStyle().ItemInnerSpacing.X);
|
||||||
|
ImGui.SetNextItemWidth(inputWidth);
|
||||||
ImUtf8.InputText("##tag"u8, ref _tag, "Local Tag Name..."u8);
|
ImUtf8.InputText("##tag"u8, ref _tag, "Local Tag Name..."u8);
|
||||||
|
|
||||||
UpdateTagCache();
|
UpdateTagCache();
|
||||||
|
|
@ -109,7 +115,7 @@ public class MultiModPanel(ModFileSystemSelector selector, ModDataEditor editor)
|
||||||
? "No tag specified."
|
? "No tag specified."
|
||||||
: $"All mods selected already contain the tag \"{_tag}\", either locally or as mod data."
|
: $"All mods selected already contain the tag \"{_tag}\", either locally or as mod data."
|
||||||
: $"Add the tag \"{_tag}\" to {_addMods.Count} mods as a local tag:\n\n\t{string.Join("\n\t", _addMods.Select(m => m.Name.Text))}";
|
: $"Add the tag \"{_tag}\" to {_addMods.Count} mods as a local tag:\n\n\t{string.Join("\n\t", _addMods.Select(m => m.Name.Text))}";
|
||||||
ImGui.SameLine();
|
ImUtf8.SameLineInner();
|
||||||
if (ImUtf8.ButtonEx(label, tooltip, width, _addMods.Count == 0))
|
if (ImUtf8.ButtonEx(label, tooltip, width, _addMods.Count == 0))
|
||||||
foreach (var mod in _addMods)
|
foreach (var mod in _addMods)
|
||||||
editor.ChangeLocalTag(mod, mod.LocalTags.Count, _tag);
|
editor.ChangeLocalTag(mod, mod.LocalTags.Count, _tag);
|
||||||
|
|
@ -122,10 +128,18 @@ public class MultiModPanel(ModFileSystemSelector selector, ModDataEditor editor)
|
||||||
? "No tag specified."
|
? "No tag specified."
|
||||||
: $"No selected mod contains the tag \"{_tag}\" locally."
|
: $"No selected mod contains the tag \"{_tag}\" locally."
|
||||||
: $"Remove the local tag \"{_tag}\" from {_removeMods.Count} mods:\n\n\t{string.Join("\n\t", _removeMods.Select(m => m.Item1.Name.Text))}";
|
: $"Remove the local tag \"{_tag}\" from {_removeMods.Count} mods:\n\n\t{string.Join("\n\t", _removeMods.Select(m => m.Item1.Name.Text))}";
|
||||||
ImGui.SameLine();
|
ImUtf8.SameLineInner();
|
||||||
if (ImUtf8.ButtonEx(label, tooltip, width, _removeMods.Count == 0))
|
if (ImUtf8.ButtonEx(label, tooltip, width, _removeMods.Count == 0))
|
||||||
foreach (var (mod, index) in _removeMods)
|
foreach (var (mod, index) in _removeMods)
|
||||||
editor.ChangeLocalTag(mod, index, string.Empty);
|
editor.ChangeLocalTag(mod, index, string.Empty);
|
||||||
|
|
||||||
|
if (predefinedTagsEnabled)
|
||||||
|
{
|
||||||
|
ImUtf8.SameLineInner();
|
||||||
|
tagManager.DrawToggleButton();
|
||||||
|
tagManager.DrawListMulti(selector.SelectedPaths.OfType<ModFileSystem.Leaf>().Select(l => l.Value));
|
||||||
|
}
|
||||||
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ using OtterGui.Classes;
|
||||||
using OtterGui.Extensions;
|
using OtterGui.Extensions;
|
||||||
using OtterGui.Raii;
|
using OtterGui.Raii;
|
||||||
using OtterGui.Services;
|
using OtterGui.Services;
|
||||||
|
using OtterGui.Text;
|
||||||
|
using Penumbra.Mods;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Penumbra.UI.Classes;
|
using Penumbra.UI.Classes;
|
||||||
|
|
@ -52,6 +54,9 @@ public sealed class PredefinedTagManager : ISavable, IReadOnlyList<string>, ISer
|
||||||
jObj.WriteTo(jWriter);
|
jObj.WriteTo(jWriter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Enabled
|
||||||
|
=> Count > 0;
|
||||||
|
|
||||||
public void Save()
|
public void Save()
|
||||||
=> _saveService.DelaySave(this, TimeSpan.FromSeconds(5));
|
=> _saveService.DelaySave(this, TimeSpan.FromSeconds(5));
|
||||||
|
|
||||||
|
|
@ -98,9 +103,9 @@ public sealed class PredefinedTagManager : ISavable, IReadOnlyList<string>, ISer
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawAddFromSharedTagsAndUpdateTags(IReadOnlyCollection<string> localTags, IReadOnlyCollection<string> modTags, bool editLocal,
|
public void DrawAddFromSharedTagsAndUpdateTags(IReadOnlyCollection<string> localTags, IReadOnlyCollection<string> modTags, bool editLocal,
|
||||||
Mods.Mod mod)
|
Mod mod)
|
||||||
{
|
{
|
||||||
DrawToggleButton();
|
DrawToggleButtonTopRight();
|
||||||
if (!DrawList(localTags, modTags, editLocal, out var changedTag, out var index))
|
if (!DrawList(localTags, modTags, editLocal, out var changedTag, out var index))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -110,17 +115,22 @@ public sealed class PredefinedTagManager : ISavable, IReadOnlyList<string>, ISer
|
||||||
_modManager.DataEditor.ChangeModTag(mod, index, changedTag);
|
_modManager.DataEditor.ChangeModTag(mod, index, changedTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawToggleButton()
|
public void DrawToggleButton()
|
||||||
{
|
{
|
||||||
ImGui.SameLine(ImGui.GetContentRegionMax().X
|
|
||||||
- ImGui.GetFrameHeight()
|
|
||||||
- (ImGui.GetScrollMaxY() > 0 ? ImGui.GetStyle().ItemInnerSpacing.X : 0));
|
|
||||||
using var color = ImRaii.PushColor(ImGuiCol.Button, ImGui.GetColorU32(ImGuiCol.ButtonActive), _isListOpen);
|
using var color = ImRaii.PushColor(ImGuiCol.Button, ImGui.GetColorU32(ImGuiCol.ButtonActive), _isListOpen);
|
||||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Tags.ToIconString(), new Vector2(ImGui.GetFrameHeight()),
|
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Tags.ToIconString(), new Vector2(ImGui.GetFrameHeight()),
|
||||||
"Add Predefined Tags...", false, true))
|
"Add Predefined Tags...", false, true))
|
||||||
_isListOpen = !_isListOpen;
|
_isListOpen = !_isListOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DrawToggleButtonTopRight()
|
||||||
|
{
|
||||||
|
ImGui.SameLine(ImGui.GetContentRegionMax().X
|
||||||
|
- ImGui.GetFrameHeight()
|
||||||
|
- (ImGui.GetScrollMaxY() > 0 ? ImGui.GetStyle().ItemInnerSpacing.X : 0));
|
||||||
|
DrawToggleButton();
|
||||||
|
}
|
||||||
|
|
||||||
private bool DrawList(IReadOnlyCollection<string> localTags, IReadOnlyCollection<string> modTags, bool editLocal, out string changedTag,
|
private bool DrawList(IReadOnlyCollection<string> localTags, IReadOnlyCollection<string> modTags, bool editLocal, out string changedTag,
|
||||||
out int changedIndex)
|
out int changedIndex)
|
||||||
{
|
{
|
||||||
|
|
@ -130,7 +140,7 @@ public sealed class PredefinedTagManager : ISavable, IReadOnlyList<string>, ISer
|
||||||
if (!_isListOpen)
|
if (!_isListOpen)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ImGui.TextUnformatted("Predefined Tags");
|
ImUtf8.Text("Predefined Tags"u8);
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
var ret = false;
|
var ret = false;
|
||||||
|
|
@ -155,6 +165,101 @@ public sealed class PredefinedTagManager : ISavable, IReadOnlyList<string>, ISer
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly List<Mod> _selectedMods = [];
|
||||||
|
private readonly List<(int Index, int DataIndex)> _countedMods = [];
|
||||||
|
|
||||||
|
private void PrepareLists(IEnumerable<Mod> selection)
|
||||||
|
{
|
||||||
|
_selectedMods.Clear();
|
||||||
|
_selectedMods.AddRange(selection);
|
||||||
|
_countedMods.EnsureCapacity(_selectedMods.Count);
|
||||||
|
while (_countedMods.Count < _selectedMods.Count)
|
||||||
|
_countedMods.Add((-1, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawListMulti(IEnumerable<Mod> selection)
|
||||||
|
{
|
||||||
|
if (!_isListOpen)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImUtf8.Text("Predefined Tags"u8);
|
||||||
|
PrepareLists(selection);
|
||||||
|
|
||||||
|
_enabledColor = ColorId.PredefinedTagAdd.Value();
|
||||||
|
_disabledColor = ColorId.PredefinedTagRemove.Value();
|
||||||
|
using var color = new ImRaii.Color();
|
||||||
|
foreach (var (tag, idx) in _predefinedTags.Keys.WithIndex())
|
||||||
|
{
|
||||||
|
var alreadyContained = 0;
|
||||||
|
var inModData = 0;
|
||||||
|
var missing = 0;
|
||||||
|
|
||||||
|
foreach (var (modIndex, mod) in _selectedMods.Index())
|
||||||
|
{
|
||||||
|
var tagIdx = mod.LocalTags.IndexOf(tag);
|
||||||
|
if (tagIdx >= 0)
|
||||||
|
{
|
||||||
|
++alreadyContained;
|
||||||
|
_countedMods[modIndex] = (tagIdx, -1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var dataIdx = mod.ModTags.IndexOf(tag);
|
||||||
|
if (dataIdx >= 0)
|
||||||
|
{
|
||||||
|
++inModData;
|
||||||
|
_countedMods[modIndex] = (-1, dataIdx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++missing;
|
||||||
|
_countedMods[modIndex] = (-1, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using var id = ImRaii.PushId(idx);
|
||||||
|
var buttonWidth = CalcTextButtonWidth(tag);
|
||||||
|
// Prevent adding a new tag past the right edge of the popup
|
||||||
|
if (buttonWidth + ImGui.GetStyle().ItemSpacing.X >= ImGui.GetContentRegionAvail().X)
|
||||||
|
ImGui.NewLine();
|
||||||
|
|
||||||
|
var (usedColor, disabled, tt) = (missing, alreadyContained) switch
|
||||||
|
{
|
||||||
|
(> 0, _) => (_enabledColor, false,
|
||||||
|
$"Add this tag to {missing} mods.{(inModData > 0 ? $" {inModData} mods contain it in their mod tags and are untouched." : string.Empty)}"),
|
||||||
|
(_, > 0) => (_disabledColor, false,
|
||||||
|
$"Remove this tag from {alreadyContained} mods.{(inModData > 0 ? $" {inModData} mods contain it in their mod tags and are untouched." : string.Empty)}"),
|
||||||
|
_ => (_disabledColor, true, "This tag is already present in the mod tags of all selected mods."),
|
||||||
|
};
|
||||||
|
color.Push(ImGuiCol.Button, usedColor);
|
||||||
|
if (ImUtf8.ButtonEx(tag, tt, new Vector2(buttonWidth, 0), disabled))
|
||||||
|
{
|
||||||
|
if (missing > 0)
|
||||||
|
foreach (var (mod, (localIdx, _)) in _selectedMods.Zip(_countedMods))
|
||||||
|
{
|
||||||
|
if (localIdx >= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_modManager.DataEditor.ChangeLocalTag(mod, mod.LocalTags.Count, tag);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
foreach (var (mod, (localIdx, _)) in _selectedMods.Zip(_countedMods))
|
||||||
|
{
|
||||||
|
if (localIdx < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_modManager.DataEditor.ChangeLocalTag(mod, localIdx, string.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui.SameLine();
|
||||||
|
|
||||||
|
color.Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.NewLine();
|
||||||
|
}
|
||||||
|
|
||||||
private bool DrawColoredButton(string buttonLabel, int index, int tagIdx, bool inOther)
|
private bool DrawColoredButton(string buttonLabel, int index, int tagIdx, bool inOther)
|
||||||
{
|
{
|
||||||
using var id = ImRaii.PushId(index);
|
using var id = ImRaii.PushId(index);
|
||||||
|
|
|
||||||
10
repo.json
10
repo.json
|
|
@ -5,8 +5,8 @@
|
||||||
"Punchline": "Runtime mod loader and manager.",
|
"Punchline": "Runtime mod loader and manager.",
|
||||||
"Description": "Runtime mod loader and manager.",
|
"Description": "Runtime mod loader and manager.",
|
||||||
"InternalName": "Penumbra",
|
"InternalName": "Penumbra",
|
||||||
"AssemblyVersion": "1.5.0.5",
|
"AssemblyVersion": "1.5.0.6",
|
||||||
"TestingAssemblyVersion": "1.5.0.5",
|
"TestingAssemblyVersion": "1.5.0.6",
|
||||||
"RepoUrl": "https://github.com/xivdev/Penumbra",
|
"RepoUrl": "https://github.com/xivdev/Penumbra",
|
||||||
"ApplicableVersion": "any",
|
"ApplicableVersion": "any",
|
||||||
"DalamudApiLevel": 13,
|
"DalamudApiLevel": 13,
|
||||||
|
|
@ -18,9 +18,9 @@
|
||||||
"LoadPriority": 69420,
|
"LoadPriority": 69420,
|
||||||
"LoadRequiredState": 2,
|
"LoadRequiredState": 2,
|
||||||
"LoadSync": true,
|
"LoadSync": true,
|
||||||
"DownloadLinkInstall": "https://github.com/xivdev/Penumbra/releases/download/1.5.0.5/Penumbra.zip",
|
"DownloadLinkInstall": "https://github.com/xivdev/Penumbra/releases/download/1.5.0.6/Penumbra.zip",
|
||||||
"DownloadLinkTesting": "https://github.com/xivdev/Penumbra/releases/download/1.5.0.5/Penumbra.zip",
|
"DownloadLinkTesting": "https://github.com/xivdev/Penumbra/releases/download/1.5.0.6/Penumbra.zip",
|
||||||
"DownloadLinkUpdate": "https://github.com/xivdev/Penumbra/releases/download/1.5.0.5/Penumbra.zip",
|
"DownloadLinkUpdate": "https://github.com/xivdev/Penumbra/releases/download/1.5.0.6/Penumbra.zip",
|
||||||
"IconUrl": "https://raw.githubusercontent.com/xivdev/Penumbra/master/images/icon.png"
|
"IconUrl": "https://raw.githubusercontent.com/xivdev/Penumbra/master/images/icon.png"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue