#include "controls/touch/event_handlers.h" #include "control.h" #include "controls/plrctrls.h" #include "cursor.h" #include "diablo.h" #include "engine.h" #include "gmenu.h" #include "inv.h" #include "panels/spell_book.hpp" #include "qol/stash.h" #include "scrollrt.h" #include "stores.h" #include "utils/ui_fwd.h" namespace devilution { namespace { VirtualGamepadEventHandler Handler(&VirtualGamepadState); Point ScaleToScreenCoordinates(float x, float y) { return Point { (int)round(x * gnScreenWidth), (int)round(y * gnScreenHeight) }; } void SimulateMouseMovement(const SDL_Event &event) { Point position = ScaleToScreenCoordinates(event.tfinger.x, event.tfinger.y); bool isInMainPanel = GetMainPanel().Contains(position); bool isInLeftPanel = GetLeftPanel().Contains(position); bool isInRightPanel = GetRightPanel().Contains(position); if (IsStashOpen) { if (!spselflag && !isInMainPanel && !isInLeftPanel && !isInRightPanel) return; } else if (invflag) { if (!spselflag && !isInMainPanel && !isInRightPanel) return; } MousePosition = position; SetPointAndClick(true); InvalidateInventorySlot(); } bool HandleGameMenuInteraction(const SDL_Event &event) { if (!gmenu_is_active()) return false; if (event.type == SDL_FINGERDOWN && gmenu_left_mouse(true)) return true; if (event.type == SDL_FINGERMOTION && gmenu_on_mouse_move()) return true; return event.type == SDL_FINGERUP && gmenu_left_mouse(false); } bool HandleStoreInteraction(const SDL_Event &event) { if (stextflag == STORE_NONE) return false; if (event.type == SDL_FINGERDOWN) CheckStoreBtn(); return true; } void HandleSpellBookInteraction(const SDL_Event &event) { if (!sbookflag) return; if (event.type == SDL_FINGERUP) CheckSBook(); } bool HandleSpeedBookInteraction(const SDL_Event &event) { if (!spselflag) return false; if (event.type == SDL_FINGERUP) SetSpell(); return true; } void HandleBottomPanelInteraction(const SDL_Event &event) { if (!gbRunGame || pcurs >= CURSOR_FIRSTITEM) return; ClearPanBtn(); if (event.type != SDL_FINGERUP) { spselflag = true; DoPanBtn(); spselflag = false; } else { DoPanBtn(); if (panbtndown) CheckBtnUp(); } } void HandleCharacterPanelInteraction(const SDL_Event &event) { if (!chrflag) return; if (event.type == SDL_FINGERDOWN) CheckChrBtns(); else if (event.type == SDL_FINGERUP && chrbtnactive) ReleaseChrBtns(false); } void HandleStashPanelInteraction(const SDL_Event &event) { if (!IsStashOpen || pcurs >= CURSOR_FIRSTITEM) return; if (event.type != SDL_FINGERUP) { CheckStashButtonPress(MousePosition); } else { CheckStashButtonRelease(MousePosition); } } } // namespace void HandleTouchEvent(const SDL_Event &event) { SetPointAndClick(false); if (Handler.Handle(event)) { return; } if (!IsAnyOf(event.type, SDL_FINGERDOWN, SDL_FINGERUP, SDL_FINGERMOTION)) { return; } SimulateMouseMovement(event); if (HandleGameMenuInteraction(event)) return; if (HandleStoreInteraction(event)) return; if (HandleSpeedBookInteraction(event)) return; HandleSpellBookInteraction(event); HandleBottomPanelInteraction(event); HandleCharacterPanelInteraction(event); HandleStashPanelInteraction(event); } bool VirtualGamepadEventHandler::Handle(const SDL_Event &event) { if (!VirtualGamepadState.isActive || !IsAnyOf(event.type, SDL_FINGERDOWN, SDL_FINGERUP, SDL_FINGERMOTION)) { VirtualGamepadState.primaryActionButton.didStateChange = false; VirtualGamepadState.secondaryActionButton.didStateChange = false; VirtualGamepadState.spellActionButton.didStateChange = false; VirtualGamepadState.cancelButton.didStateChange = false; return false; } if (charMenuButtonEventHandler.Handle(event)) return true; if (questsMenuButtonEventHandler.Handle(event)) return true; if (inventoryMenuButtonEventHandler.Handle(event)) return true; if (mapMenuButtonEventHandler.Handle(event)) return true; if (directionPadEventHandler.Handle(event)) return true; if (leveltype != DTYPE_TOWN && standButtonEventHandler.Handle(event)) return true; if (primaryActionButtonEventHandler.Handle(event)) return true; if (secondaryActionButtonEventHandler.Handle(event)) return true; if (spellActionButtonEventHandler.Handle(event)) return true; if (cancelButtonEventHandler.Handle(event)) return true; if (healthButtonEventHandler.Handle(event)) return true; if (manaButtonEventHandler.Handle(event)) return true; return false; } bool VirtualDirectionPadEventHandler::Handle(const SDL_Event &event) { switch (event.type) { case SDL_FINGERDOWN: return HandleFingerDown(event.tfinger); case SDL_FINGERUP: return HandleFingerUp(event.tfinger); case SDL_FINGERMOTION: return HandleFingerMotion(event.tfinger); default: return false; } } bool VirtualDirectionPadEventHandler::HandleFingerDown(const SDL_TouchFingerEvent &event) { if (isActive) return false; float x = event.x; float y = event.y; Point touchCoordinates = ScaleToScreenCoordinates(x, y); if (!virtualDirectionPad->area.Contains(touchCoordinates)) return false; virtualDirectionPad->UpdatePosition(touchCoordinates); activeFinger = event.fingerId; isActive = true; return true; } bool VirtualDirectionPadEventHandler::HandleFingerUp(const SDL_TouchFingerEvent &event) { if (!isActive || event.fingerId != activeFinger) return false; Point position = virtualDirectionPad->area.position; virtualDirectionPad->UpdatePosition(position); isActive = false; return true; } bool VirtualDirectionPadEventHandler::HandleFingerMotion(const SDL_TouchFingerEvent &event) { if (!isActive || event.fingerId != activeFinger) return false; float x = event.x; float y = event.y; Point touchCoordinates = ScaleToScreenCoordinates(x, y); virtualDirectionPad->UpdatePosition(touchCoordinates); return true; } bool VirtualButtonEventHandler::Handle(const SDL_Event &event) { if (!virtualButton->isUsable()) { virtualButton->didStateChange = virtualButton->isHeld; virtualButton->isHeld = false; return false; } virtualButton->didStateChange = false; switch (event.type) { case SDL_FINGERDOWN: return HandleFingerDown(event.tfinger); case SDL_FINGERUP: return HandleFingerUp(event.tfinger); case SDL_FINGERMOTION: return HandleFingerMotion(event.tfinger); default: return false; } } bool VirtualButtonEventHandler::HandleFingerDown(const SDL_TouchFingerEvent &event) { if (isActive) return false; float x = event.x; float y = event.y; Point touchCoordinates = ScaleToScreenCoordinates(x, y); if (!virtualButton->Contains(touchCoordinates)) return false; if (toggles) virtualButton->isHeld = !virtualButton->isHeld; else virtualButton->isHeld = true; virtualButton->didStateChange = true; activeFinger = event.fingerId; isActive = true; return true; } bool VirtualButtonEventHandler::HandleFingerUp(const SDL_TouchFingerEvent &event) { if (!isActive || event.fingerId != activeFinger) return false; if (!toggles) { if (virtualButton->isHeld) virtualButton->didStateChange = true; virtualButton->isHeld = false; } isActive = false; return true; } bool VirtualButtonEventHandler::HandleFingerMotion(const SDL_TouchFingerEvent &event) { if (!isActive || event.fingerId != activeFinger) return false; if (toggles) return true; float x = event.x; float y = event.y; Point touchCoordinates = ScaleToScreenCoordinates(x, y); bool wasHeld = virtualButton->isHeld; virtualButton->isHeld = virtualButton->Contains(touchCoordinates); virtualButton->didStateChange = virtualButton->isHeld != wasHeld; return true; } } // namespace devilution