Add ExportManager.

This commit is contained in:
Ottermandias 2023-03-28 16:58:20 +02:00
parent 2b7292adb8
commit a8000fbf14
11 changed files with 141 additions and 89 deletions

View file

@ -256,7 +256,7 @@ public unsafe class MetaState : IDisposable
using var decals =
new DecalReverter(_characterUtility, _resources, resolveData.ModCollection, UsesDecal(0, data));
var ret = _changeCustomize.Original(human, data, skipEquipment);
_inChangeCustomize = false;
_inChangeCustomize = false;
return ret;
}

View file

@ -10,17 +10,15 @@ public class ModBackup
{
public static bool CreatingBackup { get; private set; }
private readonly ModManager _modManager;
private readonly Mod _mod;
public readonly string Name;
public readonly bool Exists;
private readonly Mod _mod;
public readonly string Name;
public readonly bool Exists;
public ModBackup(ModManager modManager, Mod mod)
{
_modManager = modManager;
_mod = mod;
Name = Path.Combine(_modManager.ExportDirectory.FullName, _mod.ModPath.Name) + ".pmp";
Exists = File.Exists(Name);
public ModBackup(ExportManager exportManager, Mod mod)
{
_mod = mod;
Name = Path.Combine(exportManager.ExportDirectory.FullName, _mod.ModPath.Name) + ".pmp";
Exists = File.Exists(Name);
}
/// <summary> Migrate file extensions. </summary>
@ -118,7 +116,7 @@ public class ModBackup
/// Restore a mod from a pre-existing backup. Does not check if the mod contained in the backup is even similar.
/// Does an automatic reload after extraction.
/// </summary>
public void Restore()
public void Restore(ModManager modManager)
{
try
{
@ -130,7 +128,7 @@ public class ModBackup
ZipFile.ExtractToDirectory(Name, _mod.ModPath.FullName);
Penumbra.Log.Debug($"Extracted exported file {Name} to {_mod.ModPath.FullName}.");
_modManager.ReloadMod(_mod.Index);
modManager.ReloadMod(_mod.Index);
}
catch (Exception e)
{

View file

@ -0,0 +1,89 @@
using System;
using System.IO;
namespace Penumbra.Mods;
public class ExportManager : IDisposable
{
private readonly Configuration _config;
private readonly ModManager _modManager;
private DirectoryInfo? _exportDirectory;
public DirectoryInfo ExportDirectory
=> _exportDirectory ?? _modManager.BasePath;
public ExportManager(Configuration config, ModManager modManager)
{
_config = config;
_modManager = modManager;
UpdateExportDirectory(_config.ExportDirectory, false);
_modManager.ModPathChanged += OnModPathChange;
}
/// <inheritdoc cref="UpdateExportDirectory(string, bool)"/>
public void UpdateExportDirectory(string newDirectory)
=> UpdateExportDirectory(newDirectory, true);
/// <summary>
/// Update the export directory to a new directory. Can also reset it to null with empty input.
/// If the directory is changed, all existing backups will be moved to the new one.
/// </summary>
/// <param name="newDirectory">The new directory name.</param>
/// <param name="change">Can be used to stop saving for the initial setting</param>
private void UpdateExportDirectory(string newDirectory, bool change)
{
if (newDirectory.Length == 0)
{
if (_exportDirectory == null)
return;
_exportDirectory = null;
_config.ExportDirectory = string.Empty;
_config.Save();
return;
}
var dir = new DirectoryInfo(newDirectory);
if (dir.FullName.Equals(_exportDirectory?.FullName, StringComparison.OrdinalIgnoreCase))
return;
if (!dir.Exists)
try
{
Directory.CreateDirectory(dir.FullName);
}
catch (Exception e)
{
Penumbra.Log.Error($"Could not create Export Directory:\n{e}");
return;
}
if (change)
foreach (var mod in _modManager)
new ModBackup(this, mod).Move(dir.FullName);
_exportDirectory = dir;
if (!change)
return;
_config.ExportDirectory = dir.FullName;
_config.Save();
}
public void Dispose()
=> _modManager.ModPathChanged -= OnModPathChange;
/// <summary> Automatically migrate the backup file to the new name if any exists. </summary>
private void OnModPathChange(ModPathChangeType type, Mod mod, DirectoryInfo? oldDirectory,
DirectoryInfo? newDirectory)
{
if (type is not ModPathChangeType.Moved || oldDirectory == null || newDirectory == null)
return;
mod.ModPath = oldDirectory;
new ModBackup(this, mod).Move(null, newDirectory.Name);
mod.ModPath = newDirectory;
}
}

View file

@ -57,7 +57,6 @@ public partial class ModManager
}
DataEditor.MoveDataFile(oldDirectory, dir);
new ModBackup(this, mod).Move(null, dir.Name);
dir.Refresh();
mod.ModPath = dir;

View file

@ -9,11 +9,6 @@ namespace Penumbra.Mods;
public sealed partial class ModManager
{
public DirectoryInfo BasePath { get; private set; } = null!;
private DirectoryInfo? _exportDirectory;
public DirectoryInfo ExportDirectory
=> _exportDirectory ?? BasePath;
public bool Valid { get; private set; }
public event Action? ModDiscoveryStarted;
@ -105,45 +100,4 @@ public sealed partial class ModManager
if (MigrateModBackups)
ModBackup.MigrateZipToPmp(this);
}
public void UpdateExportDirectory(string newDirectory, bool change)
{
if (newDirectory.Length == 0)
{
if (_exportDirectory == null)
return;
_exportDirectory = null;
_config.ExportDirectory = string.Empty;
_config.Save();
return;
}
var dir = new DirectoryInfo(newDirectory);
if (dir.FullName.Equals(_exportDirectory?.FullName, StringComparison.OrdinalIgnoreCase))
return;
if (!dir.Exists)
try
{
Directory.CreateDirectory(dir.FullName);
}
catch (Exception e)
{
Penumbra.Log.Error($"Could not create Export Directory:\n{e}");
return;
}
if (change)
foreach (var mod in _mods)
new ModBackup(this, mod).Move(dir.FullName);
_exportDirectory = dir;
if (change)
{
_config.ExportDirectory = dir.FullName;
_config.Save();
}
}
}

View file

@ -114,7 +114,6 @@ public sealed partial class ModManager : IReadOnlyList<Mod>, IDisposable
OptionEditor = optionEditor;
ModDirectoryChanged += OnModDirectoryChange;
SetBaseDirectory(config.ModDirectory, true);
UpdateExportDirectory(_config.ExportDirectory, false);
_communicator.ModOptionChanged.Event += OnModOptionChange;
ModPathChanged += OnModPathChange;
DiscoverMods();

View file

@ -47,11 +47,11 @@ public readonly struct ModSaveGroup : ISavable
public ModSaveGroup(Mod mod, int groupIdx)
{
_basePath = mod.ModPath;
_groupIdx = groupIdx;
if (_groupIdx < 0)
_defaultMod = mod.Default;
else
_group = mod.Groups[groupIdx];
_groupIdx = groupIdx;
_group = mod.Groups[_groupIdx];
}
public ModSaveGroup(DirectoryInfo basePath, IModGroup group, int groupIdx)

View file

@ -93,6 +93,7 @@ public class PenumbraNew
.AddSingleton<ModDataEditor>()
.AddSingleton<ModOptionEditor>()
.AddSingleton<ModManager>()
.AddSingleton<ExportManager>()
.AddSingleton<ModFileSystem>();
// Add Resource services

View file

@ -2,6 +2,7 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Dalamud.Interface;
using Dalamud.Interface.ImGuiFileDialog;
@ -87,8 +88,9 @@ public class FileDialogService : IDisposable
return (valid, list) =>
{
_isOpen = false;
_startPaths[title] = GetCurrentLocation();
callback(valid, list);
var loc = HandleRoot(GetCurrentLocation());
_startPaths[title] = loc;
callback(valid, list.Select(HandleRoot).ToList());
};
}
@ -97,14 +99,20 @@ public class FileDialogService : IDisposable
return (valid, list) =>
{
_isOpen = false;
var loc = GetCurrentLocation();
if (loc.Length == 2)
loc += '\\';
var loc = HandleRoot(GetCurrentLocation());
_startPaths[title] = loc;
callback(valid, list);
callback(valid, HandleRoot(list));
};
}
private static string HandleRoot(string path)
{
if (path.Length == 2 && path[1] == ':')
return path + '\\';
return path;
}
// TODO: maybe change this from reflection when its public.
private string GetCurrentLocation()
=> (_manager.GetType().GetField("dialog", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(_manager) as FileDialog)

View file

@ -23,6 +23,7 @@ public class ModPanelEditTab : ITab
private readonly ChatService _chat;
private readonly FilenameService _filenames;
private readonly ModManager _modManager;
private readonly ExportManager _exportManager;
private readonly ModFileSystem _fileSystem;
private readonly ModFileSystemSelector _selector;
private readonly ModEditWindow _editWindow;
@ -36,15 +37,16 @@ public class ModPanelEditTab : ITab
private Mod _mod = null!;
public ModPanelEditTab(ModManager modManager, ModFileSystemSelector selector, ModFileSystem fileSystem, ChatService chat,
ModEditWindow editWindow, ModEditor editor, FilenameService filenames)
ModEditWindow editWindow, ModEditor editor, FilenameService filenames, ExportManager exportManager)
{
_modManager = modManager;
_selector = selector;
_fileSystem = fileSystem;
_chat = chat;
_editWindow = editWindow;
_editor = editor;
_filenames = filenames;
_modManager = modManager;
_selector = selector;
_fileSystem = fileSystem;
_chat = chat;
_editWindow = editWindow;
_editor = editor;
_filenames = filenames;
_exportManager = exportManager;
}
public ReadOnlySpan<byte> Label
@ -147,7 +149,7 @@ public class ModPanelEditTab : ITab
private void BackupButtons(Vector2 buttonSize)
{
var backup = new ModBackup(_modManager, _mod);
var backup = new ModBackup(_exportManager, _mod);
var tt = ModBackup.CreatingBackup
? "Already exporting a mod."
: backup.Exists
@ -168,7 +170,7 @@ public class ModPanelEditTab : ITab
: $"Exported mod \"{backup.Name}\" does not exist.";
ImGui.SameLine();
if (ImGuiUtil.DrawDisabledButton("Restore From Export", buttonSize, tt, !backup.Exists))
backup.Restore();
backup.Restore(_modManager);
}
/// <summary> Anything about editing the regular meta information about the mod. </summary>
@ -306,11 +308,11 @@ public class ModPanelEditTab : ITab
private static int _newDescriptionIdx = -1;
private static int _newDescriptionOptionIdx = -1;
private static Mod? _mod;
private static FilenameService? _fileNames;
private static FilenameService? _fileNames;
public static void OpenPopup(FilenameService filenames, Mod mod, int groupIdx, int optionIdx = -1)
{
_fileNames = filenames;
_fileNames = filenames;
_newDescriptionIdx = groupIdx;
_newDescriptionOptionIdx = optionIdx;
_newDescription = groupIdx < 0
@ -598,7 +600,8 @@ public class ModPanelEditTab : ITab
if (_dragDropGroupIdx == groupIdx)
{
var sourceOption = _dragDropOptionIdx;
panel._delayedActions.Enqueue(() => panel._modManager.OptionEditor.MoveOption(panel._mod, groupIdx, sourceOption, optionIdx));
panel._delayedActions.Enqueue(
() => panel._modManager.OptionEditor.MoveOption(panel._mod, groupIdx, sourceOption, optionIdx));
}
else
{

View file

@ -9,7 +9,6 @@ using ImGuiNET;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Widgets;
using Penumbra.Interop;
using Penumbra.Interop.Services;
using Penumbra.Mods;
using Penumbra.Services;
@ -31,7 +30,8 @@ public class SettingsTab : ITab
private readonly TutorialService _tutorial;
private readonly Penumbra _penumbra;
private readonly FileDialogService _fileDialog;
private readonly ModManager _modManager;
private readonly ModManager _modManager;
private readonly ExportManager _exportManager;
private readonly ModFileSystemSelector _selector;
private readonly CharacterUtility _characterUtility;
private readonly ResidentResourceManager _residentResources;
@ -39,7 +39,7 @@ public class SettingsTab : ITab
public SettingsTab(Configuration config, FontReloader fontReloader, TutorialService tutorial, Penumbra penumbra,
FileDialogService fileDialog, ModManager modManager, ModFileSystemSelector selector, CharacterUtility characterUtility,
ResidentResourceManager residentResources, DalamudServices dalamud)
ResidentResourceManager residentResources, DalamudServices dalamud, ExportManager exportManager)
{
_config = config;
_fontReloader = fontReloader;
@ -51,6 +51,7 @@ public class SettingsTab : ITab
_characterUtility = characterUtility;
_residentResources = residentResources;
_dalamud = dalamud;
_exportManager = exportManager;
}
public void DrawHeader()
@ -114,7 +115,7 @@ public class SettingsTab : ITab
/// <summary> Check a potential new root directory for validity and return the button text and whether it is valid. </summary>
private static (string Text, bool Valid) CheckRootDirectoryPath(string newName, string old, bool selected)
{
{
static bool IsSubPathOf(string basePath, string subPath)
{
if (basePath.Length == 0)
@ -127,7 +128,7 @@ public class SettingsTab : ITab
if (newName.Length > RootDirectoryMaxLength)
return ($"Path is too long. The maximum length is {RootDirectoryMaxLength}.", false);
if (Path.GetDirectoryName(newName) == null)
if (Path.GetDirectoryName(newName).IsNullOrEmpty())
return ("Path is not allowed to be a drive root. Please add a directory.", false);
var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
@ -553,7 +554,7 @@ public class SettingsTab : ITab
_tempExportDirectory = tmp;
if (ImGui.IsItemDeactivatedAfterEdit())
_modManager.UpdateExportDirectory(_tempExportDirectory, true);
_exportManager.UpdateExportDirectory(_tempExportDirectory);
ImGui.SameLine();
if (ImGuiUtil.DrawDisabledButton($"{FontAwesomeIcon.Folder.ToIconString()}##export", UiHelpers.IconButtonSize,
@ -567,7 +568,7 @@ public class SettingsTab : ITab
_fileDialog.OpenFolderPicker("Choose Default Export Directory", (b, s) =>
{
if (b)
Penumbra.ModManager.UpdateExportDirectory(s, true);
_exportManager.UpdateExportDirectory(s);
}, startDir, false);
}