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);
}
CreateDuplicateDataNode(parent, arguments.Mod.Name, arguments.Mod);
var (data, _) = CreateDuplicateDataNode(parent, arguments.Mod.Name, arguments.Mod);
Selection.Select(data);
break;
case ModPathChangeType.Deleted:
if (arguments.Mod.Node is not null)

View file

@ -84,9 +84,8 @@ public class ModImportManager(
return false;
}
modManager.AddMod(directory, true);
mod = modManager.LastOrDefault();
return mod != null && mod.ModPath == directory;
mod = modManager.AddMod(directory, true);
return mod is not null && mod.ModPath == directory;
}
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>
public void AddMod(DirectoryInfo modFolder, bool deleteDefaultMeta)
public Mod? AddMod(DirectoryInfo modFolder, bool deleteDefaultMeta)
{
if (this.Any(m => m.ModPath.Name == modFolder.Name))
return;
return null;
Creator.SplitMultiGroups(modFolder);
var mod = Creator.LoadMod(modFolder, true, deleteDefaultMeta);
if (mod == null)
return;
if (mod is null)
return null;
mod.Index = Count;
Mods.Add(mod);
_communicator.ModPathChanged.Invoke(new ModPathChanged.Arguments(ModPathChangeType.Added, mod, null, mod.ModPath));
Penumbra.Log.Debug($"Added new mod {mod.Name} from {modFolder.FullName}.");
return mod;
}
/// <summary>

View file

@ -25,6 +25,20 @@ public sealed class GlobalModImporter : IRequiredService, IDisposable
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()
{
_dragDropManager.RemoveSource(DragDropId);
@ -39,7 +53,9 @@ public sealed class GlobalModImporter : IRequiredService, IDisposable
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;
}
}

View file

@ -1,84 +1,87 @@
using ImSharp;
using Luna;
using Penumbra.Import.Structs;
using Penumbra.Mods.Manager;
namespace Penumbra.UI;
/// <summary> Draw the progress information for import. </summary>
public sealed class ImportPopup : Window, IUiService
{
public const string WindowLabel = "Penumbra Import Status";
private readonly ModImportManager _modImportManager;
private static readonly Vector2 OneHalf = Vector2.One / 2;
public bool WasDrawn { get; private set; }
public bool PopupWasDrawn { get; private set; }
public ImportPopup(ModImportManager modImportManager)
: base(WindowLabel,
WindowFlags.NoCollapse
| WindowFlags.NoDecoration
| WindowFlags.NoBackground
| WindowFlags.NoMove
| WindowFlags.NoInputs
| WindowFlags.NoNavFocus
| WindowFlags.NoFocusOnAppearing
| WindowFlags.NoBringToFrontOnFocus
| WindowFlags.NoDocking
| WindowFlags.NoTitleBar, true)
{
_modImportManager = modImportManager;
DisableWindowSounds = true;
IsOpen = true;
RespectCloseHotkey = false;
Collapsed = false;
SizeConstraints = new WindowSizeConstraints
{
MinimumSize = Vector2.Zero,
MaximumSize = Vector2.Zero,
};
}
public override void PreOpenCheck()
{
WasDrawn = false;
PopupWasDrawn = false;
_modImportManager.TryUnpacking();
IsOpen = true;
}
public override void Draw()
{
WasDrawn = true;
if (!_modImportManager.IsImporting(out var import))
return;
if (!Im.Popup.IsOpen("##PenumbraImportPopup"u8))
Im.Popup.Open("##PenumbraImportPopup"u8);
var display = Im.Io.DisplaySize;
var height = Math.Max(display.Y / 4, 15 * Im.Style.FrameHeightWithSpacing);
var width = display.X / 8;
var size = new Vector2(width * 2, height);
Im.Window.SetNextPosition(Im.Viewport.Main.Center, Condition.Always, OneHalf);
Im.Window.SetNextSize(size);
using var popup = Im.Popup.Begin("##PenumbraImportPopup"u8, WindowFlags.Modal);
PopupWasDrawn = true;
var terminate = false;
using (var child = Im.Child.Begin("##import"u8, new Vector2(-1, size.Y - Im.Style.FrameHeight * 2)))
{
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 = true;
}
terminate |= import.State == ImporterState.Done
? Im.Button("Close"u8, -Vector2.UnitX)
: import.DrawCancelButton(-Vector2.UnitX);
if (terminate)
_modImportManager.ClearImport();
}
}
using ImSharp;
using Luna;
using Penumbra.Import.Structs;
using Penumbra.Mods.Manager;
namespace Penumbra.UI;
/// <summary> Draw the progress information for import. </summary>
public sealed class ImportPopup : Window
{
public const string WindowLabel = "Penumbra Import Status";
private readonly ModImportManager _modImportManager;
private static readonly Vector2 OneHalf = Vector2.One / 2;
public bool WasDrawn { get; private set; }
public bool PopupWasDrawn { get; private set; }
public ImportPopup(ModImportManager modImportManager)
: base(WindowLabel,
WindowFlags.NoCollapse
| WindowFlags.NoDecoration
| WindowFlags.NoBackground
| WindowFlags.NoMove
| WindowFlags.NoInputs
| WindowFlags.NoNavFocus
| WindowFlags.NoFocusOnAppearing
| WindowFlags.NoBringToFrontOnFocus
| WindowFlags.NoDocking
| WindowFlags.NoTitleBar, true)
{
_modImportManager = modImportManager;
DisableWindowSounds = true;
IsOpen = true;
RespectCloseHotkey = false;
Collapsed = false;
SizeConstraints = new WindowSizeConstraints
{
MinimumSize = Vector2.Zero,
MaximumSize = Vector2.Zero,
};
}
public override void PreOpenCheck()
{
WasDrawn = false;
PopupWasDrawn = false;
_modImportManager.TryUnpacking();
IsOpen = true;
while (_modImportManager.AddUnpackedMod(out _))
;
}
public override void Draw()
{
WasDrawn = true;
if (!_modImportManager.IsImporting(out var import))
return;
if (!Im.Popup.IsOpen("##PenumbraImportPopup"u8))
Im.Popup.Open("##PenumbraImportPopup"u8);
var display = Im.Io.DisplaySize;
var height = Math.Max(display.Y / 4, 15 * Im.Style.FrameHeightWithSpacing);
var width = display.X / 8;
var size = new Vector2(width * 2, height);
Im.Window.SetNextPosition(Im.Viewport.Main.Center, Condition.Always, OneHalf);
Im.Window.SetNextSize(size);
using var popup = Im.Popup.Begin("##PenumbraImportPopup"u8, WindowFlags.Modal);
PopupWasDrawn = true;
var terminate = false;
using (var child = Im.Child.Begin("##import"u8, new Vector2(-1, size.Y - Im.Style.FrameHeight * 2)))
{
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 = true;
}
terminate |= import.State == ImporterState.Done
? 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 Configuration _config;
private readonly ValidityChecker _validityChecker;
private readonly GlobalModImporter _globalModImporter;
private Penumbra? _penumbra;
private MainTabBar _configTabs = null!;
private string? _lastException;
public MainWindow(IDalamudPluginInterface pi, Configuration config, ValidityChecker checker,
TutorialService tutorial)
TutorialService tutorial, GlobalModImporter globalModImporter)
: base(GetLabel(checker))
{
_pluginInterface = pi;
_config = config;
_validityChecker = checker;
_pluginInterface = pi;
_config = config;
_validityChecker = checker;
_globalModImporter = globalModImporter;
RespectCloseHotkey = true;
tutorial.UpdateTutorialStep();
@ -61,6 +63,7 @@ public sealed class MainWindow : Window
public override void Draw()
{
UiHelpers.SetupCommonSizes();
_globalModImporter.DrawWindowTarget();
try
{
if (_validityChecker.ImcExceptions.Count > 0)

View file

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