feat(vf): add CursorStack and DragState
This commit is contained in:
1 parent
cb4ba15f6e
commit
dcdca6519a
1 file changed
+97
@@ -0,0 +1,97 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "ContainerMenu.h"
|
||||||
|
|
||||||
|
namespace vf {
|
||||||
|
|
||||||
|
// Click semantics for an open ContainerMenu. This is where inventories usually
|
||||||
|
// break, so the whole vocabulary lives in one place and every action reports
|
||||||
|
// exactly what it moved.
|
||||||
|
|
||||||
|
enum class ClickKind : uint8_t {
|
||||||
|
Left, // take all / put all / swap
|
||||||
|
Right, // take half / put one
|
||||||
|
ShiftLeft, // move to the other section, merging before filling
|
||||||
|
ShiftRight, // same rule; kept distinct so callers can bind both
|
||||||
|
HotbarSwap, // number key: exchange the slot with a hotbar slot
|
||||||
|
Middle, // creative clone, otherwise nothing happens
|
||||||
|
Double, // gather every mergeable stack onto the cursor
|
||||||
|
DragLeftStart,
|
||||||
|
DragLeftAdd,
|
||||||
|
DragLeftEnd, // split the held stack evenly, remainder stays held
|
||||||
|
DragRightStart,
|
||||||
|
DragRightAdd,
|
||||||
|
DragRightEnd, // one item per dragged slot
|
||||||
|
DropOne, // Q
|
||||||
|
DropStack, // Ctrl+Q
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* clickKindName(ClickKind kind);
|
||||||
|
|
||||||
|
// The stack the mouse carries between slots. It is deliberately its own type:
|
||||||
|
// the cursor is not a menu slot and must never be reachable by index.
|
||||||
|
struct CursorStack {
|
||||||
|
MetaStack held;
|
||||||
|
|
||||||
|
bool empty() const { return held.empty(); }
|
||||||
|
void clear() { held.clear(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// A drag paints a set of slots while the button is down. The items stay on the
|
||||||
|
// cursor for the whole gesture and are only distributed on release, so an
|
||||||
|
// abandoned drag cannot lose anything.
|
||||||
|
struct DragState {
|
||||||
|
bool active = false;
|
||||||
|
bool rightButton = false;
|
||||||
|
std::vector<int> paintedSlots;
|
||||||
|
// Cursor contents when the drag began, needed to compute an even split.
|
||||||
|
MetaStack payload;
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
bool alreadyPainted(int index) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SlotAction {
|
||||||
|
ClickKind kind = ClickKind::Left;
|
||||||
|
int slotIndex = -1;
|
||||||
|
// Which hotbar slot a HotbarSwap targets, 0..8.
|
||||||
|
int hotbarButton = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
SlotAction clickAt(ClickKind kind, int slotIndex);
|
||||||
|
SlotAction hotbarSwapAt(int slotIndex, int hotbarButton);
|
||||||
|
|
||||||
|
struct SlotActionResult {
|
||||||
|
bool applied = false;
|
||||||
|
// Items that changed slot, or moved between a slot and the cursor.
|
||||||
|
int moved = 0;
|
||||||
|
// Items that left the menu entirely. They are also listed in droppedStacks
|
||||||
|
// so a caller can spawn the right entities.
|
||||||
|
int dropped = 0;
|
||||||
|
std::vector<MetaStack> droppedStacks;
|
||||||
|
// Only a creative middle click can be non-zero here. Every other action is
|
||||||
|
// conservative, which is what the invariant test pins down.
|
||||||
|
int created = 0;
|
||||||
|
bool cursorChanged = false;
|
||||||
|
bool craftedResult = false;
|
||||||
|
int craftedCount = 0;
|
||||||
|
|
||||||
|
void noteDrop(const MetaStack& stack);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Applies one click. `cursor` and `drag` are the player's own state and are
|
||||||
|
// carried between calls; the menu is the screen being clicked on.
|
||||||
|
SlotActionResult applySlotAction(ContainerMenu& menu, CursorStack& cursor, DragState& drag,
|
||||||
|
const SlotAction& action);
|
||||||
|
|
||||||
|
// Total items of one kind across everything the action model can touch: the
|
||||||
|
// menu, the cursor, and whatever a drag is holding. The invariant is that this
|
||||||
|
// number only ever changes by what an action reports as dropped or created.
|
||||||
|
int totalAcrossMenuAndCursor(const ContainerMenu& menu, const CursorStack& cursor, ItemId item);
|
||||||
|
int totalItemsAcrossMenuAndCursor(const ContainerMenu& menu, const CursorStack& cursor);
|
||||||
|
|
||||||
|
} // namespace vf
|
||||||
Reference in new issue
Block a user