Commit a9ed6469 by NTAuthority

mouse events, event listener lists, and primitive binding of mouse data to view…

mouse events, event listener lists, and primitive binding of mouse data to view angles in the temporary world viewer camera
parent c633526c
Pipeline #73 skipped
......@@ -15,6 +15,8 @@ public:
virtual void ProcessEvents() = 0;
virtual void ProcessEventsOnce() = 0;
public:
static std::unique_ptr<GameWindow> Create(const std::string& title, int defaultWidth, int defaultHeight, EventSystem* eventSystem);
};
......
......@@ -8,6 +8,7 @@
#include <Game.h>
#include <windows.h>
#include <windowsx.h>
namespace krt
{
......@@ -70,7 +71,8 @@ class Win32GameWindow : public GameWindow
: m_widthVar("r_width", ConVar_Archive, defaultWidth, &m_width),
m_heightVar("r_height", ConVar_Archive, defaultHeight, &m_height),
m_fullscreenVar("r_fullscreen", ConVar_Archive, false, &m_fullscreen),
m_eventSystem(eventSystem)
m_eventSystem(eventSystem),
m_active(false)
{
// prepare resolution
HMONITOR hMonitor = MonitorFromPoint(POINT{0, 0}, 0);
......@@ -167,10 +169,41 @@ class Win32GameWindow : public GameWindow
}
}
virtual void ProcessEventsOnce() override
{
if (m_active)
{
ProcessMouse();
}
}
private:
void ProcessMouse()
{
POINT centerPoint = {m_width / 2, m_height / 2};
ClientToScreen(m_windowHandle, &centerPoint);
// get mouse position
POINT cursorPos;
GetCursorPos(&cursorPos);
// reset to the center point
SetCursorPos(centerPoint.x, centerPoint.y);
// get delta position (from center)
int dX = cursorPos.x - centerPoint.x;
int dY = cursorPos.y - centerPoint.y;
// if there's a delta, post a mouse event
if (dX != 0 || dY != 0)
{
m_eventSystem->QueueEvent(std::make_unique<MouseEvent>(dX, dY));
}
}
LRESULT WindowProcedure(UINT msg, WPARAM wParam, LPARAM lParam)
{
int msgTimeDiff = (GetTickCount() - m_msgTime);
int msgTimeDiff = (GetTickCount() - m_msgTime);
uint64_t msgTime = theGame->GetGameTime() - msgTimeDiff;
switch (msg)
......@@ -204,6 +237,42 @@ class Win32GameWindow : public GameWindow
break;
}
case WM_ACTIVATEAPP:
{
m_active = !!wParam;
if (m_active)
{
POINT centerPoint = {m_width / 2, m_height / 2};
ClientToScreen(m_windowHandle, &centerPoint);
RECT windowRect;
GetWindowRect(m_windowHandle, &windowRect);
SetCursorPos(centerPoint.x, centerPoint.y);
SetCapture(m_windowHandle);
ClipCursor(&windowRect);
while (ShowCursor(FALSE) >= 0)
{
// do nothing
}
}
else
{
ClipCursor(nullptr);
ReleaseCapture();
while (ShowCursor(TRUE) < 0)
{
// do nothing
}
}
break;
}
case WM_CLOSE:
PostQuitMessage(0);
break;
......@@ -245,6 +314,7 @@ class Win32GameWindow : public GameWindow
bool m_fullscreen;
uint32_t m_msgTime;
bool m_active;
};
std::map<HWND, Win32GameWindow*> Win32GameWindow::ms_windowMapping;
......
......@@ -14,6 +14,8 @@ struct EditorCameraControls
void OnFrame( Camera *camera );
void AddViewAngles( Camera* camera, float yaw, float pitch );
void SetAccelerationTime( unsigned int time );
// Velocity manipulation functions.
......
......@@ -252,6 +252,69 @@ class CharEvent : public Event
std::string m_character;
};
class MouseEvent : public Event
{
public:
inline MouseEvent(int dX, int dY)
: m_dX(dX), m_dY(dY)
{
}
virtual void Handle() override;
inline int GetDeltaX() const
{
return m_dX;
}
inline int GetDeltaY() const
{
return m_dY;
}
private:
int m_dX;
int m_dY;
};
template <typename T>
struct EventListener
{
template <typename TCallback>
EventListener(const TCallback& callback)
{
m_handler = callback;
ms_listeners.insert(this);
}
~EventListener()
{
ms_listeners.erase(this);
}
private:
std::function<void(const T*)> m_handler;
// static members
public:
using TSet = std::set<EventListener*>;
static void Handle(const T* event)
{
for (auto& listener : ms_listeners)
{
listener->m_handler(event);
}
}
private:
static TSet ms_listeners;
};
#define DECLARE_EVENT_LISTENER(t) \
EventListener<t>::TSet EventListener<t>::ms_listeners;
class EventSystem
{
public:
......
......@@ -166,6 +166,24 @@ void EditorCameraControls::OnFrame( Camera *camera )
camera->SetViewMatrix( camView );
}
void EditorCameraControls::AddViewAngles( Camera* camera, float yaw, float pitch )
{
rw::Matrix camView = camera->GetViewMatrix();
if (yaw != 0 || pitch != 0)
{
float cur_yaw, cur_pitch;
matrix_get_yaw_pitch(camView, cur_yaw, cur_pitch);
// Make sure we do not go overboard, so limit pitch.
float new_pitch = std::max(-89.0f, std::min(89.0f, (float)(cur_pitch + pitch)));
matrix_from_yaw_pitch(camView, cur_yaw + yaw, new_pitch);
}
camera->SetViewMatrix(camView);
}
void EditorCameraControls::SetAccelerationTime( unsigned int time )
{
this->front_velo.SetAccelerationInterval( time );
......
......@@ -39,13 +39,24 @@ public:
void KeyEvent::Handle()
{
g_bindings->HandleKeyEvent(this);
EventListener<KeyEvent>::Handle(this);
}
void CharEvent::Handle()
{
EventListener<CharEvent>::Handle(this);
}
void MouseEvent::Handle()
{
EventListener<MouseEvent>::Handle(this);
}
DECLARE_EVENT_LISTENER(KeyEvent)
DECLARE_EVENT_LISTENER(CharEvent)
DECLARE_EVENT_LISTENER(MouseEvent)
static void ProcessConsoleInput(EventSystem* eventSystem)
{
const char* consoleBuffer = sys::GetConsoleInput();
......
......@@ -135,6 +135,8 @@ void Game::Run()
uint64_t thisTime = 0;
gameWindow->ProcessEventsOnce();
do
{
thisTime = eventSystem.HandleEvents();
......
......@@ -163,6 +163,47 @@ void World::RenderWorld( void *gfxDevice )
static Button lookUpButton("lookup");
static Button lookDownButton("lookdown");
static ConVar<bool> m_filter("m_filter", ConVar_Archive, false);
static ConVar<float> m_sensitivity("sensitivity", ConVar_Archive, 5.0f);
static ConVar<float> m_accel("m_accel", ConVar_Archive, 0.0f);
static ConVar<float> m_yaw("m_yaw", ConVar_Archive, 0.022f);
static ConVar<float> m_pitch("m_pitch", ConVar_Archive, 0.022f);
static EventListener<MouseEvent> eventListener([] (const MouseEvent* event)
{
// calculate angle movement
float mx = event->GetDeltaX();
float my = event->GetDeltaY();
// historical values for filtering
static int mouseDx[2];
static int mouseDy[2];
static int mouseIndex;
mouseDx[mouseIndex] = event->GetDeltaX();
mouseDy[mouseIndex] = event->GetDeltaY();
mouseIndex ^= 1;
// filter input
if (m_filter.GetValue())
{
mx = (mouseDx[0] + mouseDx[1]) * 0.5f;
my = (mouseDy[0] + mouseDy[1]) * 0.5f;
}
float rate = rw::length(rw::V2d(mx, my)) / theGame->GetLastFrameTime();
float factor = m_sensitivity.GetValue() + (rate * m_accel.GetValue());
mx *= factor;
my *= factor;
// apply angles to camera
krt::Camera& camera = theGame->GetWorldCamera();
editorControls.AddViewAngles(&camera, mx * m_yaw.GetValue(), my * -(m_pitch.GetValue()));
});
static std::once_flag bindingFlag;
std::call_once(bindingFlag, [] ()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment