2005-07-03 18:25:48 +02:00
|
|
|
#include "precompiled.h"
|
|
|
|
|
|
|
|
#include "MessageHandler.h"
|
|
|
|
#include "../GameLoop.h"
|
|
|
|
|
2005-09-15 07:31:49 +02:00
|
|
|
#include "maths/Vector3D.h"
|
|
|
|
#include "maths/Quaternion.h"
|
|
|
|
#include "ps/Game.h"
|
|
|
|
#include "renderer/Renderer.h"
|
2006-03-21 21:55:45 +01:00
|
|
|
#include "graphics/GameView.h"
|
2005-09-15 07:31:49 +02:00
|
|
|
|
2005-09-13 01:37:52 +02:00
|
|
|
#include <assert.h>
|
|
|
|
|
2005-07-03 18:25:48 +02:00
|
|
|
namespace AtlasMessage {
|
|
|
|
|
|
|
|
|
2005-09-14 07:37:52 +02:00
|
|
|
MESSAGEHANDLER(ScrollConstant)
|
2005-07-03 18:25:48 +02:00
|
|
|
{
|
2005-09-14 07:37:52 +02:00
|
|
|
if (msg->dir < 0 || msg->dir > 3)
|
2005-07-03 18:25:48 +02:00
|
|
|
{
|
|
|
|
debug_warn("ScrollConstant: invalid direction");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-09-14 07:37:52 +02:00
|
|
|
g_GameLoop->input.scrollSpeed[msg->dir] = msg->speed;
|
2005-07-03 18:25:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-15 07:31:49 +02:00
|
|
|
MESSAGEHANDLER(Scroll)
|
|
|
|
{
|
|
|
|
static CVector3D targetPos;
|
|
|
|
static float targetDistance = 0.f;
|
|
|
|
|
|
|
|
CMatrix3D& camera = g_Game->GetView()->GetCamera()->m_Orientation;
|
|
|
|
|
|
|
|
static CVector3D lastCameraPos = camera.GetTranslation();
|
|
|
|
|
|
|
|
// Ensure roughly correct motion when dragging is combined with other
|
2005-10-04 04:50:59 +02:00
|
|
|
// movements.
|
2005-09-15 07:31:49 +02:00
|
|
|
if (lastCameraPos != camera.GetTranslation())
|
|
|
|
targetPos += camera.GetTranslation() - lastCameraPos;
|
|
|
|
|
2005-10-04 04:50:59 +02:00
|
|
|
// General operation:
|
|
|
|
//
|
|
|
|
// When selecting a target point to drag, remember targetPos (a world-space
|
|
|
|
// point on the terrain, underneath the mouse) and targetDistance (from the
|
|
|
|
// camera to the target point).
|
|
|
|
//
|
|
|
|
// When dragging to a different position, the target point should remain
|
|
|
|
// under the moved mouse; so calculate the ray through the camera and mouse,
|
|
|
|
// multiply by targetDistance and add to targetPos, resulting in the required
|
|
|
|
// camera position.
|
|
|
|
|
2005-09-30 02:59:42 +02:00
|
|
|
if (msg->type == eScrollType::FROM)
|
2005-09-15 07:31:49 +02:00
|
|
|
{
|
|
|
|
msg->pos.GetWorldSpace(targetPos);
|
|
|
|
targetDistance = (targetPos - camera.GetTranslation()).GetLength();
|
|
|
|
}
|
2005-09-30 02:59:42 +02:00
|
|
|
else if (msg->type == eScrollType::TO)
|
2005-09-15 07:31:49 +02:00
|
|
|
{
|
|
|
|
CVector3D origin, dir;
|
|
|
|
float x, y;
|
|
|
|
msg->pos.GetScreenSpace(x, y);
|
2006-03-14 22:29:19 +01:00
|
|
|
g_Game->GetView()->GetCamera()->BuildCameraRay((int)x, (int)y, origin, dir);
|
2005-09-15 07:31:49 +02:00
|
|
|
dir *= targetDistance;
|
|
|
|
camera.Translate(targetPos - dir - origin);
|
2005-11-06 06:05:07 +01:00
|
|
|
g_Game->GetView()->GetCamera()->UpdateFrustum();
|
2005-09-15 07:31:49 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
debug_warn("Scroll: Invalid type");
|
|
|
|
}
|
|
|
|
lastCameraPos = camera.GetTranslation();
|
|
|
|
}
|
|
|
|
|
|
|
|
MESSAGEHANDLER(SmoothZoom)
|
|
|
|
{
|
|
|
|
g_GameLoop->input.zoomDelta += msg->amount;
|
|
|
|
}
|
|
|
|
|
|
|
|
MESSAGEHANDLER(RotateAround)
|
|
|
|
{
|
|
|
|
static CVector3D focusPos;
|
|
|
|
static float lastX = 0.f, lastY = 0.f;
|
|
|
|
|
|
|
|
CMatrix3D& camera = g_Game->GetView()->GetCamera()->m_Orientation;
|
|
|
|
|
2005-09-30 02:59:42 +02:00
|
|
|
if (msg->type == eRotateAroundType::FROM)
|
2005-09-15 07:31:49 +02:00
|
|
|
{
|
2005-10-04 04:50:59 +02:00
|
|
|
msg->pos.GetScreenSpace(lastX, lastY); // get mouse position
|
|
|
|
msg->pos.GetWorldSpace(focusPos); // get point on terrain under mouse
|
2005-09-15 07:31:49 +02:00
|
|
|
}
|
2005-09-30 02:59:42 +02:00
|
|
|
else if (msg->type == eRotateAroundType::TO)
|
2005-09-15 07:31:49 +02:00
|
|
|
{
|
|
|
|
float x, y;
|
2005-10-04 04:50:59 +02:00
|
|
|
msg->pos.GetScreenSpace(x, y); // get mouse position
|
2005-09-15 07:31:49 +02:00
|
|
|
|
2005-10-04 04:50:59 +02:00
|
|
|
// Rotate around X and Y axes by amounts depending on the mouse delta
|
2005-09-15 07:31:49 +02:00
|
|
|
float rotX = 6.f * (y-lastY) / g_Renderer.GetHeight();
|
|
|
|
float rotY = 6.f * (x-lastX) / g_Renderer.GetWidth();
|
|
|
|
|
|
|
|
CQuaternion q0, q1;
|
|
|
|
q0.FromAxisAngle(camera.GetLeft(), -rotX);
|
|
|
|
q1.FromAxisAngle(CVector3D(0.f, 1.f, 0.f), rotY);
|
|
|
|
CQuaternion q = q0*q1;
|
|
|
|
|
|
|
|
CVector3D origin = camera.GetTranslation();
|
|
|
|
CVector3D offset = q.Rotate(origin - focusPos);
|
|
|
|
|
|
|
|
q *= camera.GetRotation();
|
2005-09-30 02:59:42 +02:00
|
|
|
q.Normalize(); // to avoid things blowing up when turning upside-down, for some reason I don't understand
|
2005-09-15 07:31:49 +02:00
|
|
|
q.ToMatrix(camera);
|
2005-09-30 02:59:42 +02:00
|
|
|
|
|
|
|
// Make sure up is still pointing up, regardless of any rounding errors.
|
|
|
|
// (Maybe this distorts the camera in other ways, but at least the errors
|
|
|
|
// are far less noticeable to me.)
|
2005-10-04 04:50:59 +02:00
|
|
|
camera._21 = 0.f; // (_21 = Y component returned by GetLeft())
|
2005-09-30 02:59:42 +02:00
|
|
|
|
2005-09-15 07:31:49 +02:00
|
|
|
camera.Translate(focusPos + offset);
|
2005-11-06 06:05:07 +01:00
|
|
|
g_Game->GetView()->GetCamera()->UpdateFrustum();
|
2005-09-15 07:31:49 +02:00
|
|
|
|
|
|
|
lastX = x;
|
|
|
|
lastY = y;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
debug_warn("RotateAround: Invalid type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-13 01:37:52 +02:00
|
|
|
}
|