#include "CSceneNodeAnimatorCameraMaya.h"
#include "ICursorControl.h"
#include "ICameraSceneNode.h"
#include "SViewFrustum.h"
#include "ISceneManager.h"
namespace irr
{
namespace scene
{
CSceneNodeAnimatorCameraMaya::CSceneNodeAnimatorCameraMaya(gui::ICursorControl* cursor, f32 rotate, f32 zoom, f32 translate)
: CursorControl(cursor), Zooming(false), Rotating(false), Moving(false),
Translating(false), ZoomSpeed(zoom), RotateSpeed(rotate), TranslateSpeed(translate),
CurrentZoom(70.0f), RotX(0.0f), RotY(0.0f), OldCamera(0), MousePos(0.5f, 0.5f)
{
#ifdef _DEBUG
setDebugName("CSceneNodeAnimatorCameraMaya");
#endif
if (CursorControl)
{
CursorControl->grab();
MousePos = CursorControl->getRelativePosition();
}
allKeysUp();
}
CSceneNodeAnimatorCameraMaya::~CSceneNodeAnimatorCameraMaya()
{
if (CursorControl)
CursorControl->drop();
}
bool CSceneNodeAnimatorCameraMaya::OnEvent(const SEvent& event)
{
if (event.EventType != EET_MOUSE_INPUT_EVENT)
return false;
switch(event.MouseInput.Event)
{
case EMIE_LMOUSE_PRESSED_DOWN:
MouseKeys[0] = true;
break;
case EMIE_RMOUSE_PRESSED_DOWN:
MouseKeys[2] = true;
break;
case EMIE_MMOUSE_PRESSED_DOWN:
MouseKeys[1] = true;
break;
case EMIE_LMOUSE_LEFT_UP:
MouseKeys[0] = false;
break;
case EMIE_RMOUSE_LEFT_UP:
MouseKeys[2] = false;
break;
case EMIE_MMOUSE_LEFT_UP:
MouseKeys[1] = false;
break;
case EMIE_MOUSE_MOVED:
MousePos = CursorControl->getRelativePosition();
break;
case EMIE_MOUSE_WHEEL:
case EMIE_LMOUSE_DOUBLE_CLICK:
case EMIE_RMOUSE_DOUBLE_CLICK:
case EMIE_MMOUSE_DOUBLE_CLICK:
case EMIE_LMOUSE_TRIPLE_CLICK:
case EMIE_RMOUSE_TRIPLE_CLICK:
case EMIE_MMOUSE_TRIPLE_CLICK:
case EMIE_COUNT:
return false;
}
return true;
}
void CSceneNodeAnimatorCameraMaya::animateNode(ISceneNode *node, u32 timeMs)
{
if (!node || node->getType() != ESNT_CAMERA)
return;
ICameraSceneNode* camera = static_cast<ICameraSceneNode*>(node);
if(!camera->isInputReceiverEnabled())
return;
scene::ISceneManager * smgr = camera->getSceneManager();
if(smgr && smgr->getActiveCamera() != camera)
return;
if (OldCamera != camera)
{
OldTarget = camera->getTarget();
OldCamera = camera;
LastCameraTarget = OldTarget;
}
else
{
OldTarget += camera->getTarget() - LastCameraTarget;
}
core::vector3df target = camera->getTarget();
f32 nRotX = RotX;
f32 nRotY = RotY;
f32 nZoom = CurrentZoom;
if ( (isMouseKeyDown(0) && isMouseKeyDown(2)) || isMouseKeyDown(1) )
{
if (!Zooming)
{
ZoomStart = MousePos;
Zooming = true;
nZoom = CurrentZoom;
}
else
{
const f32 targetMinDistance = 0.1f;
nZoom += (ZoomStart.X - MousePos.X) * ZoomSpeed;
if (nZoom < targetMinDistance)
nZoom = targetMinDistance;
}
}
else if (Zooming)
{
const f32 old = CurrentZoom;
CurrentZoom = CurrentZoom + (ZoomStart.X - MousePos.X ) * ZoomSpeed;
nZoom = CurrentZoom;
if (nZoom < 0)
nZoom = CurrentZoom = old;
Zooming = false;
}
core::vector3df translate(OldTarget), upVector(camera->getUpVector());
core::vector3df tvectX = Pos - target;
tvectX = tvectX.crossProduct(upVector);
tvectX.normalize();
const SViewFrustum* const va = camera->getViewFrustum();
core::vector3df tvectY = (va->getFarLeftDown() - va->getFarRightDown());
tvectY = tvectY.crossProduct(upVector.Y > 0 ? Pos - target : target - Pos);
tvectY.normalize();
if (isMouseKeyDown(2) && !Zooming)
{
if (!Translating)
{
TranslateStart = MousePos;
Translating = true;
}
else
{
translate += tvectX * (TranslateStart.X - MousePos.X)*TranslateSpeed +
tvectY * (TranslateStart.Y - MousePos.Y)*TranslateSpeed;
}
}
else if (Translating)
{
translate += tvectX * (TranslateStart.X - MousePos.X)*TranslateSpeed +
tvectY * (TranslateStart.Y - MousePos.Y)*TranslateSpeed;
OldTarget = translate;
Translating = false;
}
if (isMouseKeyDown(0) && !Zooming)
{
if (!Rotating)
{
RotateStart = MousePos;
Rotating = true;
nRotX = RotX;
nRotY = RotY;
}
else
{
nRotX += (RotateStart.X - MousePos.X) * RotateSpeed;
nRotY += (RotateStart.Y - MousePos.Y) * RotateSpeed;
}
}
else if (Rotating)
{
RotX += (RotateStart.X - MousePos.X) * RotateSpeed;
RotY += (RotateStart.Y - MousePos.Y) * RotateSpeed;
nRotX = RotX;
nRotY = RotY;
Rotating = false;
}
target = translate;
Pos.X = nZoom + target.X;
Pos.Y = target.Y;
Pos.Z = target.Z;
Pos.rotateXYBy(nRotY, target);
Pos.rotateXZBy(-nRotX, target);
upVector.set(0,1,0);
upVector.rotateXYBy(-nRotY);
upVector.rotateXZBy(-nRotX+180.f);
camera->setPosition(Pos);
camera->setTarget(target);
camera->setUpVector(upVector);
LastCameraTarget = camera->getTarget();
}
bool CSceneNodeAnimatorCameraMaya::isMouseKeyDown(s32 key)
{
return MouseKeys[key];
}
void CSceneNodeAnimatorCameraMaya::allKeysUp()
{
for (s32 i=0; i<3; ++i)
MouseKeys[i] = false;
}
void CSceneNodeAnimatorCameraMaya::setRotateSpeed(f32 speed)
{
RotateSpeed = speed;
}
void CSceneNodeAnimatorCameraMaya::setMoveSpeed(f32 speed)
{
TranslateSpeed = speed;
}
void CSceneNodeAnimatorCameraMaya::setZoomSpeed(f32 speed)
{
ZoomSpeed = speed;
}
f32 CSceneNodeAnimatorCameraMaya::getRotateSpeed() const
{
return RotateSpeed;
}
f32 CSceneNodeAnimatorCameraMaya::getMoveSpeed() const
{
return TranslateSpeed;
}
f32 CSceneNodeAnimatorCameraMaya::getZoomSpeed() const
{
return ZoomSpeed;
}
ISceneNodeAnimator* CSceneNodeAnimatorCameraMaya::createClone(ISceneNode* node, ISceneManager* newManager)
{
CSceneNodeAnimatorCameraMaya * newAnimator =
new CSceneNodeAnimatorCameraMaya(CursorControl, RotateSpeed, ZoomSpeed, TranslateSpeed);
return newAnimator;
}
}
}