mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
All Linebreaks to LF.
This commit is contained in:
parent
82dff6be25
commit
de8930c574
32 changed files with 1356 additions and 1356 deletions
|
|
@ -1,4 +1,4 @@
|
|||
using Dalamud.Configuration;
|
||||
using Dalamud.Configuration;
|
||||
using Dalamud.Plugin;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
|
@ -13,7 +13,7 @@ namespace Penumbra
|
|||
public bool IsEnabled { get; set; } = true;
|
||||
|
||||
public bool ShowAdvanced { get; set; }
|
||||
|
||||
|
||||
public bool DisableFileSystemNotifications { get; set; }
|
||||
|
||||
public bool EnableHttpApi { get; set; }
|
||||
|
|
|
|||
|
|
@ -1,54 +1,54 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using Dalamud.Game.ClientState.Actors;
|
||||
using Dalamud.Game.ClientState.Actors.Types;
|
||||
using System.Runtime.InteropServices;
|
||||
using Dalamud.Game.ClientState.Actors;
|
||||
using Dalamud.Game.ClientState.Actors.Types;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Penumbra
|
||||
{
|
||||
public static class RefreshActors
|
||||
{
|
||||
private const int RenderModeOffset = 0x0104;
|
||||
private const int RenderTaskPlayerDelay = 75;
|
||||
private const int RenderTaskOtherDelay = 25;
|
||||
private const int ModelInvisibilityFlag = 0b10;
|
||||
|
||||
private static async void Redraw(Actor actor)
|
||||
{
|
||||
var ptr = actor.Address;
|
||||
var renderModePtr = ptr + RenderModeOffset;
|
||||
var renderStatus = Marshal.ReadInt32(renderModePtr);
|
||||
|
||||
async void DrawObject(int delay)
|
||||
{
|
||||
Marshal.WriteInt32(renderModePtr, renderStatus | ModelInvisibilityFlag);
|
||||
await Task.Delay(delay);
|
||||
Marshal.WriteInt32(renderModePtr, renderStatus & ~ModelInvisibilityFlag);
|
||||
}
|
||||
|
||||
if (actor.ObjectKind == Dalamud.Game.ClientState.Actors.ObjectKind.Player)
|
||||
{
|
||||
DrawObject(RenderTaskPlayerDelay);
|
||||
await Task.Delay(RenderTaskPlayerDelay);
|
||||
}
|
||||
else
|
||||
DrawObject(RenderTaskOtherDelay);
|
||||
|
||||
}
|
||||
|
||||
public static void RedrawSpecific(ActorTable actors, string name)
|
||||
{
|
||||
if (name?.Length == 0)
|
||||
RedrawAll(actors);
|
||||
|
||||
foreach (var actor in actors)
|
||||
if (actor.Name == name)
|
||||
Redraw(actor);
|
||||
}
|
||||
|
||||
public static void RedrawAll(ActorTable actors)
|
||||
{
|
||||
foreach (var actor in actors)
|
||||
Redraw(actor);
|
||||
}
|
||||
public static class RefreshActors
|
||||
{
|
||||
private const int RenderModeOffset = 0x0104;
|
||||
private const int RenderTaskPlayerDelay = 75;
|
||||
private const int RenderTaskOtherDelay = 25;
|
||||
private const int ModelInvisibilityFlag = 0b10;
|
||||
|
||||
private static async void Redraw(Actor actor)
|
||||
{
|
||||
var ptr = actor.Address;
|
||||
var renderModePtr = ptr + RenderModeOffset;
|
||||
var renderStatus = Marshal.ReadInt32(renderModePtr);
|
||||
|
||||
async void DrawObject(int delay)
|
||||
{
|
||||
Marshal.WriteInt32(renderModePtr, renderStatus | ModelInvisibilityFlag);
|
||||
await Task.Delay(delay);
|
||||
Marshal.WriteInt32(renderModePtr, renderStatus & ~ModelInvisibilityFlag);
|
||||
}
|
||||
|
||||
if (actor.ObjectKind == Dalamud.Game.ClientState.Actors.ObjectKind.Player)
|
||||
{
|
||||
DrawObject(RenderTaskPlayerDelay);
|
||||
await Task.Delay(RenderTaskPlayerDelay);
|
||||
}
|
||||
else
|
||||
DrawObject(RenderTaskOtherDelay);
|
||||
|
||||
}
|
||||
|
||||
public static void RedrawSpecific(ActorTable actors, string name)
|
||||
{
|
||||
if (name?.Length == 0)
|
||||
RedrawAll(actors);
|
||||
|
||||
foreach (var actor in actors)
|
||||
if (actor.Name == name)
|
||||
Redraw(actor);
|
||||
}
|
||||
|
||||
public static void RedrawAll(ActorTable actors)
|
||||
{
|
||||
foreach (var actor in actors)
|
||||
Redraw(actor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,9 +55,9 @@ namespace Penumbra.Importer
|
|||
case ".ttmp":
|
||||
case ".ttmp2":
|
||||
VerifyVersionAndImport(modPackFile);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException( $"Unrecognized modpack format: {modPackFile.Extension}", nameof(modPackFile) );
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ namespace Penumbra.Importer
|
|||
ImportV2ModPack(modPackFile, extractedModPack, modRaw);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
if (modPackFile.Extension != ".ttmp")
|
||||
PluginLog.Warning($"File {modPackFile.FullName} seems to be a V1 TTMP, but has the wrong extension.");
|
||||
ImportV1ModPack(modPackFile, extractedModPack, modRaw);
|
||||
|
|
@ -223,11 +223,11 @@ namespace Penumbra.Importer
|
|||
// Iterate through all pages
|
||||
foreach( var page in modList.ModPackPages)
|
||||
{
|
||||
foreach(var group in page.ModGroups)
|
||||
{
|
||||
foreach(var group in page.ModGroups)
|
||||
{
|
||||
var groupFolder = new DirectoryInfo(Path.Combine(newModFolder.FullName, group.GroupName.ReplaceInvalidPathSymbols()));
|
||||
foreach(var option in group.OptionList)
|
||||
{
|
||||
foreach(var option in group.OptionList)
|
||||
{
|
||||
var optionFolder = new DirectoryInfo( Path.Combine( groupFolder.FullName, option.Name.ReplaceInvalidPathSymbols()) );
|
||||
ExtractSimpleModList( optionFolder, option.ModsJsons, modData );
|
||||
}
|
||||
|
|
@ -249,7 +249,7 @@ namespace Penumbra.Importer
|
|||
GroupName = group.GroupName,
|
||||
Options = new List<Option>(),
|
||||
};
|
||||
foreach( var opt in group.OptionList )
|
||||
foreach( var opt in group.OptionList )
|
||||
{
|
||||
var optio = new Option
|
||||
{
|
||||
|
|
@ -258,13 +258,13 @@ namespace Penumbra.Importer
|
|||
OptionFiles = new Dictionary<string, HashSet<string>>()
|
||||
};
|
||||
var optDir = new DirectoryInfo(Path.Combine( groupFolder.FullName, opt.Name.ReplaceInvalidPathSymbols()));
|
||||
if (optDir.Exists)
|
||||
if (optDir.Exists)
|
||||
{
|
||||
foreach ( var file in optDir.EnumerateFiles("*.*", SearchOption.AllDirectories) )
|
||||
foreach ( var file in optDir.EnumerateFiles("*.*", SearchOption.AllDirectories) )
|
||||
{
|
||||
optio.AddFile(file.FullName.Substring(baseFolder.FullName.Length).TrimStart('\\'), file.FullName.Substring(optDir.FullName.Length).TrimStart('\\').Replace('\\','/'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Inf.Options.Add( optio );
|
||||
}
|
||||
meta.Groups.Add( group.GroupName, Inf );
|
||||
|
|
|
|||
|
|
@ -1,163 +1,163 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using Dalamud.Plugin;
|
||||
|
||||
namespace Penumbra.Models
|
||||
{
|
||||
public class Deduplicator
|
||||
{
|
||||
private DirectoryInfo baseDir;
|
||||
private int baseDirLength;
|
||||
private ModMeta mod;
|
||||
private SHA256 hasher = null;
|
||||
|
||||
private Dictionary<long, List<FileInfo>> filesBySize;
|
||||
|
||||
private ref SHA256 Sha()
|
||||
{
|
||||
if (hasher == null)
|
||||
hasher = SHA256.Create();
|
||||
return ref hasher;
|
||||
}
|
||||
|
||||
public Deduplicator(DirectoryInfo baseDir, ModMeta mod)
|
||||
{
|
||||
this.baseDir = baseDir;
|
||||
this.baseDirLength = baseDir.FullName.Length;
|
||||
this.mod = mod;
|
||||
filesBySize = new();
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using Dalamud.Plugin;
|
||||
|
||||
BuildDict();
|
||||
}
|
||||
|
||||
private void BuildDict()
|
||||
{
|
||||
foreach( var file in baseDir.EnumerateFiles( "*.*", SearchOption.AllDirectories ) )
|
||||
{
|
||||
var fileLength = file.Length;
|
||||
if (filesBySize.TryGetValue(fileLength, out var files))
|
||||
files.Add(file);
|
||||
else
|
||||
filesBySize[fileLength] = new(){ file };
|
||||
}
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
foreach (var pair in filesBySize)
|
||||
{
|
||||
if (pair.Value.Count < 2)
|
||||
continue;
|
||||
|
||||
if (pair.Value.Count == 2)
|
||||
{
|
||||
if (CompareFilesDirectly(pair.Value[0], pair.Value[1]))
|
||||
ReplaceFile(pair.Value[0], pair.Value[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
var deleted = Enumerable.Repeat(false, pair.Value.Count).ToArray();
|
||||
var hashes = pair.Value.Select( F => ComputeHash(F)).ToArray();
|
||||
|
||||
for (var i = 0; i < pair.Value.Count; ++i)
|
||||
{
|
||||
if (deleted[i])
|
||||
continue;
|
||||
|
||||
for (var j = i + 1; j < pair.Value.Count; ++j)
|
||||
{
|
||||
if (deleted[j])
|
||||
continue;
|
||||
|
||||
if (!CompareHashes(hashes[i], hashes[j]))
|
||||
continue;
|
||||
|
||||
ReplaceFile(pair.Value[i], pair.Value[j]);
|
||||
deleted[j] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ClearEmptySubDirectories(baseDir);
|
||||
}
|
||||
|
||||
private void ReplaceFile(FileInfo f1, FileInfo f2)
|
||||
{
|
||||
var relName1 = f1.FullName.Substring(baseDirLength).TrimStart('\\');
|
||||
var relName2 = f2.FullName.Substring(baseDirLength).TrimStart('\\');
|
||||
|
||||
var inOption = false;
|
||||
foreach (var group in mod.Groups.Select( g => g.Value.Options))
|
||||
{
|
||||
foreach (var option in group)
|
||||
{
|
||||
if (option.OptionFiles.TryGetValue(relName2, out var values))
|
||||
{
|
||||
inOption = true;
|
||||
foreach (var value in values)
|
||||
option.AddFile(relName1, value);
|
||||
option.OptionFiles.Remove(relName2);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!inOption)
|
||||
{
|
||||
const string duplicates = "Duplicates";
|
||||
if (!mod.Groups.ContainsKey(duplicates))
|
||||
{
|
||||
InstallerInfo info = new()
|
||||
{
|
||||
GroupName = duplicates,
|
||||
SelectionType = SelectType.Single,
|
||||
Options = new()
|
||||
{
|
||||
new()
|
||||
{
|
||||
OptionName = "Required",
|
||||
OptionDesc = "",
|
||||
OptionFiles = new()
|
||||
}
|
||||
}
|
||||
};
|
||||
mod.Groups.Add(duplicates, info);
|
||||
}
|
||||
mod.Groups[duplicates].Options[0].AddFile(relName1, relName2.Replace('\\', '/'));
|
||||
mod.Groups[duplicates].Options[0].AddFile(relName1, relName1.Replace('\\', '/'));
|
||||
}
|
||||
PluginLog.Information($"File {relName1} and {relName2} are identical. Deleting the second.");
|
||||
f2.Delete();
|
||||
}
|
||||
|
||||
public static bool CompareFilesDirectly(FileInfo f1, FileInfo f2)
|
||||
{
|
||||
return File.ReadAllBytes(f1.FullName).SequenceEqual(File.ReadAllBytes(f2.FullName));
|
||||
}
|
||||
|
||||
public static bool CompareHashes(byte[] f1, byte[] f2)
|
||||
{
|
||||
return StructuralComparisons.StructuralEqualityComparer.Equals(f1, f2);
|
||||
}
|
||||
|
||||
public byte[] ComputeHash(FileInfo f)
|
||||
{
|
||||
var stream = File.OpenRead( f.FullName );
|
||||
var ret = Sha().ComputeHash(stream);
|
||||
stream.Dispose();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Does not delete the base directory itself even if it is completely empty at the end.
|
||||
public static void ClearEmptySubDirectories(DirectoryInfo baseDir)
|
||||
{
|
||||
foreach (var subDir in baseDir.GetDirectories())
|
||||
{
|
||||
ClearEmptySubDirectories(subDir);
|
||||
if (subDir.GetFiles().Length == 0 && subDir.GetDirectories().Length == 0)
|
||||
subDir.Delete();
|
||||
}
|
||||
}
|
||||
namespace Penumbra.Models
|
||||
{
|
||||
public class Deduplicator
|
||||
{
|
||||
private DirectoryInfo baseDir;
|
||||
private int baseDirLength;
|
||||
private ModMeta mod;
|
||||
private SHA256 hasher = null;
|
||||
|
||||
private Dictionary<long, List<FileInfo>> filesBySize;
|
||||
|
||||
private ref SHA256 Sha()
|
||||
{
|
||||
if (hasher == null)
|
||||
hasher = SHA256.Create();
|
||||
return ref hasher;
|
||||
}
|
||||
|
||||
public Deduplicator(DirectoryInfo baseDir, ModMeta mod)
|
||||
{
|
||||
this.baseDir = baseDir;
|
||||
this.baseDirLength = baseDir.FullName.Length;
|
||||
this.mod = mod;
|
||||
filesBySize = new();
|
||||
|
||||
BuildDict();
|
||||
}
|
||||
|
||||
private void BuildDict()
|
||||
{
|
||||
foreach( var file in baseDir.EnumerateFiles( "*.*", SearchOption.AllDirectories ) )
|
||||
{
|
||||
var fileLength = file.Length;
|
||||
if (filesBySize.TryGetValue(fileLength, out var files))
|
||||
files.Add(file);
|
||||
else
|
||||
filesBySize[fileLength] = new(){ file };
|
||||
}
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
foreach (var pair in filesBySize)
|
||||
{
|
||||
if (pair.Value.Count < 2)
|
||||
continue;
|
||||
|
||||
if (pair.Value.Count == 2)
|
||||
{
|
||||
if (CompareFilesDirectly(pair.Value[0], pair.Value[1]))
|
||||
ReplaceFile(pair.Value[0], pair.Value[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
var deleted = Enumerable.Repeat(false, pair.Value.Count).ToArray();
|
||||
var hashes = pair.Value.Select( F => ComputeHash(F)).ToArray();
|
||||
|
||||
for (var i = 0; i < pair.Value.Count; ++i)
|
||||
{
|
||||
if (deleted[i])
|
||||
continue;
|
||||
|
||||
for (var j = i + 1; j < pair.Value.Count; ++j)
|
||||
{
|
||||
if (deleted[j])
|
||||
continue;
|
||||
|
||||
if (!CompareHashes(hashes[i], hashes[j]))
|
||||
continue;
|
||||
|
||||
ReplaceFile(pair.Value[i], pair.Value[j]);
|
||||
deleted[j] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ClearEmptySubDirectories(baseDir);
|
||||
}
|
||||
|
||||
private void ReplaceFile(FileInfo f1, FileInfo f2)
|
||||
{
|
||||
var relName1 = f1.FullName.Substring(baseDirLength).TrimStart('\\');
|
||||
var relName2 = f2.FullName.Substring(baseDirLength).TrimStart('\\');
|
||||
|
||||
var inOption = false;
|
||||
foreach (var group in mod.Groups.Select( g => g.Value.Options))
|
||||
{
|
||||
foreach (var option in group)
|
||||
{
|
||||
if (option.OptionFiles.TryGetValue(relName2, out var values))
|
||||
{
|
||||
inOption = true;
|
||||
foreach (var value in values)
|
||||
option.AddFile(relName1, value);
|
||||
option.OptionFiles.Remove(relName2);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!inOption)
|
||||
{
|
||||
const string duplicates = "Duplicates";
|
||||
if (!mod.Groups.ContainsKey(duplicates))
|
||||
{
|
||||
InstallerInfo info = new()
|
||||
{
|
||||
GroupName = duplicates,
|
||||
SelectionType = SelectType.Single,
|
||||
Options = new()
|
||||
{
|
||||
new()
|
||||
{
|
||||
OptionName = "Required",
|
||||
OptionDesc = "",
|
||||
OptionFiles = new()
|
||||
}
|
||||
}
|
||||
};
|
||||
mod.Groups.Add(duplicates, info);
|
||||
}
|
||||
mod.Groups[duplicates].Options[0].AddFile(relName1, relName2.Replace('\\', '/'));
|
||||
mod.Groups[duplicates].Options[0].AddFile(relName1, relName1.Replace('\\', '/'));
|
||||
}
|
||||
PluginLog.Information($"File {relName1} and {relName2} are identical. Deleting the second.");
|
||||
f2.Delete();
|
||||
}
|
||||
|
||||
public static bool CompareFilesDirectly(FileInfo f1, FileInfo f2)
|
||||
{
|
||||
return File.ReadAllBytes(f1.FullName).SequenceEqual(File.ReadAllBytes(f2.FullName));
|
||||
}
|
||||
|
||||
public static bool CompareHashes(byte[] f1, byte[] f2)
|
||||
{
|
||||
return StructuralComparisons.StructuralEqualityComparer.Equals(f1, f2);
|
||||
}
|
||||
|
||||
public byte[] ComputeHash(FileInfo f)
|
||||
{
|
||||
var stream = File.OpenRead( f.FullName );
|
||||
var ret = Sha().ComputeHash(stream);
|
||||
stream.Dispose();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Does not delete the base directory itself even if it is completely empty at the end.
|
||||
public static void ClearEmptySubDirectories(DirectoryInfo baseDir)
|
||||
{
|
||||
foreach (var subDir in baseDir.GetDirectories())
|
||||
{
|
||||
ClearEmptySubDirectories(subDir);
|
||||
if (subDir.GetFiles().Length == 0 && subDir.GetDirectories().Length == 0)
|
||||
subDir.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ namespace Penumbra.Models
|
|||
if (OptionFiles.TryGetValue(filePath, out var set))
|
||||
return set.Add(gamePath);
|
||||
else
|
||||
OptionFiles[filePath] = new(){ gamePath };
|
||||
OptionFiles[filePath] = new(){ gamePath };
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System;
|
||||
|
||||
namespace Penumbra.Models
|
||||
|
|
@ -21,25 +21,25 @@ namespace Penumbra.Models
|
|||
|
||||
public Dictionary< string, string > FileSwaps { get; } = new();
|
||||
|
||||
public Dictionary<string, InstallerInfo> Groups { get; set; } = new();
|
||||
|
||||
[JsonIgnore]
|
||||
public Dictionary<string, InstallerInfo> Groups { get; set; } = new();
|
||||
|
||||
[JsonIgnore]
|
||||
public bool HasGroupWithConfig { get; set; } = false;
|
||||
|
||||
public static ModMeta LoadFromFile(string filePath)
|
||||
{
|
||||
|
||||
public static ModMeta LoadFromFile(string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
var meta = JsonConvert.DeserializeObject< ModMeta >( File.ReadAllText( filePath ) );
|
||||
meta.HasGroupWithConfig = meta.Groups != null && meta.Groups.Count > 0
|
||||
&& meta.Groups.Values.Any( G => G.SelectionType == SelectType.Multi || G.Options.Count > 1);
|
||||
meta.HasGroupWithConfig = meta.Groups != null && meta.Groups.Count > 0
|
||||
&& meta.Groups.Values.Any( G => G.SelectionType == SelectType.Multi || G.Options.Count > 1);
|
||||
return meta;
|
||||
}
|
||||
catch( Exception)
|
||||
{
|
||||
return null;
|
||||
// todo: handle broken mods properly
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -246,17 +246,17 @@ namespace Penumbra.Mods
|
|||
}
|
||||
|
||||
public void DeleteMod( ResourceMod mod )
|
||||
{
|
||||
if (mod?.ModBasePath?.Exists ?? false)
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(mod.ModBasePath.FullName, true);
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
PluginLog.Error($"Could not delete the mod {mod.ModBasePath.Name}:\n{e}");
|
||||
}
|
||||
{
|
||||
if (mod?.ModBasePath?.Exists ?? false)
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(mod.ModBasePath.FullName, true);
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
PluginLog.Error($"Could not delete the mod {mod.ModBasePath.Name}:\n{e}");
|
||||
}
|
||||
}
|
||||
DiscoverMods();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Penumbra.Mods
|
|||
PluginLog.LogError( "no basepath has been set on {ResourceModName}", Meta.Name );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ModFiles.Clear();
|
||||
// we don't care about any _files_ in the root dir, but any folders should be a game folder/file combo
|
||||
foreach( var dir in ModBasePath.EnumerateDirectories() )
|
||||
|
|
@ -35,7 +35,7 @@ namespace Penumbra.Mods
|
|||
|
||||
// Only add if not in a sub-folder, otherwise it was already added.
|
||||
//foreach( var pair in Meta.Groups.FileToGameAndGroup )
|
||||
// if (pair.Key.IndexOfAny(new[]{'/', '\\'}) < 0)
|
||||
// if (pair.Key.IndexOfAny(new[]{'/', '\\'}) < 0)
|
||||
// ModFiles.Add( new FileInfo(Path.Combine(ModBasePath.FullName, pair.Key)) );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using System.Linq;
|
||||
using System.Linq;
|
||||
using Dalamud.Game.Command;
|
||||
using Dalamud.Plugin;
|
||||
using EmbedIO;
|
||||
|
|
@ -70,7 +70,7 @@ namespace Penumbra
|
|||
public void CreateWebServer()
|
||||
{
|
||||
var prefix = "http://localhost:42069/";
|
||||
|
||||
|
||||
ShutdownWebServer();
|
||||
|
||||
_webServer = new WebServer( o => o
|
||||
|
|
@ -119,14 +119,14 @@ namespace Penumbra
|
|||
$"Reloaded Penumbra mods. You have {ModManager.Mods.ModSettings.Count} mods, {ModManager.Mods.EnabledMods.Length} of which are enabled."
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "redraw":
|
||||
{
|
||||
if (args.Length > 1)
|
||||
RefreshActors.RedrawSpecific(PluginInterface.ClientState.Actors, string.Join(" ", args.Skip(1)));
|
||||
else
|
||||
RefreshActors.RedrawAll(PluginInterface.ClientState.Actors);
|
||||
break;
|
||||
}
|
||||
case "redraw":
|
||||
{
|
||||
if (args.Length > 1)
|
||||
RefreshActors.RedrawSpecific(PluginInterface.ClientState.Actors, string.Join(" ", args.Skip(1)));
|
||||
else
|
||||
RefreshActors.RedrawAll(PluginInterface.ClientState.Actors);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
|
@ -127,10 +127,10 @@ namespace Penumbra
|
|||
if( LogAllFiles )
|
||||
{
|
||||
PluginLog.Log( "[GetResourceHandler] {0}", gameFsPath );
|
||||
}
|
||||
|
||||
if (Plugin.Configuration.IsEnabled)
|
||||
{
|
||||
}
|
||||
|
||||
if (Plugin.Configuration.IsEnabled)
|
||||
{
|
||||
var replacementPath = Plugin.ModManager.ResolveSwappedOrReplacementFilePath( gameFsPath );
|
||||
|
||||
// path must be < 260 because statically defined array length :(
|
||||
|
|
@ -152,9 +152,9 @@ namespace Penumbra
|
|||
|
||||
#if DEBUG
|
||||
PluginLog.Log( "[GetResourceHandler] resolved {GamePath} to {NewPath}", gameFsPath, replacementPath );
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
return CallOriginalHandler( isSync, pFileManager, pCategoryId, pResourceType, pResourceHash, pPath, pUnknown, isUnknown );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
namespace Penumbra.Structs
|
||||
namespace Penumbra.Structs
|
||||
{
|
||||
public enum FileMode : uint
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Penumbra.Structs
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Penumbra.Structs
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,130 +1,130 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using ImGuiNET;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using ImGuiNET;
|
||||
|
||||
namespace Penumbra.UI
|
||||
{
|
||||
public static partial class ImGuiCustom
|
||||
{
|
||||
public static void BeginFramedGroup(string label) => BeginFramedGroupInternal(ref label, ZeroVector, false);
|
||||
public static void BeginFramedGroup(string label, Vector2 minSize) => BeginFramedGroupInternal(ref label, minSize, false);
|
||||
|
||||
public static bool BeginFramedGroupEdit(ref string label) => BeginFramedGroupInternal(ref label, ZeroVector, true);
|
||||
public static bool BeginFramedGroupEdit(ref string label, Vector2 minSize) => BeginFramedGroupInternal(ref label, minSize, true);
|
||||
|
||||
private static bool BeginFramedGroupInternal(ref string label, Vector2 minSize, bool edit)
|
||||
{
|
||||
var itemSpacing = ImGui.GetStyle().ItemSpacing;
|
||||
var frameHeight = ImGui.GetFrameHeight();
|
||||
var halfFrameHeight = new Vector2(ImGui.GetFrameHeight() / 2, 0);
|
||||
|
||||
ImGui.BeginGroup(); // First group
|
||||
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, ZeroVector);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, ZeroVector);
|
||||
|
||||
ImGui.BeginGroup(); // Second group
|
||||
|
||||
var effectiveSize = minSize;
|
||||
if (effectiveSize.X < 0)
|
||||
effectiveSize.X = ImGui.GetContentRegionAvail().X;
|
||||
|
||||
// Ensure width.
|
||||
ImGui.Dummy(new(effectiveSize.X, 0));
|
||||
// Ensure left half boundary width/distance.
|
||||
ImGui.Dummy(halfFrameHeight);
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.BeginGroup(); // Third group.
|
||||
// Ensure right half of boundary width/distance
|
||||
ImGui.Dummy(halfFrameHeight);
|
||||
|
||||
// Label block
|
||||
ImGui.SameLine();
|
||||
var ret = false;
|
||||
if (edit)
|
||||
ret = ImGuiCustom.ResizingTextInput(ref label, 1024);
|
||||
else
|
||||
ImGui.TextUnformatted(label);
|
||||
|
||||
var labelMin = ImGui.GetItemRectMin();
|
||||
var labelMax = ImGui.GetItemRectMax();
|
||||
ImGui.SameLine();
|
||||
// Ensure height and distance to label.
|
||||
ImGui.Dummy(new Vector2(0, frameHeight + itemSpacing.Y));
|
||||
|
||||
ImGui.BeginGroup(); // Fourth Group.
|
||||
|
||||
ImGui.PopStyleVar(2);
|
||||
|
||||
ImGui.SetWindowSize(new Vector2(ImGui.GetWindowSize().X - frameHeight, ImGui.GetWindowSize().Y));
|
||||
|
||||
var itemWidth = ImGui.CalcItemWidth();
|
||||
ImGui.PushItemWidth(Math.Max(0f, itemWidth - frameHeight));
|
||||
|
||||
labelStack.Add((labelMin, labelMax));
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static void DrawClippedRect(Vector2 clipMin, Vector2 clipMax, Vector2 drawMin, Vector2 drawMax, uint color, float thickness)
|
||||
{
|
||||
ImGui.PushClipRect(clipMin, clipMax, true);
|
||||
ImGui.GetWindowDrawList().AddRect(drawMin, drawMax, color, thickness);
|
||||
ImGui.PopClipRect();
|
||||
}
|
||||
|
||||
public static void EndFramedGroup()
|
||||
{
|
||||
uint borderColor = ImGui.ColorConvertFloat4ToU32(ImGui.GetStyle().Colors[(int)ImGuiCol.Border]);
|
||||
Vector2 itemSpacing = ImGui.GetStyle().ItemSpacing;
|
||||
float frameHeight = ImGui.GetFrameHeight();
|
||||
Vector2 halfFrameHeight = new(ImGui.GetFrameHeight() / 2, 0);
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, ZeroVector);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, ZeroVector);
|
||||
|
||||
ImGui.EndGroup(); // Close fourth group
|
||||
ImGui.EndGroup(); // Close third group
|
||||
|
||||
ImGui.SameLine();
|
||||
// Ensure right distance.
|
||||
ImGui.Dummy(halfFrameHeight);
|
||||
// Ensure bottom distance
|
||||
ImGui.Dummy(new Vector2(0, frameHeight/2 - itemSpacing.Y));
|
||||
ImGui.EndGroup(); // Close second group
|
||||
|
||||
var itemMin = ImGui.GetItemRectMin();
|
||||
var itemMax = ImGui.GetItemRectMax();
|
||||
var (currentLabelMin, currentLabelMax) = labelStack[labelStack.Count - 1];
|
||||
labelStack.RemoveAt(labelStack.Count - 1);
|
||||
|
||||
var halfFrame = new Vector2(frameHeight / 8, frameHeight / 2);
|
||||
currentLabelMin.X -= itemSpacing.X;
|
||||
currentLabelMax.X += itemSpacing.X;
|
||||
var frameMin = itemMin + halfFrame;
|
||||
var frameMax = itemMax - new Vector2(halfFrame.X, 0);
|
||||
|
||||
// Left
|
||||
DrawClippedRect(new(-float.MaxValue , -float.MaxValue ), new(currentLabelMin.X, float.MaxValue ), frameMin, frameMax, borderColor, halfFrame.X);
|
||||
// Right
|
||||
DrawClippedRect(new(currentLabelMax.X, -float.MaxValue ), new(float.MaxValue , float.MaxValue ), frameMin, frameMax, borderColor, halfFrame.X);
|
||||
// Top
|
||||
DrawClippedRect(new(currentLabelMin.X, -float.MaxValue ), new(currentLabelMax.X, currentLabelMin.Y), frameMin, frameMax, borderColor, halfFrame.X);
|
||||
// Bottom
|
||||
DrawClippedRect(new(currentLabelMin.X, currentLabelMax.Y), new(currentLabelMax.X, float.MaxValue ), frameMin, frameMax, borderColor, halfFrame.X);
|
||||
|
||||
ImGui.PopStyleVar(2);
|
||||
ImGui.SetWindowSize(new Vector2(ImGui.GetWindowSize().X + frameHeight, ImGui.GetWindowSize().Y));
|
||||
ImGui.Dummy(ZeroVector);
|
||||
|
||||
ImGui.EndGroup(); // Close first group
|
||||
}
|
||||
|
||||
private static readonly Vector2 ZeroVector = new(0, 0);
|
||||
|
||||
private static List<(Vector2, Vector2)> labelStack = new();
|
||||
{
|
||||
public static partial class ImGuiCustom
|
||||
{
|
||||
public static void BeginFramedGroup(string label) => BeginFramedGroupInternal(ref label, ZeroVector, false);
|
||||
public static void BeginFramedGroup(string label, Vector2 minSize) => BeginFramedGroupInternal(ref label, minSize, false);
|
||||
|
||||
public static bool BeginFramedGroupEdit(ref string label) => BeginFramedGroupInternal(ref label, ZeroVector, true);
|
||||
public static bool BeginFramedGroupEdit(ref string label, Vector2 minSize) => BeginFramedGroupInternal(ref label, minSize, true);
|
||||
|
||||
private static bool BeginFramedGroupInternal(ref string label, Vector2 minSize, bool edit)
|
||||
{
|
||||
var itemSpacing = ImGui.GetStyle().ItemSpacing;
|
||||
var frameHeight = ImGui.GetFrameHeight();
|
||||
var halfFrameHeight = new Vector2(ImGui.GetFrameHeight() / 2, 0);
|
||||
|
||||
ImGui.BeginGroup(); // First group
|
||||
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, ZeroVector);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, ZeroVector);
|
||||
|
||||
ImGui.BeginGroup(); // Second group
|
||||
|
||||
var effectiveSize = minSize;
|
||||
if (effectiveSize.X < 0)
|
||||
effectiveSize.X = ImGui.GetContentRegionAvail().X;
|
||||
|
||||
// Ensure width.
|
||||
ImGui.Dummy(new(effectiveSize.X, 0));
|
||||
// Ensure left half boundary width/distance.
|
||||
ImGui.Dummy(halfFrameHeight);
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.BeginGroup(); // Third group.
|
||||
// Ensure right half of boundary width/distance
|
||||
ImGui.Dummy(halfFrameHeight);
|
||||
|
||||
// Label block
|
||||
ImGui.SameLine();
|
||||
var ret = false;
|
||||
if (edit)
|
||||
ret = ImGuiCustom.ResizingTextInput(ref label, 1024);
|
||||
else
|
||||
ImGui.TextUnformatted(label);
|
||||
|
||||
var labelMin = ImGui.GetItemRectMin();
|
||||
var labelMax = ImGui.GetItemRectMax();
|
||||
ImGui.SameLine();
|
||||
// Ensure height and distance to label.
|
||||
ImGui.Dummy(new Vector2(0, frameHeight + itemSpacing.Y));
|
||||
|
||||
ImGui.BeginGroup(); // Fourth Group.
|
||||
|
||||
ImGui.PopStyleVar(2);
|
||||
|
||||
ImGui.SetWindowSize(new Vector2(ImGui.GetWindowSize().X - frameHeight, ImGui.GetWindowSize().Y));
|
||||
|
||||
var itemWidth = ImGui.CalcItemWidth();
|
||||
ImGui.PushItemWidth(Math.Max(0f, itemWidth - frameHeight));
|
||||
|
||||
labelStack.Add((labelMin, labelMax));
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static void DrawClippedRect(Vector2 clipMin, Vector2 clipMax, Vector2 drawMin, Vector2 drawMax, uint color, float thickness)
|
||||
{
|
||||
ImGui.PushClipRect(clipMin, clipMax, true);
|
||||
ImGui.GetWindowDrawList().AddRect(drawMin, drawMax, color, thickness);
|
||||
ImGui.PopClipRect();
|
||||
}
|
||||
|
||||
public static void EndFramedGroup()
|
||||
{
|
||||
uint borderColor = ImGui.ColorConvertFloat4ToU32(ImGui.GetStyle().Colors[(int)ImGuiCol.Border]);
|
||||
Vector2 itemSpacing = ImGui.GetStyle().ItemSpacing;
|
||||
float frameHeight = ImGui.GetFrameHeight();
|
||||
Vector2 halfFrameHeight = new(ImGui.GetFrameHeight() / 2, 0);
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, ZeroVector);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, ZeroVector);
|
||||
|
||||
ImGui.EndGroup(); // Close fourth group
|
||||
ImGui.EndGroup(); // Close third group
|
||||
|
||||
ImGui.SameLine();
|
||||
// Ensure right distance.
|
||||
ImGui.Dummy(halfFrameHeight);
|
||||
// Ensure bottom distance
|
||||
ImGui.Dummy(new Vector2(0, frameHeight/2 - itemSpacing.Y));
|
||||
ImGui.EndGroup(); // Close second group
|
||||
|
||||
var itemMin = ImGui.GetItemRectMin();
|
||||
var itemMax = ImGui.GetItemRectMax();
|
||||
var (currentLabelMin, currentLabelMax) = labelStack[labelStack.Count - 1];
|
||||
labelStack.RemoveAt(labelStack.Count - 1);
|
||||
|
||||
var halfFrame = new Vector2(frameHeight / 8, frameHeight / 2);
|
||||
currentLabelMin.X -= itemSpacing.X;
|
||||
currentLabelMax.X += itemSpacing.X;
|
||||
var frameMin = itemMin + halfFrame;
|
||||
var frameMax = itemMax - new Vector2(halfFrame.X, 0);
|
||||
|
||||
// Left
|
||||
DrawClippedRect(new(-float.MaxValue , -float.MaxValue ), new(currentLabelMin.X, float.MaxValue ), frameMin, frameMax, borderColor, halfFrame.X);
|
||||
// Right
|
||||
DrawClippedRect(new(currentLabelMax.X, -float.MaxValue ), new(float.MaxValue , float.MaxValue ), frameMin, frameMax, borderColor, halfFrame.X);
|
||||
// Top
|
||||
DrawClippedRect(new(currentLabelMin.X, -float.MaxValue ), new(currentLabelMax.X, currentLabelMin.Y), frameMin, frameMax, borderColor, halfFrame.X);
|
||||
// Bottom
|
||||
DrawClippedRect(new(currentLabelMin.X, currentLabelMax.Y), new(currentLabelMax.X, float.MaxValue ), frameMin, frameMax, borderColor, halfFrame.X);
|
||||
|
||||
ImGui.PopStyleVar(2);
|
||||
ImGui.SetWindowSize(new Vector2(ImGui.GetWindowSize().X + frameHeight, ImGui.GetWindowSize().Y));
|
||||
ImGui.Dummy(ZeroVector);
|
||||
|
||||
ImGui.EndGroup(); // Close first group
|
||||
}
|
||||
|
||||
private static readonly Vector2 ZeroVector = new(0, 0);
|
||||
|
||||
private static List<(Vector2, Vector2)> labelStack = new();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +1,43 @@
|
|||
using ImGuiNET;
|
||||
|
||||
using ImGuiNET;
|
||||
|
||||
namespace Penumbra.UI
|
||||
{
|
||||
public static partial class ImGuiCustom
|
||||
{
|
||||
public static bool RenameableCombo(string label, ref int currentItem, ref string newName, string[] items, int numItems)
|
||||
{
|
||||
var ret = false;
|
||||
newName = "";
|
||||
var newOption = "";
|
||||
if (ImGui.BeginCombo(label, (numItems > 0) ? items[currentItem] : newOption))
|
||||
{
|
||||
for (var i = 0; i < numItems; ++i)
|
||||
{
|
||||
var isSelected = i == currentItem;
|
||||
ImGui.SetNextItemWidth(-1);
|
||||
if (ImGui.InputText($"##{label}_{i}", ref items[i], 64, ImGuiInputTextFlags.EnterReturnsTrue))
|
||||
{
|
||||
currentItem = i;
|
||||
newName = items[i];
|
||||
ret = true;
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
if (isSelected)
|
||||
ImGui.SetItemDefaultFocus();
|
||||
}
|
||||
ImGui.SetNextItemWidth(-1);
|
||||
if (ImGui.InputText($"##{label}_new", ref newOption, 64, ImGuiInputTextFlags.EnterReturnsTrue))
|
||||
{
|
||||
currentItem = numItems;
|
||||
newName = newOption;
|
||||
ret = true;
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
if (numItems == 0)
|
||||
ImGui.SetItemDefaultFocus();
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
{
|
||||
public static partial class ImGuiCustom
|
||||
{
|
||||
public static bool RenameableCombo(string label, ref int currentItem, ref string newName, string[] items, int numItems)
|
||||
{
|
||||
var ret = false;
|
||||
newName = "";
|
||||
var newOption = "";
|
||||
if (ImGui.BeginCombo(label, (numItems > 0) ? items[currentItem] : newOption))
|
||||
{
|
||||
for (var i = 0; i < numItems; ++i)
|
||||
{
|
||||
var isSelected = i == currentItem;
|
||||
ImGui.SetNextItemWidth(-1);
|
||||
if (ImGui.InputText($"##{label}_{i}", ref items[i], 64, ImGuiInputTextFlags.EnterReturnsTrue))
|
||||
{
|
||||
currentItem = i;
|
||||
newName = items[i];
|
||||
ret = true;
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
if (isSelected)
|
||||
ImGui.SetItemDefaultFocus();
|
||||
}
|
||||
ImGui.SetNextItemWidth(-1);
|
||||
if (ImGui.InputText($"##{label}_new", ref newOption, 64, ImGuiInputTextFlags.EnterReturnsTrue))
|
||||
{
|
||||
currentItem = numItems;
|
||||
newName = newOption;
|
||||
ret = true;
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
if (numItems == 0)
|
||||
ImGui.SetItemDefaultFocus();
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +1,40 @@
|
|||
using System.Collections.Generic;
|
||||
using ImGuiNET;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using ImGuiNET;
|
||||
|
||||
namespace Penumbra.UI
|
||||
{
|
||||
public static partial class ImGuiCustom
|
||||
{
|
||||
public static bool InputOrText(bool editable, string label, ref string text, uint maxLength)
|
||||
{
|
||||
if (editable)
|
||||
return ResizingTextInput(label, ref text, maxLength);
|
||||
|
||||
ImGui.Text(text);
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool ResizingTextInput(string label, ref string input, uint maxLength) => ResizingTextInputIntern(label, ref input, maxLength).Item1;
|
||||
public static bool ResizingTextInput(ref string input, uint maxLength)
|
||||
{
|
||||
var (ret, id) = ResizingTextInputIntern($"##{input}", ref input, maxLength);
|
||||
if (ret)
|
||||
_textInputWidths.Remove(id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static (bool, uint) ResizingTextInputIntern(string label, ref string input, uint maxLength)
|
||||
{
|
||||
var id = ImGui.GetID(label);
|
||||
if (!_textInputWidths.TryGetValue(id, out var width))
|
||||
width = ImGui.CalcTextSize(input).X + 10;
|
||||
|
||||
ImGui.SetNextItemWidth(width);
|
||||
var ret = ImGui.InputText(label, ref input, maxLength, ImGuiInputTextFlags.EnterReturnsTrue);
|
||||
_textInputWidths[id] = ImGui.CalcTextSize(input).X + 10;
|
||||
return (ret, id);
|
||||
}
|
||||
|
||||
private static readonly Dictionary<uint, float> _textInputWidths = new();
|
||||
}
|
||||
{
|
||||
public static partial class ImGuiCustom
|
||||
{
|
||||
public static bool InputOrText(bool editable, string label, ref string text, uint maxLength)
|
||||
{
|
||||
if (editable)
|
||||
return ResizingTextInput(label, ref text, maxLength);
|
||||
|
||||
ImGui.Text(text);
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool ResizingTextInput(string label, ref string input, uint maxLength) => ResizingTextInputIntern(label, ref input, maxLength).Item1;
|
||||
public static bool ResizingTextInput(ref string input, uint maxLength)
|
||||
{
|
||||
var (ret, id) = ResizingTextInputIntern($"##{input}", ref input, maxLength);
|
||||
if (ret)
|
||||
_textInputWidths.Remove(id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static (bool, uint) ResizingTextInputIntern(string label, ref string input, uint maxLength)
|
||||
{
|
||||
var id = ImGui.GetID(label);
|
||||
if (!_textInputWidths.TryGetValue(id, out var width))
|
||||
width = ImGui.CalcTextSize(input).X + 10;
|
||||
|
||||
ImGui.SetNextItemWidth(width);
|
||||
var ret = ImGui.InputText(label, ref input, maxLength, ImGuiInputTextFlags.EnterReturnsTrue);
|
||||
_textInputWidths[id] = ImGui.CalcTextSize(input).X + 10;
|
||||
return (ret, id);
|
||||
}
|
||||
|
||||
private static readonly Dictionary<uint, float> _textInputWidths = new();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +1,26 @@
|
|||
using ImGuiNET;
|
||||
|
||||
using ImGuiNET;
|
||||
|
||||
namespace Penumbra.UI
|
||||
{
|
||||
public static partial class ImGuiCustom
|
||||
{
|
||||
public static void VerticalDistance(float distance)
|
||||
{
|
||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + distance);
|
||||
}
|
||||
|
||||
public static void RightJustifiedText(float pos, string text)
|
||||
{
|
||||
ImGui.SetCursorPosX(pos - ImGui.CalcTextSize(text).X - 2 * ImGui.GetStyle().ItemSpacing.X);
|
||||
ImGui.Text(text);
|
||||
}
|
||||
|
||||
public static void RightJustifiedLabel(float pos, string text)
|
||||
{
|
||||
ImGui.SetCursorPosX(pos - ImGui.CalcTextSize(text).X - ImGui.GetStyle().ItemSpacing.X / 2);
|
||||
ImGui.Text(text);
|
||||
ImGui.SameLine(pos);
|
||||
}
|
||||
|
||||
}
|
||||
{
|
||||
public static partial class ImGuiCustom
|
||||
{
|
||||
public static void VerticalDistance(float distance)
|
||||
{
|
||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + distance);
|
||||
}
|
||||
|
||||
public static void RightJustifiedText(float pos, string text)
|
||||
{
|
||||
ImGui.SetCursorPosX(pos - ImGui.CalcTextSize(text).X - 2 * ImGui.GetStyle().ItemSpacing.X);
|
||||
ImGui.Text(text);
|
||||
}
|
||||
|
||||
public static void RightJustifiedLabel(float pos, string text)
|
||||
{
|
||||
ImGui.SetCursorPosX(pos - ImGui.CalcTextSize(text).X - ImGui.GetStyle().ItemSpacing.X / 2);
|
||||
ImGui.Text(text);
|
||||
ImGui.SameLine(pos);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -2,40 +2,40 @@ using System.Numerics;
|
|||
using ImGuiNET;
|
||||
|
||||
namespace Penumbra.UI
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private class LaunchButton
|
||||
{
|
||||
// magic numbers
|
||||
private const int Padding = 50;
|
||||
private const int Width = 200;
|
||||
private const int Height = 45;
|
||||
private const string MenuButtonsName = "Penumbra Menu Buttons";
|
||||
private const string MenuButtonLabel = "Manage Mods";
|
||||
|
||||
private static readonly Vector2 WindowSize = new(Width, Height);
|
||||
private static readonly Vector2 WindowPosOffset = new(Padding + Width, Padding + Height);
|
||||
|
||||
private readonly ImGuiWindowFlags ButtonFlags = ImGuiWindowFlags.AlwaysAutoResize
|
||||
| ImGuiWindowFlags.NoBackground
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private class LaunchButton
|
||||
{
|
||||
// magic numbers
|
||||
private const int Padding = 50;
|
||||
private const int Width = 200;
|
||||
private const int Height = 45;
|
||||
private const string MenuButtonsName = "Penumbra Menu Buttons";
|
||||
private const string MenuButtonLabel = "Manage Mods";
|
||||
|
||||
private static readonly Vector2 WindowSize = new(Width, Height);
|
||||
private static readonly Vector2 WindowPosOffset = new(Padding + Width, Padding + Height);
|
||||
|
||||
private readonly ImGuiWindowFlags ButtonFlags = ImGuiWindowFlags.AlwaysAutoResize
|
||||
| ImGuiWindowFlags.NoBackground
|
||||
| ImGuiWindowFlags.NoDecoration
|
||||
| ImGuiWindowFlags.NoMove
|
||||
| ImGuiWindowFlags.NoScrollbar
|
||||
| ImGuiWindowFlags.NoResize
|
||||
| ImGuiWindowFlags.NoSavedSettings;
|
||||
|
||||
private readonly SettingsInterface _base;
|
||||
private readonly Dalamud.Game.ClientState.Condition _condition;
|
||||
|
||||
public LaunchButton(SettingsInterface ui)
|
||||
{
|
||||
_base = ui;
|
||||
_condition = ui._plugin.PluginInterface.ClientState.Condition;
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
| ImGuiWindowFlags.NoSavedSettings;
|
||||
|
||||
private readonly SettingsInterface _base;
|
||||
private readonly Dalamud.Game.ClientState.Condition _condition;
|
||||
|
||||
public LaunchButton(SettingsInterface ui)
|
||||
{
|
||||
_base = ui;
|
||||
_condition = ui._plugin.PluginInterface.ClientState.Condition;
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
if( !_condition.Any() && !_base._menu.Visible )
|
||||
{
|
||||
var ss = ImGui.GetIO().DisplaySize;
|
||||
|
|
@ -49,8 +49,8 @@ namespace Penumbra.UI
|
|||
|
||||
ImGui.End();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +1,28 @@
|
|||
using ImGuiNET;
|
||||
|
||||
namespace Penumbra.UI
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private class MenuBar
|
||||
{
|
||||
private const string MenuLabel = "Penumbra";
|
||||
private const string MenuItemToggle = "Toggle UI";
|
||||
private const string SlashCommand = "/penumbra";
|
||||
private const string MenuItemRediscover = "Rediscover Mods";
|
||||
private const string MenuItemHide = "Hide Menu Bar";
|
||||
|
||||
#if DEBUG
|
||||
private bool _showDebugBar = true;
|
||||
#else
|
||||
private const bool _showDebugBar = false;
|
||||
#endif
|
||||
|
||||
private readonly SettingsInterface _base;
|
||||
public MenuBar(SettingsInterface ui) => _base = ui;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private class MenuBar
|
||||
{
|
||||
private const string MenuLabel = "Penumbra";
|
||||
private const string MenuItemToggle = "Toggle UI";
|
||||
private const string SlashCommand = "/penumbra";
|
||||
private const string MenuItemRediscover = "Rediscover Mods";
|
||||
private const string MenuItemHide = "Hide Menu Bar";
|
||||
|
||||
#if DEBUG
|
||||
private bool _showDebugBar = true;
|
||||
#else
|
||||
private const bool _showDebugBar = false;
|
||||
#endif
|
||||
|
||||
private readonly SettingsInterface _base;
|
||||
public MenuBar(SettingsInterface ui) => _base = ui;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
if( _showDebugBar && ImGui.BeginMainMenuBar() )
|
||||
{
|
||||
if( ImGui.BeginMenu( MenuLabel ) )
|
||||
|
|
@ -31,18 +31,18 @@ namespace Penumbra.UI
|
|||
_base.FlipVisibility();
|
||||
|
||||
if( ImGui.MenuItem( MenuItemRediscover ) )
|
||||
_base.ReloadMods();
|
||||
#if DEBUG
|
||||
if ( ImGui.MenuItem( MenuItemHide) )
|
||||
_showDebugBar = false;
|
||||
_base.ReloadMods();
|
||||
#if DEBUG
|
||||
if ( ImGui.MenuItem( MenuItemHide) )
|
||||
_showDebugBar = false;
|
||||
#endif
|
||||
|
||||
ImGui.EndMenu();
|
||||
}
|
||||
|
||||
ImGui.EndMainMenuBar();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,45 +2,45 @@ using System.IO;
|
|||
using System.Numerics;
|
||||
|
||||
namespace Penumbra.UI
|
||||
{
|
||||
{
|
||||
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;
|
||||
|
||||
{
|
||||
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;
|
||||
_launchButton = new(this);
|
||||
_menuBar = new(this);
|
||||
{
|
||||
_plugin = plugin;
|
||||
_launchButton = new(this);
|
||||
_menuBar = new(this);
|
||||
_menu = new(this);
|
||||
}
|
||||
|
||||
public void FlipVisibility() => _menu.Visible = !_menu.Visible;
|
||||
|
||||
}
|
||||
|
||||
public void FlipVisibility() => _menu.Visible = !_menu.Visible;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
_menuBar.Draw();
|
||||
_launchButton.Draw();
|
||||
_menuBar.Draw();
|
||||
_launchButton.Draw();
|
||||
_menu.Draw();
|
||||
}
|
||||
|
||||
private void ReloadMods()
|
||||
{
|
||||
{
|
||||
_menu._installedTab._selector.ClearSelection();
|
||||
// create the directory if it doesn't exist
|
||||
Directory.CreateDirectory( _plugin.Configuration.CurrentCollection );
|
||||
|
||||
_plugin.ModManager.DiscoverMods( _plugin.Configuration.CurrentCollection );
|
||||
_menu._effectiveTab.RebuildFileList(_plugin.Configuration.ShowAdvanced);
|
||||
}
|
||||
_plugin.ModManager.DiscoverMods( _plugin.Configuration.CurrentCollection );
|
||||
_menu._effectiveTab.RebuildFileList(_plugin.Configuration.ShowAdvanced);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,45 +2,45 @@ using System.Numerics;
|
|||
using ImGuiNET;
|
||||
|
||||
namespace Penumbra.UI
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private partial class SettingsMenu
|
||||
{
|
||||
private const string PenumbraSettingsLabel = "PenumbraSettings";
|
||||
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private partial class SettingsMenu
|
||||
{
|
||||
private const string PenumbraSettingsLabel = "PenumbraSettings";
|
||||
|
||||
private static readonly Vector2 MinSettingsSize = new( 800, 450 );
|
||||
private static readonly Vector2 MaxSettingsSize = new( 69420, 42069 );
|
||||
|
||||
private readonly SettingsInterface _base;
|
||||
public readonly TabSettings _settingsTab;
|
||||
public readonly TabImport _importTab;
|
||||
public readonly TabBrowser _browserTab;
|
||||
public readonly TabInstalled _installedTab;
|
||||
public readonly TabEffective _effectiveTab;
|
||||
|
||||
public SettingsMenu(SettingsInterface ui)
|
||||
{
|
||||
_base = ui;
|
||||
_settingsTab = new(_base);
|
||||
_importTab = new(_base);
|
||||
_browserTab = new();
|
||||
_installedTab = new(_base);
|
||||
_effectiveTab = new(_base);
|
||||
}
|
||||
|
||||
private static readonly Vector2 MaxSettingsSize = new( 69420, 42069 );
|
||||
|
||||
private readonly SettingsInterface _base;
|
||||
public readonly TabSettings _settingsTab;
|
||||
public readonly TabImport _importTab;
|
||||
public readonly TabBrowser _browserTab;
|
||||
public readonly TabInstalled _installedTab;
|
||||
public readonly TabEffective _effectiveTab;
|
||||
|
||||
public SettingsMenu(SettingsInterface ui)
|
||||
{
|
||||
_base = ui;
|
||||
_settingsTab = new(_base);
|
||||
_importTab = new(_base);
|
||||
_browserTab = new();
|
||||
_installedTab = new(_base);
|
||||
_effectiveTab = new(_base);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
private const bool DefaultVisibility = true;
|
||||
private const bool DefaultVisibility = true;
|
||||
#else
|
||||
private const bool DefaultVisibility = false;
|
||||
#endif
|
||||
public bool Visible = DefaultVisibility;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
#endif
|
||||
public bool Visible = DefaultVisibility;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
if( !Visible )
|
||||
return;
|
||||
|
||||
return;
|
||||
|
||||
ImGui.SetNextWindowSizeConstraints( MinSettingsSize, MaxSettingsSize );
|
||||
#if DEBUG
|
||||
var ret = ImGui.Begin( _base._plugin.PluginDebugTitleStr, ref Visible );
|
||||
|
|
@ -49,12 +49,12 @@ namespace Penumbra.UI
|
|||
#endif
|
||||
if( !ret )
|
||||
return;
|
||||
|
||||
ImGui.BeginTabBar( PenumbraSettingsLabel );
|
||||
|
||||
|
||||
ImGui.BeginTabBar( PenumbraSettingsLabel );
|
||||
|
||||
_settingsTab.Draw();
|
||||
_importTab.Draw();
|
||||
|
||||
_importTab.Draw();
|
||||
|
||||
if( !_importTab.IsImporting() )
|
||||
{
|
||||
_browserTab.Draw();
|
||||
|
|
@ -65,8 +65,8 @@ namespace Penumbra.UI
|
|||
}
|
||||
|
||||
ImGui.EndTabBar();
|
||||
ImGui.End();
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui.End();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
using System.Diagnostics;
|
||||
using ImGuiNET;
|
||||
|
||||
using System.Diagnostics;
|
||||
using ImGuiNET;
|
||||
|
||||
namespace Penumbra.UI
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private class TabBrowser
|
||||
{
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private class TabBrowser
|
||||
{
|
||||
[Conditional( "DEBUG" )]
|
||||
public void Draw()
|
||||
{
|
||||
|
|
@ -16,7 +16,7 @@ namespace Penumbra.UI
|
|||
|
||||
ImGui.Text( "woah" );
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +1,50 @@
|
|||
using System.Linq;
|
||||
using ImGuiNET;
|
||||
using Penumbra.Mods;
|
||||
|
||||
using System.Linq;
|
||||
using ImGuiNET;
|
||||
using Penumbra.Mods;
|
||||
|
||||
namespace Penumbra.UI
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private class TabEffective
|
||||
{
|
||||
private const string LabelTab = "Effective File List";
|
||||
private const float TextSizePadding = 5f;
|
||||
|
||||
private ModManager _mods;
|
||||
private (string, string)[] _fileList = null;
|
||||
private float _maxGamePath = 0f;
|
||||
|
||||
public TabEffective(SettingsInterface ui)
|
||||
{
|
||||
_mods = ui._plugin.ModManager;
|
||||
RebuildFileList(ui._plugin.Configuration.ShowAdvanced);
|
||||
}
|
||||
|
||||
public void RebuildFileList(bool advanced)
|
||||
{
|
||||
if (advanced)
|
||||
{
|
||||
_fileList = _mods.ResolvedFiles.Select( P => (P.Value.FullName, P.Key) ).ToArray();
|
||||
_maxGamePath = ((_fileList.Length > 0) ? _fileList.Max( P => ImGui.CalcTextSize(P.Item2).X ) : 0f) + TextSizePadding;
|
||||
}
|
||||
else
|
||||
{
|
||||
_fileList = null;
|
||||
_maxGamePath = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawFileLine((string, string) file)
|
||||
{
|
||||
ImGui.Selectable(file.Item2);
|
||||
ImGui.SameLine();
|
||||
ImGui.SetCursorPosX(_maxGamePath);
|
||||
ImGui.TextUnformatted(" <-- ");
|
||||
ImGui.SameLine();
|
||||
ImGui.Selectable(file.Item1);
|
||||
}
|
||||
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private class TabEffective
|
||||
{
|
||||
private const string LabelTab = "Effective File List";
|
||||
private const float TextSizePadding = 5f;
|
||||
|
||||
private ModManager _mods;
|
||||
private (string, string)[] _fileList = null;
|
||||
private float _maxGamePath = 0f;
|
||||
|
||||
public TabEffective(SettingsInterface ui)
|
||||
{
|
||||
_mods = ui._plugin.ModManager;
|
||||
RebuildFileList(ui._plugin.Configuration.ShowAdvanced);
|
||||
}
|
||||
|
||||
public void RebuildFileList(bool advanced)
|
||||
{
|
||||
if (advanced)
|
||||
{
|
||||
_fileList = _mods.ResolvedFiles.Select( P => (P.Value.FullName, P.Key) ).ToArray();
|
||||
_maxGamePath = ((_fileList.Length > 0) ? _fileList.Max( P => ImGui.CalcTextSize(P.Item2).X ) : 0f) + TextSizePadding;
|
||||
}
|
||||
else
|
||||
{
|
||||
_fileList = null;
|
||||
_maxGamePath = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawFileLine((string, string) file)
|
||||
{
|
||||
ImGui.Selectable(file.Item2);
|
||||
ImGui.SameLine();
|
||||
ImGui.SetCursorPosX(_maxGamePath);
|
||||
ImGui.TextUnformatted(" <-- ");
|
||||
ImGui.SameLine();
|
||||
ImGui.Selectable(file.Item1);
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
var ret = ImGui.BeginTabItem( LabelTab );
|
||||
|
|
@ -53,14 +53,14 @@ namespace Penumbra.UI
|
|||
|
||||
if( ImGui.ListBoxHeader( "##effective_files", AutoFillSize ) )
|
||||
{
|
||||
foreach( var file in _fileList )
|
||||
DrawFileLine(file);
|
||||
|
||||
foreach( var file in _fileList )
|
||||
DrawFileLine(file);
|
||||
|
||||
ImGui.ListBoxFooter();
|
||||
}
|
||||
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +1,42 @@
|
|||
using ImGuiNET;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using System.IO;
|
||||
using System;
|
||||
using Penumbra.Importer;
|
||||
using Dalamud.Plugin;
|
||||
using System.Numerics;
|
||||
|
||||
using ImGuiNET;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using System.IO;
|
||||
using System;
|
||||
using Penumbra.Importer;
|
||||
using Dalamud.Plugin;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Penumbra.UI
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private class TabImport
|
||||
{
|
||||
private const string LabelTab = "Import Mods";
|
||||
private const string LabelImportButton = "Import TexTools Modpacks";
|
||||
private const string FileTypeFilter = "TexTools TTMP Modpack (*.ttmp2)|*.ttmp*|All files (*.*)|*.*";
|
||||
private const string LabelFileDialog = "Pick one or more modpacks.";
|
||||
private const string LabelFileImportRunning = "Import in progress...";
|
||||
private const string TooltipModpack1 = "Writing modpack to disk before extracting...";
|
||||
private const string FailedImport = "One or more of your modpacks failed to import.\nPlease submit a bug report.";
|
||||
|
||||
private const uint ColorRed = 0xFF0000C8;
|
||||
|
||||
private static readonly Vector2 ImportBarSize = new( -1, 0 );
|
||||
|
||||
private bool _isImportRunning = false;
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private class TabImport
|
||||
{
|
||||
private const string LabelTab = "Import Mods";
|
||||
private const string LabelImportButton = "Import TexTools Modpacks";
|
||||
private const string FileTypeFilter = "TexTools TTMP Modpack (*.ttmp2)|*.ttmp*|All files (*.*)|*.*";
|
||||
private const string LabelFileDialog = "Pick one or more modpacks.";
|
||||
private const string LabelFileImportRunning = "Import in progress...";
|
||||
private const string TooltipModpack1 = "Writing modpack to disk before extracting...";
|
||||
private const string FailedImport = "One or more of your modpacks failed to import.\nPlease submit a bug report.";
|
||||
|
||||
private const uint ColorRed = 0xFF0000C8;
|
||||
|
||||
private static readonly Vector2 ImportBarSize = new( -1, 0 );
|
||||
|
||||
private bool _isImportRunning = false;
|
||||
private bool _hasError = false;
|
||||
private TexToolsImport _texToolsImport = null!;
|
||||
private readonly SettingsInterface _base;
|
||||
|
||||
public TabImport(SettingsInterface ui) => _base = ui;
|
||||
|
||||
public bool IsImporting() => _isImportRunning;
|
||||
|
||||
private void RunImportTask()
|
||||
{
|
||||
_isImportRunning = true;
|
||||
private TexToolsImport _texToolsImport = null!;
|
||||
private readonly SettingsInterface _base;
|
||||
|
||||
public TabImport(SettingsInterface ui) => _base = ui;
|
||||
|
||||
public bool IsImporting() => _isImportRunning;
|
||||
|
||||
private void RunImportTask()
|
||||
{
|
||||
_isImportRunning = true;
|
||||
Task.Run( async () =>
|
||||
{
|
||||
var picker = new OpenFileDialog
|
||||
|
|
@ -51,7 +51,7 @@ namespace Penumbra.UI
|
|||
|
||||
if( result == DialogResult.OK )
|
||||
{
|
||||
_hasError = false;
|
||||
_hasError = false;
|
||||
|
||||
foreach( var fileName in picker.FileNames )
|
||||
{
|
||||
|
|
@ -73,19 +73,19 @@ namespace Penumbra.UI
|
|||
|
||||
_texToolsImport = null;
|
||||
_base.ReloadMods();
|
||||
}
|
||||
}
|
||||
_isImportRunning = false;
|
||||
} );
|
||||
}
|
||||
|
||||
private void DrawImportButton()
|
||||
{
|
||||
} );
|
||||
}
|
||||
|
||||
private void DrawImportButton()
|
||||
{
|
||||
if( ImGui.Button( LabelImportButton ) )
|
||||
{
|
||||
RunImportTask();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawImportProgress()
|
||||
{
|
||||
ImGui.Button( LabelFileImportRunning );
|
||||
|
|
@ -116,12 +116,12 @@ namespace Penumbra.UI
|
|||
}
|
||||
|
||||
private void DrawFailedImportMessage()
|
||||
{
|
||||
{
|
||||
ImGui.PushStyleColor( ImGuiCol.Text, ColorRed );
|
||||
ImGui.Text( FailedImport );
|
||||
ImGui.Text( FailedImport );
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
var ret = ImGui.BeginTabItem( LabelTab );
|
||||
|
|
@ -131,13 +131,13 @@ namespace Penumbra.UI
|
|||
if( !_isImportRunning )
|
||||
DrawImportButton();
|
||||
else
|
||||
DrawImportProgress();
|
||||
|
||||
if (_hasError)
|
||||
DrawImportProgress();
|
||||
|
||||
if (_hasError)
|
||||
DrawFailedImportMessage();
|
||||
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,53 +1,53 @@
|
|||
using ImGuiNET;
|
||||
|
||||
using ImGuiNET;
|
||||
|
||||
namespace Penumbra.UI
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private partial class TabInstalled
|
||||
{
|
||||
private const string LabelTab = "Installed Mods";
|
||||
|
||||
private readonly SettingsInterface _base;
|
||||
public readonly Selector _selector;
|
||||
public readonly ModPanel _modPanel;
|
||||
|
||||
public TabInstalled(SettingsInterface ui)
|
||||
{
|
||||
_base = ui;
|
||||
_selector = new(_base);
|
||||
_modPanel = new(_base, _selector);
|
||||
}
|
||||
|
||||
private void DrawNoModsAvailable()
|
||||
{
|
||||
ImGui.Text( "You don't have any mods :(" );
|
||||
ImGuiCustom.VerticalDistance(20f);
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private partial class TabInstalled
|
||||
{
|
||||
private const string LabelTab = "Installed Mods";
|
||||
|
||||
private readonly SettingsInterface _base;
|
||||
public readonly Selector _selector;
|
||||
public readonly ModPanel _modPanel;
|
||||
|
||||
public TabInstalled(SettingsInterface ui)
|
||||
{
|
||||
_base = ui;
|
||||
_selector = new(_base);
|
||||
_modPanel = new(_base, _selector);
|
||||
}
|
||||
|
||||
private void DrawNoModsAvailable()
|
||||
{
|
||||
ImGui.Text( "You don't have any mods :(" );
|
||||
ImGuiCustom.VerticalDistance(20f);
|
||||
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." );
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
var ret = ImGui.BeginTabItem( LabelTab );
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
var ret = ImGui.BeginTabItem( LabelTab );
|
||||
if( !ret )
|
||||
return;
|
||||
|
||||
if (_base._plugin.ModManager.Mods != null)
|
||||
{
|
||||
_selector.Draw();
|
||||
ImGui.SameLine();
|
||||
_modPanel.Draw();
|
||||
}
|
||||
else
|
||||
DrawNoModsAvailable();
|
||||
|
||||
ImGui.EndTabItem();
|
||||
|
||||
return;
|
||||
|
||||
if (_base._plugin.ModManager.Mods != null)
|
||||
{
|
||||
_selector.Draw();
|
||||
ImGui.SameLine();
|
||||
_modPanel.Draw();
|
||||
}
|
||||
else
|
||||
DrawNoModsAvailable();
|
||||
|
||||
ImGui.EndTabItem();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ namespace Penumbra.UI
|
|||
private const string ButtonRemoveFromGroup = "Remove from Group";
|
||||
private const string TooltipGamePathText = "Click to copy to clipboard.";
|
||||
private const string TooltipAboutEdit = "Use Ctrl+Enter for newlines.";
|
||||
|
||||
|
||||
private const string TextDefaultGamePath = "default";
|
||||
private const char GamePathsSeparator = ';';
|
||||
private static readonly string TooltipFilesTabEdit = $"{TooltipFilesTab}\nRed Files are replaced in another group or a different option in this group, but not contained in the current option.";
|
||||
|
|
|
|||
|
|
@ -1,149 +1,149 @@
|
|||
using ImGuiNET;
|
||||
using Dalamud.Plugin;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Diagnostics;
|
||||
using Penumbra.Models;
|
||||
|
||||
using ImGuiNET;
|
||||
using Dalamud.Plugin;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Diagnostics;
|
||||
using Penumbra.Models;
|
||||
|
||||
namespace Penumbra.UI
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private class ModPanel
|
||||
{
|
||||
private const string LabelModPanel = "selectedModInfo";
|
||||
private const string LabelEditName = "##editName";
|
||||
private const string LabelEditVersion = "##editVersion";
|
||||
private const string LabelEditAuthor = "##editAuthor";
|
||||
private const string LabelEditWebsite = "##editWebsite";
|
||||
private const string ButtonOpenWebsite = "Open Website";
|
||||
private const string LabelModEnabled = "Enabled";
|
||||
private const string LabelEditingEnabled = "Enable Editing";
|
||||
private const string ButtonOpenModFolder = "Open Mod Folder";
|
||||
private const string TooltipOpenModFolder = "Open the directory containing this mod in your default file explorer.";
|
||||
private const string ButtonEditJson = "Edit JSON";
|
||||
private const string TooltipEditJson = "Open the JSON configuration file in your default application for .json.";
|
||||
private const string ButtonReloadJson = "Reload JSON";
|
||||
private const string TooltipReloadJson = "Reload the configuration of all mods.";
|
||||
private const string ButtonDeduplicate = "Deduplicate";
|
||||
private const string TooltipDeduplicate = "Try to find identical files and remove duplicate occurences to reduce the mods disk size. Introduces an invisible single-option Group \"Duplicates\".";
|
||||
|
||||
private const float HeaderLineDistance = 10f;
|
||||
private static readonly Vector4 GreyColor = new( 1f, 1f, 1f, 0.66f );
|
||||
|
||||
private readonly SettingsInterface _base;
|
||||
private readonly Selector _selector;
|
||||
public readonly PluginDetails _details;
|
||||
|
||||
private bool _editMode = false;
|
||||
private string _currentWebsite;
|
||||
private bool _validWebsite;
|
||||
|
||||
public ModPanel(SettingsInterface ui, Selector s)
|
||||
{
|
||||
_base = ui;
|
||||
_selector = s;
|
||||
_details = new(_base, _selector);
|
||||
_currentWebsite = Meta?.Website;
|
||||
}
|
||||
|
||||
private ModInfo Mod { get{ return _selector.Mod(); } }
|
||||
private ModMeta Meta { get{ return Mod?.Mod.Meta; } }
|
||||
|
||||
private void DrawName()
|
||||
{
|
||||
var name = Meta.Name;
|
||||
if (ImGuiCustom.InputOrText(_editMode, LabelEditName, ref name, 64)
|
||||
&& name.Length > 0 && name != Meta.Name)
|
||||
{
|
||||
Meta.Name = name;
|
||||
_selector.SaveCurrentMod();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawVersion()
|
||||
{
|
||||
if (_editMode)
|
||||
{
|
||||
ImGui.BeginGroup();
|
||||
ImGui.Text("(Version ");
|
||||
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, ZeroVector);
|
||||
ImGui.SameLine();
|
||||
var version = Meta.Version ?? "";
|
||||
if (ImGuiCustom.ResizingTextInput( LabelEditVersion, ref version, 16)
|
||||
&& version != Meta.Version)
|
||||
{
|
||||
Meta.Version = version.Length > 0 ? version : null;
|
||||
_selector.SaveCurrentMod();
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.Text(")");
|
||||
ImGui.PopStyleVar();
|
||||
ImGui.EndGroup();
|
||||
}
|
||||
else if ((Meta.Version?.Length ?? 0) > 0)
|
||||
{
|
||||
ImGui.Text( $"(Version {Meta.Version})" );
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawAuthor()
|
||||
{
|
||||
ImGui.BeginGroup();
|
||||
ImGui.TextColored( GreyColor, "by" );
|
||||
|
||||
ImGui.SameLine();
|
||||
var author = Meta.Author ?? "";
|
||||
if (ImGuiCustom.InputOrText(_editMode, LabelEditAuthor, ref author, 64)
|
||||
&& author != Meta.Author)
|
||||
{
|
||||
Meta.Author = author.Length > 0 ? author : null;
|
||||
_selector.SaveCurrentMod();
|
||||
}
|
||||
ImGui.EndGroup();
|
||||
}
|
||||
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private class ModPanel
|
||||
{
|
||||
private const string LabelModPanel = "selectedModInfo";
|
||||
private const string LabelEditName = "##editName";
|
||||
private const string LabelEditVersion = "##editVersion";
|
||||
private const string LabelEditAuthor = "##editAuthor";
|
||||
private const string LabelEditWebsite = "##editWebsite";
|
||||
private const string ButtonOpenWebsite = "Open Website";
|
||||
private const string LabelModEnabled = "Enabled";
|
||||
private const string LabelEditingEnabled = "Enable Editing";
|
||||
private const string ButtonOpenModFolder = "Open Mod Folder";
|
||||
private const string TooltipOpenModFolder = "Open the directory containing this mod in your default file explorer.";
|
||||
private const string ButtonEditJson = "Edit JSON";
|
||||
private const string TooltipEditJson = "Open the JSON configuration file in your default application for .json.";
|
||||
private const string ButtonReloadJson = "Reload JSON";
|
||||
private const string TooltipReloadJson = "Reload the configuration of all mods.";
|
||||
private const string ButtonDeduplicate = "Deduplicate";
|
||||
private const string TooltipDeduplicate = "Try to find identical files and remove duplicate occurences to reduce the mods disk size. Introduces an invisible single-option Group \"Duplicates\".";
|
||||
|
||||
private const float HeaderLineDistance = 10f;
|
||||
private static readonly Vector4 GreyColor = new( 1f, 1f, 1f, 0.66f );
|
||||
|
||||
private readonly SettingsInterface _base;
|
||||
private readonly Selector _selector;
|
||||
public readonly PluginDetails _details;
|
||||
|
||||
private bool _editMode = false;
|
||||
private string _currentWebsite;
|
||||
private bool _validWebsite;
|
||||
|
||||
public ModPanel(SettingsInterface ui, Selector s)
|
||||
{
|
||||
_base = ui;
|
||||
_selector = s;
|
||||
_details = new(_base, _selector);
|
||||
_currentWebsite = Meta?.Website;
|
||||
}
|
||||
|
||||
private ModInfo Mod { get{ return _selector.Mod(); } }
|
||||
private ModMeta Meta { get{ return Mod?.Mod.Meta; } }
|
||||
|
||||
private void DrawName()
|
||||
{
|
||||
var name = Meta.Name;
|
||||
if (ImGuiCustom.InputOrText(_editMode, LabelEditName, ref name, 64)
|
||||
&& name.Length > 0 && name != Meta.Name)
|
||||
{
|
||||
Meta.Name = name;
|
||||
_selector.SaveCurrentMod();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawVersion()
|
||||
{
|
||||
if (_editMode)
|
||||
{
|
||||
ImGui.BeginGroup();
|
||||
ImGui.Text("(Version ");
|
||||
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, ZeroVector);
|
||||
ImGui.SameLine();
|
||||
var version = Meta.Version ?? "";
|
||||
if (ImGuiCustom.ResizingTextInput( LabelEditVersion, ref version, 16)
|
||||
&& version != Meta.Version)
|
||||
{
|
||||
Meta.Version = version.Length > 0 ? version : null;
|
||||
_selector.SaveCurrentMod();
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.Text(")");
|
||||
ImGui.PopStyleVar();
|
||||
ImGui.EndGroup();
|
||||
}
|
||||
else if ((Meta.Version?.Length ?? 0) > 0)
|
||||
{
|
||||
ImGui.Text( $"(Version {Meta.Version})" );
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawAuthor()
|
||||
{
|
||||
ImGui.BeginGroup();
|
||||
ImGui.TextColored( GreyColor, "by" );
|
||||
|
||||
ImGui.SameLine();
|
||||
var author = Meta.Author ?? "";
|
||||
if (ImGuiCustom.InputOrText(_editMode, LabelEditAuthor, ref author, 64)
|
||||
&& author != Meta.Author)
|
||||
{
|
||||
Meta.Author = author.Length > 0 ? author : null;
|
||||
_selector.SaveCurrentMod();
|
||||
}
|
||||
ImGui.EndGroup();
|
||||
}
|
||||
|
||||
private void DrawWebsite()
|
||||
{
|
||||
ImGui.BeginGroup();
|
||||
if (_editMode)
|
||||
{
|
||||
{
|
||||
ImGui.BeginGroup();
|
||||
if (_editMode)
|
||||
{
|
||||
ImGui.TextColored( GreyColor, "from" );
|
||||
ImGui.SameLine();
|
||||
var website = Meta.Website ?? "";
|
||||
if (ImGuiCustom.ResizingTextInput(LabelEditWebsite, ref website, 512)
|
||||
&& website != Meta.Website)
|
||||
{
|
||||
Meta.Website = website.Length > 0 ? website : null;
|
||||
_selector.SaveCurrentMod();
|
||||
}
|
||||
}
|
||||
else if (( Meta.Website?.Length ?? 0 ) > 0)
|
||||
{
|
||||
if (_currentWebsite != Meta.Website)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
var website = Meta.Website ?? "";
|
||||
if (ImGuiCustom.ResizingTextInput(LabelEditWebsite, ref website, 512)
|
||||
&& website != Meta.Website)
|
||||
{
|
||||
Meta.Website = website.Length > 0 ? website : null;
|
||||
_selector.SaveCurrentMod();
|
||||
}
|
||||
}
|
||||
else if (( Meta.Website?.Length ?? 0 ) > 0)
|
||||
{
|
||||
if (_currentWebsite != Meta.Website)
|
||||
{
|
||||
_currentWebsite = Meta.Website;
|
||||
_validWebsite = Uri.TryCreate( Meta.Website, UriKind.Absolute, out var uriResult )
|
||||
&& ( uriResult.Scheme == Uri.UriSchemeHttps || uriResult.Scheme == Uri.UriSchemeHttp );
|
||||
_validWebsite = Uri.TryCreate( Meta.Website, UriKind.Absolute, out var uriResult )
|
||||
&& ( uriResult.Scheme == Uri.UriSchemeHttps || uriResult.Scheme == Uri.UriSchemeHttp );
|
||||
}
|
||||
if( _validWebsite )
|
||||
{
|
||||
if( ImGui.SmallButton( ButtonOpenWebsite ) )
|
||||
{
|
||||
try
|
||||
if( ImGui.SmallButton( ButtonOpenWebsite ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
var process = new ProcessStartInfo(Meta.Website)
|
||||
{
|
||||
UseShellExecute = true
|
||||
};
|
||||
Process.Start(process);
|
||||
}
|
||||
catch(System.ComponentModel.Win32Exception)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
var process = new ProcessStartInfo(Meta.Website)
|
||||
{
|
||||
UseShellExecute = true
|
||||
};
|
||||
Process.Start(process);
|
||||
}
|
||||
catch(System.ComponentModel.Win32Exception)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
if( ImGui.IsItemHovered() )
|
||||
|
|
@ -155,121 +155,121 @@ namespace Penumbra.UI
|
|||
ImGui.SameLine();
|
||||
ImGui.Text( Meta.Website );
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui.EndGroup();
|
||||
}
|
||||
|
||||
private void DrawHeaderLine()
|
||||
{
|
||||
DrawName();
|
||||
ImGui.SameLine();
|
||||
DrawVersion();
|
||||
ImGui.SameLine();
|
||||
DrawAuthor();
|
||||
}
|
||||
|
||||
private void DrawHeaderLine()
|
||||
{
|
||||
DrawName();
|
||||
ImGui.SameLine();
|
||||
DrawWebsite();
|
||||
}
|
||||
|
||||
private void DrawEnabledMark()
|
||||
{
|
||||
DrawVersion();
|
||||
ImGui.SameLine();
|
||||
DrawAuthor();
|
||||
ImGui.SameLine();
|
||||
DrawWebsite();
|
||||
}
|
||||
|
||||
private void DrawEnabledMark()
|
||||
{
|
||||
var enabled = Mod.Enabled;
|
||||
if( ImGui.Checkbox( LabelModEnabled, ref enabled ) )
|
||||
{
|
||||
Mod.Enabled = enabled;
|
||||
_base._plugin.ModManager.Mods.Save();
|
||||
_base._plugin.ModManager.CalculateEffectiveFileList();
|
||||
_base._plugin.ModManager.CalculateEffectiveFileList();
|
||||
_base._menu._effectiveTab.RebuildFileList(_base._plugin.Configuration.ShowAdvanced);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawEditableMark()
|
||||
{
|
||||
ImGui.Checkbox( LabelEditingEnabled, ref _editMode);
|
||||
}
|
||||
|
||||
private void DrawOpenModFolderButton()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawEditableMark()
|
||||
{
|
||||
ImGui.Checkbox( LabelEditingEnabled, ref _editMode);
|
||||
}
|
||||
|
||||
private void DrawOpenModFolderButton()
|
||||
{
|
||||
if( ImGui.Button( ButtonOpenModFolder ) )
|
||||
{
|
||||
Process.Start( Mod.Mod.ModBasePath.FullName );
|
||||
}
|
||||
}
|
||||
if( ImGui.IsItemHovered() )
|
||||
ImGui.SetTooltip( TooltipOpenModFolder );
|
||||
}
|
||||
|
||||
private void DrawEditJsonButton()
|
||||
{
|
||||
ImGui.SetTooltip( TooltipOpenModFolder );
|
||||
}
|
||||
|
||||
private void DrawEditJsonButton()
|
||||
{
|
||||
if( ImGui.Button( ButtonEditJson ) )
|
||||
{
|
||||
Process.Start( _selector.SaveCurrentMod() );
|
||||
}
|
||||
}
|
||||
if( ImGui.IsItemHovered() )
|
||||
ImGui.SetTooltip( TooltipEditJson );
|
||||
}
|
||||
|
||||
private void DrawReloadJsonButton()
|
||||
{
|
||||
ImGui.SetTooltip( TooltipEditJson );
|
||||
}
|
||||
|
||||
private void DrawReloadJsonButton()
|
||||
{
|
||||
if( ImGui.Button( ButtonReloadJson ) )
|
||||
{
|
||||
_selector.ReloadCurrentMod();
|
||||
}
|
||||
}
|
||||
if( ImGui.IsItemHovered() )
|
||||
ImGui.SetTooltip( TooltipReloadJson );
|
||||
}
|
||||
|
||||
private void DrawDeduplicateButton()
|
||||
{
|
||||
ImGui.SetTooltip( TooltipReloadJson );
|
||||
}
|
||||
|
||||
private void DrawDeduplicateButton()
|
||||
{
|
||||
if( ImGui.Button( ButtonDeduplicate ) )
|
||||
{
|
||||
new Deduplicator(Mod.Mod.ModBasePath, Meta).Run();
|
||||
_selector.SaveCurrentMod();
|
||||
Mod.Mod.RefreshModFiles();
|
||||
_base._plugin.ModManager.CalculateEffectiveFileList();
|
||||
{
|
||||
new Deduplicator(Mod.Mod.ModBasePath, Meta).Run();
|
||||
_selector.SaveCurrentMod();
|
||||
Mod.Mod.RefreshModFiles();
|
||||
_base._plugin.ModManager.CalculateEffectiveFileList();
|
||||
_base._menu._effectiveTab.RebuildFileList(_base._plugin.Configuration.ShowAdvanced);
|
||||
}
|
||||
}
|
||||
if( ImGui.IsItemHovered() )
|
||||
ImGui.SetTooltip( TooltipDeduplicate );
|
||||
}
|
||||
|
||||
private void DrawEditLine()
|
||||
{
|
||||
DrawOpenModFolderButton();
|
||||
ImGui.SameLine();
|
||||
DrawEditJsonButton();
|
||||
ImGui.SameLine();
|
||||
DrawReloadJsonButton();
|
||||
ImGui.SameLine();
|
||||
DrawDeduplicateButton();
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
ImGui.SetTooltip( TooltipDeduplicate );
|
||||
}
|
||||
|
||||
private void DrawEditLine()
|
||||
{
|
||||
DrawOpenModFolderButton();
|
||||
ImGui.SameLine();
|
||||
DrawEditJsonButton();
|
||||
ImGui.SameLine();
|
||||
DrawReloadJsonButton();
|
||||
ImGui.SameLine();
|
||||
DrawDeduplicateButton();
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
if( Mod != null )
|
||||
{
|
||||
try
|
||||
{
|
||||
var ret = ImGui.BeginChild( LabelModPanel, AutoFillSize, true );
|
||||
if (!ret)
|
||||
var ret = ImGui.BeginChild( LabelModPanel, AutoFillSize, true );
|
||||
if (!ret)
|
||||
return;
|
||||
|
||||
|
||||
DrawHeaderLine();
|
||||
|
||||
|
||||
// Next line with fixed distance.
|
||||
ImGuiCustom.VerticalDistance(HeaderLineDistance);
|
||||
|
||||
DrawEnabledMark();
|
||||
if (_base._plugin.Configuration.ShowAdvanced)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
DrawEditableMark();
|
||||
}
|
||||
|
||||
// Next line, if editable.
|
||||
if (_editMode)
|
||||
DrawEditLine();
|
||||
|
||||
DrawEnabledMark();
|
||||
if (_base._plugin.Configuration.ShowAdvanced)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
DrawEditableMark();
|
||||
}
|
||||
|
||||
// Next line, if editable.
|
||||
if (_editMode)
|
||||
DrawEditLine();
|
||||
|
||||
_details.Draw(_editMode);
|
||||
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
catch( Exception ex )
|
||||
|
|
@ -277,7 +277,7 @@ namespace Penumbra.UI
|
|||
PluginLog.LogError( ex, "fuck" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,53 +1,53 @@
|
|||
using System.Numerics;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json;
|
||||
using ImGuiNET;
|
||||
using Penumbra.Mods;
|
||||
using Penumbra.Models;
|
||||
using Dalamud.Interface;
|
||||
|
||||
using System.Numerics;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json;
|
||||
using ImGuiNET;
|
||||
using Penumbra.Mods;
|
||||
using Penumbra.Models;
|
||||
using Dalamud.Interface;
|
||||
|
||||
namespace Penumbra.UI
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private class Selector
|
||||
{
|
||||
private const string LabelSelectorList = "##availableModList";
|
||||
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{ get{ return _base._plugin.ModManager.Mods; } }
|
||||
|
||||
private ModInfo _mod = null;
|
||||
private int _index = 0;
|
||||
private int? _deleteIndex = null;
|
||||
|
||||
public Selector(SettingsInterface ui)
|
||||
{
|
||||
_base = ui;
|
||||
}
|
||||
|
||||
private void DrawPriorityChangeButton(string iconString, bool up, int unavailableWhen)
|
||||
{
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private class Selector
|
||||
{
|
||||
private const string LabelSelectorList = "##availableModList";
|
||||
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{ get{ return _base._plugin.ModManager.Mods; } }
|
||||
|
||||
private ModInfo _mod = null;
|
||||
private int _index = 0;
|
||||
private int? _deleteIndex = null;
|
||||
|
||||
public Selector(SettingsInterface ui)
|
||||
{
|
||||
_base = ui;
|
||||
}
|
||||
|
||||
private void DrawPriorityChangeButton(string iconString, bool up, int unavailableWhen)
|
||||
{
|
||||
ImGui.PushFont( UiBuilder.IconFont );
|
||||
if( _index != unavailableWhen )
|
||||
{
|
||||
{
|
||||
if( ImGui.Button( iconString, SelectorButtonSizes ) )
|
||||
{
|
||||
{
|
||||
SetSelection(_index);
|
||||
_base._plugin.ModManager.ChangeModPriority( _mod, up );
|
||||
_index += up ? 1 : -1;
|
||||
|
|
@ -60,18 +60,18 @@ namespace Penumbra.UI
|
|||
ImGui.PopStyleVar();
|
||||
}
|
||||
|
||||
ImGui.PopFont();
|
||||
|
||||
ImGui.PopFont();
|
||||
|
||||
if( ImGui.IsItemHovered() )
|
||||
{
|
||||
ImGui.SetTooltip(
|
||||
_base._plugin.Configuration.InvertModListOrder ^ up ? TooltipMoveDown : TooltipMoveUp
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawModTrashButton()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawModTrashButton()
|
||||
{
|
||||
ImGui.PushFont( UiBuilder.IconFont );
|
||||
|
||||
if( ImGui.Button( FontAwesomeIcon.Trash.ToIconString(), SelectorButtonSizes ) )
|
||||
|
|
@ -79,48 +79,48 @@ namespace Penumbra.UI
|
|||
_deleteIndex = _index;
|
||||
}
|
||||
|
||||
ImGui.PopFont();
|
||||
|
||||
ImGui.PopFont();
|
||||
|
||||
if( ImGui.IsItemHovered() )
|
||||
ImGui.SetTooltip( TooltipDelete );
|
||||
}
|
||||
|
||||
private void DrawModAddButton()
|
||||
{
|
||||
ImGui.SetTooltip( TooltipDelete );
|
||||
}
|
||||
|
||||
private void DrawModAddButton()
|
||||
{
|
||||
ImGui.PushFont( UiBuilder.IconFont );
|
||||
|
||||
if( ImGui.Button( FontAwesomeIcon.Plus.ToIconString(), SelectorButtonSizes ) )
|
||||
{
|
||||
{
|
||||
// Do nothing. YEAH. #TODO.
|
||||
}
|
||||
|
||||
ImGui.PopFont();
|
||||
|
||||
ImGui.PopFont();
|
||||
|
||||
if( ImGui.IsItemHovered() )
|
||||
ImGui.SetTooltip( TooltipAdd );
|
||||
}
|
||||
|
||||
private void DrawModsSelectorButtons()
|
||||
{
|
||||
ImGui.SetTooltip( TooltipAdd );
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
DrawPriorityChangeButton(ArrowUpString, false, 0);
|
||||
ImGui.SameLine();
|
||||
DrawPriorityChangeButton(ArrowDownString, true, Mods?.ModSettings.Count - 1 ?? 0);
|
||||
ImGui.SameLine();
|
||||
DrawModTrashButton();
|
||||
ImGui.SameLine();
|
||||
DrawModAddButton();
|
||||
|
||||
ImGui.PopStyleVar( 3 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DrawDeleteModal()
|
||||
{
|
||||
if( _deleteIndex == null )
|
||||
return;
|
||||
if( _deleteIndex == null )
|
||||
return;
|
||||
|
||||
ImGui.OpenPopup( DialogDeleteMod );
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ namespace Penumbra.UI
|
|||
if( _mod?.Mod == null )
|
||||
{
|
||||
ImGui.CloseCurrentPopup();
|
||||
ImGui.EndPopup();
|
||||
ImGui.EndPopup();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ namespace Penumbra.UI
|
|||
{
|
||||
ImGui.CloseCurrentPopup();
|
||||
_base._plugin.ModManager.DeleteMod( _mod.Mod );
|
||||
ClearSelection();
|
||||
ClearSelection();
|
||||
_base.ReloadMods();
|
||||
}
|
||||
|
||||
|
|
@ -156,14 +156,14 @@ namespace Penumbra.UI
|
|||
}
|
||||
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
if (Mods == null)
|
||||
return;
|
||||
|
||||
{
|
||||
if (Mods == null)
|
||||
return;
|
||||
|
||||
// Selector pane
|
||||
ImGui.BeginGroup();
|
||||
ImGui.PushStyleVar( ImGuiStyleVar.ItemSpacing, ZeroVector );
|
||||
|
|
@ -203,37 +203,37 @@ namespace Penumbra.UI
|
|||
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;
|
||||
}
|
||||
|
||||
public 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public 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 )
|
||||
{
|
||||
for( var modIndex = 0; modIndex < Mods.ModSettings.Count; modIndex++ )
|
||||
|
|
@ -242,39 +242,39 @@ namespace Penumbra.UI
|
|||
|
||||
if( mod.Mod.Meta.Name != name )
|
||||
continue;
|
||||
|
||||
|
||||
SetSelection(modIndex, mod);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private string GetCurrentModMetaFile()
|
||||
{
|
||||
if( _mod == null )
|
||||
return "";
|
||||
return 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();
|
||||
_base._plugin.ModManager.CalculateEffectiveFileList();
|
||||
}
|
||||
|
||||
public string SaveCurrentMod()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetCurrentModMetaFile()
|
||||
{
|
||||
if( _mod == null )
|
||||
return "";
|
||||
return 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();
|
||||
_base._plugin.ModManager.CalculateEffectiveFileList();
|
||||
}
|
||||
|
||||
public string SaveCurrentMod()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,113 +1,113 @@
|
|||
using System.Diagnostics;
|
||||
using ImGuiNET;
|
||||
|
||||
using System.Diagnostics;
|
||||
using ImGuiNET;
|
||||
|
||||
namespace Penumbra.UI
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private class TabSettings
|
||||
{
|
||||
private const string LabelTab = "Settings";
|
||||
private const string LabelRootFolder = "Root Folder";
|
||||
private const string LabelRediscoverButton = "Rediscover Mods";
|
||||
private const string LabelOpenFolder = "Open Mods Folder";
|
||||
private const string LabelEnabled = "Enable Mods";
|
||||
private const string LabelInvertModOrder = "Invert mod load order (mods are loaded bottom up)";
|
||||
private const string LabelShowAdvanced = "Show Advanced Settings";
|
||||
private const string LabelLogLoadedFiles = "Log all loaded files";
|
||||
private const string LabelDisableNotifications = "Disable filesystem change notifications";
|
||||
private const string LabelEnableHttpApi = "Enable HTTP API";
|
||||
private const string LabelReloadResource = "Reload Player Resource";
|
||||
|
||||
private readonly SettingsInterface _base;
|
||||
private readonly Configuration _config;
|
||||
private bool _configChanged;
|
||||
|
||||
public TabSettings(SettingsInterface ui)
|
||||
{
|
||||
_base = ui;
|
||||
_config = _base._plugin.Configuration;
|
||||
_configChanged = false;
|
||||
}
|
||||
|
||||
private void DrawRootFolder()
|
||||
{
|
||||
var basePath = _config.CurrentCollection;
|
||||
{
|
||||
public partial class SettingsInterface
|
||||
{
|
||||
private class TabSettings
|
||||
{
|
||||
private const string LabelTab = "Settings";
|
||||
private const string LabelRootFolder = "Root Folder";
|
||||
private const string LabelRediscoverButton = "Rediscover Mods";
|
||||
private const string LabelOpenFolder = "Open Mods Folder";
|
||||
private const string LabelEnabled = "Enable Mods";
|
||||
private const string LabelInvertModOrder = "Invert mod load order (mods are loaded bottom up)";
|
||||
private const string LabelShowAdvanced = "Show Advanced Settings";
|
||||
private const string LabelLogLoadedFiles = "Log all loaded files";
|
||||
private const string LabelDisableNotifications = "Disable filesystem change notifications";
|
||||
private const string LabelEnableHttpApi = "Enable HTTP API";
|
||||
private const string LabelReloadResource = "Reload Player Resource";
|
||||
|
||||
private readonly SettingsInterface _base;
|
||||
private readonly Configuration _config;
|
||||
private bool _configChanged;
|
||||
|
||||
public TabSettings(SettingsInterface ui)
|
||||
{
|
||||
_base = ui;
|
||||
_config = _base._plugin.Configuration;
|
||||
_configChanged = false;
|
||||
}
|
||||
|
||||
private void DrawRootFolder()
|
||||
{
|
||||
var basePath = _config.CurrentCollection;
|
||||
if( ImGui.InputText( LabelRootFolder, ref basePath, 255 ) && _config.CurrentCollection != basePath )
|
||||
{
|
||||
_config.CurrentCollection = basePath;
|
||||
_configChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawRediscoverButton()
|
||||
{
|
||||
_config.CurrentCollection = basePath;
|
||||
_configChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawRediscoverButton()
|
||||
{
|
||||
if( ImGui.Button( LabelRediscoverButton ) )
|
||||
{
|
||||
_base.ReloadMods();
|
||||
_base._menu._installedTab._selector.ClearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawOpenModsButton()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawOpenModsButton()
|
||||
{
|
||||
if( ImGui.Button( LabelOpenFolder ) )
|
||||
{
|
||||
Process.Start( _config.CurrentCollection );
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawEnabledBox()
|
||||
{
|
||||
var enabled = _config.IsEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawEnabledBox()
|
||||
{
|
||||
var enabled = _config.IsEnabled;
|
||||
if( ImGui.Checkbox( LabelEnabled, ref enabled ) )
|
||||
{
|
||||
_config.IsEnabled = enabled;
|
||||
_configChanged = true;
|
||||
RefreshActors.RedrawAll(_base._plugin.PluginInterface.ClientState.Actors);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawInvertModOrderBox()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawInvertModOrderBox()
|
||||
{
|
||||
var invertOrder = _config.InvertModListOrder;
|
||||
if( ImGui.Checkbox( LabelInvertModOrder, ref invertOrder ) )
|
||||
{
|
||||
_config.InvertModListOrder = invertOrder;
|
||||
_base.ReloadMods();
|
||||
_base.ReloadMods();
|
||||
_configChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawShowAdvancedBox()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawShowAdvancedBox()
|
||||
{
|
||||
var showAdvanced = _config.ShowAdvanced;
|
||||
if( ImGui.Checkbox( LabelShowAdvanced, ref showAdvanced ) )
|
||||
{
|
||||
_config.ShowAdvanced = showAdvanced;
|
||||
_configChanged = true;
|
||||
_config.ShowAdvanced = showAdvanced;
|
||||
_configChanged = true;
|
||||
_base._menu._effectiveTab.RebuildFileList(showAdvanced);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawLogLoadedFilesBox()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawLogLoadedFilesBox()
|
||||
{
|
||||
if( _base._plugin.ResourceLoader != null )
|
||||
ImGui.Checkbox( LabelLogLoadedFiles, ref _base._plugin.ResourceLoader.LogAllFiles );
|
||||
}
|
||||
|
||||
private void DrawDisableNotificationsBox()
|
||||
{
|
||||
ImGui.Checkbox( LabelLogLoadedFiles, ref _base._plugin.ResourceLoader.LogAllFiles );
|
||||
}
|
||||
|
||||
private void DrawDisableNotificationsBox()
|
||||
{
|
||||
var fswatch = _config.DisableFileSystemNotifications;
|
||||
if( ImGui.Checkbox( LabelDisableNotifications, ref fswatch ) )
|
||||
{
|
||||
_config.DisableFileSystemNotifications = fswatch;
|
||||
_configChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawEnableHttpApiBox()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawEnableHttpApiBox()
|
||||
{
|
||||
var http = _config.EnableHttpApi;
|
||||
if( ImGui.Checkbox( LabelEnableHttpApi, ref http ) )
|
||||
{
|
||||
|
|
@ -118,57 +118,57 @@ namespace Penumbra.UI
|
|||
|
||||
_config.EnableHttpApi = http;
|
||||
_configChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawReloadResourceButton()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawReloadResourceButton()
|
||||
{
|
||||
if( ImGui.Button( LabelReloadResource ) )
|
||||
{
|
||||
_base._plugin.GameUtils.ReloadPlayerResources();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawAdvancedSettings()
|
||||
{
|
||||
DrawLogLoadedFilesBox();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawAdvancedSettings()
|
||||
{
|
||||
DrawLogLoadedFilesBox();
|
||||
DrawDisableNotificationsBox();
|
||||
DrawEnableHttpApiBox();
|
||||
DrawReloadResourceButton();
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
DrawEnableHttpApiBox();
|
||||
DrawReloadResourceButton();
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
var ret = ImGui.BeginTabItem( LabelTab );
|
||||
if( !ret )
|
||||
return;
|
||||
return;
|
||||
|
||||
DrawRootFolder();
|
||||
|
||||
DrawRediscoverButton();
|
||||
ImGui.SameLine();
|
||||
ImGui.SameLine();
|
||||
DrawOpenModsButton();
|
||||
|
||||
|
||||
ImGuiCustom.VerticalDistance(DefaultVerticalSpace);
|
||||
DrawEnabledBox();
|
||||
DrawEnabledBox();
|
||||
|
||||
ImGuiCustom.VerticalDistance(DefaultVerticalSpace);
|
||||
DrawInvertModOrderBox();
|
||||
|
||||
|
||||
ImGuiCustom.VerticalDistance(DefaultVerticalSpace);
|
||||
DrawShowAdvancedBox();
|
||||
|
||||
|
||||
if( _config.ShowAdvanced )
|
||||
DrawAdvancedSettings();
|
||||
|
||||
if( _configChanged )
|
||||
if( _configChanged )
|
||||
{
|
||||
_config.Save();
|
||||
_configChanged = false;
|
||||
_config.Save();
|
||||
_configChanged = false;
|
||||
}
|
||||
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
using System.Linq;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Penumbra.Util
|
||||
|
|
|
|||
|
|
@ -1,55 +1,55 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
public class SingleOrArrayConverter<T> : JsonConverter
|
||||
{
|
||||
public override bool CanConvert( Type objectType )
|
||||
{
|
||||
return (objectType == typeof(HashSet<T>));
|
||||
}
|
||||
|
||||
public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer )
|
||||
{
|
||||
var token = JToken.Load(reader);
|
||||
if (token.Type == JTokenType.Array)
|
||||
{
|
||||
return token.ToObject<HashSet<T>>();
|
||||
}
|
||||
return new HashSet<T>{ token.ToObject<T>() };
|
||||
}
|
||||
|
||||
public override bool CanWrite => false;
|
||||
|
||||
public override void WriteJson( JsonWriter writer, object value, JsonSerializer serializer )
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class DictSingleOrArrayConverter<T,U> : JsonConverter
|
||||
{
|
||||
public override bool CanConvert( Type objectType )
|
||||
{
|
||||
return (objectType == typeof(Dictionary<T, HashSet<U>>));
|
||||
}
|
||||
|
||||
public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer )
|
||||
{
|
||||
var token = JToken.Load(reader);
|
||||
|
||||
if (token.Type == JTokenType.Array)
|
||||
{
|
||||
return token.ToObject<HashSet<T>>();
|
||||
}
|
||||
return new HashSet<T>{ token.ToObject<T>() };
|
||||
}
|
||||
|
||||
public override bool CanWrite => false;
|
||||
|
||||
public override void WriteJson( JsonWriter writer, object value, JsonSerializer serializer )
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
public class SingleOrArrayConverter<T> : JsonConverter
|
||||
{
|
||||
public override bool CanConvert( Type objectType )
|
||||
{
|
||||
return (objectType == typeof(HashSet<T>));
|
||||
}
|
||||
|
||||
public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer )
|
||||
{
|
||||
var token = JToken.Load(reader);
|
||||
if (token.Type == JTokenType.Array)
|
||||
{
|
||||
return token.ToObject<HashSet<T>>();
|
||||
}
|
||||
return new HashSet<T>{ token.ToObject<T>() };
|
||||
}
|
||||
|
||||
public override bool CanWrite => false;
|
||||
|
||||
public override void WriteJson( JsonWriter writer, object value, JsonSerializer serializer )
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class DictSingleOrArrayConverter<T,U> : JsonConverter
|
||||
{
|
||||
public override bool CanConvert( Type objectType )
|
||||
{
|
||||
return (objectType == typeof(Dictionary<T, HashSet<U>>));
|
||||
}
|
||||
|
||||
public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer )
|
||||
{
|
||||
var token = JToken.Load(reader);
|
||||
|
||||
if (token.Type == JTokenType.Array)
|
||||
{
|
||||
return token.ToObject<HashSet<T>>();
|
||||
}
|
||||
return new HashSet<T>{ token.ToObject<T>() };
|
||||
}
|
||||
|
||||
public override bool CanWrite => false;
|
||||
|
||||
public override void WriteJson( JsonWriter writer, object value, JsonSerializer serializer )
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
using System.IO;
|
||||
|
||||
namespace Penumbra
|
||||
{
|
||||
public static class StringPathExtensions
|
||||
{
|
||||
private static char[] _invalid = Path.GetInvalidFileNameChars();
|
||||
public static string ReplaceInvalidPathSymbols( this string s, string replacement = "_" )
|
||||
{
|
||||
return string.Join( replacement, s.Split( _invalid ) );
|
||||
}
|
||||
|
||||
public static string RemoveInvalidPathSymbols( this string s )
|
||||
{
|
||||
return string.Concat( s.Split( _invalid ) );
|
||||
}
|
||||
}
|
||||
using System.IO;
|
||||
|
||||
namespace Penumbra
|
||||
{
|
||||
public static class StringPathExtensions
|
||||
{
|
||||
private static char[] _invalid = Path.GetInvalidFileNameChars();
|
||||
public static string ReplaceInvalidPathSymbols( this string s, string replacement = "_" )
|
||||
{
|
||||
return string.Join( replacement, s.Split( _invalid ) );
|
||||
}
|
||||
|
||||
public static string RemoveInvalidPathSymbols( this string s )
|
||||
{
|
||||
return string.Concat( s.Split( _invalid ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue