mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
mod reordering, deleting, conflict resolution, some other fixes
This commit is contained in:
parent
fbb39a8626
commit
7f1fd95a78
10 changed files with 605 additions and 203 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
using Dalamud.Configuration;
|
using Dalamud.Configuration;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Penumbra
|
namespace Penumbra
|
||||||
{
|
{
|
||||||
|
|
@ -11,7 +12,9 @@ namespace Penumbra
|
||||||
|
|
||||||
public bool IsEnabled { get; set; } = true;
|
public bool IsEnabled { get; set; } = true;
|
||||||
|
|
||||||
public string BaseFolder { get; set; } = @"D:/ffxiv/fs_mods/";
|
public string CurrentCollection { get; set; } = @"D:/ffxiv/fs_mods/";
|
||||||
|
|
||||||
|
public List< string > ModCollections { get; set; } = new();
|
||||||
|
|
||||||
// the below exist just to make saving less cumbersome
|
// the below exist just to make saving less cumbersome
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,100 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using Dalamud.Plugin;
|
|
||||||
using Penumbra.Models;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Penumbra
|
|
||||||
{
|
|
||||||
public class ModManager
|
|
||||||
{
|
|
||||||
public DirectoryInfo BasePath { get; set; }
|
|
||||||
|
|
||||||
public readonly Dictionary< string, ResourceMod > AvailableMods = new Dictionary< string, ResourceMod >();
|
|
||||||
|
|
||||||
public readonly Dictionary< string, FileInfo > ResolvedFiles = new Dictionary< string, FileInfo >();
|
|
||||||
|
|
||||||
public ModManager( DirectoryInfo basePath )
|
|
||||||
{
|
|
||||||
BasePath = basePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModManager()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DiscoverMods()
|
|
||||||
{
|
|
||||||
if( BasePath == null )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !BasePath.Exists )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AvailableMods.Clear();
|
|
||||||
ResolvedFiles.Clear();
|
|
||||||
|
|
||||||
// get all mod dirs
|
|
||||||
foreach( var modDir in BasePath.EnumerateDirectories() )
|
|
||||||
{
|
|
||||||
var metaFile = modDir.EnumerateFiles().FirstOrDefault( f => f.Name == "meta.json" );
|
|
||||||
|
|
||||||
if( metaFile == null )
|
|
||||||
{
|
|
||||||
PluginLog.LogError( "mod meta is missing for resource mod: {ResourceModLocation}", modDir );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var meta = JsonConvert.DeserializeObject< Models.ModMeta >( File.ReadAllText( metaFile.FullName ) );
|
|
||||||
|
|
||||||
var mod = new ResourceMod
|
|
||||||
{
|
|
||||||
Meta = meta,
|
|
||||||
ModBasePath = modDir
|
|
||||||
};
|
|
||||||
|
|
||||||
AvailableMods[ modDir.Name ] = mod;
|
|
||||||
mod.RefreshModFiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: sort the mods by priority here so that the file discovery works correctly
|
|
||||||
|
|
||||||
foreach( var mod in AvailableMods.Select( m => m.Value ) )
|
|
||||||
{
|
|
||||||
// fixup path
|
|
||||||
var baseDir = mod.ModBasePath.FullName;
|
|
||||||
|
|
||||||
foreach( var file in mod.ModFiles )
|
|
||||||
{
|
|
||||||
var path = file.FullName.Substring( baseDir.Length ).ToLowerInvariant()
|
|
||||||
.TrimStart( '\\' ).Replace( '\\', '/' );
|
|
||||||
|
|
||||||
// todo: notify when collisions happen? or some extra state on the file? not sure yet
|
|
||||||
// this code is shit all the same
|
|
||||||
|
|
||||||
if( !ResolvedFiles.ContainsKey( path ) )
|
|
||||||
{
|
|
||||||
ResolvedFiles[ path ] = file;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PluginLog.LogError(
|
|
||||||
"a different mod already fucks this file: {FilePath}",
|
|
||||||
ResolvedFiles[ path ].FullName
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileInfo GetCandidateForGameFile( string resourcePath )
|
|
||||||
{
|
|
||||||
return ResolvedFiles.TryGetValue( resourcePath.ToLowerInvariant(), out var fileInfo ) ? fileInfo : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
15
Penumbra/Models/ModInfo.cs
Normal file
15
Penumbra/Models/ModInfo.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Penumbra.Mods;
|
||||||
|
|
||||||
|
namespace Penumbra.Models
|
||||||
|
{
|
||||||
|
public class ModInfo
|
||||||
|
{
|
||||||
|
public string FolderName { get; set; }
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
public int Priority { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public ResourceMod Mod { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
182
Penumbra/Mods/ModCollection.cs
Normal file
182
Penumbra/Mods/ModCollection.cs
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using Dalamud.Plugin;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Penumbra.Models;
|
||||||
|
|
||||||
|
namespace Penumbra.Mods
|
||||||
|
{
|
||||||
|
public class ModCollection
|
||||||
|
{
|
||||||
|
private readonly DirectoryInfo _basePath;
|
||||||
|
|
||||||
|
public List< ModInfo > ModSettings { get; set; }
|
||||||
|
public ResourceMod[] EnabledMods { get; set; }
|
||||||
|
|
||||||
|
public ModCollection( DirectoryInfo basePath )
|
||||||
|
{
|
||||||
|
_basePath = basePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Load()
|
||||||
|
{
|
||||||
|
// find the collection json
|
||||||
|
var collectionPath = Path.Combine( _basePath.FullName, "collection.json" );
|
||||||
|
if( File.Exists( collectionPath ) )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ModSettings = JsonConvert.DeserializeObject< List< ModInfo > >( File.ReadAllText( collectionPath ) );
|
||||||
|
ModSettings = ModSettings.OrderBy( x => x.Priority ).ToList();
|
||||||
|
}
|
||||||
|
catch( Exception e )
|
||||||
|
{
|
||||||
|
PluginLog.Error( $"failed to read log collection information, failed path: {collectionPath}, err: {e.Message}" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if( ModSettings != null )
|
||||||
|
{
|
||||||
|
foreach( var ms in ModSettings )
|
||||||
|
{
|
||||||
|
PluginLog.Information(
|
||||||
|
"mod: {ModName} Enabled: {Enabled} Priority: {Priority}",
|
||||||
|
ms.FolderName, ms.Enabled, ms.Priority
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ModSettings ??= new();
|
||||||
|
var foundMods = new List< string >();
|
||||||
|
|
||||||
|
foreach( var modDir in _basePath.EnumerateDirectories() )
|
||||||
|
{
|
||||||
|
var metaFile = modDir.EnumerateFiles().FirstOrDefault( f => f.Name == "meta.json" );
|
||||||
|
|
||||||
|
if( metaFile == null )
|
||||||
|
{
|
||||||
|
PluginLog.LogError( "mod meta is missing for resource mod: {ResourceModLocation}", modDir );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var meta = JsonConvert.DeserializeObject< ModMeta >( File.ReadAllText( metaFile.FullName ) );
|
||||||
|
|
||||||
|
var mod = new ResourceMod
|
||||||
|
{
|
||||||
|
Meta = meta,
|
||||||
|
ModBasePath = modDir
|
||||||
|
};
|
||||||
|
|
||||||
|
var modEntry = FindOrCreateModSettings( mod );
|
||||||
|
foundMods.Add( modDir.Name );
|
||||||
|
mod.RefreshModFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove any mods from the collection we didn't find
|
||||||
|
ModSettings = ModSettings.Where(
|
||||||
|
x =>
|
||||||
|
foundMods.Any(
|
||||||
|
fm => string.Equals( x.FolderName, fm, StringComparison.InvariantCultureIgnoreCase )
|
||||||
|
)
|
||||||
|
).ToList();
|
||||||
|
|
||||||
|
// reorder the resourcemods list so we can just directly iterate
|
||||||
|
EnabledMods = GetOrderedAndEnabledModList().ToArray();
|
||||||
|
|
||||||
|
// write the collection metadata back to disk
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
var collectionPath = Path.Combine( _basePath.FullName, "collection.json" );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var data = JsonConvert.SerializeObject( ModSettings.OrderBy( x => x.Priority ).ToList() );
|
||||||
|
File.WriteAllText( collectionPath, data );
|
||||||
|
}
|
||||||
|
catch( Exception e )
|
||||||
|
{
|
||||||
|
PluginLog.Error( $"failed to write log collection information, failed path: {collectionPath}, err: {e.Message}" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReorderMod( ModInfo info, bool up )
|
||||||
|
{
|
||||||
|
// todo: certified fucked tier
|
||||||
|
|
||||||
|
var prio = info.Priority;
|
||||||
|
var swapPrio = up ? prio + 1 : prio - 1;
|
||||||
|
var swapMeta = ModSettings.FirstOrDefault( x => x.Priority == swapPrio );
|
||||||
|
|
||||||
|
if( swapMeta == null )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.Priority = swapPrio;
|
||||||
|
swapMeta.Priority = prio;
|
||||||
|
|
||||||
|
// reorder mods list
|
||||||
|
ModSettings = ModSettings.OrderBy( x => x.Priority ).ToList();
|
||||||
|
EnabledMods = GetOrderedAndEnabledModList().ToArray();
|
||||||
|
|
||||||
|
// save new prios
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModInfo FindModSettings( string name )
|
||||||
|
{
|
||||||
|
var settings = ModSettings.FirstOrDefault(
|
||||||
|
x => string.Equals( x.FolderName, name, StringComparison.InvariantCultureIgnoreCase )
|
||||||
|
);
|
||||||
|
#if DEBUG
|
||||||
|
PluginLog.Information( "finding mod {ModName} - found: {ModSettingsExist}", name, settings != null );
|
||||||
|
#endif
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModInfo AddModSettings( ResourceMod mod )
|
||||||
|
{
|
||||||
|
var entry = new ModInfo
|
||||||
|
{
|
||||||
|
Priority = ModSettings.Count,
|
||||||
|
FolderName = mod.ModBasePath.Name,
|
||||||
|
Enabled = true,
|
||||||
|
Mod = mod
|
||||||
|
};
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
PluginLog.Information( "creating mod settings {ModName}", entry.FolderName );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ModSettings.Add( entry );
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModInfo FindOrCreateModSettings( ResourceMod mod )
|
||||||
|
{
|
||||||
|
var settings = FindModSettings( mod.ModBasePath.Name );
|
||||||
|
if( settings != null )
|
||||||
|
{
|
||||||
|
settings.Mod = mod;
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AddModSettings( mod );
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable< ResourceMod > GetOrderedAndEnabledModList()
|
||||||
|
{
|
||||||
|
return ModSettings
|
||||||
|
.Where( x => x.Enabled )
|
||||||
|
.OrderBy( x => x.Priority )
|
||||||
|
.Select( x => x.Mod );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
104
Penumbra/Mods/ModManager.cs
Normal file
104
Penumbra/Mods/ModManager.cs
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Penumbra.Models;
|
||||||
|
|
||||||
|
namespace Penumbra.Mods
|
||||||
|
{
|
||||||
|
public class ModManager
|
||||||
|
{
|
||||||
|
public readonly Dictionary< string, FileInfo > ResolvedFiles = new();
|
||||||
|
|
||||||
|
public ModCollection Mods { get; set; }
|
||||||
|
|
||||||
|
public ResourceMod[] AvailableMods => Mods?.EnabledMods;
|
||||||
|
|
||||||
|
private DirectoryInfo _basePath;
|
||||||
|
|
||||||
|
public void DiscoverMods()
|
||||||
|
{
|
||||||
|
if( _basePath == null )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DiscoverMods( _basePath );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DiscoverMods( string basePath )
|
||||||
|
{
|
||||||
|
DiscoverMods( new DirectoryInfo( basePath ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DiscoverMods( DirectoryInfo basePath )
|
||||||
|
{
|
||||||
|
if( basePath == null )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !basePath.Exists )
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory( basePath.FullName );
|
||||||
|
}
|
||||||
|
|
||||||
|
_basePath = basePath;
|
||||||
|
|
||||||
|
ResolvedFiles.Clear();
|
||||||
|
|
||||||
|
Mods = new ModCollection( basePath );
|
||||||
|
Mods.Load();
|
||||||
|
Mods.Save();
|
||||||
|
|
||||||
|
CalculateEffectiveFileList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CalculateEffectiveFileList()
|
||||||
|
{
|
||||||
|
ResolvedFiles.Clear();
|
||||||
|
|
||||||
|
var registeredFiles = new Dictionary< string, string >();
|
||||||
|
|
||||||
|
foreach( var mod in Mods.GetOrderedAndEnabledModList() )
|
||||||
|
{
|
||||||
|
mod.FileConflicts?.Clear();
|
||||||
|
|
||||||
|
// fixup path
|
||||||
|
var baseDir = mod.ModBasePath.FullName;
|
||||||
|
|
||||||
|
foreach( var file in mod.ModFiles )
|
||||||
|
{
|
||||||
|
var path = file.FullName.Substring( baseDir.Length )
|
||||||
|
.TrimStart( '\\' ).Replace( '\\', '/' );
|
||||||
|
|
||||||
|
if( !ResolvedFiles.ContainsKey( path ) )
|
||||||
|
{
|
||||||
|
ResolvedFiles[ path ] = file;
|
||||||
|
registeredFiles[ path ] = mod.Meta.Name;
|
||||||
|
}
|
||||||
|
else if( registeredFiles.TryGetValue( path, out var modName ) )
|
||||||
|
{
|
||||||
|
mod.AddConflict( modName, path );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ChangeModPriority( ModInfo info, bool up = false )
|
||||||
|
{
|
||||||
|
Mods.ReorderMod( info, up );
|
||||||
|
CalculateEffectiveFileList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteMod( ResourceMod mod )
|
||||||
|
{
|
||||||
|
Directory.Delete( mod.ModBasePath.FullName, true );
|
||||||
|
DiscoverMods();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public FileInfo GetCandidateForGameFile( string resourcePath )
|
||||||
|
{
|
||||||
|
return ResolvedFiles.TryGetValue( resourcePath.ToLowerInvariant(), out var fileInfo ) ? fileInfo : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using Penumbra.Models;
|
using Penumbra.Models;
|
||||||
|
|
||||||
namespace Penumbra
|
namespace Penumbra.Mods
|
||||||
{
|
{
|
||||||
public class ResourceMod
|
public class ResourceMod
|
||||||
{
|
{
|
||||||
|
|
@ -12,7 +11,9 @@ namespace Penumbra
|
||||||
|
|
||||||
public DirectoryInfo ModBasePath { get; set; }
|
public DirectoryInfo ModBasePath { get; set; }
|
||||||
|
|
||||||
public List< FileInfo > ModFiles { get; } = new List< FileInfo >();
|
public List< FileInfo > ModFiles { get; } = new();
|
||||||
|
|
||||||
|
public Dictionary< string, List< string > > FileConflicts { get; set; } = new();
|
||||||
|
|
||||||
public void RefreshModFiles()
|
public void RefreshModFiles()
|
||||||
{
|
{
|
||||||
|
|
@ -31,5 +32,23 @@ namespace Penumbra
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddConflict( string modName, string path )
|
||||||
|
{
|
||||||
|
if( FileConflicts.TryGetValue( modName, out var arr ) )
|
||||||
|
{
|
||||||
|
if( !arr.Contains( path ) )
|
||||||
|
{
|
||||||
|
arr.Add( path );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileConflicts[ modName ] = new List< string >
|
||||||
|
{
|
||||||
|
path
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,56 +1,63 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net472</TargetFramework>
|
<TargetFramework>net472</TargetFramework>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<AssemblyTitle>Penumbra</AssemblyTitle>
|
<AssemblyTitle>Penumbra</AssemblyTitle>
|
||||||
<Company>absolute gangstas</Company>
|
<Company>absolute gangstas</Company>
|
||||||
<Product>Penumbra</Product>
|
<Product>Penumbra</Product>
|
||||||
<Copyright>Copyright © 2020</Copyright>
|
<Copyright>Copyright © 2020</Copyright>
|
||||||
<FileVersion>1.0.0.0</FileVersion>
|
<FileVersion>1.0.0.0</FileVersion>
|
||||||
<AssemblyVersion>1.0.0.0</AssemblyVersion>
|
<AssemblyVersion>1.0.0.0</AssemblyVersion>
|
||||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<DebugType>full</DebugType>
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DebugType>full</DebugType>
|
||||||
</PropertyGroup>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
</PropertyGroup>
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
</PropertyGroup>
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<ItemGroup>
|
<DebugType>pdbonly</DebugType>
|
||||||
<Reference Include="Dalamud">
|
</PropertyGroup>
|
||||||
<HintPath>..\libs\Dalamud.dll</HintPath>
|
|
||||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\Dalamud.dll</HintPath>
|
<ItemGroup>
|
||||||
<HintPath>$(DALAMUD_ROOT)\Dalamud.dll</HintPath>
|
<Reference Include="Dalamud">
|
||||||
<Private>False</Private>
|
<HintPath>..\libs\Dalamud.dll</HintPath>
|
||||||
</Reference>
|
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\Dalamud.dll</HintPath>
|
||||||
<Reference Include="ImGui.NET">
|
<HintPath>$(DALAMUD_ROOT)\Dalamud.dll</HintPath>
|
||||||
<HintPath>..\libs\ImGui.NET.dll</HintPath>
|
<Private>False</Private>
|
||||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\ImGui.NET.dll</HintPath>
|
</Reference>
|
||||||
<HintPath>$(DALAMUD_ROOT)\ImGui.NET.dll</HintPath>
|
<Reference Include="ImGui.NET">
|
||||||
<Private>False</Private>
|
<HintPath>..\libs\ImGui.NET.dll</HintPath>
|
||||||
</Reference>
|
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\ImGui.NET.dll</HintPath>
|
||||||
<Reference Include="ImGuiScene">
|
<HintPath>$(DALAMUD_ROOT)\ImGui.NET.dll</HintPath>
|
||||||
<HintPath>..\libs\ImGuiScene.dll</HintPath>
|
<Private>False</Private>
|
||||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\ImGuiScene.dll</HintPath>
|
</Reference>
|
||||||
<HintPath>$(DALAMUD_ROOT)\ImGuiScene.dll</HintPath>
|
<Reference Include="ImGuiScene">
|
||||||
<Private>False</Private>
|
<HintPath>..\libs\ImGuiScene.dll</HintPath>
|
||||||
</Reference>
|
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\ImGuiScene.dll</HintPath>
|
||||||
<Reference Include="Lumina">
|
<HintPath>$(DALAMUD_ROOT)\ImGuiScene.dll</HintPath>
|
||||||
<HintPath>..\libs\Lumina.dll</HintPath>
|
<Private>False</Private>
|
||||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\Lumina.dll</HintPath>
|
</Reference>
|
||||||
<HintPath>$(DALAMUD_ROOT)\Lumina.dll</HintPath>
|
<Reference Include="Lumina">
|
||||||
<Private>False</Private>
|
<HintPath>..\libs\Lumina.dll</HintPath>
|
||||||
</Reference>
|
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\Lumina.dll</HintPath>
|
||||||
<Reference Include="System.Windows.Forms" />
|
<HintPath>$(DALAMUD_ROOT)\Lumina.dll</HintPath>
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Private>False</Private>
|
||||||
<Reference Include="Microsoft.CSharp" />
|
</Reference>
|
||||||
<Reference Include="System.Net.Http" />
|
</ItemGroup>
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DotNetZip" Version="1.13.8" />
|
<Reference Include="System.Windows.Forms" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
<PackageReference Include="Reloaded.Hooks" Version="2.4.1" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
</ItemGroup>
|
<Reference Include="System.Net.Http" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="DotNetZip" Version="1.13.8" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
|
<PackageReference Include="Reloaded.Hooks" Version="2.4.1" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -1,6 +1,13 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using Dalamud.Game.Command;
|
using Dalamud.Game.Command;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
|
using Penumbra.Extensions;
|
||||||
|
using Penumbra.Mods;
|
||||||
|
using Penumbra.UI;
|
||||||
|
|
||||||
namespace Penumbra
|
namespace Penumbra
|
||||||
{
|
{
|
||||||
|
|
@ -19,6 +26,8 @@ namespace Penumbra
|
||||||
|
|
||||||
public SettingsInterface SettingsInterface { get; set; }
|
public SettingsInterface SettingsInterface { get; set; }
|
||||||
|
|
||||||
|
public string PluginDebugTitleStr { get; private set; }
|
||||||
|
|
||||||
public void Initialize( DalamudPluginInterface pluginInterface )
|
public void Initialize( DalamudPluginInterface pluginInterface )
|
||||||
{
|
{
|
||||||
PluginInterface = pluginInterface;
|
PluginInterface = pluginInterface;
|
||||||
|
|
@ -26,8 +35,8 @@ namespace Penumbra
|
||||||
Configuration = PluginInterface.GetPluginConfig() as Configuration ?? new Configuration();
|
Configuration = PluginInterface.GetPluginConfig() as Configuration ?? new Configuration();
|
||||||
Configuration.Initialize( PluginInterface );
|
Configuration.Initialize( PluginInterface );
|
||||||
|
|
||||||
ModManager = new ModManager( new DirectoryInfo( Configuration.BaseFolder ) );
|
ModManager = new ModManager();
|
||||||
ModManager.DiscoverMods();
|
ModManager.DiscoverMods( Configuration.CurrentCollection );
|
||||||
|
|
||||||
ResourceLoader = new ResourceLoader( this );
|
ResourceLoader = new ResourceLoader( this );
|
||||||
|
|
||||||
|
|
@ -39,9 +48,11 @@ namespace Penumbra
|
||||||
|
|
||||||
ResourceLoader.Init();
|
ResourceLoader.Init();
|
||||||
ResourceLoader.Enable();
|
ResourceLoader.Enable();
|
||||||
|
|
||||||
SettingsInterface = new SettingsInterface( this );
|
SettingsInterface = new SettingsInterface( this );
|
||||||
PluginInterface.UiBuilder.OnBuildUi += SettingsInterface.Draw;
|
PluginInterface.UiBuilder.OnBuildUi += SettingsInterface.Draw;
|
||||||
|
|
||||||
|
PluginDebugTitleStr = $"{Name} - Debug Build";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
{
|
{
|
||||||
LoadUnpackedResource = 0,
|
LoadUnpackedResource = 0,
|
||||||
LoadFileResource = 1, // Shit in My Games uses this
|
LoadFileResource = 1, // Shit in My Games uses this
|
||||||
LoadSqpackResource = 0x0B
|
// some shit here, the game does some jump if its < 0xA for other files for some reason but there's no impl, probs debug?
|
||||||
|
LoadIndexResource = 0xA, // load index/index2
|
||||||
|
LoadSqPackResource = 0xB
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,15 +3,15 @@ using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.Remoting.Messaging;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using Penumbra.Importer;
|
using Penumbra.Importer;
|
||||||
|
using Penumbra.Models;
|
||||||
|
|
||||||
namespace Penumbra
|
namespace Penumbra.UI
|
||||||
{
|
{
|
||||||
public class SettingsInterface
|
public class SettingsInterface
|
||||||
{
|
{
|
||||||
|
|
@ -22,11 +22,14 @@ namespace Penumbra
|
||||||
private static readonly Vector2 AutoFillSize = new Vector2( -1, -1 );
|
private static readonly Vector2 AutoFillSize = new Vector2( -1, -1 );
|
||||||
private static readonly Vector2 ModListSize = new Vector2( 200, -1 );
|
private static readonly Vector2 ModListSize = new Vector2( 200, -1 );
|
||||||
|
|
||||||
private static readonly Vector2 MinSettingsSize = new Vector2( 650, 450 );
|
private static readonly Vector2 MinSettingsSize = new Vector2( 800, 450 );
|
||||||
private static readonly Vector2 MaxSettingsSize = new Vector2( 69420, 42069 );
|
private static readonly Vector2 MaxSettingsSize = new Vector2( 69420, 42069 );
|
||||||
|
|
||||||
|
private const string DialogDeleteMod = "PenumbraDeleteMod";
|
||||||
|
|
||||||
private int _selectedModIndex;
|
private int _selectedModIndex;
|
||||||
private ResourceMod _selectedMod;
|
private int? _selectedModDeleteIndex;
|
||||||
|
private ModInfo _selectedMod;
|
||||||
|
|
||||||
private bool _isImportRunning = false;
|
private bool _isImportRunning = false;
|
||||||
|
|
||||||
|
|
@ -38,7 +41,11 @@ namespace Penumbra
|
||||||
public void Draw()
|
public void Draw()
|
||||||
{
|
{
|
||||||
ImGui.SetNextWindowSizeConstraints( MinSettingsSize, MaxSettingsSize );
|
ImGui.SetNextWindowSizeConstraints( MinSettingsSize, MaxSettingsSize );
|
||||||
|
#if DEBUG
|
||||||
|
var ret = ImGui.Begin( _plugin.PluginDebugTitleStr );
|
||||||
|
#else
|
||||||
var ret = ImGui.Begin( _plugin.Name );
|
var ret = ImGui.Begin( _plugin.Name );
|
||||||
|
#endif
|
||||||
if( !ret )
|
if( !ret )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
@ -50,6 +57,8 @@ namespace Penumbra
|
||||||
DrawResourceMods();
|
DrawResourceMods();
|
||||||
DrawEffectiveFileList();
|
DrawEffectiveFileList();
|
||||||
|
|
||||||
|
DrawDeleteModal();
|
||||||
|
|
||||||
ImGui.EndTabBar();
|
ImGui.EndTabBar();
|
||||||
|
|
||||||
ImGui.End();
|
ImGui.End();
|
||||||
|
|
@ -64,17 +73,17 @@ namespace Penumbra
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUCKKKKK
|
// FUCKKKKK
|
||||||
var basePath = _plugin.Configuration.BaseFolder;
|
var basePath = _plugin.Configuration.CurrentCollection;
|
||||||
if( ImGui.InputText( "Root Folder", ref basePath, 255 ) )
|
if( ImGui.InputText( "Root Folder", ref basePath, 255 ) )
|
||||||
{
|
{
|
||||||
_plugin.Configuration.BaseFolder = basePath;
|
_plugin.Configuration.CurrentCollection = basePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ImGui.Button( "Rediscover Mods" ) )
|
if( ImGui.Button( "Rediscover Mods" ) )
|
||||||
{
|
{
|
||||||
ReloadMods();
|
ReloadMods();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ImGui.Button( "Reload Player Resource" ) )
|
if( ImGui.Button( "Reload Player Resource" ) )
|
||||||
{
|
{
|
||||||
_plugin.ResourceLoader.ReloadPlayerResource();
|
_plugin.ResourceLoader.ReloadPlayerResource();
|
||||||
|
|
@ -103,7 +112,7 @@ namespace Penumbra
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var importer =
|
var importer =
|
||||||
new TexToolsImport( new DirectoryInfo( _plugin.Configuration.BaseFolder ) );
|
new TexToolsImport( new DirectoryInfo( _plugin.Configuration.CurrentCollection ) );
|
||||||
|
|
||||||
foreach( var fileName in picker.FileNames )
|
foreach( var fileName in picker.FileNames )
|
||||||
{
|
{
|
||||||
|
|
@ -135,7 +144,7 @@ namespace Penumbra
|
||||||
{
|
{
|
||||||
_plugin.Configuration.Save();
|
_plugin.Configuration.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( _plugin.ResourceLoader != null )
|
if( _plugin.ResourceLoader != null )
|
||||||
{
|
{
|
||||||
ImGui.Checkbox( "DEBUG Log all loaded files", ref _plugin.ResourceLoader.LogAllFiles );
|
ImGui.Checkbox( "DEBUG Log all loaded files", ref _plugin.ResourceLoader.LogAllFiles );
|
||||||
|
|
@ -151,16 +160,45 @@ namespace Penumbra
|
||||||
ImGui.PushStyleVar( ImGuiStyleVar.ItemSpacing, new Vector2( 0, 0 ) );
|
ImGui.PushStyleVar( ImGuiStyleVar.ItemSpacing, new Vector2( 0, 0 ) );
|
||||||
|
|
||||||
// Inlay selector list
|
// Inlay selector list
|
||||||
ImGui.BeginChild( "availableModList", new Vector2( 180, -ImGui.GetFrameHeightWithSpacing() ), true );
|
ImGui.BeginChild( "availableModList", new Vector2( 240, -ImGui.GetFrameHeightWithSpacing() ), true );
|
||||||
|
|
||||||
for( var modIndex = 0; modIndex < _plugin.ModManager.AvailableMods.Count; modIndex++ )
|
if( _plugin.ModManager.Mods != null )
|
||||||
{
|
{
|
||||||
var mod = _plugin.ModManager.AvailableMods.ElementAt( modIndex );
|
for( var modIndex = 0; modIndex < _plugin.ModManager.Mods.ModSettings.Count; modIndex++ )
|
||||||
|
|
||||||
if( ImGui.Selectable( mod.Value.Meta.Name, modIndex == _selectedModIndex ) )
|
|
||||||
{
|
{
|
||||||
_selectedModIndex = modIndex;
|
var settings = _plugin.ModManager.Mods.ModSettings[ modIndex ];
|
||||||
_selectedMod = mod.Value;
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,14 +210,16 @@ namespace Penumbra
|
||||||
ImGui.PushFont( UiBuilder.IconFont );
|
ImGui.PushFont( UiBuilder.IconFont );
|
||||||
if( _selectedModIndex != 0 )
|
if( _selectedModIndex != 0 )
|
||||||
{
|
{
|
||||||
if( ImGui.Button( FontAwesomeIcon.ArrowUp.ToIconString(), new Vector2( 45, 0 ) ) )
|
if( ImGui.Button( FontAwesomeIcon.ArrowUp.ToIconString(), new Vector2( 60, 0 ) ) )
|
||||||
{
|
{
|
||||||
|
_plugin.ModManager.ChangeModPriority( _selectedMod );
|
||||||
|
_selectedModIndex -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ImGui.PushStyleVar( ImGuiStyleVar.Alpha, 0.5f );
|
ImGui.PushStyleVar( ImGuiStyleVar.Alpha, 0.5f );
|
||||||
ImGui.Button( FontAwesomeIcon.ArrowUp.ToIconString(), new Vector2( 45, 0 ) );
|
ImGui.Button( FontAwesomeIcon.ArrowUp.ToIconString(), new Vector2( 60, 0 ) );
|
||||||
ImGui.PopStyleVar();
|
ImGui.PopStyleVar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -192,16 +232,18 @@ namespace Penumbra
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
|
|
||||||
if( _selectedModIndex != _plugin.ModManager.AvailableMods.Count - 1 )
|
if( _selectedModIndex != _plugin.ModManager.Mods?.ModSettings.Count - 1 )
|
||||||
{
|
{
|
||||||
if( ImGui.Button( FontAwesomeIcon.ArrowDown.ToIconString(), new Vector2( 45, 0 ) ) )
|
if( ImGui.Button( FontAwesomeIcon.ArrowDown.ToIconString(), new Vector2( 60, 0 ) ) )
|
||||||
{
|
{
|
||||||
|
_plugin.ModManager.ChangeModPriority( _selectedMod, true );
|
||||||
|
_selectedModIndex += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ImGui.PushStyleVar( ImGuiStyleVar.Alpha, 0.5f );
|
ImGui.PushStyleVar( ImGuiStyleVar.Alpha, 0.5f );
|
||||||
ImGui.Button( FontAwesomeIcon.ArrowDown.ToIconString(), new Vector2( 45, 0 ) );
|
ImGui.Button( FontAwesomeIcon.ArrowDown.ToIconString(), new Vector2( 60, 0 ) );
|
||||||
ImGui.PopStyleVar();
|
ImGui.PopStyleVar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -215,8 +257,9 @@ namespace Penumbra
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
|
|
||||||
if( ImGui.Button( FontAwesomeIcon.Trash.ToIconString(), new Vector2( 45, 0 ) ) )
|
if( ImGui.Button( FontAwesomeIcon.Trash.ToIconString(), new Vector2( 60, 0 ) ) )
|
||||||
{
|
{
|
||||||
|
_selectedModDeleteIndex = _selectedModIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.PopFont();
|
ImGui.PopFont();
|
||||||
|
|
@ -228,7 +271,7 @@ namespace Penumbra
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
|
|
||||||
if( ImGui.Button( FontAwesomeIcon.Plus.ToIconString(), new Vector2( 45, 0 ) ) )
|
if( ImGui.Button( FontAwesomeIcon.Plus.ToIconString(), new Vector2( 60, 0 ) ) )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -242,14 +285,67 @@ namespace Penumbra
|
||||||
ImGui.EndGroup();
|
ImGui.EndGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawResourceMods()
|
void DrawDeleteModal()
|
||||||
{
|
{
|
||||||
var ret = ImGui.BeginTabItem( "Resource Mods" );
|
if( _selectedModDeleteIndex != null )
|
||||||
|
ImGui.OpenPopup( DialogDeleteMod );
|
||||||
|
|
||||||
|
var ret = ImGui.BeginPopupModal( DialogDeleteMod );
|
||||||
if( !ret )
|
if( !ret )
|
||||||
{
|
{
|
||||||
return;
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawResourceMods()
|
||||||
|
{
|
||||||
|
var ret = ImGui.BeginTabItem( "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();
|
DrawModsSelector();
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
|
|
@ -260,29 +356,78 @@ namespace Penumbra
|
||||||
{
|
{
|
||||||
ImGui.BeginChild( "selectedModInfo", AutoFillSize, true );
|
ImGui.BeginChild( "selectedModInfo", AutoFillSize, true );
|
||||||
|
|
||||||
ImGui.Text( _selectedMod.Meta.Name );
|
ImGui.Text( _selectedMod.Mod.Meta.Name );
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.TextColored( new Vector4( 1f, 1f, 1f, 0.66f ), "by" );
|
ImGui.TextColored( new Vector4( 1f, 1f, 1f, 0.66f ), "by" );
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.Text( _selectedMod.Meta.Author );
|
ImGui.Text( _selectedMod.Mod.Meta.Author );
|
||||||
|
|
||||||
ImGui.TextWrapped( _selectedMod.Meta.Description ?? "" );
|
ImGui.TextWrapped( _selectedMod.Mod.Meta.Description ?? "" );
|
||||||
|
|
||||||
ImGui.SetCursorPosY( ImGui.GetCursorPosY() + 12 );
|
ImGui.SetCursorPosY( ImGui.GetCursorPosY() + 10 );
|
||||||
|
|
||||||
// list files
|
var enabled = _selectedMod.Enabled;
|
||||||
ImGui.Text( "Files:" );
|
if( ImGui.Checkbox( "Enabled", ref enabled ) )
|
||||||
ImGui.SetNextItemWidth( -1 );
|
|
||||||
if( ImGui.ListBoxHeader( "##", AutoFillSize ) )
|
|
||||||
{
|
{
|
||||||
foreach( var file in _selectedMod.ModFiles )
|
_selectedMod.Enabled = enabled;
|
||||||
|
_plugin.ModManager.Mods.Save();
|
||||||
|
_plugin.ModManager.CalculateEffectiveFileList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ImGui.Button( "Open Mod Folder" ) )
|
||||||
|
{
|
||||||
|
Process.Start( _selectedMod.Mod.ModBasePath.FullName );
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.BeginTabBar( "PenumbraPluginDetails" );
|
||||||
|
if( ImGui.BeginTabItem( "Files" ) )
|
||||||
|
{
|
||||||
|
ImGui.SetNextItemWidth( -1 );
|
||||||
|
if( ImGui.ListBoxHeader( "##", AutoFillSize ) )
|
||||||
{
|
{
|
||||||
ImGui.Selectable( file.FullName );
|
foreach( var file in _selectedMod.Mod.ModFiles )
|
||||||
|
{
|
||||||
|
ImGui.Selectable( file.FullName );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.ListBoxFooter();
|
ImGui.EndTabBar();
|
||||||
|
|
||||||
ImGui.EndChild();
|
ImGui.EndChild();
|
||||||
}
|
}
|
||||||
catch( Exception ex )
|
catch( Exception ex )
|
||||||
|
|
@ -294,6 +439,23 @@ namespace Penumbra
|
||||||
ImGui.EndTabItem();
|
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()
|
void DrawEffectiveFileList()
|
||||||
{
|
{
|
||||||
var ret = ImGui.BeginTabItem( "Effective File List" );
|
var ret = ImGui.BeginTabItem( "Effective File List" );
|
||||||
|
|
@ -319,10 +481,7 @@ namespace Penumbra
|
||||||
private void ReloadMods()
|
private void ReloadMods()
|
||||||
{
|
{
|
||||||
_selectedMod = null;
|
_selectedMod = null;
|
||||||
|
_plugin.ModManager.DiscoverMods( _plugin.Configuration.CurrentCollection );
|
||||||
// haha yikes
|
|
||||||
_plugin.ModManager = new ModManager( new DirectoryInfo( _plugin.Configuration.BaseFolder ) );
|
|
||||||
_plugin.ModManager.DiscoverMods();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue