feat: add dragAdd and dragEnd to SlotAction

This commit is contained in:
dualfroz committed 2026-09-09 18:33:00 +02:00
1 parent dbf9f81545
commit fea440d31f
1 file changed
+160
+160
View File
@@ -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<int>(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