mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-13 20:24:17 +01:00
339 lines
No EOL
12 KiB
C#
339 lines
No EOL
12 KiB
C#
using System.IO;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
using Dalamud.Interface;
|
|
using ImGuiNET;
|
|
using Newtonsoft.Json;
|
|
using Penumbra.Models;
|
|
using Penumbra.Mods;
|
|
|
|
namespace Penumbra.UI
|
|
{
|
|
public partial class SettingsInterface
|
|
{
|
|
private class Selector
|
|
{
|
|
private const string LabelSelectorList = "##availableModList";
|
|
private const string LabelModFilter = "##ModFilter";
|
|
private const string TooltipModFilter = "Filter mods for those containing the given substring.";
|
|
private const string TooltipMoveDown = "Move the selected mod down in priority";
|
|
private const string TooltipMoveUp = "Move the selected mod up in priority";
|
|
private const string TooltipDelete = "Delete the selected mod";
|
|
private const string TooltipAdd = "Add an empty mod";
|
|
private const string DialogDeleteMod = "PenumbraDeleteMod";
|
|
private const string ButtonYesDelete = "Yes, delete it";
|
|
private const string ButtonNoDelete = "No, keep it";
|
|
private const float SelectorPanelWidth = 240f;
|
|
private const uint DisabledModColor = 0xFF666666;
|
|
private const uint ConflictingModColor = 0xFFAAAAFF;
|
|
|
|
private static readonly Vector2 SelectorButtonSizes = new( 60, 0 );
|
|
private static readonly string ArrowUpString = FontAwesomeIcon.ArrowUp.ToIconString();
|
|
private static readonly string ArrowDownString = FontAwesomeIcon.ArrowDown.ToIconString();
|
|
|
|
private readonly SettingsInterface _base;
|
|
private ModCollection? Mods => Service< ModManager >.Get().Mods;
|
|
|
|
private ModInfo? _mod;
|
|
private int _index;
|
|
private int? _deleteIndex;
|
|
private string _modFilter = "";
|
|
private string[]? _modNamesLower;
|
|
|
|
|
|
public Selector( SettingsInterface ui )
|
|
{
|
|
_base = ui;
|
|
ResetModNamesLower();
|
|
}
|
|
|
|
public void ResetModNamesLower()
|
|
{
|
|
_modNamesLower = Mods?.ModSettings?.Where(I => I.Mod != null)
|
|
.Select( I => I.Mod!.Meta.Name.ToLowerInvariant() ).ToArray() ?? new string[]{};
|
|
}
|
|
|
|
private void DrawPriorityChangeButton( string iconString, bool up, int unavailableWhen )
|
|
{
|
|
ImGui.PushFont( UiBuilder.IconFont );
|
|
if( _index != unavailableWhen )
|
|
{
|
|
if( ImGui.Button( iconString, SelectorButtonSizes ) )
|
|
{
|
|
SetSelection( _index );
|
|
Service< ModManager >.Get().ChangeModPriority( _mod!, up );
|
|
_modNamesLower!.Swap( _index, _index + ( up ? 1 : -1 ) );
|
|
_index += up ? 1 : -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ImGui.PushStyleVar( ImGuiStyleVar.Alpha, 0.5f );
|
|
ImGui.Button( iconString, SelectorButtonSizes );
|
|
ImGui.PopStyleVar();
|
|
}
|
|
|
|
ImGui.PopFont();
|
|
|
|
if( ImGui.IsItemHovered() )
|
|
{
|
|
ImGui.SetTooltip(
|
|
_base._plugin!.Configuration!.InvertModListOrder ^ up ? TooltipMoveDown : TooltipMoveUp
|
|
);
|
|
}
|
|
}
|
|
|
|
private void DrawModTrashButton()
|
|
{
|
|
ImGui.PushFont( UiBuilder.IconFont );
|
|
|
|
if( ImGui.Button( FontAwesomeIcon.Trash.ToIconString(), SelectorButtonSizes ) )
|
|
{
|
|
_deleteIndex = _index;
|
|
}
|
|
|
|
ImGui.PopFont();
|
|
|
|
if( ImGui.IsItemHovered() )
|
|
{
|
|
ImGui.SetTooltip( TooltipDelete );
|
|
}
|
|
}
|
|
|
|
private static void DrawModAddButton()
|
|
{
|
|
ImGui.PushFont( UiBuilder.IconFont );
|
|
|
|
if( ImGui.Button( FontAwesomeIcon.Plus.ToIconString(), SelectorButtonSizes ) )
|
|
{
|
|
// Do nothing. YEAH. #TODO.
|
|
}
|
|
|
|
ImGui.PopFont();
|
|
|
|
if( ImGui.IsItemHovered() )
|
|
{
|
|
ImGui.SetTooltip( TooltipAdd );
|
|
}
|
|
}
|
|
|
|
private void DrawModsSelectorFilter()
|
|
{
|
|
ImGui.SetNextItemWidth( SelectorButtonSizes.X * 4 );
|
|
var tmp = _modFilter;
|
|
if( ImGui.InputTextWithHint( LabelModFilter, "Filter Mods...", ref tmp, 256 ) )
|
|
{
|
|
_modFilter = tmp.ToLowerInvariant();
|
|
}
|
|
|
|
if( ImGui.IsItemHovered() )
|
|
{
|
|
ImGui.SetTooltip( TooltipModFilter );
|
|
}
|
|
}
|
|
|
|
private void DrawModsSelectorButtons()
|
|
{
|
|
// Selector controls
|
|
ImGui.PushStyleVar( ImGuiStyleVar.WindowPadding, ZeroVector );
|
|
ImGui.PushStyleVar( ImGuiStyleVar.FrameRounding, 0 );
|
|
|
|
DrawPriorityChangeButton( ArrowUpString, false, 0 );
|
|
ImGui.SameLine();
|
|
DrawPriorityChangeButton( ArrowDownString, true, Mods?.ModSettings?.Count - 1 ?? 0 );
|
|
ImGui.SameLine();
|
|
DrawModTrashButton();
|
|
ImGui.SameLine();
|
|
DrawModAddButton();
|
|
|
|
ImGui.PopStyleVar( 3 );
|
|
}
|
|
|
|
private void DrawDeleteModal()
|
|
{
|
|
if( _deleteIndex == null )
|
|
{
|
|
return;
|
|
}
|
|
|
|
ImGui.OpenPopup( DialogDeleteMod );
|
|
|
|
var ret = ImGui.BeginPopupModal( DialogDeleteMod );
|
|
if( !ret )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( _mod?.Mod == null )
|
|
{
|
|
ImGui.CloseCurrentPopup();
|
|
ImGui.EndPopup();
|
|
return;
|
|
}
|
|
|
|
ImGui.Text( "Are you sure you want to delete the following mod:" );
|
|
// todo: why the fuck does this become null??????
|
|
ImGui.Text( _mod?.Mod?.Meta?.Name );
|
|
|
|
if( ImGui.Button( ButtonYesDelete ) )
|
|
{
|
|
ImGui.CloseCurrentPopup();
|
|
Service< ModManager >.Get().DeleteMod( _mod?.Mod );
|
|
ClearSelection();
|
|
_base.ReloadMods();
|
|
}
|
|
|
|
ImGui.SameLine();
|
|
|
|
if( ImGui.Button( ButtonNoDelete ) )
|
|
{
|
|
ImGui.CloseCurrentPopup();
|
|
_deleteIndex = null;
|
|
}
|
|
|
|
ImGui.EndPopup();
|
|
}
|
|
|
|
|
|
public void Draw()
|
|
{
|
|
if( Mods == null )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Selector pane
|
|
ImGui.BeginGroup();
|
|
ImGui.PushStyleVar( ImGuiStyleVar.ItemSpacing, ZeroVector );
|
|
|
|
DrawModsSelectorFilter();
|
|
|
|
// Inlay selector list
|
|
ImGui.BeginChild( LabelSelectorList, new Vector2( SelectorPanelWidth, -ImGui.GetFrameHeightWithSpacing() ), true );
|
|
|
|
if( Mods.ModSettings != null )
|
|
{
|
|
for( var modIndex = 0; modIndex < Mods.ModSettings.Count; modIndex++ )
|
|
{
|
|
var settings = Mods.ModSettings[ modIndex ];
|
|
var modName = settings.Mod.Meta.Name;
|
|
if( _modFilter.Length > 0 && !_modNamesLower![ modIndex ].Contains( _modFilter ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var changedColour = false;
|
|
if( !settings.Enabled )
|
|
{
|
|
ImGui.PushStyleColor( ImGuiCol.Text, DisabledModColor );
|
|
changedColour = true;
|
|
}
|
|
else if( settings.Mod.FileConflicts.Any() )
|
|
{
|
|
ImGui.PushStyleColor( ImGuiCol.Text, ConflictingModColor );
|
|
changedColour = true;
|
|
}
|
|
|
|
#if DEBUG
|
|
var selected = ImGui.Selectable(
|
|
$"id={modIndex} {modName}",
|
|
modIndex == _index
|
|
);
|
|
#else
|
|
var selected = ImGui.Selectable( modName, modIndex == _index );
|
|
#endif
|
|
|
|
if( changedColour )
|
|
{
|
|
ImGui.PopStyleColor();
|
|
}
|
|
|
|
if( selected )
|
|
{
|
|
SetSelection( modIndex, settings );
|
|
}
|
|
}
|
|
}
|
|
|
|
ImGui.EndChild();
|
|
|
|
DrawModsSelectorButtons();
|
|
ImGui.EndGroup();
|
|
|
|
DrawDeleteModal();
|
|
}
|
|
|
|
public ModInfo? Mod() => _mod;
|
|
|
|
private void SetSelection( int idx, ModInfo? info )
|
|
{
|
|
_mod = info;
|
|
if( idx != _index )
|
|
{
|
|
_base._menu.InstalledTab.ModPanel.Details.ResetState();
|
|
}
|
|
|
|
_index = idx;
|
|
_deleteIndex = null;
|
|
}
|
|
|
|
private void SetSelection( int idx )
|
|
{
|
|
if( idx >= ( Mods?.ModSettings?.Count ?? 0 ) )
|
|
{
|
|
idx = -1;
|
|
}
|
|
|
|
if( idx < 0 )
|
|
{
|
|
SetSelection( 0, null );
|
|
}
|
|
else
|
|
{
|
|
SetSelection( idx, Mods!.ModSettings![ idx ] );
|
|
}
|
|
}
|
|
|
|
public void ClearSelection() => SetSelection( -1 );
|
|
|
|
public void SelectModByName( string name )
|
|
{
|
|
var idx = Mods?.ModSettings?.FindIndex( mod => mod.Mod.Meta.Name == name ) ?? -1;
|
|
SetSelection( idx );
|
|
}
|
|
|
|
private string GetCurrentModMetaFile()
|
|
=> _mod == null ? "" : Path.Combine( _mod.Mod.ModBasePath.FullName, "meta.json" );
|
|
|
|
public void ReloadCurrentMod()
|
|
{
|
|
var metaPath = GetCurrentModMetaFile();
|
|
if( metaPath.Length > 0 && File.Exists( metaPath ) )
|
|
{
|
|
_mod!.Mod.Meta = ModMeta.LoadFromFile( metaPath ) ?? _mod.Mod.Meta;
|
|
_base._menu.InstalledTab.ModPanel.Details.ResetState();
|
|
}
|
|
|
|
_mod!.Mod.RefreshModFiles();
|
|
Service< ModManager >.Get().CalculateEffectiveFileList();
|
|
_base._menu.EffectiveTab.RebuildFileList( _base._plugin!.Configuration!.ShowAdvanced );
|
|
ResetModNamesLower();
|
|
}
|
|
|
|
public string SaveCurrentMod()
|
|
{
|
|
if( _mod == null )
|
|
return "";
|
|
|
|
var metaPath = GetCurrentModMetaFile();
|
|
if( metaPath.Length > 0 )
|
|
{
|
|
File.WriteAllText( metaPath, JsonConvert.SerializeObject( _mod.Mod.Meta, Formatting.Indented ) );
|
|
}
|
|
|
|
_base._menu.InstalledTab.ModPanel.Details.ResetState();
|
|
return metaPath;
|
|
}
|
|
}
|
|
}
|
|
} |