Add unpacking to import popup and fix line endings, improve global mod importer.

This commit is contained in:
Ottermandias 2026-01-08 23:17:26 +01:00
parent 31ea4902ca
commit 93e685ce58
8 changed files with 136 additions and 108 deletions

2
Luna

@ -1 +1 @@
Subproject commit d580f7a6ec62b0d7d60be07130133a54f10a3337 Subproject commit 616d66b1d384588c23a3b5725ad1330037ce6987

View file

@ -68,7 +68,8 @@ public sealed class ModFileSystem : BaseFileSystem, IDisposable, IRequiredServic
NotificationType.Warning); NotificationType.Warning);
} }
CreateDuplicateDataNode(parent, arguments.Mod.Name, arguments.Mod); var (data, _) = CreateDuplicateDataNode(parent, arguments.Mod.Name, arguments.Mod);
Selection.Select(data);
break; break;
case ModPathChangeType.Deleted: case ModPathChangeType.Deleted:
if (arguments.Mod.Node is not null) if (arguments.Mod.Node is not null)

View file

@ -84,9 +84,8 @@ public class ModImportManager(
return false; return false;
} }
modManager.AddMod(directory, true); mod = modManager.AddMod(directory, true);
mod = modManager.LastOrDefault(); return mod is not null && mod.ModPath == directory;
return mod != null && mod.ModPath == directory;
} }
public void Dispose() public void Dispose()

View file

@ -82,20 +82,21 @@ public sealed class ModManager : ModStorage, IDisposable, Luna.IService
} }
/// <summary> Load a new mod and add it to the manager if successful. </summary> /// <summary> Load a new mod and add it to the manager if successful. </summary>
public void AddMod(DirectoryInfo modFolder, bool deleteDefaultMeta) public Mod? AddMod(DirectoryInfo modFolder, bool deleteDefaultMeta)
{ {
if (this.Any(m => m.ModPath.Name == modFolder.Name)) if (this.Any(m => m.ModPath.Name == modFolder.Name))
return; return null;
Creator.SplitMultiGroups(modFolder); Creator.SplitMultiGroups(modFolder);
var mod = Creator.LoadMod(modFolder, true, deleteDefaultMeta); var mod = Creator.LoadMod(modFolder, true, deleteDefaultMeta);
if (mod == null) if (mod is null)
return; return null;
mod.Index = Count; mod.Index = Count;
Mods.Add(mod); Mods.Add(mod);
_communicator.ModPathChanged.Invoke(new ModPathChanged.Arguments(ModPathChangeType.Added, mod, null, mod.ModPath)); _communicator.ModPathChanged.Invoke(new ModPathChanged.Arguments(ModPathChangeType.Added, mod, null, mod.ModPath));
Penumbra.Log.Debug($"Added new mod {mod.Name} from {modFolder.FullName}."); Penumbra.Log.Debug($"Added new mod {mod.Name} from {modFolder.FullName}.");
return mod;
} }
/// <summary> /// <summary>

View file

@ -25,6 +25,20 @@ public sealed class GlobalModImporter : IRequiredService, IDisposable
dragDropManager.AddTarget(DragDropId, ImportFiles); dragDropManager.AddTarget(DragDropId, ImportFiles);
} }
public void DrawItemTarget()
{
using var target = Im.DragDrop.Target();
if (target.IsDropping("ModDragDrop"u8))
ImportFiles(_dragDropManager.DalamudManager.Files, []);
}
public void DrawWindowTarget()
{
using var target = Im.DragDrop.TargetWindow();
if (target.IsDropping("ModDragDrop"u8))
ImportFiles(_dragDropManager.DalamudManager.Files, []);
}
public void Dispose() public void Dispose()
{ {
_dragDropManager.RemoveSource(DragDropId); _dragDropManager.RemoveSource(DragDropId);
@ -39,7 +53,9 @@ public sealed class GlobalModImporter : IRequiredService, IDisposable
private static bool DragTooltip(IDragDropManager manager) private static bool DragTooltip(IDragDropManager manager)
{ {
Im.Text($"Dragging mods for import:\n\t{StringU8.Join("\n\t"u8, manager.Files.Select(Path.GetFileName))}"); Im.Text(manager.Files.Count > 1 ? "Dragging mods for import:"u8 : "Dragging mod for import:"u8);
foreach (var file in manager.Files.Select(Path.GetFileName))
Im.BulletText(file!);
return true; return true;
} }
} }

View file

@ -1,84 +1,87 @@
using ImSharp; using ImSharp;
using Luna; using Luna;
using Penumbra.Import.Structs; using Penumbra.Import.Structs;
using Penumbra.Mods.Manager; using Penumbra.Mods.Manager;
namespace Penumbra.UI; namespace Penumbra.UI;
/// <summary> Draw the progress information for import. </summary> /// <summary> Draw the progress information for import. </summary>
public sealed class ImportPopup : Window, IUiService public sealed class ImportPopup : Window
{ {
public const string WindowLabel = "Penumbra Import Status"; public const string WindowLabel = "Penumbra Import Status";
private readonly ModImportManager _modImportManager; private readonly ModImportManager _modImportManager;
private static readonly Vector2 OneHalf = Vector2.One / 2; private static readonly Vector2 OneHalf = Vector2.One / 2;
public bool WasDrawn { get; private set; } public bool WasDrawn { get; private set; }
public bool PopupWasDrawn { get; private set; } public bool PopupWasDrawn { get; private set; }
public ImportPopup(ModImportManager modImportManager) public ImportPopup(ModImportManager modImportManager)
: base(WindowLabel, : base(WindowLabel,
WindowFlags.NoCollapse WindowFlags.NoCollapse
| WindowFlags.NoDecoration | WindowFlags.NoDecoration
| WindowFlags.NoBackground | WindowFlags.NoBackground
| WindowFlags.NoMove | WindowFlags.NoMove
| WindowFlags.NoInputs | WindowFlags.NoInputs
| WindowFlags.NoNavFocus | WindowFlags.NoNavFocus
| WindowFlags.NoFocusOnAppearing | WindowFlags.NoFocusOnAppearing
| WindowFlags.NoBringToFrontOnFocus | WindowFlags.NoBringToFrontOnFocus
| WindowFlags.NoDocking | WindowFlags.NoDocking
| WindowFlags.NoTitleBar, true) | WindowFlags.NoTitleBar, true)
{ {
_modImportManager = modImportManager; _modImportManager = modImportManager;
DisableWindowSounds = true; DisableWindowSounds = true;
IsOpen = true; IsOpen = true;
RespectCloseHotkey = false; RespectCloseHotkey = false;
Collapsed = false; Collapsed = false;
SizeConstraints = new WindowSizeConstraints SizeConstraints = new WindowSizeConstraints
{ {
MinimumSize = Vector2.Zero, MinimumSize = Vector2.Zero,
MaximumSize = Vector2.Zero, MaximumSize = Vector2.Zero,
}; };
} }
public override void PreOpenCheck() public override void PreOpenCheck()
{ {
WasDrawn = false; WasDrawn = false;
PopupWasDrawn = false; PopupWasDrawn = false;
_modImportManager.TryUnpacking(); _modImportManager.TryUnpacking();
IsOpen = true; IsOpen = true;
}
while (_modImportManager.AddUnpackedMod(out _))
public override void Draw() ;
{ }
WasDrawn = true;
if (!_modImportManager.IsImporting(out var import)) public override void Draw()
return; {
WasDrawn = true;
if (!Im.Popup.IsOpen("##PenumbraImportPopup"u8)) if (!_modImportManager.IsImporting(out var import))
Im.Popup.Open("##PenumbraImportPopup"u8); return;
var display = Im.Io.DisplaySize; if (!Im.Popup.IsOpen("##PenumbraImportPopup"u8))
var height = Math.Max(display.Y / 4, 15 * Im.Style.FrameHeightWithSpacing); Im.Popup.Open("##PenumbraImportPopup"u8);
var width = display.X / 8;
var size = new Vector2(width * 2, height); var display = Im.Io.DisplaySize;
Im.Window.SetNextPosition(Im.Viewport.Main.Center, Condition.Always, OneHalf); var height = Math.Max(display.Y / 4, 15 * Im.Style.FrameHeightWithSpacing);
Im.Window.SetNextSize(size); var width = display.X / 8;
using var popup = Im.Popup.Begin("##PenumbraImportPopup"u8, WindowFlags.Modal); var size = new Vector2(width * 2, height);
PopupWasDrawn = true; Im.Window.SetNextPosition(Im.Viewport.Main.Center, Condition.Always, OneHalf);
var terminate = false; Im.Window.SetNextSize(size);
using (var child = Im.Child.Begin("##import"u8, new Vector2(-1, size.Y - Im.Style.FrameHeight * 2))) using var popup = Im.Popup.Begin("##PenumbraImportPopup"u8, WindowFlags.Modal);
{ PopupWasDrawn = true;
if (child.Success && import.DrawProgressInfo(new Vector2(-1, Im.Style.FrameHeight))) var terminate = false;
if (!Im.Mouse.IsHoveringRectangle(Rectangle.FromSize(Im.Window.Position, Im.Window.Size)) using (var child = Im.Child.Begin("##import"u8, new Vector2(-1, size.Y - Im.Style.FrameHeight * 2)))
&& Im.Mouse.IsClicked(MouseButton.Left)) {
terminate = true; if (child.Success && import.DrawProgressInfo(new Vector2(-1, Im.Style.FrameHeight)))
} if (!Im.Mouse.IsHoveringRectangle(Rectangle.FromSize(Im.Window.Position, Im.Window.Size))
&& Im.Mouse.IsClicked(MouseButton.Left))
terminate |= import.State == ImporterState.Done terminate = true;
? Im.Button("Close"u8, -Vector2.UnitX) }
: import.DrawCancelButton(-Vector2.UnitX);
if (terminate) terminate |= import.State == ImporterState.Done
_modImportManager.ClearImport(); ? Im.Button("Close"u8, -Vector2.UnitX)
} : import.DrawCancelButton(-Vector2.UnitX);
} if (terminate)
_modImportManager.ClearImport();
}
}

View file

@ -12,17 +12,19 @@ public sealed class MainWindow : Window
private readonly IDalamudPluginInterface _pluginInterface; private readonly IDalamudPluginInterface _pluginInterface;
private readonly Configuration _config; private readonly Configuration _config;
private readonly ValidityChecker _validityChecker; private readonly ValidityChecker _validityChecker;
private readonly GlobalModImporter _globalModImporter;
private Penumbra? _penumbra; private Penumbra? _penumbra;
private MainTabBar _configTabs = null!; private MainTabBar _configTabs = null!;
private string? _lastException; private string? _lastException;
public MainWindow(IDalamudPluginInterface pi, Configuration config, ValidityChecker checker, public MainWindow(IDalamudPluginInterface pi, Configuration config, ValidityChecker checker,
TutorialService tutorial) TutorialService tutorial, GlobalModImporter globalModImporter)
: base(GetLabel(checker)) : base(GetLabel(checker))
{ {
_pluginInterface = pi; _pluginInterface = pi;
_config = config; _config = config;
_validityChecker = checker; _validityChecker = checker;
_globalModImporter = globalModImporter;
RespectCloseHotkey = true; RespectCloseHotkey = true;
tutorial.UpdateTutorialStep(); tutorial.UpdateTutorialStep();
@ -61,6 +63,7 @@ public sealed class MainWindow : Window
public override void Draw() public override void Draw()
{ {
UiHelpers.SetupCommonSizes(); UiHelpers.SetupCommonSizes();
_globalModImporter.DrawWindowTarget();
try try
{ {
if (_validityChecker.ImcExceptions.Count > 0) if (_validityChecker.ImcExceptions.Count > 0)

View file

@ -1,3 +1,4 @@
using ImSharp;
using Luna; using Luna;
using Penumbra.Collections.Manager; using Penumbra.Collections.Manager;
using Penumbra.Mods; using Penumbra.Mods;
@ -16,9 +17,11 @@ public sealed class ModFileSystemDrawer : FileSystemDrawer<ModFileSystemCache.Mo
public readonly FileDialogService FileService; public readonly FileDialogService FileService;
public readonly TutorialService Tutorial; public readonly TutorialService Tutorial;
public readonly CommunicatorService Communicator; public readonly CommunicatorService Communicator;
public readonly GlobalModImporter GlobalModImporter;
public ModFileSystemDrawer(ModFileSystem fileSystem, ModManager modManager, CollectionManager collectionManager, Configuration config, public ModFileSystemDrawer(ModFileSystem fileSystem, ModManager modManager, CollectionManager collectionManager, Configuration config,
ModImportManager modImport, FileDialogService fileService, TutorialService tutorial, CommunicatorService communicator) ModImportManager modImport, FileDialogService fileService, TutorialService tutorial, CommunicatorService communicator,
GlobalModImporter globalModImporter)
: base(fileSystem, new ModFilter(modManager, collectionManager.Active)) : base(fileSystem, new ModFilter(modManager, collectionManager.Active))
{ {
ModManager = modManager; ModManager = modManager;
@ -27,27 +30,29 @@ public sealed class ModFileSystemDrawer : FileSystemDrawer<ModFileSystemCache.Mo
ModImport = modImport; ModImport = modImport;
FileService = fileService; FileService = fileService;
Tutorial = tutorial; Tutorial = tutorial;
Communicator = communicator; Communicator = communicator;
GlobalModImporter = globalModImporter;
SortMode = Config.SortMode;
MainContext.AddButton(new ClearTemporarySettingsButton(this), 105); MainContext.AddButton(new ClearTemporarySettingsButton(this), 105);
MainContext.AddButton(new ClearDefaultImportFolderButton(this), -10); MainContext.AddButton(new ClearDefaultImportFolderButton(this), -10);
MainContext.AddButton(new ClearQuickMoveFoldersButtons(this), -20); MainContext.AddButton(new ClearQuickMoveFoldersButtons(this), -20);
FolderContext.AddButton(new SetDescendantsButton(this, true), 11); FolderContext.AddButton(new SetDescendantsButton(this, true), 11);
FolderContext.AddButton(new SetDescendantsButton(this, false), 10); FolderContext.AddButton(new SetDescendantsButton(this, false), 10);
FolderContext.AddButton(new SetDescendantsButton(this, true, true), 6); FolderContext.AddButton(new SetDescendantsButton(this, true, true), 6);
FolderContext.AddButton(new SetDescendantsButton(this, false, true), 5); FolderContext.AddButton(new SetDescendantsButton(this, false, true), 5);
FolderContext.AddButton(new SetDefaultImportFolderButton(this), -50); FolderContext.AddButton(new SetDefaultImportFolderButton(this), -50);
FolderContext.AddButton(new SetQuickMoveFoldersButtons(this), -70); FolderContext.AddButton(new SetQuickMoveFoldersButtons(this), -70);
DataContext.AddButton(new ToggleFavoriteButton(this), 10); DataContext.AddButton(new ToggleFavoriteButton(this), 10);
DataContext.AddButton(new TemporaryButtons(this), 20); DataContext.AddButton(new TemporaryButtons(this), 20);
DataContext.AddButton(new MoveToQuickMoveFoldersButtons(this), -100); DataContext.AddButton(new MoveToQuickMoveFoldersButtons(this), -100);
Footer.Buttons.AddButton(new AddNewModButton(this), 1000); Footer.Buttons.AddButton(new AddNewModButton(this), 1000);
Footer.Buttons.AddButton(new ImportModButton(this), 900); Footer.Buttons.AddButton(new ImportModButton(this), 900);
Footer.Buttons.AddButton(new HelpButton(this), 500); Footer.Buttons.AddButton(new HelpButton(this), 500);
Footer.Buttons.AddButton(new DeleteSelectionButton(this), -100); Footer.Buttons.AddButton(new DeleteSelectionButton(this), -100);
} }
public override ReadOnlySpan<byte> Id public override ReadOnlySpan<byte> Id