minor fixing, adapting for mobile web
This commit is contained in:
1 parent
44cc0fba67
commit
eac914e073
6 files changed
+393
-129
No files matched your search
+215
-98
@@ -390,96 +390,51 @@ namespace ZL
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
if (event.type == SDL_FINGERDOWN) {
|
||||
int mx = static_cast<int>(event.tfinger.x * Environment::projectionWidth);
|
||||
int my = static_cast<int>(event.tfinger.y * Environment::projectionHeight);
|
||||
handleDown(static_cast<int64_t>(event.tfinger.fingerId), mx, my);
|
||||
}
|
||||
else if (event.type == SDL_FINGERUP) {
|
||||
int mx = static_cast<int>(event.tfinger.x * Environment::projectionWidth);
|
||||
int my = static_cast<int>(event.tfinger.y * Environment::projectionHeight);
|
||||
handleUp(static_cast<int64_t>(event.tfinger.fingerId), mx, my);
|
||||
}
|
||||
else if (event.type == SDL_FINGERMOTION) {
|
||||
int mx = static_cast<int>(event.tfinger.x * Environment::projectionWidth);
|
||||
int my = static_cast<int>(event.tfinger.y * Environment::projectionHeight);
|
||||
handleMotion(static_cast<int64_t>(event.tfinger.fingerId), mx, my);
|
||||
}
|
||||
#else
|
||||
// Emscripten on mobile browser: handle real touch events with per-finger IDs.
|
||||
// SDL_HINT_TOUCH_MOUSE_EVENTS="0" is set in main.cpp so these don't
|
||||
// Touch events (real fingers on Android and on mobile browsers via Emscripten).
|
||||
// SDL_HINT_TOUCH_MOUSE_EVENTS="0" is set in main.cpp so these do not
|
||||
// also fire SDL_MOUSEBUTTONDOWN, preventing double-processing.
|
||||
#ifdef EMSCRIPTEN
|
||||
if (event.type == SDL_FINGERDOWN) {
|
||||
if (event.type == SDL_FINGERDOWN || event.type == SDL_FINGERUP || event.type == SDL_FINGERMOTION) {
|
||||
int eventX = static_cast<int>(event.tfinger.x * Environment::width);
|
||||
int eventY = static_cast<int>(event.tfinger.y * Environment::height);
|
||||
int mx = static_cast<int>(event.tfinger.x * Environment::projectionWidth);
|
||||
int my = static_cast<int>(event.tfinger.y * Environment::projectionHeight);
|
||||
handleDown(static_cast<int64_t>(event.tfinger.fingerId), mx, my);
|
||||
}
|
||||
else if (event.type == SDL_FINGERUP) {
|
||||
int mx = static_cast<int>(event.tfinger.x * Environment::projectionWidth);
|
||||
int my = static_cast<int>(event.tfinger.y * Environment::projectionHeight);
|
||||
handleUp(static_cast<int64_t>(event.tfinger.fingerId), mx, my);
|
||||
}
|
||||
else if (event.type == SDL_FINGERMOTION) {
|
||||
int mx = static_cast<int>(event.tfinger.x * Environment::projectionWidth);
|
||||
int my = static_cast<int>(event.tfinger.y * Environment::projectionHeight);
|
||||
handleMotion(static_cast<int64_t>(event.tfinger.fingerId), mx, my);
|
||||
}
|
||||
#endif
|
||||
int64_t fingerId = static_cast<int64_t>(event.tfinger.fingerId);
|
||||
|
||||
if (event.type == SDL_FINGERDOWN) {
|
||||
onPointerDown(fingerId, eventX, eventY, mx, my);
|
||||
}
|
||||
else if (event.type == SDL_FINGERUP) {
|
||||
onPointerUp(fingerId, eventX, eventY, mx, my);
|
||||
}
|
||||
else {
|
||||
onPointerMotion(fingerId, eventX, eventY, mx, my);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Mouse-left maps to a single virtual touch with MOUSE_FINGER_ID.
|
||||
// Right mouse is intentionally unused now — camera rotation is on hold-and-drag.
|
||||
if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP) {
|
||||
if (event.button.button == SDL_BUTTON_LEFT) {
|
||||
int mx = static_cast<int>((float)event.button.x / Environment::width * Environment::projectionWidth);
|
||||
int my = static_cast<int>((float)event.button.y / Environment::height * Environment::projectionHeight);
|
||||
|
||||
if (event.type == SDL_MOUSEBUTTONDOWN) {
|
||||
std::cout << "\n========== MOUSE DOWN EVENT ==========" << std::endl;
|
||||
handleDown(ZL::UiManager::MOUSE_FINGER_ID, mx, my);
|
||||
int eventX = event.button.x;
|
||||
int eventY = event.button.y;
|
||||
int mx = static_cast<int>((float)eventX / Environment::width * Environment::projectionWidth);
|
||||
int my = static_cast<int>((float)eventY / Environment::height * Environment::projectionHeight);
|
||||
|
||||
if (menuManager.uiManager.isUiInteractionForFinger(ZL::UiManager::MOUSE_FINGER_ID)) {
|
||||
std::cout << "[CLICK] UI handled, skipping character movement" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentLocation)
|
||||
{
|
||||
currentLocation->handleDown(ZL::UiManager::MOUSE_FINGER_ID, event.button.x, event.button.y, mx, my);
|
||||
}
|
||||
///.....
|
||||
} else {
|
||||
handleUp(ZL::UiManager::MOUSE_FINGER_ID, mx, my);
|
||||
}
|
||||
}
|
||||
else if (event.button.button == SDL_BUTTON_RIGHT) {
|
||||
if (event.type == SDL_MOUSEBUTTONDOWN) {
|
||||
rightMouseDown = true;
|
||||
lastMouseX = event.button.x;
|
||||
lastMouseY = event.button.y;
|
||||
if (currentLocation)
|
||||
{
|
||||
currentLocation->rightMouseDown = true;
|
||||
currentLocation->lastMouseX = event.button.x;
|
||||
currentLocation->lastMouseY = event.button.y;
|
||||
}
|
||||
onPointerDown(ZL::UiManager::MOUSE_FINGER_ID, eventX, eventY, mx, my);
|
||||
}
|
||||
else {
|
||||
rightMouseDown = false;
|
||||
if (currentLocation)
|
||||
{
|
||||
currentLocation->rightMouseDown = false;
|
||||
}
|
||||
onPointerUp(ZL::UiManager::MOUSE_FINGER_ID, eventX, eventY, mx, my);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.type == SDL_MOUSEMOTION) {
|
||||
int mx = static_cast<int>((float)event.motion.x / Environment::width * Environment::projectionWidth);
|
||||
int my = static_cast<int>((float)event.motion.y / Environment::height * Environment::projectionHeight);
|
||||
handleMotion(ZL::UiManager::MOUSE_FINGER_ID, mx, my);
|
||||
if (currentLocation)
|
||||
{
|
||||
currentLocation->handleMotion(ZL::UiManager::MOUSE_FINGER_ID, event.motion.x, event.motion.y, mx, my);
|
||||
}
|
||||
int eventX = event.motion.x;
|
||||
int eventY = event.motion.y;
|
||||
int mx = static_cast<int>((float)eventX / Environment::width * Environment::projectionWidth);
|
||||
int my = static_cast<int>((float)eventY / Environment::height * Environment::projectionHeight);
|
||||
onPointerMotion(ZL::UiManager::MOUSE_FINGER_ID, eventX, eventY, mx, my);
|
||||
}
|
||||
|
||||
if (event.type == SDL_MOUSEWHEEL) {
|
||||
@@ -560,7 +515,6 @@ namespace ZL
|
||||
if (event.type == SDL_KEYUP) {
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
render();
|
||||
|
||||
@@ -568,39 +522,202 @@ namespace ZL
|
||||
|
||||
}
|
||||
|
||||
void Game::handleDown(int64_t fingerId, int mx, int my)
|
||||
int Game::countNonUiPointers() const
|
||||
{
|
||||
int uiX = mx;
|
||||
int uiY = Environment::projectionHeight - my;
|
||||
|
||||
|
||||
menuManager.uiManager.onTouchDown(fingerId, uiX, uiY);
|
||||
|
||||
int n = 0;
|
||||
for (const auto& kv : activePointers) {
|
||||
if (!kv.second.capturedByUi) ++n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void Game::handleUp(int64_t fingerId, int mx, int my)
|
||||
void Game::enterCameraDragMode(int eventX, int eventY)
|
||||
{
|
||||
int uiX = mx;
|
||||
int uiY = Environment::projectionHeight - my;
|
||||
cameraDragging = true;
|
||||
if (currentLocation) {
|
||||
currentLocation->cameraDragging = true;
|
||||
// Anchor on the *current* position, not the original press, so the
|
||||
// camera doesn't snap by however far the finger drifted before the
|
||||
// movement threshold was crossed.
|
||||
currentLocation->lastMouseX = eventX;
|
||||
currentLocation->lastMouseY = eventY;
|
||||
}
|
||||
}
|
||||
|
||||
// Check BEFORE onTouchUp erases the finger from the map.
|
||||
// If this finger started on a UI element, don't notify space —
|
||||
// otherwise space would think the ship-control finger was released.
|
||||
bool wasUiInteraction = menuManager.uiManager.isUiInteractionForFinger(fingerId);
|
||||
void Game::exitCameraDragMode()
|
||||
{
|
||||
cameraDragging = false;
|
||||
if (currentLocation) {
|
||||
currentLocation->cameraDragging = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Game::startPinch()
|
||||
{
|
||||
// Pick the first two non-UI pointers as pinch anchors.
|
||||
bool foundA = false, foundB = false;
|
||||
for (auto& kv : activePointers) {
|
||||
if (kv.second.capturedByUi) continue;
|
||||
if (!foundA) {
|
||||
pinchFingerA = kv.first;
|
||||
foundA = true;
|
||||
}
|
||||
else if (!foundB) {
|
||||
pinchFingerB = kv.first;
|
||||
foundB = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundA || !foundB) return;
|
||||
|
||||
const PointerState& a = activePointers[pinchFingerA];
|
||||
const PointerState& b = activePointers[pinchFingerB];
|
||||
float dx = static_cast<float>(a.eventX - b.eventX);
|
||||
float dy = static_cast<float>(a.eventY - b.eventY);
|
||||
pinchStartDistance = std::sqrt(dx * dx + dy * dy);
|
||||
pinchStartZoom = Environment::zoom;
|
||||
pinchActive = true;
|
||||
}
|
||||
|
||||
void Game::updatePinchZoom()
|
||||
{
|
||||
auto itA = activePointers.find(pinchFingerA);
|
||||
auto itB = activePointers.find(pinchFingerB);
|
||||
if (itA == activePointers.end() || itB == activePointers.end()) return;
|
||||
if (pinchStartDistance <= 1.0f) return;
|
||||
|
||||
float dx = static_cast<float>(itA->second.eventX - itB->second.eventX);
|
||||
float dy = static_cast<float>(itA->second.eventY - itB->second.eventY);
|
||||
float dist = std::sqrt(dx * dx + dy * dy);
|
||||
if (dist <= 1.0f) return;
|
||||
|
||||
float newZoom = pinchStartZoom * (pinchStartDistance / dist);
|
||||
// Match the wheel-zoom lower bound so both gestures clamp the same way.
|
||||
static const float zoomMin = 2.0f;
|
||||
if (newZoom < zoomMin) newZoom = zoomMin;
|
||||
Environment::zoom = newZoom;
|
||||
}
|
||||
|
||||
void Game::endPinch()
|
||||
{
|
||||
pinchActive = false;
|
||||
pinchStartDistance = 0.0f;
|
||||
pinchStartZoom = 0.0f;
|
||||
}
|
||||
|
||||
void Game::onPointerDown(int64_t fingerId, int eventX, int eventY, int mx, int my)
|
||||
{
|
||||
PointerState st;
|
||||
st.eventX = st.downEventX = eventX;
|
||||
st.eventY = st.downEventY = eventY;
|
||||
st.mx = st.downMx = mx;
|
||||
st.my = st.downMy = my;
|
||||
|
||||
const int uiX = mx;
|
||||
const int uiY = Environment::projectionHeight - my;
|
||||
menuManager.uiManager.onTouchDown(fingerId, uiX, uiY);
|
||||
st.capturedByUi = menuManager.uiManager.isUiInteractionForFinger(fingerId);
|
||||
|
||||
activePointers[fingerId] = st;
|
||||
|
||||
if (st.capturedByUi) {
|
||||
// UI button / slider / text-field grabbed this press; don't drive
|
||||
// gameplay or pinch from it.
|
||||
return;
|
||||
}
|
||||
|
||||
if (countNonUiPointers() >= 2) {
|
||||
// Second finger landed on the gameplay area: switch to pinch-zoom
|
||||
// and abandon any in-flight tap/camera-drag.
|
||||
if (cameraDragging) {
|
||||
exitCameraDragMode();
|
||||
}
|
||||
hasPrimaryPointer = false;
|
||||
if (!pinchActive) {
|
||||
startPinch();
|
||||
}
|
||||
}
|
||||
else {
|
||||
hasPrimaryPointer = true;
|
||||
primaryPointerId = fingerId;
|
||||
}
|
||||
}
|
||||
|
||||
void Game::onPointerUp(int64_t fingerId, int eventX, int eventY, int mx, int my)
|
||||
{
|
||||
const int uiX = mx;
|
||||
const int uiY = Environment::projectionHeight - my;
|
||||
menuManager.uiManager.onTouchUp(fingerId, uiX, uiY);
|
||||
|
||||
auto it = activePointers.find(fingerId);
|
||||
if (it == activePointers.end()) return;
|
||||
PointerState st = it->second;
|
||||
activePointers.erase(it);
|
||||
|
||||
// Pinch ends as soon as either anchor is lifted. The remaining finger,
|
||||
// if any, is *not* promoted back to a primary tap — the user was mid-
|
||||
// gesture, not starting a fresh press.
|
||||
if (pinchActive && (fingerId == pinchFingerA || fingerId == pinchFingerB)) {
|
||||
endPinch();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasPrimaryPointer || fingerId != primaryPointerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool wasDragging = cameraDragging;
|
||||
if (cameraDragging) {
|
||||
exitCameraDragMode();
|
||||
}
|
||||
hasPrimaryPointer = false;
|
||||
|
||||
if (st.capturedByUi || wasDragging) {
|
||||
// UI handled the press, or it was a camera-rotation drag — no tap action.
|
||||
return;
|
||||
}
|
||||
|
||||
// Tap → walk-to / interact, using the original press coords so the target
|
||||
// isn't shifted by tiny finger drift before release.
|
||||
if (currentLocation) {
|
||||
currentLocation->handleDown(fingerId, st.downEventX, st.downEventY, st.downMx, st.downMy);
|
||||
}
|
||||
}
|
||||
|
||||
void Game::handleMotion(int64_t fingerId, int mx, int my)
|
||||
void Game::onPointerMotion(int64_t fingerId, int eventX, int eventY, int mx, int my)
|
||||
{
|
||||
int uiX = mx;
|
||||
int uiY = Environment::projectionHeight - my;
|
||||
|
||||
// Check before onTouchMove so the "started on UI" state is preserved
|
||||
// regardless of what onTouchMove does internally.
|
||||
bool wasUiInteraction = menuManager.uiManager.isUiInteractionForFinger(fingerId);
|
||||
const int uiX = mx;
|
||||
const int uiY = Environment::projectionHeight - my;
|
||||
menuManager.uiManager.onTouchMove(fingerId, uiX, uiY);
|
||||
|
||||
auto it = activePointers.find(fingerId);
|
||||
if (it != activePointers.end()) {
|
||||
it->second.eventX = eventX;
|
||||
it->second.eventY = eventY;
|
||||
it->second.mx = mx;
|
||||
it->second.my = my;
|
||||
}
|
||||
|
||||
if (pinchActive) {
|
||||
updatePinchZoom();
|
||||
return;
|
||||
}
|
||||
|
||||
// Only the primary, non-UI-captured pointer can promote itself into a
|
||||
// camera-rotation drag once it crosses the movement threshold.
|
||||
if (hasPrimaryPointer && fingerId == primaryPointerId && it != activePointers.end()
|
||||
&& !it->second.capturedByUi && !cameraDragging) {
|
||||
int dx = mx - it->second.downMx;
|
||||
int dy = my - it->second.downMy;
|
||||
if (dx * dx + dy * dy >= CAMERA_DRAG_PIXEL_THRESHOLD * CAMERA_DRAG_PIXEL_THRESHOLD) {
|
||||
enterCameraDragMode(eventX, eventY);
|
||||
}
|
||||
}
|
||||
|
||||
if (currentLocation) {
|
||||
// Forwarded for dialogue hover and (when cameraDragging) camera rotation.
|
||||
currentLocation->handleMotion(fingerId, eventX, eventY, mx, my);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ZL
|
||||
Reference in new issue
Block a user