forked from teamnwah/openmw-tes3coop
Added camera movement (arrows/WASD). No mouse look yet.
This commit is contained in:
parent
af7c87e8dc
commit
6b6f5b95ec
7 changed files with 186 additions and 32 deletions
|
@ -28,7 +28,7 @@ set(OGRE ogre/renderer.cpp)
|
||||||
set(OGRE_HEADER ogre/renderer.hpp)
|
set(OGRE_HEADER ogre/renderer.hpp)
|
||||||
|
|
||||||
set(INPUT input/oismanager.cpp)
|
set(INPUT input/oismanager.cpp)
|
||||||
set(INPUT_HEADER input/oismanager.hpp input/listener.hpp input/func_binder.hpp input/dispatch_map.hpp input/dispatcher.hpp)
|
set(INPUT_HEADER input/oismanager.hpp input/listener.hpp input/func_binder.hpp input/dispatch_map.hpp input/dispatcher.hpp input/poller.hpp)
|
||||||
|
|
||||||
set(GAME game/main.cpp game/engine.cpp)
|
set(GAME game/main.cpp game/engine.cpp)
|
||||||
set(GAME_HEADER game/mwinput/inputmanager.hpp game/engine.hpp)
|
set(GAME_HEADER game/mwinput/inputmanager.hpp game/engine.hpp)
|
||||||
|
@ -38,7 +38,7 @@ set(ESM_STORE_HEADER esm_store/cell_store.hpp esm_store/reclists.hpp esm_store/s
|
||||||
|
|
||||||
set(GAMEREND game/mwrender/mwscene.cpp game/mwrender/cell.cpp game/mwrender/interior.cpp)
|
set(GAMEREND game/mwrender/mwscene.cpp game/mwrender/cell.cpp game/mwrender/interior.cpp)
|
||||||
set(GAMEREND_HEADER game/mwrender/cell.hpp game/mwrender/mwscene.hpp
|
set(GAMEREND_HEADER game/mwrender/cell.hpp game/mwrender/mwscene.hpp
|
||||||
game/mwrender/interior.hpp)
|
game/mwrender/interior.hpp game/mwrender/playerpos.hpp)
|
||||||
|
|
||||||
set(ESM_HEADER esm/defs.hpp esm/loadcell.hpp esm/loadfact.hpp esm/loadltex.hpp
|
set(ESM_HEADER esm/defs.hpp esm/loadcell.hpp esm/loadfact.hpp esm/loadltex.hpp
|
||||||
esm/loadskil.hpp
|
esm/loadskil.hpp
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "mwrender/interior.hpp"
|
#include "mwrender/interior.hpp"
|
||||||
#include "mwinput/inputmanager.hpp"
|
#include "mwinput/inputmanager.hpp"
|
||||||
|
#include "mwrender/playerpos.hpp"
|
||||||
|
|
||||||
OMW::Engine::Engine() {}
|
OMW::Engine::Engine() {}
|
||||||
|
|
||||||
|
@ -118,9 +119,12 @@ void OMW::Engine::go()
|
||||||
|
|
||||||
std::cout << "\nSetting up cell rendering\n";
|
std::cout << "\nSetting up cell rendering\n";
|
||||||
|
|
||||||
// Sets up camera, scene manager etc
|
// Sets up camera, scene manager, and viewport.
|
||||||
MWRender::MWScene scene(mOgre);
|
MWRender::MWScene scene(mOgre);
|
||||||
|
|
||||||
|
// Used to control the player camera and position
|
||||||
|
MWRender::PlayerPos player(scene.getCamera());
|
||||||
|
|
||||||
// This connects the cell data with the rendering scene.
|
// This connects the cell data with the rendering scene.
|
||||||
MWRender::InteriorCellRender rend(cell, scene);
|
MWRender::InteriorCellRender rend(cell, scene);
|
||||||
|
|
||||||
|
@ -130,7 +134,7 @@ void OMW::Engine::go()
|
||||||
std::cout << "Setting up input system\n";
|
std::cout << "Setting up input system\n";
|
||||||
|
|
||||||
// Sets up the input system
|
// Sets up the input system
|
||||||
MWInput::MWInputManager input(mOgre);
|
MWInput::MWInputManager input(mOgre, player);
|
||||||
|
|
||||||
std::cout << "\nStart! Press Q/ESC or close window to exit.\n";
|
std::cout << "\nStart! Press Q/ESC or close window to exit.\n";
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
#ifndef _INPUT_MWINPUTMANAGER_H
|
#ifndef _MWINPUT_MWINPUTMANAGER_H
|
||||||
#define _INPUT_MWINPUTMANAGER_H
|
#define _MWINPUT_MWINPUTMANAGER_H
|
||||||
|
|
||||||
#include "input/listener.hpp"
|
#include "input/listener.hpp"
|
||||||
#include "input/dispatcher.hpp"
|
#include "input/dispatcher.hpp"
|
||||||
|
#include "input/poller.hpp"
|
||||||
#include "boost/bind.hpp"
|
#include "boost/bind.hpp"
|
||||||
|
#include "game/mwrender/playerpos.hpp"
|
||||||
|
|
||||||
namespace MWInput
|
namespace MWInput
|
||||||
{
|
{
|
||||||
|
@ -11,21 +13,35 @@ namespace MWInput
|
||||||
{
|
{
|
||||||
A_Quit, // Exit the program
|
A_Quit, // Exit the program
|
||||||
|
|
||||||
|
A_MoveLeft, // Move player left / right
|
||||||
|
A_MoveRight,
|
||||||
|
A_MoveUp, // Move up / down
|
||||||
|
A_MoveDown,
|
||||||
|
A_MoveForward, // Forward / Backward
|
||||||
|
A_MoveBackward,
|
||||||
|
|
||||||
A_LAST // Marker for the last item
|
A_LAST // Marker for the last item
|
||||||
};
|
};
|
||||||
|
|
||||||
// Class that handles all input and key bindings for OpenMW
|
// Class that handles all input and key bindings for OpenMW
|
||||||
class MWInputManager
|
class MWInputManager : public Ogre::FrameListener
|
||||||
{
|
{
|
||||||
|
// Note: the order here is important. The OISManager must be
|
||||||
|
// initialized before poller and listener.
|
||||||
Input::Dispatcher disp;
|
Input::Dispatcher disp;
|
||||||
Input::OISManager input;
|
Input::OISManager input;
|
||||||
|
Input::Poller poller;
|
||||||
Input::InputListener listener;
|
Input::InputListener listener;
|
||||||
|
MWRender::PlayerPos &player;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MWInputManager(Render::OgreRenderer &ogre)
|
MWInputManager(Render::OgreRenderer &ogre,
|
||||||
|
MWRender::PlayerPos &_player)
|
||||||
: disp(A_LAST),
|
: disp(A_LAST),
|
||||||
input(ogre),
|
input(ogre),
|
||||||
listener(ogre, input, disp)
|
poller(input),
|
||||||
|
listener(ogre, input, disp),
|
||||||
|
player(_player)
|
||||||
{
|
{
|
||||||
using namespace Input;
|
using namespace Input;
|
||||||
using namespace OIS;
|
using namespace OIS;
|
||||||
|
@ -35,9 +51,56 @@ namespace MWInput
|
||||||
boost::bind(&InputListener::exitNow, &listener),
|
boost::bind(&InputListener::exitNow, &listener),
|
||||||
"Quit program");
|
"Quit program");
|
||||||
|
|
||||||
|
// Add ourselves as a frame listener, to catch movement keys
|
||||||
|
ogre.getRoot()->addFrameListener(this);
|
||||||
|
|
||||||
// Key bindings
|
// Key bindings
|
||||||
disp.bind(KC_Q, A_Quit);
|
disp.bind(KC_Q, A_Quit);
|
||||||
disp.bind(KC_ESCAPE, A_Quit);
|
disp.bind(KC_ESCAPE, A_Quit);
|
||||||
|
|
||||||
|
// Key bindings for polled keys
|
||||||
|
|
||||||
|
// Arrow keys
|
||||||
|
poller.bind(A_MoveLeft, KC_LEFT);
|
||||||
|
poller.bind(A_MoveRight, KC_RIGHT);
|
||||||
|
poller.bind(A_MoveForward, KC_UP);
|
||||||
|
poller.bind(A_MoveBackward, KC_DOWN);
|
||||||
|
|
||||||
|
// WASD keys
|
||||||
|
poller.bind(A_MoveLeft, KC_A);
|
||||||
|
poller.bind(A_MoveRight, KC_D);
|
||||||
|
poller.bind(A_MoveForward, KC_W);
|
||||||
|
poller.bind(A_MoveBackward, KC_D);
|
||||||
|
|
||||||
|
// Use shift and ctrl for up and down
|
||||||
|
poller.bind(A_MoveUp, KC_LSHIFT);
|
||||||
|
poller.bind(A_MoveDown, KC_LCONTROL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used to check for movement keys
|
||||||
|
bool frameStarted(const Ogre::FrameEvent &evt)
|
||||||
|
{
|
||||||
|
float speed = 300 * evt.timeSinceLastFrame;
|
||||||
|
float moveX = 0, moveY = 0, moveZ = 0;
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
if(poller.isDown(A_MoveLeft)) moveX -= speed;
|
||||||
|
if(poller.isDown(A_MoveRight)) moveX += speed;
|
||||||
|
if(poller.isDown(A_MoveForward)) moveZ -= speed;
|
||||||
|
if(poller.isDown(A_MoveBackward)) moveZ += speed;
|
||||||
|
|
||||||
|
// TODO: These should be enabled for floating modes (like
|
||||||
|
// swimming and levitation) and disabled for everything else.
|
||||||
|
if(poller.isDown(A_MoveUp)) moveY += speed;
|
||||||
|
if(poller.isDown(A_MoveDown)) moveY -= speed;
|
||||||
|
|
||||||
|
if(moveX == 0 && moveY == 0 && moveZ == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
player.moveRel(moveX, moveY, moveZ);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
56
game/mwrender/playerpos.hpp
Normal file
56
game/mwrender/playerpos.hpp
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#ifndef _MWRENDER_PLAYERPOS_H
|
||||||
|
#define _MWRENDER_PLAYERPOS_H
|
||||||
|
|
||||||
|
#include "OgreCamera.h"
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
// This class keeps track of the player position. It takes care of
|
||||||
|
// camera movement, sound listener updates, and collision handling
|
||||||
|
// (to be done).
|
||||||
|
class PlayerPos
|
||||||
|
{
|
||||||
|
float x, y, z;
|
||||||
|
Ogre::Camera *camera;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PlayerPos(Ogre::Camera *cam) :
|
||||||
|
camera(cam), x(0), y(0), z(0) {}
|
||||||
|
|
||||||
|
// Set the player position. Uses Morrowind coordinates.
|
||||||
|
void setPos(float _x, float _y, float _z)
|
||||||
|
{
|
||||||
|
x = _x;
|
||||||
|
y = _y;
|
||||||
|
z = _z;
|
||||||
|
|
||||||
|
// TODO: Update sound listener
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the player relative to her own position and
|
||||||
|
// orientation. After the call, the new position is returned.
|
||||||
|
void moveRel(float &relX, float &relY, float &relZ)
|
||||||
|
{
|
||||||
|
using namespace Ogre;
|
||||||
|
|
||||||
|
// Move camera relative to its own direction
|
||||||
|
camera->moveRelative(Vector3(relX,0,relZ));
|
||||||
|
|
||||||
|
// Up/down movement is always done relative the world axis.
|
||||||
|
camera->move(Vector3(0,relY,0));
|
||||||
|
|
||||||
|
// Get new camera position, converting back to MW coords.
|
||||||
|
Vector3 pos = camera->getPosition();
|
||||||
|
relX = pos[0];
|
||||||
|
relY = -pos[2];
|
||||||
|
relZ = pos[1];
|
||||||
|
|
||||||
|
// TODO: Collision detection must be used to find the REAL new
|
||||||
|
// position.
|
||||||
|
|
||||||
|
// Set the position
|
||||||
|
setPos(relX, relY, relZ);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -24,6 +24,9 @@ namespace Input
|
||||||
mMouse = input.mouse;
|
mMouse = input.mouse;
|
||||||
mKeyboard = input.keyboard;
|
mKeyboard = input.keyboard;
|
||||||
|
|
||||||
|
assert(mKeyboard);
|
||||||
|
assert(mWindow);
|
||||||
|
|
||||||
// Add ourself to the managers
|
// Add ourself to the managers
|
||||||
rend.getRoot() -> addFrameListener(this);
|
rend.getRoot() -> addFrameListener(this);
|
||||||
mKeyboard -> setEventCallback(this);
|
mKeyboard -> setEventCallback(this);
|
||||||
|
|
51
input/poller.hpp
Normal file
51
input/poller.hpp
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef _INPUT_POLLER_H
|
||||||
|
#define _INPUT_POLLER_H
|
||||||
|
|
||||||
|
#include "dispatch_map.hpp"
|
||||||
|
#include "oismanager.hpp"
|
||||||
|
|
||||||
|
namespace Input {
|
||||||
|
|
||||||
|
/** The poller is used to check (poll) for keys rather than waiting
|
||||||
|
for events. TODO: Might make this OIS-independent later. */
|
||||||
|
struct Poller
|
||||||
|
{
|
||||||
|
DispatchMap map;
|
||||||
|
OIS::Keyboard *keyboard;
|
||||||
|
|
||||||
|
Poller(Input::OISManager &ois)
|
||||||
|
{
|
||||||
|
keyboard = ois.keyboard;
|
||||||
|
assert(keyboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Bind or unbind a given action with a key. The action is the first
|
||||||
|
parameter, the key is the second.
|
||||||
|
*/
|
||||||
|
void bind(int in, int out) { map.bind(in, out); }
|
||||||
|
void unbind(int in, int out) { map.unbind(in, out); }
|
||||||
|
bool isBound(int in) const { return map.isBound(in); }
|
||||||
|
|
||||||
|
/// Check whether a given action button is currently pressed.
|
||||||
|
typedef DispatchMap::OutList _O;
|
||||||
|
bool isDown(int index) const
|
||||||
|
{
|
||||||
|
assert(keyboard);
|
||||||
|
|
||||||
|
// No bindings, no action
|
||||||
|
if(!isBound(index))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Get all the keys bound to this action, and check them.
|
||||||
|
const _O &list = map.getList(index);
|
||||||
|
_O::const_iterator it;
|
||||||
|
for(it = list.begin(); it != list.end(); it++)
|
||||||
|
// If there's any match, we're good to go.
|
||||||
|
if(keyboard->isKeyDown((OIS::KeyCode)*it)) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -130,11 +130,6 @@ InputListener mInput;
|
||||||
|
|
||||||
// Functions called from D during event handling
|
// 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
|
// Dump screen contents to file
|
||||||
extern "C" void ogre_screenshot(char* filename)
|
extern "C" void ogre_screenshot(char* filename)
|
||||||
{
|
{
|
||||||
|
@ -160,15 +155,6 @@ extern "C" void ogre_rotateCamera(float x, float y)
|
||||||
mCamera->setOrientation(nopitch);
|
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'
|
// Get current camera orientation, in the form of 'front' and 'up'
|
||||||
// vectors.
|
// vectors.
|
||||||
extern "C" void ogre_getCameraOrientation(float *fx, float *fy, float *fz,
|
extern "C" void ogre_getCameraOrientation(float *fx, float *fy, float *fz,
|
||||||
|
@ -212,12 +198,3 @@ extern "C" void ogre_setCameraRotation(float r1, float r2, float r3)
|
||||||
// Rotates first around z, then y, then x
|
// Rotates first around z, then y, then x
|
||||||
mCamera->setOrientation(xr*yr*zr);
|
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));
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue