SDcmWeb/webassembly/events.cpp
2025-10-12 00:17:30 +09:00

406 lines
12 KiB
C++

//
// Window and input event handling
//
#include <algorithm>
#include <SDL.h>
#include <SDL_opengles2.h>
#include "events.h"
// #define EVENTS_DEBUG
void EventHandler::windowResizeEvent(int width, int height)
{
if(width<=0 || height<=0)
{
return;
}
printf("windowResizeEvnet: %d, %d\n", width, height);
glViewport(0, 0, width, height);
mCamera.setWindowSize(width, height);
m_InteractionMode = (int)MODE_PAN;
}
SDL_Renderer* EventHandler::GetRenderer()
{
return m_pRenderer;
}
void EventHandler::SetInteractionMode(int mode)
{
m_InteractionMode = mode;
}
void EventHandler::initWindow(const char* title)
{
// Create SDL window
/*
mpWindow =
SDL_CreateWindow(title,
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
mCamera.windowSize().width, mCamera.windowSize().height,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE| SDL_WINDOW_SHOWN);
*/
SDL_CreateWindowAndRenderer(mCamera.windowSize().width, mCamera.windowSize().height,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE| SDL_WINDOW_SHOWN,
&mpWindow, &m_pRenderer);
mWindowID = SDL_GetWindowID(mpWindow);
printf("Window Created!!!! Width:%d, Height: %d\n", mCamera.windowSize().width, mCamera.windowSize().height);
// Create OpenGLES 2 context on SDL window
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetSwapInterval(1);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GLContext glc = SDL_GL_CreateContext(mpWindow);
// Set clear color to black
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
// Initialize viewport
windowResizeEvent(mCamera.windowSize().width, mCamera.windowSize().height);
m_nEventType = 0;
m_fDeltaX = 0;
m_fDeltaY = 0;
}
void EventHandler::swapWindow()
{
SDL_GL_SwapWindow(mpWindow);
}
void EventHandler::zoom(float fDelta)
{
//float zoomDelta = mouseWheelDown ? -cMouseWheelZoomDelta : cMouseWheelZoomDelta;
float zoomDelta = 0.0f;
if(fDelta>0)
{
zoomDelta = -cMouseWheelZoomDelta;
}
else
{
zoomDelta = cMouseWheelZoomDelta;
}
mCamera.setZoomDelta(zoomDelta);
}
void EventHandler::zoomEventMouse(bool mouseWheelDown, int x, int y)
{
float preZoomWorldX, preZoomWorldY;
mCamera.windowToWorldCoords(mMousePositionX, mMousePositionY, preZoomWorldX, preZoomWorldY);
// Zoom by scaling up/down in 0.05 increments
float zoomDelta = mouseWheelDown ? -cMouseWheelZoomDelta : cMouseWheelZoomDelta;
mCamera.setZoomDelta(zoomDelta);
// Zoom to point: Keep the world coords under mouse position the same before and after the zoom
float postZoomWorldX, postZoomWorldY;
mCamera.windowToWorldCoords(mMousePositionX, mMousePositionY, postZoomWorldX, postZoomWorldY);
Vec2 deltaWorld = { postZoomWorldX - preZoomWorldX, postZoomWorldY - preZoomWorldY };
mCamera.setPanDelta (deltaWorld);
}
void EventHandler::zoomEventPinch (float pinchDist, float pinchX, float pinchY)
{
float preZoomWorldX, preZoomWorldY;
mCamera.normWindowToWorldCoords(pinchX, pinchY, preZoomWorldX, preZoomWorldY);
// Zoom in/out by positive/negative mPinch distance
float zoomDelta = pinchDist * cPinchScale;
mCamera.setZoomDelta(zoomDelta);
// Zoom to point: Keep the world coords under pinch position the same before and after the zoom
float postZoomWorldX, postZoomWorldY;
mCamera.normWindowToWorldCoords(pinchX, pinchY, postZoomWorldX, postZoomWorldY);
Vec2 deltaWorld = { postZoomWorldX - preZoomWorldX, postZoomWorldY - preZoomWorldY };
mCamera.setPanDelta (deltaWorld);
}
void EventHandler::SetMouseButtonDownPosition(int x, int y)
{
mMouseButtonDownX = x;
mMouseButtonDownY = y;
mMouseButtonDown = true;
mCamera.setBasePan();
}
void EventHandler::SetMouseButtonUpPosition(int x, int y)
{
m_nEventType = 3;
mMouseButtonDown = false;
}
void EventHandler::panEventMouse(int x, int y)
{
m_nEventType = 1;
int deltaX = mCamera.windowSize().width / 2 + (x - mMouseButtonDownX),
deltaY = mCamera.windowSize().height / 2 + (y - mMouseButtonDownY);
if(m_InteractionMode&InteractionMode::MODE_WIDTHLEVEL)
{
m_fDeltaX = x - mMouseButtonDownX;
m_fDeltaY = y - mMouseButtonDownY;
return;
}
float deviceX, deviceY;
mCamera.windowToDeviceCoords(deltaX, deltaY, deviceX, deviceY);
Vec2 pan = { mCamera.basePan().x + deviceX / mCamera.zoom(),
mCamera.basePan().y + deviceY / mCamera.zoom() / mCamera.aspect() };
mCamera.setPan(pan);
/*
int deltaX = mCamera.windowSize().width / 2 + (x - mMouseButtonDownX),
deltaY = mCamera.windowSize().height / 2 + (y - mMouseButtonDownY);
m_nEventType = 1;
m_fDeltaX = x - mMouseButtonDownX;
m_fDeltaY = y - mMouseButtonDownY;
return;
float deviceX, deviceY;
mCamera.windowToDeviceCoords(deltaX, deltaY, deviceX, deviceY);
Vec2 pan = { mCamera.basePan().x + deviceX / mCamera.zoom(),
mCamera.basePan().y + deviceY / mCamera.zoom() / mCamera.aspect() };
mCamera.setPan(pan);
*/
}
void EventHandler::panEventFinger(float x, float y)
{
m_nEventType = 2;
if(m_InteractionMode&InteractionMode::MODE_WIDTHLEVEL)
{
int nWidth = mCamera.windowSize().width;
int nHeight = mCamera.windowSize().height;
m_fDeltaX = (x - mFingerDownX)*nWidth;
m_fDeltaY = (y - mFingerDownY)*nHeight;
return;
}
float deltaX = 0.5f + (x - mFingerDownX),
deltaY = 0.5f + (y - mFingerDownY);
float deviceX, deviceY;
mCamera.normWindowToDeviceCoords(deltaX, deltaY, deviceX, deviceY);
Vec2 pan = { mCamera.basePan().x + deviceX / mCamera.zoom(),
mCamera.basePan().y + deviceY / mCamera.zoom() / mCamera.aspect() };
mCamera.setPan(pan);
/*
float deltaX = 0.5f + (x - mFingerDownX),
deltaY = 0.5f + (y - mFingerDownY);
m_nEventType = 2;
int nWidth = mCamera.windowSize().width;
int nHeight = mCamera.windowSize().height;
m_fDeltaX = (x - mFingerDownX)*nWidth;
m_fDeltaY = (y - mFingerDownY)*nHeight;
return;
float deviceX, deviceY;
mCamera.normWindowToDeviceCoords(deltaX, deltaY, deviceX, deviceY);
Vec2 pan = { mCamera.basePan().x + deviceX / mCamera.zoom(),
mCamera.basePan().y + deviceY / mCamera.zoom() / mCamera.aspect() };
mCamera.setPan(pan);
*/
}
int EventHandler::GetEventType()
{
return m_nEventType;
}
float EventHandler::GetDeltaX()
{
return m_fDeltaX;
}
float EventHandler::GetDeltaY()
{
return m_fDeltaY;
}
void EventHandler::processEvents()
{
// Handle events
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
std::terminate();
break;
case SDL_WINDOWEVENT:
{
if (event.window.windowID == mWindowID
&& event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
int width = event.window.data1, height = event.window.data2;
windowResizeEvent(width, height);
}
break;
}
case SDL_MOUSEWHEEL:
{
// SDL_MOUSEWHEEL regression?
// m->y no longer reliable (often y is 0 when mouse wheel is spun up or down), use m->preciseY instead
SDL_MouseWheelEvent *m = (SDL_MouseWheelEvent*)&event;
#ifdef EVENTS_DEBUG
printf ("SDL_MOUSEWHEEL= x,y=%d,%d preciseX,preciseY=%f,%f\n", m->x, m->y, m->preciseX, m->preciseY);
#endif
bool mouseWheelDown = (m->preciseY < 0.0);
if(m_InteractionMode&InteractionMode::MODE_SCROLL)
{
zoomEventMouse(mouseWheelDown, mMousePositionX, mMousePositionY);
}
break;
}
case SDL_MOUSEMOTION:
{
SDL_MouseMotionEvent *m = (SDL_MouseMotionEvent*)&event;
mMousePositionX = m->x;
mMousePositionY = m->y;
if (mMouseButtonDown && !mFingerDown && !mPinch)
panEventMouse(mMousePositionX, mMousePositionY);
break;
}
case SDL_MOUSEBUTTONDOWN:
{
SDL_MouseButtonEvent *m = (SDL_MouseButtonEvent*)&event;
if (m->button == SDL_BUTTON_LEFT && !mFingerDown && !mPinch)
{
mMouseButtonDown = true;
mMouseButtonDownX = m->x;
mMouseButtonDownY = m->y;
mCamera.setBasePan();
}
if (m->button == SDL_BUTTON_RIGHT && !mFingerDown && !mPinch)
{
printf("C++: 오른쪽 마우스 버튼이 눌렸습니다! 좌표: x=%d, y=%d\n", m->x, m->y);
//mMouseButtonDown = true;
//mMouseButtonDownX = m->x;
//mMouseButtonDownY = m->y;
//mCamera.setBasePan();
}
break;
}
case SDL_MOUSEBUTTONUP:
{
SDL_MouseButtonEvent *m = (SDL_MouseButtonEvent*)&event;
if (m->button == SDL_BUTTON_LEFT)
{
mMouseButtonDown = false;
m_nEventType = 3;
}
break;
}
case SDL_FINGERMOTION:
if (mFingerDown)
{
SDL_TouchFingerEvent *m = (SDL_TouchFingerEvent*)&event;
// Finger down and finger moving must match
if (m->fingerId == mFingerDownId)
panEventFinger(m->x, m->y);
}
else
{
}
break;
case SDL_FINGERDOWN:
if (!mPinch)
{
// Finger already down means multiple fingers, which is handled by multigesture event
if (mFingerDown)
mFingerDown = false;
else
{
SDL_TouchFingerEvent *m = (SDL_TouchFingerEvent*)&event;
mFingerDown = true;
mFingerDownX = m->x;
mFingerDownY = m->y;
mFingerDownId = m->fingerId;
mCamera.setBasePan();
}
}
break;
case SDL_MULTIGESTURE:
{
SDL_MultiGestureEvent *m = (SDL_MultiGestureEvent*)&event;
if (m->numFingers == 2 && fabs(m->dDist) >= cPinchZoomThreshold)
{
mPinch = true;
mFingerDown = false;
mMouseButtonDown = false;
if(m_InteractionMode&InteractionMode::MODE_SCROLL)
{
zoomEventPinch(m->dDist, m->x, m->y);
}
}
break;
}
case SDL_FINGERUP:
m_nEventType = 4;
mFingerDown = false;
mPinch = false;
break;
}
#ifdef EVENTS_DEBUG
printf ("event=%d mousePos=%d,%d mouseButtonDown=%d fingerDown=%d pinch=%d aspect=%f window=%dx%d\n",
event.type, mMousePositionX, mMousePositionY, mMouseButtonDown, mFingerDown, mPinch, mCamera.aspect(), mCamera.windowSize().width, mCamera.windowSize().height);
printf (" zoom=%f pan=%f,%f\n", mCamera.zoom(), mCamera.pan()[0], mCamera.pan()[1]);
#endif
}
}