From fea440d31fb1aa8a1e5be0663e302c5743e89b48 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Wed, 9 Sep 2026 18:33:00 +0200 Subject: [PATCH] feat: add dragAdd and dragEnd to SlotAction --- core/src/SlotAction.cpp | 160 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/core/src/SlotAction.cpp b/core/src/SlotAction.cpp index cb6c454..fae5c24 100644 --- a/core/src/SlotAction.cpp +++ b/core/src/SlotAction.cpp @@ -303,3 +303,163 @@ SlotActionResult dragStart(ContainerMenu& menu, CursorStack& cursor, DragState& return out; } +SlotActionResult dragAdd(ContainerMenu& menu, CursorStack& cursor, DragState& drag, + const SlotAction& action, bool rightButton) { + SlotActionResult out; + if (!drag.active || drag.rightButton != rightButton) return out; + int index = action.slotIndex; + if (!menu.validIndex(index) || drag.alreadyPainted(index)) return out; + if (!menu.canPlace(index, cursor.held)) return out; + const MetaStack& existing = menu.stackAt(index); + if (!existing.empty() && !stacksMergeable(existing, cursor.held)) return out; + drag.paintedSlots.push_back(index); + out.applied = true; + return out; +} + +SlotActionResult dragEnd(ContainerMenu& menu, CursorStack& cursor, DragState& drag, + bool rightButton) { + SlotActionResult out; + if (!drag.active || drag.rightButton != rightButton) return out; + + int painted = static_cast(drag.paintedSlots.size()); + if (painted == 0 || cursor.empty()) { + drag.reset(); + out.applied = true; + return out; + } + + int share = rightButton ? 1 : drag.payload.count / painted; + if (share > 0) { + for (int index : drag.paintedSlots) { + if (cursor.empty()) break; + MetaStack portion = splitOff(cursor.held, share); + int moved = putIntoSlot(menu, index, portion); + out.moved += moved; + if (!portion.empty()) transferAll(portion, cursor.held); + } + } + + drag.reset(); + out.cursorChanged = out.moved > 0; + out.applied = true; + return out; +} + +SlotActionResult dropAction(ContainerMenu& menu, CursorStack& cursor, const SlotAction& action, + bool wholeStack) { + SlotActionResult out; + + if (!cursor.empty()) { + if (menu.validIndex(action.slotIndex)) return out; + MetaStack thrown = wholeStack ? splitOff(cursor.held, cursor.held.count) + : splitOff(cursor.held, 1); + out.noteDrop(thrown); + out.cursorChanged = true; + out.applied = true; + return out; + } + + if (!menu.validIndex(action.slotIndex)) return out; + int index = action.slotIndex; + if (menu.stackAt(index).empty()) return out; + int amount = wholeStack ? menu.stackAt(index).count : 1; + // A result slot always hands over a whole craft: there is no such thing as + // crafting one third of a recipe, so Q on a result drops the whole batch. + MetaStack thrown = takeFromSlot(menu, index, amount, out); + if (thrown.empty()) return out; + out.noteDrop(thrown); + out.applied = true; + return out; +} + +} // namespace + +const char* clickKindName(ClickKind kind) { + switch (kind) { + case ClickKind::Left: return "left"; + case ClickKind::Right: return "right"; + case ClickKind::ShiftLeft: return "shiftLeft"; + case ClickKind::ShiftRight: return "shiftRight"; + case ClickKind::HotbarSwap: return "hotbarSwap"; + case ClickKind::Middle: return "middle"; + case ClickKind::Double: return "double"; + case ClickKind::DragLeftStart: return "dragLeftStart"; + case ClickKind::DragLeftAdd: return "dragLeftAdd"; + case ClickKind::DragLeftEnd: return "dragLeftEnd"; + case ClickKind::DragRightStart: return "dragRightStart"; + case ClickKind::DragRightAdd: return "dragRightAdd"; + case ClickKind::DragRightEnd: return "dragRightEnd"; + case ClickKind::DropOne: return "dropOne"; + case ClickKind::DropStack: return "dropStack"; + case ClickKind::Count: break; + } + return "unknown"; +} + +void DragState::reset() { + active = false; + rightButton = false; + paintedSlots.clear(); + payload.clear(); +} + +bool DragState::alreadyPainted(int index) const { + return std::find(paintedSlots.begin(), paintedSlots.end(), index) != paintedSlots.end(); +} + +SlotAction clickAt(ClickKind kind, int slotIndex) { + SlotAction action; + action.kind = kind; + action.slotIndex = slotIndex; + return action; +} + +SlotAction hotbarSwapAt(int slotIndex, int hotbarButton) { + SlotAction action; + action.kind = ClickKind::HotbarSwap; + action.slotIndex = slotIndex; + action.hotbarButton = hotbarButton; + return action; +} + +void SlotActionResult::noteDrop(const MetaStack& stack) { + if (stack.empty()) return; + dropped += stack.count; + droppedStacks.push_back(stack); +} + +SlotActionResult applySlotAction(ContainerMenu& menu, CursorStack& cursor, DragState& drag, + const SlotAction& action) { + switch (action.kind) { + case ClickKind::Left: return leftClick(menu, cursor, action); + case ClickKind::Right: return rightClick(menu, cursor, action); + case ClickKind::ShiftLeft: + case ClickKind::ShiftRight: return shiftClick(menu, action); + case ClickKind::HotbarSwap: return hotbarSwap(menu, action); + case ClickKind::Middle: return middleClick(menu, cursor, action); + case ClickKind::Double: return doubleClick(menu, cursor); + case ClickKind::DragLeftStart: return dragStart(menu, cursor, drag, action, false); + case ClickKind::DragLeftAdd: return dragAdd(menu, cursor, drag, action, false); + case ClickKind::DragLeftEnd: return dragEnd(menu, cursor, drag, false); + case ClickKind::DragRightStart: return dragStart(menu, cursor, drag, action, true); + case ClickKind::DragRightAdd: return dragAdd(menu, cursor, drag, action, true); + case ClickKind::DragRightEnd: return dragEnd(menu, cursor, drag, true); + case ClickKind::DropOne: return dropAction(menu, cursor, action, false); + case ClickKind::DropStack: return dropAction(menu, cursor, action, true); + case ClickKind::Count: break; + } + return SlotActionResult{}; +} + +int totalAcrossMenuAndCursor(const ContainerMenu& menu, const CursorStack& cursor, ItemId item) { + int total = menu.totalOf(item); + if (!cursor.empty() && cursor.held.item == item) total += cursor.held.count; + return total; +} + +int totalItemsAcrossMenuAndCursor(const ContainerMenu& menu, const CursorStack& cursor) { + return menu.totalItems() + cursor.held.count; +} + +} // namespace vf