diff --git a/Luna b/Luna index d580f7a6..616d66b1 160000 --- a/Luna +++ b/Luna @@ -1 +1 @@ -Subproject commit d580f7a6ec62b0d7d60be07130133a54f10a3337 +Subproject commit 616d66b1d384588c23a3b5725ad1330037ce6987 diff --git a/Penumbra/Mods/Manager/ModFileSystem.cs b/Penumbra/Mods/Manager/ModFileSystem.cs index 810bc731..4528b9fc 100644 --- a/Penumbra/Mods/Manager/ModFileSystem.cs +++ b/Penumbra/Mods/Manager/ModFileSystem.cs @@ -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) diff --git a/Penumbra/Mods/Manager/ModImportManager.cs b/Penumbra/Mods/Manager/ModImportManager.cs index bef6254c..613a89f5 100644 --- a/Penumbra/Mods/Manager/ModImportManager.cs +++ b/Penumbra/Mods/Manager/ModImportManager.cs @@ -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() diff --git a/Penumbra/Mods/Manager/ModManager.cs b/Penumbra/Mods/Manager/ModManager.cs index 6cac3c79..ce7de910 100644 --- a/Penumbra/Mods/Manager/ModManager.cs +++ b/Penumbra/Mods/Manager/ModManager.cs @@ -82,20 +82,21 @@ public sealed class ModManager : ModStorage, IDisposable, Luna.IService } /// Load a new mod and add it to the manager if successful. - 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; } /// diff --git a/Penumbra/UI/GlobalModImporter.cs b/Penumbra/UI/GlobalModImporter.cs index 592131b7..2e63cd23 100644 --- a/Penumbra/UI/GlobalModImporter.cs +++ b/Penumbra/UI/GlobalModImporter.cs @@ -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; } } diff --git a/Penumbra/UI/ImportPopup.cs b/Penumbra/UI/ImportPopup.cs index 626ddd40..4e8184fd 100644 --- a/Penumbra/UI/ImportPopup.cs +++ b/Penumbra/UI/ImportPopup.cs @@ -1,84 +1,87 @@ -using ImSharp; -using Luna; -using Penumbra.Import.Structs; -using Penumbra.Mods.Manager; - -namespace Penumbra.UI; - -/// Draw the progress information for import. -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; + +/// Draw the progress information for import. +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(); + } +} diff --git a/Penumbra/UI/MainWindow/MainWindow.cs b/Penumbra/UI/MainWindow/MainWindow.cs index ac0f15f0..d3094940 100644 --- a/Penumbra/UI/MainWindow/MainWindow.cs +++ b/Penumbra/UI/MainWindow/MainWindow.cs @@ -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) diff --git a/Penumbra/UI/ModsTab/Selector/ModFileSystemDrawer.cs b/Penumbra/UI/ModsTab/Selector/ModFileSystemDrawer.cs index f66ef125..b1dad750 100644 --- a/Penumbra/UI/ModsTab/Selector/ModFileSystemDrawer.cs +++ b/Penumbra/UI/ModsTab/Selector/ModFileSystemDrawer.cs @@ -1,3 +1,4 @@ +using ImSharp; using Luna; using Penumbra.Collections.Manager; using Penumbra.Mods; @@ -16,9 +17,11 @@ public sealed class ModFileSystemDrawer : FileSystemDrawer Id