mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-30 12:23:41 +01:00
Complete refactoring of interface code. Addition of 'Enable Mods' checkmark, that just (de)activates all mods at once without changing settings. Allow editing of mod json inside the interface in advanced mode.
This commit is contained in:
parent
5462bb6f05
commit
7e51e663ec
20 changed files with 2274 additions and 872 deletions
|
|
@ -1,871 +1,46 @@
|
|||
using System;
|
||||
using System.ComponentModel.Design;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Plugin;
|
||||
using ImGuiNET;
|
||||
using Newtonsoft.Json;
|
||||
using Penumbra.Importer;
|
||||
using Penumbra.Models;
|
||||
|
||||
namespace Penumbra.UI
|
||||
{
|
||||
public class SettingsInterface
|
||||
{
|
||||
private readonly Plugin _plugin;
|
||||
|
||||
public bool Visible;
|
||||
public bool ShowDebugBar;
|
||||
|
||||
private static readonly Vector2 AutoFillSize = new Vector2( -1, -1 );
|
||||
private static readonly Vector2 ModListSize = new Vector2( 200, -1 );
|
||||
|
||||
private static readonly Vector2 MinSettingsSize = new Vector2( 800, 450 );
|
||||
private static readonly Vector2 MaxSettingsSize = new Vector2( 69420, 42069 );
|
||||
|
||||
private const string DialogDeleteMod = "PenumbraDeleteMod";
|
||||
|
||||
private int _selectedModIndex;
|
||||
private int? _selectedModDeleteIndex;
|
||||
private ModInfo _selectedMod;
|
||||
|
||||
private bool _isImportRunning;
|
||||
private TexToolsImport _texToolsImport = null!;
|
||||
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private const float DefaultVerticalSpace = 20f;
|
||||
|
||||
private static readonly Vector2 AutoFillSize = new(-1, -1);
|
||||
private static readonly Vector2 ZeroVector = new( 0, 0);
|
||||
|
||||
private readonly Plugin _plugin;
|
||||
|
||||
private readonly LaunchButton _launchButton;
|
||||
private readonly MenuBar _menuBar;
|
||||
private readonly SettingsMenu _menu;
|
||||
|
||||
public SettingsInterface( Plugin plugin )
|
||||
{
|
||||
_plugin = plugin;
|
||||
#if DEBUG
|
||||
Visible = true;
|
||||
ShowDebugBar = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
_plugin = plugin;
|
||||
_launchButton = new(this);
|
||||
_menuBar = new(this);
|
||||
_menu = new(this);
|
||||
}
|
||||
|
||||
public void FlipVisibility() => _menu.Visible = !_menu.Visible;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
if( ShowDebugBar && ImGui.BeginMainMenuBar() )
|
||||
{
|
||||
if( ImGui.BeginMenu( "Penumbra" ) )
|
||||
{
|
||||
if( ImGui.MenuItem( "Toggle UI", "/penumbra", Visible ) )
|
||||
{
|
||||
Visible = !Visible;
|
||||
}
|
||||
|
||||
if( ImGui.MenuItem( "Rediscover Mods" ) )
|
||||
{
|
||||
ReloadMods();
|
||||
}
|
||||
|
||||
// ImGui.Separator();
|
||||
// #if DEBUG
|
||||
// ImGui.Text( _plugin.PluginDebugTitleStr );
|
||||
// #else
|
||||
// ImGui.Text( _plugin.Name );
|
||||
// #endif
|
||||
|
||||
ImGui.EndMenu();
|
||||
}
|
||||
|
||||
ImGui.EndMainMenuBar();
|
||||
}
|
||||
|
||||
if( !_plugin.PluginInterface.ClientState.Condition.Any() && !Visible )
|
||||
{
|
||||
// draw mods button on da menu :DDD
|
||||
var ss = ImGui.GetIO().DisplaySize;
|
||||
var padding = 50;
|
||||
var width = 200;
|
||||
var height = 45;
|
||||
|
||||
// magic numbers
|
||||
ImGui.SetNextWindowPos( new Vector2( ss.X - padding - width, ss.Y - padding - height ), ImGuiCond.Always );
|
||||
|
||||
if(
|
||||
ImGui.Begin(
|
||||
"Penumbra Menu Buttons",
|
||||
ImGuiWindowFlags.AlwaysAutoResize |
|
||||
ImGuiWindowFlags.NoBackground |
|
||||
ImGuiWindowFlags.NoDecoration |
|
||||
ImGuiWindowFlags.NoMove |
|
||||
ImGuiWindowFlags.NoScrollbar |
|
||||
ImGuiWindowFlags.NoResize |
|
||||
ImGuiWindowFlags.NoSavedSettings
|
||||
)
|
||||
)
|
||||
{
|
||||
if( ImGui.Button( "Manage Mods", new Vector2( width, height ) ) )
|
||||
{
|
||||
Visible = !Visible;
|
||||
}
|
||||
|
||||
ImGui.End();
|
||||
}
|
||||
}
|
||||
|
||||
if( !Visible )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui.SetNextWindowSizeConstraints( MinSettingsSize, MaxSettingsSize );
|
||||
#if DEBUG
|
||||
var ret = ImGui.Begin( _plugin.PluginDebugTitleStr, ref Visible );
|
||||
#else
|
||||
var ret = ImGui.Begin( _plugin.Name, ref Visible );
|
||||
#endif
|
||||
if( !ret )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui.BeginTabBar( "PenumbraSettings" );
|
||||
|
||||
DrawSettingsTab();
|
||||
DrawImportTab();
|
||||
|
||||
|
||||
if( !_isImportRunning )
|
||||
{
|
||||
DrawModBrowser();
|
||||
|
||||
DrawInstalledMods();
|
||||
|
||||
if( _plugin.Configuration.ShowAdvanced )
|
||||
{
|
||||
DrawEffectiveFileList();
|
||||
}
|
||||
|
||||
DrawDeleteModal();
|
||||
}
|
||||
|
||||
ImGui.EndTabBar();
|
||||
|
||||
ImGui.End();
|
||||
}
|
||||
|
||||
void DrawImportTab()
|
||||
{
|
||||
var ret = ImGui.BeginTabItem( "Import Mods" );
|
||||
if( !ret )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( !_isImportRunning )
|
||||
{
|
||||
if( ImGui.Button( "Import TexTools Modpacks" ) )
|
||||
{
|
||||
_isImportRunning = true;
|
||||
|
||||
Task.Run( async () =>
|
||||
{
|
||||
var picker = new OpenFileDialog
|
||||
{
|
||||
Multiselect = true,
|
||||
Filter = "TexTools TTMP Modpack (*.ttmp2)|*.ttmp*|All files (*.*)|*.*",
|
||||
CheckFileExists = true,
|
||||
Title = "Pick one or more modpacks."
|
||||
};
|
||||
|
||||
var result = await picker.ShowDialogAsync();
|
||||
|
||||
if( result == DialogResult.OK )
|
||||
{
|
||||
foreach( var fileName in picker.FileNames )
|
||||
{
|
||||
PluginLog.Log( "-> {0} START", fileName );
|
||||
|
||||
try
|
||||
{
|
||||
_texToolsImport = new TexToolsImport( new DirectoryInfo( _plugin.Configuration.CurrentCollection ) );
|
||||
_texToolsImport.ImportModPack( new FileInfo( fileName ) );
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
PluginLog.LogError( ex, "Could not import one or more modpacks." );
|
||||
}
|
||||
|
||||
PluginLog.Log( "-> {0} OK!", fileName );
|
||||
}
|
||||
|
||||
_texToolsImport = null;
|
||||
ReloadMods();
|
||||
}
|
||||
|
||||
_isImportRunning = false;
|
||||
} );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.Button( "Import in progress..." );
|
||||
|
||||
if( _texToolsImport != null )
|
||||
{
|
||||
switch( _texToolsImport.State )
|
||||
{
|
||||
case ImporterState.None:
|
||||
break;
|
||||
case ImporterState.WritingPackToDisk:
|
||||
ImGui.Text( "Writing modpack to disk before extracting..." );
|
||||
break;
|
||||
case ImporterState.ExtractingModFiles:
|
||||
{
|
||||
var str =
|
||||
$"{_texToolsImport.CurrentModPack} - {_texToolsImport.CurrentProgress} of {_texToolsImport.TotalProgress} files";
|
||||
|
||||
ImGui.ProgressBar( _texToolsImport.Progress, new Vector2( -1, 0 ), str );
|
||||
break;
|
||||
}
|
||||
case ImporterState.Done:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
|
||||
[Conditional( "DEBUG" )]
|
||||
void DrawModBrowser()
|
||||
{
|
||||
var ret = ImGui.BeginTabItem( "Available Mods" );
|
||||
if( !ret )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui.Text( "woah" );
|
||||
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
|
||||
void DrawSettingsTab()
|
||||
{
|
||||
var ret = ImGui.BeginTabItem( "Settings" );
|
||||
if( !ret )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool dirty = false;
|
||||
|
||||
// FUCKKKKK
|
||||
var basePath = _plugin.Configuration.CurrentCollection;
|
||||
if( ImGui.InputText( "Root Folder", ref basePath, 255 ) )
|
||||
{
|
||||
_plugin.Configuration.CurrentCollection = basePath;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
if( ImGui.Button( "Rediscover Mods" ) )
|
||||
{
|
||||
ReloadMods();
|
||||
_selectedModIndex = 0;
|
||||
_selectedMod = null;
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if( ImGui.Button( "Open Mods Folder" ) )
|
||||
{
|
||||
Process.Start( _plugin.Configuration.CurrentCollection );
|
||||
}
|
||||
|
||||
ImGui.SetCursorPosY( ImGui.GetCursorPosY() + 20 );
|
||||
|
||||
var invertOrder = _plugin.Configuration.InvertModListOrder;
|
||||
if( ImGui.Checkbox( "Invert mod load order (mods are loaded bottom up)", ref invertOrder ) )
|
||||
{
|
||||
_plugin.Configuration.InvertModListOrder = invertOrder;
|
||||
dirty = true;
|
||||
|
||||
ReloadMods();
|
||||
}
|
||||
|
||||
ImGui.SetCursorPosY( ImGui.GetCursorPosY() + 20 );
|
||||
|
||||
var showAdvanced = _plugin.Configuration.ShowAdvanced;
|
||||
if( ImGui.Checkbox( "Show Advanced Settings", ref showAdvanced ) )
|
||||
{
|
||||
_plugin.Configuration.ShowAdvanced = showAdvanced;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
if( _plugin.Configuration.ShowAdvanced )
|
||||
{
|
||||
if( _plugin.ResourceLoader != null )
|
||||
{
|
||||
ImGui.Checkbox( "Log all loaded files", ref _plugin.ResourceLoader.LogAllFiles );
|
||||
}
|
||||
|
||||
var fswatch = _plugin.Configuration.DisableFileSystemNotifications;
|
||||
if( ImGui.Checkbox( "Disable filesystem change notifications", ref fswatch ) )
|
||||
{
|
||||
_plugin.Configuration.DisableFileSystemNotifications = fswatch;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
var http = _plugin.Configuration.EnableHttpApi;
|
||||
if( ImGui.Checkbox( "Enable HTTP API", ref http ) )
|
||||
{
|
||||
if( http )
|
||||
{
|
||||
_plugin.CreateWebServer();
|
||||
}
|
||||
else
|
||||
{
|
||||
_plugin.ShutdownWebServer();
|
||||
}
|
||||
|
||||
_plugin.Configuration.EnableHttpApi = http;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
if( ImGui.Button( "Reload Player Resource" ) )
|
||||
{
|
||||
_plugin.GameUtils.ReloadPlayerResources();
|
||||
}
|
||||
}
|
||||
|
||||
if( dirty )
|
||||
{
|
||||
_plugin.Configuration.Save();
|
||||
}
|
||||
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
|
||||
void DrawModsSelector()
|
||||
{
|
||||
// Selector pane
|
||||
ImGui.BeginGroup();
|
||||
ImGui.PushStyleVar( ImGuiStyleVar.ItemSpacing, new Vector2( 0, 0 ) );
|
||||
|
||||
// Inlay selector list
|
||||
ImGui.BeginChild( "availableModList", new Vector2( 240, -ImGui.GetFrameHeightWithSpacing() ), true );
|
||||
|
||||
if( _plugin.ModManager.Mods != null )
|
||||
{
|
||||
for( var modIndex = 0; modIndex < _plugin.ModManager.Mods.ModSettings.Count; modIndex++ )
|
||||
{
|
||||
var settings = _plugin.ModManager.Mods.ModSettings[ modIndex ];
|
||||
|
||||
var changedColour = false;
|
||||
if( !settings.Enabled )
|
||||
{
|
||||
ImGui.PushStyleColor( ImGuiCol.Text, 0xFF666666 );
|
||||
changedColour = true;
|
||||
}
|
||||
else if( settings.Mod.FileConflicts.Any() )
|
||||
{
|
||||
ImGui.PushStyleColor( ImGuiCol.Text, 0xFFAAAAFF );
|
||||
changedColour = true;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
var selected = ImGui.Selectable(
|
||||
$"id={modIndex} {settings.Mod.Meta.Name}",
|
||||
modIndex == _selectedModIndex
|
||||
);
|
||||
#else
|
||||
var selected = ImGui.Selectable( settings.Mod.Meta.Name, modIndex == _selectedModIndex );
|
||||
#endif
|
||||
|
||||
if( changedColour )
|
||||
{
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
|
||||
if( selected )
|
||||
{
|
||||
_selectedModIndex = modIndex;
|
||||
_selectedMod = settings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndChild();
|
||||
|
||||
// Selector controls
|
||||
ImGui.PushStyleVar( ImGuiStyleVar.WindowPadding, new Vector2( 0, 0 ) );
|
||||
ImGui.PushStyleVar( ImGuiStyleVar.FrameRounding, 0 );
|
||||
ImGui.PushFont( UiBuilder.IconFont );
|
||||
if( _selectedModIndex != 0 )
|
||||
{
|
||||
if( ImGui.Button( FontAwesomeIcon.ArrowUp.ToIconString(), new Vector2( 60, 0 ) ) )
|
||||
{
|
||||
_plugin.ModManager.ChangeModPriority( _selectedMod );
|
||||
_selectedModIndex -= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.PushStyleVar( ImGuiStyleVar.Alpha, 0.5f );
|
||||
ImGui.Button( FontAwesomeIcon.ArrowUp.ToIconString(), new Vector2( 60, 0 ) );
|
||||
ImGui.PopStyleVar();
|
||||
}
|
||||
|
||||
ImGui.PopFont();
|
||||
|
||||
if( ImGui.IsItemHovered() )
|
||||
{
|
||||
ImGui.SetTooltip(
|
||||
_plugin.Configuration.InvertModListOrder
|
||||
? "Move the selected mod down in priority"
|
||||
: "Move the selected mod up in priority"
|
||||
);
|
||||
}
|
||||
|
||||
ImGui.PushFont( UiBuilder.IconFont );
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if( _selectedModIndex != _plugin.ModManager.Mods?.ModSettings.Count - 1 )
|
||||
{
|
||||
if( ImGui.Button( FontAwesomeIcon.ArrowDown.ToIconString(), new Vector2( 60, 0 ) ) )
|
||||
{
|
||||
_plugin.ModManager.ChangeModPriority( _selectedMod, true );
|
||||
_selectedModIndex += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.PushStyleVar( ImGuiStyleVar.Alpha, 0.5f );
|
||||
ImGui.Button( FontAwesomeIcon.ArrowDown.ToIconString(), new Vector2( 60, 0 ) );
|
||||
ImGui.PopStyleVar();
|
||||
}
|
||||
|
||||
|
||||
ImGui.PopFont();
|
||||
|
||||
if( ImGui.IsItemHovered() )
|
||||
{
|
||||
ImGui.SetTooltip(
|
||||
_plugin.Configuration.InvertModListOrder
|
||||
? "Move the selected mod up in priority"
|
||||
: "Move the selected mod down in priority"
|
||||
);
|
||||
}
|
||||
|
||||
ImGui.PushFont( UiBuilder.IconFont );
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if( ImGui.Button( FontAwesomeIcon.Trash.ToIconString(), new Vector2( 60, 0 ) ) )
|
||||
{
|
||||
_selectedModDeleteIndex = _selectedModIndex;
|
||||
}
|
||||
|
||||
ImGui.PopFont();
|
||||
|
||||
if( ImGui.IsItemHovered() )
|
||||
ImGui.SetTooltip( "Delete the selected mod" );
|
||||
|
||||
ImGui.PushFont( UiBuilder.IconFont );
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if( ImGui.Button( FontAwesomeIcon.Plus.ToIconString(), new Vector2( 60, 0 ) ) )
|
||||
{
|
||||
}
|
||||
|
||||
ImGui.PopFont();
|
||||
|
||||
if( ImGui.IsItemHovered() )
|
||||
ImGui.SetTooltip( "Add an empty mod" );
|
||||
|
||||
ImGui.PopStyleVar( 3 );
|
||||
|
||||
ImGui.EndGroup();
|
||||
}
|
||||
|
||||
void DrawDeleteModal()
|
||||
{
|
||||
if( _selectedModDeleteIndex != null )
|
||||
ImGui.OpenPopup( DialogDeleteMod );
|
||||
|
||||
var ret = ImGui.BeginPopupModal( DialogDeleteMod );
|
||||
if( !ret )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( _selectedMod?.Mod == null )
|
||||
{
|
||||
ImGui.CloseCurrentPopup();
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
|
||||
ImGui.Text( "Are you sure you want to delete the following mod:" );
|
||||
// todo: why the fuck does this become null??????
|
||||
ImGui.Text( _selectedMod?.Mod?.Meta?.Name );
|
||||
|
||||
if( ImGui.Button( "Yes, delete it" ) )
|
||||
{
|
||||
ImGui.CloseCurrentPopup();
|
||||
_plugin.ModManager.DeleteMod( _selectedMod.Mod );
|
||||
_selectedMod = null;
|
||||
_selectedModIndex = 0;
|
||||
_selectedModDeleteIndex = null;
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if( ImGui.Button( "No, keep it" ) )
|
||||
{
|
||||
ImGui.CloseCurrentPopup();
|
||||
_selectedModDeleteIndex = null;
|
||||
}
|
||||
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
|
||||
// Website button with On-Hover address if valid http(s), otherwise text.
|
||||
private void DrawWebsiteText()
|
||||
{
|
||||
if( ( _selectedMod.Mod.Meta.Website?.Length ?? 0 ) <= 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var validUrl = Uri.TryCreate( _selectedMod.Mod.Meta.Website, UriKind.Absolute, out Uri uriResult )
|
||||
&& ( uriResult.Scheme == Uri.UriSchemeHttps || uriResult.Scheme == Uri.UriSchemeHttp );
|
||||
ImGui.SameLine();
|
||||
if( validUrl )
|
||||
{
|
||||
if( ImGui.SmallButton( "Open Website" ) )
|
||||
{
|
||||
Process.Start( _selectedMod.Mod.Meta.Website );
|
||||
}
|
||||
|
||||
if( ImGui.IsItemHovered() )
|
||||
ImGui.SetTooltip( _selectedMod.Mod.Meta.Website );
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.TextColored( new Vector4( 1f, 1f, 1f, 0.66f ), "from" );
|
||||
ImGui.SameLine();
|
||||
ImGui.Text( _selectedMod.Mod.Meta.Website );
|
||||
}
|
||||
}
|
||||
|
||||
// Create Mod-Handling buttons.
|
||||
private void DrawEditButtons()
|
||||
{
|
||||
ImGui.SameLine();
|
||||
if( ImGui.Button( "Open Mod Folder" ) )
|
||||
{
|
||||
Process.Start( _selectedMod.Mod.ModBasePath.FullName );
|
||||
}
|
||||
if( ImGui.IsItemHovered() )
|
||||
ImGui.SetTooltip( "Open the directory containing this mod in your default file explorer." );
|
||||
|
||||
ImGui.SameLine();
|
||||
if( ImGui.Button( "Edit JSON" ) )
|
||||
{
|
||||
var metaPath = Path.Combine( _selectedMod.Mod.ModBasePath.FullName, "meta.json" );
|
||||
File.WriteAllText( metaPath, JsonConvert.SerializeObject( _selectedMod.Mod.Meta, Formatting.Indented ) );
|
||||
Process.Start( metaPath );
|
||||
}
|
||||
if( ImGui.IsItemHovered() )
|
||||
ImGui.SetTooltip( "Open the JSON configuration file in your default application for .json." );
|
||||
|
||||
ImGui.SameLine();
|
||||
if( ImGui.Button( "Reload JSON" ) )
|
||||
{
|
||||
ReloadMods();
|
||||
}
|
||||
if( ImGui.IsItemHovered() )
|
||||
ImGui.SetTooltip( "Reload the configuration of all mods." );
|
||||
|
||||
ImGui.SameLine();
|
||||
if( ImGui.Button( "Deduplicate" ) )
|
||||
{
|
||||
new Deduplicator(_selectedMod.Mod.ModBasePath, _selectedMod.Mod.Meta).Run();
|
||||
var metaPath = Path.Combine( _selectedMod.Mod.ModBasePath.FullName, "meta.json" );
|
||||
File.WriteAllText( metaPath, JsonConvert.SerializeObject( _selectedMod.Mod.Meta, Formatting.Indented ) );
|
||||
ReloadMods();
|
||||
}
|
||||
if( ImGui.IsItemHovered() )
|
||||
ImGui.SetTooltip( "Try to find identical files and remove duplicate occurences to reduce the mods disk size." );
|
||||
}
|
||||
|
||||
private void DrawGroupSelectors()
|
||||
{
|
||||
//Spahetti code time
|
||||
var mod = _plugin.SettingsInterface._selectedMod;
|
||||
var conf = mod.Conf;
|
||||
var settings = mod.Mod.Meta.Groups;
|
||||
foreach( var g in settings )
|
||||
{
|
||||
switch( g.Value.SelectionType )
|
||||
{
|
||||
case SelectType.Multi:
|
||||
{
|
||||
var i = 0;
|
||||
var flag = conf[g.Key];
|
||||
foreach( var opt in g.Value.Options )
|
||||
{
|
||||
var enab = ( flag & 1 << i ) != 0;
|
||||
if( ImGui.Checkbox( g.Value.GroupName + " - " + opt.OptionName, ref enab ) )
|
||||
{
|
||||
flag = flag ^= 1 << i;
|
||||
conf[g.Key] = flag;
|
||||
_plugin.ModManager.Mods.Save();
|
||||
_plugin.ModManager.CalculateEffectiveFileList();
|
||||
}
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SelectType.Single:
|
||||
{
|
||||
var code = conf[g.Key];
|
||||
if( g.Value.Options.Count > 1 )
|
||||
{
|
||||
if( ImGui.Combo( g.Value.GroupName, ref code, g.Value.Options.Select( x => x.OptionName ).ToArray(), g.Value.Options.ToArray().Length ) )
|
||||
{
|
||||
conf[g.Key] = code;
|
||||
_plugin.ModManager.Mods.Save();
|
||||
_plugin.ModManager.CalculateEffectiveFileList();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawInstalledMods()
|
||||
{
|
||||
var ret = ImGui.BeginTabItem( "Installed Mods" );
|
||||
if( !ret )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( _plugin.ModManager.Mods == null )
|
||||
{
|
||||
ImGui.Text( "You don't have any mods :(" );
|
||||
ImGui.SetCursorPosY( ImGui.GetCursorPosY() + 20 );
|
||||
ImGui.Text( "You'll need to install them first by creating a folder close to the root of your drive (preferably an SSD)." );
|
||||
ImGui.Text( "For example: D:/ffxiv/mods/" );
|
||||
ImGui.Text( "And pasting that path into the settings tab and clicking the 'Rediscover Mods' button." );
|
||||
ImGui.Text( "You can return to this tab once you've done that." );
|
||||
ImGui.EndTabItem();
|
||||
return;
|
||||
}
|
||||
|
||||
DrawModsSelector();
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if( _selectedMod != null )
|
||||
{
|
||||
try
|
||||
{
|
||||
ImGui.BeginChild( "selectedModInfo", AutoFillSize, true );
|
||||
|
||||
ImGui.Text( _selectedMod.Mod.Meta.Name );
|
||||
|
||||
// (Version ...) or nothing.
|
||||
if( ( _selectedMod.Mod.Meta.Version?.Length ?? 0 ) > 0 )
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGui.Text( $"(Version {_selectedMod.Mod.Meta.Version})" );
|
||||
}
|
||||
|
||||
// by Author or Unknown.
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored( new Vector4( 1f, 1f, 1f, 0.66f ), "by" );
|
||||
ImGui.SameLine();
|
||||
if( ( _selectedMod.Mod.Meta.Author?.Length ?? 0 ) > 0 )
|
||||
ImGui.Text( _selectedMod.Mod.Meta.Author );
|
||||
else
|
||||
ImGui.Text( "Unknown" );
|
||||
|
||||
DrawWebsiteText();
|
||||
|
||||
ImGui.SetCursorPosY( ImGui.GetCursorPosY() + 10 );
|
||||
|
||||
var enabled = _selectedMod.Enabled;
|
||||
if( ImGui.Checkbox( "Enabled", ref enabled ) )
|
||||
{
|
||||
_selectedMod.Enabled = enabled;
|
||||
_plugin.ModManager.Mods.Save();
|
||||
_plugin.ModManager.CalculateEffectiveFileList();
|
||||
}
|
||||
|
||||
DrawEditButtons();
|
||||
|
||||
ImGui.BeginTabBar( "PenumbraPluginDetails" );
|
||||
|
||||
if( _selectedMod.Mod.Meta.Description?.Length > 0 && ImGui.BeginTabItem( "About" ) )
|
||||
{
|
||||
ImGui.TextWrapped( _selectedMod.Mod.Meta.Description );
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
|
||||
if( ( _selectedMod.Mod.Meta.ChangedItems?.Count ?? 0 ) > 0 )
|
||||
{
|
||||
if( ImGui.BeginTabItem( "Changed Items" ) )
|
||||
{
|
||||
ImGui.SetNextItemWidth( -1 );
|
||||
if( ImGui.ListBoxHeader( "###", AutoFillSize ) )
|
||||
foreach( var item in _selectedMod.Mod.Meta.ChangedItems )
|
||||
ImGui.Selectable( item );
|
||||
ImGui.ListBoxFooter();
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
}
|
||||
if(_selectedMod.Mod.Meta.HasGroupWithConfig) {
|
||||
if(ImGui.BeginTabItem( "Configuration" ))
|
||||
{
|
||||
DrawGroupSelectors();
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
}
|
||||
if( ImGui.BeginTabItem( "Files" ) )
|
||||
{
|
||||
ImGui.SetNextItemWidth( -1 );
|
||||
if( ImGui.ListBoxHeader( "##", AutoFillSize ) )
|
||||
foreach( var file in _selectedMod.Mod.ModFiles )
|
||||
ImGui.Selectable( file.FullName );
|
||||
|
||||
ImGui.ListBoxFooter();
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
|
||||
if( _selectedMod.Mod.Meta.FileSwaps.Any() )
|
||||
{
|
||||
if( ImGui.BeginTabItem( "File Swaps" ) )
|
||||
{
|
||||
ImGui.SetNextItemWidth( -1 );
|
||||
if( ImGui.ListBoxHeader( "##", AutoFillSize ) )
|
||||
{
|
||||
foreach( var file in _selectedMod.Mod.Meta.FileSwaps )
|
||||
{
|
||||
// todo: fucking gross alloc every frame * items
|
||||
ImGui.Selectable( $"{file.Key} -> {file.Value}" );
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.ListBoxFooter();
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
}
|
||||
|
||||
if( _selectedMod.Mod.FileConflicts.Any() )
|
||||
{
|
||||
if( ImGui.BeginTabItem( "File Conflicts" ) )
|
||||
{
|
||||
ImGui.SetNextItemWidth( -1 );
|
||||
if( ImGui.ListBoxHeader( "##", AutoFillSize ) )
|
||||
{
|
||||
foreach( var kv in _selectedMod.Mod.FileConflicts )
|
||||
{
|
||||
var mod = kv.Key;
|
||||
var files = kv.Value;
|
||||
|
||||
if( ImGui.Selectable( mod ) )
|
||||
{
|
||||
SelectModByName( mod );
|
||||
}
|
||||
|
||||
ImGui.Indent( 15 );
|
||||
foreach( var file in files )
|
||||
{
|
||||
ImGui.Selectable( file );
|
||||
}
|
||||
|
||||
ImGui.Unindent( 15 );
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.ListBoxFooter();
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndTabBar();
|
||||
ImGui.EndChild();
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
PluginLog.LogError( ex, "fuck" );
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
|
||||
void SelectModByName( string name )
|
||||
{
|
||||
for( var modIndex = 0; modIndex < _plugin.ModManager.Mods.ModSettings.Count; modIndex++ )
|
||||
{
|
||||
var mod = _plugin.ModManager.Mods.ModSettings[ modIndex ];
|
||||
|
||||
if( mod.Mod.Meta.Name != name )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_selectedMod = mod;
|
||||
_selectedModIndex = modIndex;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawEffectiveFileList()
|
||||
{
|
||||
var ret = ImGui.BeginTabItem( "Effective File List" );
|
||||
if( !ret )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( ImGui.ListBoxHeader( "##", AutoFillSize ) )
|
||||
{
|
||||
// todo: virtualise this
|
||||
foreach( var file in _plugin.ModManager.ResolvedFiles )
|
||||
{
|
||||
ImGui.Selectable( file.Value.FullName + " -> " + file.Key );
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.ListBoxFooter();
|
||||
|
||||
ImGui.EndTabItem();
|
||||
_menuBar.Draw();
|
||||
_launchButton.Draw();
|
||||
_menu.Draw();
|
||||
}
|
||||
|
||||
private void ReloadMods()
|
||||
{
|
||||
_selectedMod = null;
|
||||
|
||||
{
|
||||
_menu._installedTab._selector.ClearSelection();
|
||||
// create the directory if it doesn't exist
|
||||
Directory.CreateDirectory( _plugin.Configuration.CurrentCollection );
|
||||
|
||||
_plugin.ModManager.DiscoverMods( _plugin.Configuration.CurrentCollection );
|
||||
|
||||
// May select a different mod than before if mods were added or deleted, but will not crash.
|
||||
if( _selectedModIndex < _plugin.ModManager.Mods.ModSettings.Count )
|
||||
{
|
||||
_selectedMod = _plugin.ModManager.Mods.ModSettings[ _selectedModIndex ];
|
||||
}
|
||||
else
|
||||
{
|
||||
_selectedModIndex = 0;
|
||||
_selectedMod = null;
|
||||
}
|
||||
}
|
||||
_menu._effectiveTab.RebuildFileList(_plugin.Configuration.ShowAdvanced);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue