mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
871 lines
No EOL
30 KiB
C#
871 lines
No EOL
30 KiB
C#
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 SettingsInterface( Plugin plugin )
|
|
{
|
|
_plugin = plugin;
|
|
#if DEBUG
|
|
Visible = true;
|
|
ShowDebugBar = true;
|
|
#endif
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
private void ReloadMods()
|
|
{
|
|
_selectedMod = null;
|
|
|
|
// 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;
|
|
}
|
|
}
|
|
}
|
|
} |