Skip to content

feat(inventory-list): implement marquee multi-selection#189

Draft
zndxcvbn wants to merge 6 commits into
mainfrom
feat-multi-selection
Draft

feat(inventory-list): implement marquee multi-selection#189
zndxcvbn wants to merge 6 commits into
mainfrom
feat-multi-selection

Conversation

@zndxcvbn

@zndxcvbn zndxcvbn commented Apr 30, 2026

Copy link
Copy Markdown
Collaborator

Description

This PR introduces a Windows-style marquee selection system for inventory management, allowing users to select, deselect, and perform batch actions on multiple items simultaneously. A setting to enable/disable this function is provided.
This feature is enabled by default. If the setting isn't present in the configuration, it's disabled.
Currently only InventoryMenu is supported.

Key Features

  • Marquee Selection (Ctrl + Drag): Users can draw a selection box in the inventory to select groups of items.
  • XOR Toggle Logic: Holding Ctrl while drawing a new marquee box will invert the selection state of items (selecting new ones and deselecting already highlighted ones), matching standard OS behavior.
  • Asynchronous Batch Drop: Pressing the Drop (R) key while multiple items are selected initiates a prioritized drop queue. Items are processed one per frame to prevent engine bottlenecks and ensure the C++ backend correctly registers each removal.

Tasks

  • Add multi-selection support for placing items in a ContainerMenu.

Summary by CodeRabbit

  • New Features

    • Marquee-based multi-selection: drag (with Ctrl) to select multiple items and Ctrl+click to toggle individual selections.
    • Batch actions for multi-selected items (items drop sequentially while keeping UI responsive).
    • Selection now clears when using navigation controls.
  • Bug Fixes

    • Visual selection indicators correctly reflect both normal and marquee selections.

@coderabbitai

coderabbitai Bot commented Apr 30, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds marquee-based multi-selection to the inventory: new MarqueeSelectionController, integration in InventoryMenu, per-entry marquee selection state in TabularListEntry, SWF export and build updates, and a config flag to enable the feature.

Changes

Cohort / File(s) Summary
Configuration
data/interface/skyui/config.txt
Enable marquee multi-selection via selection.marquee.enabled = true.
List Entry UI
source/actionscript/Common/skyui/components/list/TabularListEntry.as
Persist current entry/list references, expose setMultiSelected(Boolean), show selection indicator when entry is actually selected or isMarqueeSelected, and reset indicator position/opacity on setup.
Marquee Controller
source/actionscript/Common/skyui/components/list/MarqueeSelectionController.as
New controller managing Ctrl+drag marquee, baseline selection capture, marquee drawing, intersection checks updating per-entry setMultiSelected, Ctrl-click toggles, batch drop queueing and per-frame processing, and selection clearing.
Inventory Menu Integration
source/actionscript/ItemMenus/InventoryMenu.as
Instantiates/configures MarqueeSelectionController, routes mouse/input events to it, defers equip/drop logic when marquee actions are active, and intercepts item selection to let controller handle marquee behavior.
SWF Export
source/swf/inventorymenu.xml
Adds exported sprite for __Packages.skyui.components.list.MarqueeSelectionController (spriteId=74) for runtime inclusion.
Build Sources
source/swfsources.cmake
Include new MarqueeSelectionController.as in the inventorymenu SWF sources.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant InventoryMenu
    participant MarqueeSelectionController
    participant TabularListEntry

    User->>InventoryMenu: mouse down (Ctrl)+drag
    InventoryMenu->>MarqueeSelectionController: onMouseDown(details)
    activate MarqueeSelectionController
    MarqueeSelectionController->>MarqueeSelectionController: create marquee, capture baseline
    User->>InventoryMenu: mouse move
    InventoryMenu->>MarqueeSelectionController: onMouseMove(details)
    MarqueeSelectionController->>InventoryMenu: compute intersections
    MarqueeSelectionController->>TabularListEntry: setMultiSelected(true/false) per intersected entry
    TabularListEntry->>TabularListEntry: set isMarqueeSelected and update indicator
    User->>InventoryMenu: mouse up
    InventoryMenu->>MarqueeSelectionController: onMouseUp()
    MarqueeSelectionController->>MarqueeSelectionController: hide marquee, finalize selection
    deactivate MarqueeSelectionController

    User->>InventoryMenu: request Drop
    InventoryMenu->>MarqueeSelectionController: startBatchDrop()
    activate MarqueeSelectionController
    MarqueeSelectionController->>InventoryMenu: queue indices, disable input
    MarqueeSelectionController->>InventoryMenu: per-frame -> doSetSelectedIndex & ItemDrop (for each queued index)
    MarqueeSelectionController->>MarqueeSelectionController: restore input, clear selection
    deactivate MarqueeSelectionController
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • doodlum
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat(inventory-list): implement marquee multi-selection' directly describes the main changeset, which introduces a marquee-based multi-selection system across multiple files including a new MarqueeSelectionController class and supporting configuration.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@source/actionscript/ItemMenus/InventoryMenu.as`:
- Around line 59-61: The code directly dereferences
a_config.ItemList.selection.marquee.enabled which can throw if any node is
missing; in InventoryMenu (where _enableMarquee is set) guard each level
(a_config, a_config.ItemList, a_config.ItemList.selection,
a_config.ItemList.selection.marquee) before reading .enabled and otherwise set
this._enableMarquee = false; update the assignment near the existing block to
check existence (or use a safe-navigation-style helper) and only assign the
enabled value when defined, defaulting to false when nodes are absent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 6d9bda57-ca7e-4542-aed9-0f6223217a7a

📥 Commits

Reviewing files that changed from the base of the PR and between 5f411a5 and df51efd.

📒 Files selected for processing (3)
  • data/interface/skyui/config.txt
  • source/actionscript/Common/skyui/components/list/TabularListEntry.as
  • source/actionscript/ItemMenus/InventoryMenu.as

Comment on lines +59 to +61
if (a_config.ItemList.selection.marquee.enabled != undefined) {
this._enableMarquee = a_config.ItemList.selection.marquee.enabled;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard nested marquee config access.

Line 59 dereferences deep properties directly; if a user runs with an older config shape, this can break menu initialization. Default to false when nodes are missing.

Suggested fix
-      if (a_config.ItemList.selection.marquee.enabled != undefined) {
-         this._enableMarquee = a_config.ItemList.selection.marquee.enabled;
-      }
+      var marqueeCfg = (a_config.ItemList != undefined && a_config.ItemList.selection != undefined)
+         ? a_config.ItemList.selection.marquee
+         : undefined;
+      this._enableMarquee = (marqueeCfg != undefined && marqueeCfg.enabled == true);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (a_config.ItemList.selection.marquee.enabled != undefined) {
this._enableMarquee = a_config.ItemList.selection.marquee.enabled;
}
var marqueeCfg = (a_config.ItemList != undefined && a_config.ItemList.selection != undefined)
? a_config.ItemList.selection.marquee
: undefined;
this._enableMarquee = (marqueeCfg != undefined && marqueeCfg.enabled == true);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@source/actionscript/ItemMenus/InventoryMenu.as` around lines 59 - 61, The
code directly dereferences a_config.ItemList.selection.marquee.enabled which can
throw if any node is missing; in InventoryMenu (where _enableMarquee is set)
guard each level (a_config, a_config.ItemList, a_config.ItemList.selection,
a_config.ItemList.selection.marquee) before reading .enabled and otherwise set
this._enableMarquee = false; update the assignment near the existing block to
check existence (or use a safe-navigation-style helper) and only assign the
enabled value when defined, defaulting to false when nodes are absent.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
source/actionscript/ItemMenus/InventoryMenu.as (1)

53-55: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard the nested marquee config lookup.

This still dereferences a_config.ItemList.selection.marquee.enabled eagerly, so older or partial config shapes can break menu setup before _marqueeController.enabled is assigned.

Suggested fix
-      if (a_config.ItemList.selection.marquee.enabled != undefined) {
-         this._marqueeController.enabled = a_config.ItemList.selection.marquee.enabled;
-      }
+      var marqueeCfg = (a_config.ItemList != undefined && a_config.ItemList.selection != undefined)
+         ? a_config.ItemList.selection.marquee
+         : undefined;
+      this._marqueeController.enabled = (marqueeCfg != undefined && marqueeCfg.enabled == true);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@source/actionscript/ItemMenus/InventoryMenu.as` around lines 53 - 55, The
code directly dereferences a_config.ItemList.selection.marquee.enabled which can
throw if ItemList, selection, or marquee are missing; update the
InventoryMenu.as initialization to first verify each intermediate exists (e.g.,
check a_config.ItemList && a_config.ItemList.selection &&
a_config.ItemList.selection.marquee) before reading .enabled, then assign to
this._marqueeController.enabled only when that value is defined; reference the
a_config.ItemList.selection.marquee.enabled lookup and the
this._marqueeController.enabled assignment when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@source/actionscript/Common/skyui/components/list/MarqueeSelectionController.as`:
- Around line 119-124: The queued drop path is being used even for a single
marquee-selected entry, causing full-stack drops; change the branch in
MarqueeSelectionController where it checks this._dropQueue.length to
special-case length == 1: if length > 1 keep the current batch flow (sort
_dropQueue, set list.disableInput, this._isProcessingQueue = true and set
this._menu.onEnterFrame = mx.utils.Delegate.create(this,
this.processDropQueue)), but if length == 1 bypass the queued/batch logic and
call the normal InventoryMenu.DropItem flow for that single entry so quantity
handling is preserved (do not set disableInput/_isProcessingQueue or
onEnterFrame for the single-item case).

---

Duplicate comments:
In `@source/actionscript/ItemMenus/InventoryMenu.as`:
- Around line 53-55: The code directly dereferences
a_config.ItemList.selection.marquee.enabled which can throw if ItemList,
selection, or marquee are missing; update the InventoryMenu.as initialization to
first verify each intermediate exists (e.g., check a_config.ItemList &&
a_config.ItemList.selection && a_config.ItemList.selection.marquee) before
reading .enabled, then assign to this._marqueeController.enabled only when that
value is defined; reference the a_config.ItemList.selection.marquee.enabled
lookup and the this._marqueeController.enabled assignment when making the
change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: fcd1d5e8-5e22-4ab0-9dac-a570ba981c0d

📥 Commits

Reviewing files that changed from the base of the PR and between df51efd and 0a195ec.

📒 Files selected for processing (4)
  • source/actionscript/Common/skyui/components/list/MarqueeSelectionController.as
  • source/actionscript/ItemMenus/InventoryMenu.as
  • source/swf/inventorymenu.xml
  • source/swfsources.cmake

Comment thread source/actionscript/Common/skyui/components/list/MarqueeSelectionController.as Outdated
@zndxcvbn zndxcvbn marked this pull request as draft April 30, 2026 18:56
@zndxcvbn zndxcvbn added icebox A good idea on the back burner labels May 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

icebox A good idea on the back burner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant