- Mouse wheel zoom.
- Rotate camera around character with left mouse button.
- Rotate camera up and down with right mouse. Player rotation is handled separately, however camera updates based on the rotation of the player.
I have an issue when I rotate the player outside of the camera and then push the right mouse button, it "snaps" back, which it shouldn't do and I can't quite figure it out. I think I need to update "cameraPosition" based on the new camera location due to the outside player rotation, but can't figure it out. Can anyone help? (Ignore the class names, I have modified the good RTS camera animator for this and haven't updated yet)
Code: Select all
#include "CSceneNodeAnimatorRTS.h"
using namespace irr;
using namespace core;
using namespace gui;
using namespace io;
using namespace scene;
using namespace video;
CSceneNodeAnimatorRTS::CSceneNodeAnimatorRTS(irr::core::vector3df cameraPosition, gui::ICursorControl* cursorControl) : cameraPosition(cameraPosition), cursorControl(cursorControl)
{
initCam();
}
CSceneNodeAnimatorRTS::~CSceneNodeAnimatorRTS()
{
}
void CSceneNodeAnimatorRTS::initCam()
{
activeMouseButton = USE_MOUSE_L;
camera = NULL;
parent = NULL;
cameraOrbit = 90.0f;
cameraAngle = 30.0f;
cameraAngleMin = 15.0f;
cameraAngleMax = 88.0f;
cameraDistance = 100.0f;
cameraDistanceMin = 50.0f;
cameraDistanceMax = 300.0f;
cameraSpeedMouse = 5.0f;
cameraSpeedDrift = 100.0f;
cameraSpeedScroll = 5.0f;
cameraMinX = 0.0f;
cameraMaxX = 250.0f;
cameraMinZ = 0.0f;
cameraMaxZ = 250.0f;
cameraOrbitOld = 0.0f;
cameraAngleOld = 0.0f;
firstTime = true;
mouseMoved = false;
mouseZoom = false;
mouseDownL = false;
mouseDownR = false;
mouseDownM = false;
movingCamera = false;
rotatingParent = false;
for (u32 i = 0; i < KEY_KEY_CODES_COUNT; ++i) keyDown[i] = false;
timeThen = 0;
if (cursorControl)
{
cursorControl->grab();
cursor = cursorOld = cursorControl->getRelativePosition();
}
}
bool CSceneNodeAnimatorRTS::OnEvent(const irr::SEvent& event)
{
switch (event.EventType)
{
case EET_KEY_INPUT_EVENT : return OnKeyInputEvent(event);
case EET_MOUSE_INPUT_EVENT :
{
switch (event.MouseInput.Event)
{
case EMIE_LMOUSE_PRESSED_DOWN : return OnLMousePressedDown(event);
case EMIE_LMOUSE_LEFT_UP : return OnLMouseLeftUp(event);
case EMIE_RMOUSE_PRESSED_DOWN : return OnRMousePressedDown(event);
case EMIE_RMOUSE_LEFT_UP : return OnRMouseLeftUp(event);
case EMIE_MMOUSE_PRESSED_DOWN : return OnMMousePressedDown(event);
case EMIE_MMOUSE_LEFT_UP : return OnMMouseLeftUp(event);
case EMIE_MOUSE_MOVED : return OnMouseMoved(event);
case EMIE_MOUSE_WHEEL : return OnMouseWheel(event);
}
}
}
return false;
}
bool CSceneNodeAnimatorRTS::OnKeyInputEvent(const irr::SEvent &e)
{
keyDown[e.KeyInput.Key] = e.KeyInput.PressedDown;
return false;
}
bool CSceneNodeAnimatorRTS::OnLMousePressedDown(const irr::SEvent &e)
{
mouseDownL = true;
return CameraMouseButton(e);
}
bool CSceneNodeAnimatorRTS::OnLMouseLeftUp(const irr::SEvent &e)
{
mouseDownL = false;
return false;
}
bool CSceneNodeAnimatorRTS::OnRMousePressedDown(const irr::SEvent &e)
{
mouseDownR = true;
return CameraMouseButton(e);
}
bool CSceneNodeAnimatorRTS::OnRMouseLeftUp(const irr::SEvent &e)
{
mouseDownR = false;
return false;
}
bool CSceneNodeAnimatorRTS::OnMMousePressedDown(const SEvent &e)
{
mouseDownM = true;
return CameraMouseButton(e);
}
bool CSceneNodeAnimatorRTS::OnMMouseLeftUp(const irr::SEvent &e)
{
mouseDownM = false;
return false;
}
bool CSceneNodeAnimatorRTS::OnMouseMoved(const irr::SEvent &e)
{
return CameraMouseMoved(e);
}
bool CSceneNodeAnimatorRTS::OnMouseWheel(const irr::SEvent &e)
{
return CameraMouseWheel(e);
}
bool CSceneNodeAnimatorRTS::CameraMouseButton(const irr::SEvent &e)
{
cursorOld.X = (f32)e.MouseInput.X;
cursorOld.Y = (f32)e.MouseInput.Y;
cursorDelta.X = 0.0f;
cursorDelta.Y = 0.0f;
cursorDeltaOld.X = 0.0f;
cursorDeltaOld.Y = 0.0f;
cameraOrbitOld = cameraOrbit;
cameraAngleOld = cameraAngle;
return false;
}
bool CSceneNodeAnimatorRTS::CameraMouseMoved(const irr::SEvent &e)
{
//if( (activeMouseButton == USE_MOUSE_L && mouseDownL) ||
// (activeMouseButton == USE_MOUSE_R && mouseDownR) ||
// (activeMouseButton == USE_MOUSE_M && mouseDownM))
if(mouseDownL || mouseDownR)
{
cursor.X = (f32)e.MouseInput.X;
cursor.Y = (f32)e.MouseInput.Y;
cursorDelta.X = (cursor.X - cursorOld.X) / cameraSpeedMouse;
cursorDelta.Y = (cursor.Y - cursorOld.Y) / cameraSpeedMouse;
if (cursorDelta.Y > (88.0f - cameraAngleOld))
{
cursorOld.Y += (cursorDelta.Y - cursorDeltaOld.Y);
cursorDelta.Y = 88.0f - cameraAngleOld;
}
if (cursorDelta.Y < (-88.0f - cameraAngleOld))
{
cursorOld.Y += (cursorDelta.Y - cursorDeltaOld.Y);
cursorDelta.Y = -88.0f - cameraAngleOld;
}
cursorDeltaOld.X = cursorDelta.X;
cursorDeltaOld.Y = cursorDelta.Y;
cameraAngle = fmod((cameraAngleOld + cursorDelta.Y), 360.0f);
if(cameraAngle > cameraAngleMax) cameraAngle = cameraAngleMax;
if(cameraAngle < cameraAngleMin) cameraAngle = cameraAngleMin;
float tmpOrbit = fmod((cameraOrbitOld + cursorDelta.X), 360.0f);
if(mouseDownL)
{
cameraOrbit = tmpOrbit;
}
}
return false;
}
bool CSceneNodeAnimatorRTS::CameraMouseWheel(const irr::SEvent &e)
{
cameraDistance -= (e.MouseInput.Wheel * cameraSpeedScroll);
if(cameraDistance < cameraDistanceMin) cameraDistance = cameraDistanceMin;
if(cameraDistance > cameraDistanceMax) cameraDistance = cameraDistanceMax;
return false;
}
void CSceneNodeAnimatorRTS::animateNode(irr::scene::ISceneNode* node, irr::u32 timeMs)
{
if (!node || node->getType() != ESNT_CAMERA) { return; }
camera = static_cast<ICameraSceneNode*>(node);
parent = camera->getParent();
if (!parent)
{
return;
}
if (firstTime)
{
camera->setPosition(cameraPosition);
camera->setTarget(parent->getPosition());
firstTime = false;
}
timeDelta = (f32)(timeMs - timeThen) * 0.001f;
timeThen = timeMs;
core::vector3df position = cameraPosition;
core::vector3df rotation = parent->getRotation();
f32 NEWcameraOrbit = cameraOrbit - 90.0f;
f32 NEWcameraAngle = cameraAngle * -1.0f + 45.0f;
matrix4 m, n;
n.setRotationDegrees(core::vector3df(-NEWcameraAngle, NEWcameraOrbit, 0));
n.rotateVect(position);
// Perform zooming
position.setLength(cameraDistance);
camera->setPosition(position);
camera->setTarget(parent->getPosition());
camera->updateAbsolutePosition();
}
void CSceneNodeAnimatorRTS::setDeadZone(irr::f32 newMinX, irr::f32 newMaxX, irr::f32 newMinZ, irr::f32 newMaxZ)
{
cameraMinX = newMinX;
cameraMaxX = newMaxX;
cameraMinZ = newMinZ;
cameraMaxZ = newMaxZ;
}
void CSceneNodeAnimatorRTS::setCameraPosition(irr::core::vector3df position)
{
if (camera && parent)
{
camera->setPosition(position);
camera->setTarget(parent->getPosition());
cameraPosition = position;
}
}