openmw-tes3coop/ogre/cpp_framelistener.cpp
2009-05-03 14:35:43 +00:00

214 lines
6 KiB
C++

/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008 Nicolay Korslund
Email: < korslund@gmail.com >
WWW: http://openmw.snaptoad.com/
This file (cpp_framelistener.cpp) is part of the OpenMW package.
OpenMW is distributed as free software: you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 3, as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see
http://www.gnu.org/licenses/ .
*/
#include <stdint.h>
// Callbacks to D code.
// Called once each frame
extern "C" int32_t d_frameStarted(float time, int guiMode);
// Handle events
extern "C" void d_handleKey(int keycode, uint32_t text);
extern "C" void d_handleMouseMove(const OIS::MouseState *state);
extern "C" void d_handleMouseButton(const OIS::MouseState *state,
int32_t button);
// Frame listener, passed to Ogre. The only thing we use this for is
// to capture input and pass control to D code.
class MorroFrameListener: public FrameListener
{
public:
// Start of frame
bool frameStarted(const FrameEvent& evt)
{
if(mWindow->isClosed())
return false;
// Capture keyboard and mouse events
mKeyboard->capture();
mMouse->capture();
// Notify the GUI
mGUI->injectFrameEntered(evt.timeSinceLastFrame);
// Turn over control to the D code
return d_frameStarted(evt.timeSinceLastFrame, guiMode);
}
};
// Recieves input events and sends them to the D event handler.
class InputListener : public OIS::KeyListener, public OIS::MouseListener
{
public:
bool keyPressed( const OIS::KeyEvent &arg )
{
/*
std::cout << "KeyPressed {" << arg.key
<< ", " << ((OIS::Keyboard*)(arg.device))->getAsString(arg.key)
<< "} || Character (" << (char)arg.text << ")\n";
//*/
d_handleKey(arg.key, arg.text);
return true;
}
bool mouseMoved( const OIS::MouseEvent &arg )
{
/*
const OIS::MouseState& s = arg.state;
std::cout << "MouseMoved: Abs("
<< s.X.abs << ", " << s.Y.abs << ", " << s.Z.abs << ") Rel("
<< s.X.rel << ", " << s.Y.rel << ", " << s.Z.rel << ")\n";
*/
// TODO: this should be handled elsewhere later on, most likely in
// Monster script.
if(guiMode)
mGUI->injectMouseMove(arg);
else
d_handleMouseMove(&arg.state);
return true;
}
bool mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
{
/*
const OIS::MouseState& s = arg.state;
std::cout << "Mouse button #" << id << " pressed. Abs("
<< s.X.abs << ", " << s.Y.abs << ", " << s.Z.abs << ") Rel("
<< s.X.rel << ", " << s.Y.rel << ", " << s.Z.rel << ")\n";
*/
if(guiMode)
mGUI->injectMousePress(arg, id);
d_handleMouseButton(&arg.state, id);
return true;
}
bool mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
{
if(guiMode)
mGUI->injectMouseRelease(arg, id);
return true;
}
// Unused
bool keyReleased( const OIS::KeyEvent &arg ) { return true; }
};
MorroFrameListener mFrameListener;
InputListener mInput;
// Functions called from D during event handling
extern "C" int32_t ois_isPressed(int32_t keysym)
{
return mKeyboard->isKeyDown((OIS::KeyCode)keysym);
}
// Dump screen contents to file
extern "C" void ogre_screenshot(char* filename)
{
mWindow->writeContentsToFile(filename);
//This doesn't work, I think I have to set up an overlay or
//something first and display the text manually.
//mWindow->setDebugText(String("Wrote ") + filename);
}
// Rotate camera as result of mouse movement
extern "C" void ogre_rotateCamera(float x, float y)
{
mCamera->yaw(Degree(-x));
Quaternion nopitch = mCamera->getOrientation();
mCamera->pitch(Degree(-y));
// Is the camera close to being upside down?
if(mCamera->getUp()[1] <= 0.1)
// If so, undo the last pitch
mCamera->setOrientation(nopitch);
}
// Get current camera position
extern "C" void ogre_getCameraPos(float *x, float *y, float *z)
{
Vector3 pos = mCamera->getPosition();
*x = pos[0];
*y = -pos[2];
*z = pos[1];
}
// Get current camera orientation, in the form of 'front' and 'up'
// vectors.
extern "C" void ogre_getCameraOrientation(float *fx, float *fy, float *fz,
float *ux, float *uy, float *uz)
{
Vector3 front = mCamera->getDirection();
Vector3 up = mCamera->getUp();
*fx = front[0];
*fy = -front[2];
*fz = front[1];
*ux = up[0];
*uy = -up[2];
*uz = up[1];
}
// Move camera
extern "C" void ogre_moveCamera(float x, float y, float z)
{
// Transforms Morrowind coordinates to OGRE coordinates. The camera
// is not affected by the rotation of the root node, so we must
// transform this manually.
mCamera->setPosition(Vector3(x,z+90,-y));
//g_light->setPosition(mCamera->getPosition());
}
// Rotate camera using Morrowind rotation specifiers
extern "C" void ogre_setCameraRotation(float r1, float r2, float r3)
{
// TODO: This translation is probably not correct, but for now I
// have no reference point. Fix it later when we teleport from one
// cell to another, so we have something to compare against.
// Rotate around X axis
Quaternion xr(Radian(-r1), Vector3::UNIT_X);
// Rotate around Y axis
Quaternion yr(Radian(r3+3.14), Vector3::UNIT_Y);
// Rotate around Z axis
Quaternion zr(Radian(-r2), Vector3::UNIT_Z);
// Rotates first around z, then y, then x
mCamera->setOrientation(xr*yr*zr);
}
// Move camera relative to its own axis set.
extern "C" void ogre_moveCameraRel(float x, float y, float z)
{
mCamera->moveRelative(Vector3(x,0,z));
// up/down movement is always done relative the world axis
mCamera->move(Vector3(0,y,0));
}