forked from teamnwah/openmw-tes3coop
Added Mangle::Input with SDL and OIS implementation. WIP.
parent
eed875ae04
commit
96e456ee09
@ -0,0 +1,95 @@
|
||||
#ifndef MANGLE_INPUT_DRIVER_H
|
||||
#define MANGLE_INPUT_DRIVER_H
|
||||
|
||||
#include "../tools/shared_ptr.hpp"
|
||||
|
||||
namespace Mangle
|
||||
{
|
||||
namespace Input
|
||||
{
|
||||
/** Generic callback for input events. The meaning of the
|
||||
parameters depend on the system producing the events.
|
||||
*/
|
||||
struct Event
|
||||
{
|
||||
/// Event types
|
||||
enum EventType
|
||||
{
|
||||
EV_Unknown = -1, // Unknown event type
|
||||
EV_KeyDown = 1, // Key, mouse or other button was pressed
|
||||
EV_KeyUp = 2, // Key, mouse or other button was released
|
||||
EV_MouseMove = 3, // Mouse movement (all axis movement?)
|
||||
EV_Other = 4 // Other event
|
||||
};
|
||||
|
||||
/**
|
||||
Called upon all events. The first parameter give the event
|
||||
type, the second gives additional data (usually the local
|
||||
keysym as defined by the driver), and the pointer points to
|
||||
the full custom event structure provided by the driver (the
|
||||
type may vary depending on the EventType, this is defined in
|
||||
the Driver documentation.)
|
||||
*/
|
||||
virtual void event(EventType type, int index, const void *p) = 0;
|
||||
virtual ~Event() {}
|
||||
};
|
||||
|
||||
/** Input::Driver is the main interface to any input system that
|
||||
handles keyboard and/or mouse input, along with any other
|
||||
input source like joysticks.
|
||||
|
||||
It is really a generalized event system, and could also be
|
||||
used for non-input related events. The definition of the event
|
||||
codes and structures are entirely dependent on the
|
||||
implementation.
|
||||
|
||||
A system-independent key code list will be found in keys.hpp,
|
||||
and input drivers should privide optional translations to/from
|
||||
this list for full compatibility.
|
||||
*/
|
||||
struct Driver
|
||||
{
|
||||
virtual ~Driver() {}
|
||||
|
||||
/** Captures input and produces the relevant events from it. An
|
||||
event callback must be set with setEvent(), or all events
|
||||
will be ignored.
|
||||
*/
|
||||
virtual void capture() = 0;
|
||||
|
||||
/** Check the state of a given key or button. The key/button
|
||||
definitions depends on the driver.
|
||||
*/
|
||||
virtual bool isDown(int index) = 0;
|
||||
|
||||
/** Show or hide system mouse cursor
|
||||
*/
|
||||
virtual void showMouse(bool show) = 0;
|
||||
|
||||
/** Set the event handler for input events. The evt->event()
|
||||
function is called for each event. The meaning of the index
|
||||
and *p parameters will be specific to each driver and to
|
||||
each input system.
|
||||
*/
|
||||
void setEvent(Event *evt)
|
||||
{ event = evt; }
|
||||
|
||||
/** Instigate an event. Is used internally for all events, but
|
||||
can also be called from the outside to "fake" events from
|
||||
this driver.
|
||||
*/
|
||||
void makeEvent(Event::EventType type, int index, const void *p=NULL)
|
||||
{
|
||||
if(event)
|
||||
event->event(type,index,p);
|
||||
}
|
||||
|
||||
private:
|
||||
/// Holds the event callback set byt setEvent()
|
||||
Event *event;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<Driver> DriverPtr;
|
||||
}
|
||||
}
|
||||
#endif
|
@ -0,0 +1,148 @@
|
||||
#include "ois_driver.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <sstream>
|
||||
#include <OgreRenderWindow.h>
|
||||
#include <OIS/OIS.h>
|
||||
|
||||
#ifdef __APPLE_CC__
|
||||
#include <Carbon/Carbon.h>
|
||||
#endif
|
||||
|
||||
using namespace Mangle::Input;
|
||||
using namespace OIS;
|
||||
|
||||
struct Mangle::Input::OISListener : OIS::KeyListener, OIS::MouseListener
|
||||
{
|
||||
OISDriver &drv;
|
||||
|
||||
OISListener(OISDriver &driver)
|
||||
: drv(driver) {}
|
||||
|
||||
bool keyPressed( const OIS::KeyEvent &arg )
|
||||
{
|
||||
drv.makeEvent(Event::EV_KeyDown, arg.key, &arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool keyReleased( const OIS::KeyEvent &arg )
|
||||
{
|
||||
drv.makeEvent(Event::EV_KeyUp, arg.key, &arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
|
||||
{
|
||||
// Mouse button events are handled as key events
|
||||
// TODO: Translate mouse buttons into pseudo-keysyms
|
||||
drv.makeEvent(Event::EV_KeyDown, -1, &arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
|
||||
{
|
||||
// TODO: ditto
|
||||
drv.makeEvent(Event::EV_KeyUp, -1, &arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mouseMoved( const OIS::MouseEvent &arg )
|
||||
{
|
||||
drv.makeEvent(Event::EV_MouseMove, -1, &arg);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
OISDriver::OISDriver(Ogre::RenderWindow *window, bool exclusive)
|
||||
{
|
||||
assert(window);
|
||||
|
||||
size_t windowHnd;
|
||||
|
||||
window->getCustomAttribute("WINDOW", &windowHnd);
|
||||
|
||||
std::ostringstream windowHndStr;
|
||||
ParamList pl;
|
||||
|
||||
windowHndStr << windowHnd;
|
||||
pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
|
||||
|
||||
// Set non-exclusive mouse and keyboard input if the user requested
|
||||
// it.
|
||||
if(!exclusive)
|
||||
{
|
||||
#if defined OIS_WIN32_PLATFORM
|
||||
pl.insert(std::make_pair(std::string("w32_mouse"),
|
||||
std::string("DISCL_FOREGROUND" )));
|
||||
pl.insert(std::make_pair(std::string("w32_mouse"),
|
||||
std::string("DISCL_NONEXCLUSIVE")));
|
||||
pl.insert(std::make_pair(std::string("w32_keyboard"),
|
||||
std::string("DISCL_FOREGROUND")));
|
||||
pl.insert(std::make_pair(std::string("w32_keyboard"),
|
||||
std::string("DISCL_NONEXCLUSIVE")));
|
||||
#elif defined OIS_LINUX_PLATFORM
|
||||
pl.insert(std::make_pair(std::string("x11_mouse_grab"),
|
||||
std::string("false")));
|
||||
pl.insert(std::make_pair(std::string("x11_mouse_hide"),
|
||||
std::string("false")));
|
||||
pl.insert(std::make_pair(std::string("x11_keyboard_grab"),
|
||||
std::string("false")));
|
||||
pl.insert(std::make_pair(std::string("XAutoRepeatOn"),
|
||||
std::string("true")));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __APPLE_CC__
|
||||
// Give the application window focus to receive input events
|
||||
ProcessSerialNumber psn = { 0, kCurrentProcess };
|
||||
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
||||
SetFrontProcess(&psn);
|
||||
#endif
|
||||
|
||||
inputMgr = InputManager::createInputSystem( pl );
|
||||
|
||||
// Create all devices
|
||||
keyboard = static_cast<Keyboard*>(inputMgr->createInputObject
|
||||
( OISKeyboard, true ));
|
||||
mouse = static_cast<Mouse*>(inputMgr->createInputObject
|
||||
( OISMouse, true ));
|
||||
|
||||
// Set mouse region
|
||||
const MouseState &ms = mouse->getMouseState();
|
||||
ms.width = window->getWidth();
|
||||
ms.height = window->getHeight();
|
||||
|
||||
// Set up the input listener
|
||||
listener = new OISListener(*this);
|
||||
keyboard-> setEventCallback(listener);
|
||||
mouse-> setEventCallback(listener);
|
||||
}
|
||||
|
||||
OISDriver::~OISDriver()
|
||||
{
|
||||
// Delete the listener object
|
||||
if(listener)
|
||||
delete listener;
|
||||
|
||||
if(inputMgr == NULL) return;
|
||||
|
||||
// Kill the input systems. This will reset input options such as key
|
||||
// repeat rate.
|
||||
inputMgr->destroyInputObject(keyboard);
|
||||
inputMgr->destroyInputObject(mouse);
|
||||
InputManager::destroyInputSystem(inputMgr);
|
||||
inputMgr = NULL;
|
||||
}
|
||||
|
||||
void OISDriver::capture()
|
||||
{
|
||||
// Capture keyboard and mouse events
|
||||
keyboard->capture();
|
||||
mouse->capture();
|
||||
}
|
||||
|
||||
bool OISDriver::isDown(int index)
|
||||
{
|
||||
// TODO: Extend to mouse buttons as well
|
||||
return keyboard->isKeyDown((OIS::KeyCode)index);
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
#ifndef MANGLE_INPUT_OIS_DRIVER_H
|
||||
#define MANGLE_INPUT_OIS_DRIVER_H
|
||||
|
||||
#include "../driver.hpp"
|
||||
|
||||
namespace OIS
|
||||
{
|
||||
class InputManager;
|
||||
class Mouse;
|
||||
class Keyboard;
|
||||
}
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class RenderWindow;
|
||||
}
|
||||
|
||||
namespace Mangle
|
||||
{
|
||||
namespace Input
|
||||
{
|
||||
struct OISListener;
|
||||
|
||||
/** Input driver for OIS, the input manager typically used with
|
||||
Ogre.
|
||||
*/
|
||||
struct OISDriver : Driver
|
||||
{
|
||||
/// If exclusive=true, then we capture mouse and keyboard from
|
||||
/// the OS.
|
||||
OISDriver(Ogre::RenderWindow *window, bool exclusive=true);
|
||||
~OISDriver();
|
||||
|
||||
void capture();
|
||||
bool isDown(int index);
|
||||
/// Not currently supported.
|
||||
void showMouse(bool) {}
|
||||
|
||||
private:
|
||||
OIS::InputManager *inputMgr;
|
||||
OIS::Mouse *mouse;
|
||||
OIS::Keyboard *keyboard;
|
||||
|
||||
OISListener *listener;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
@ -0,0 +1,54 @@
|
||||
#include "sdl_driver.hpp"
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
using namespace Mangle::Input;
|
||||
|
||||
void SDLDriver::capture()
|
||||
{
|
||||
// Poll for events
|
||||
SDL_Event evt;
|
||||
while(SDL_PollEvent(&evt))
|
||||
{
|
||||
Event::EventType type = Event::EV_Unknown;
|
||||
int index = -1;
|
||||
|
||||
switch(evt.type)
|
||||
{
|
||||
// For key events, send the keysym as the index.
|
||||
case SDL_KEYDOWN:
|
||||
type = Event::EV_KeyDown;
|
||||
index = evt.key.keysym.sym;
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
type = Event::EV_KeyUp;
|
||||
index = evt.key.keysym.sym;
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
type = Event::EV_MouseMove;
|
||||
break;
|
||||
// Add more event types later
|
||||
}
|
||||
|
||||
// Pass the event along, using -1 as index for unidentified
|
||||
// event types.
|
||||
makeEvent(type, index, &evt);
|
||||
}
|
||||
}
|
||||
|
||||
bool SDLDriver::isDown(int index)
|
||||
{
|
||||
int num;
|
||||
Uint8 *keys = SDL_GetKeyState(&num);
|
||||
assert(index >= 0 && index < num);
|
||||
|
||||
// The returned array from GetKeyState is indexed by the
|
||||
// SDLK_KEYNAME enums and is just a list of bools. If the indexed
|
||||
// value is true, the button is down.
|
||||
return keys[index];
|
||||
}
|
||||
|
||||
void SDLDriver::showMouse(bool show)
|
||||
{
|
||||
SDL_ShowCursor(show?SDL_ENABLE:SDL_DISABLE);
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
#ifndef MANGLE_INPUT_SDL_DRIVER_H
|
||||
#define MANGLE_INPUT_SDL_DRIVER_H
|
||||
|
||||
#include "../driver.hpp"
|
||||
|
||||
namespace Mangle
|
||||
{
|
||||
namespace Input
|
||||
{
|
||||
/** Input driver for SDL. As the input system of SDL is seldomly
|
||||
used alone (most often along with the video system), it is
|
||||
assumed that you do your own initialization and cleanup of SDL
|
||||
before and after using this driver.
|
||||
|
||||
The Event.event() calls will be given the proper EV_ type, the
|
||||
key index (for key up/down events), and a pointer to the full
|
||||
SDL_Event structure.
|
||||
*/
|
||||
struct SDLDriver : Driver
|
||||
{
|
||||
void capture();
|
||||
bool isDown(int index);
|
||||
void showMouse(bool);
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
@ -0,0 +1,2 @@
|
||||
*_test
|
||||
ogre.cfg
|
@ -0,0 +1,12 @@
|
||||
GCC=g++
|
||||
|
||||
all: sdl_driver_test ois_driver_test
|
||||
|
||||
sdl_driver_test: sdl_driver_test.cpp
|
||||
$(GCC) $< ../servers/sdl_driver.cpp -o $@ -I/usr/include/SDL/ -lSDL
|
||||
|
||||
ois_driver_test: ois_driver_test.cpp
|
||||
$(GCC) $< ../servers/ois_driver.cpp -o $@ -I/usr/local/include/OGRE/ -lOgreMain -lOIS -lboost_filesystem
|
||||
|
||||
clean:
|
||||
rm *_test
|
@ -0,0 +1,34 @@
|
||||
#include <iostream>
|
||||
#include "../driver.hpp"
|
||||
#include <unistd.h>
|
||||
using namespace std;
|
||||
using namespace Mangle::Input;
|
||||
|
||||
Driver *input;
|
||||
|
||||
struct MyCB : Event
|
||||
{
|
||||
void event(Event::EventType type, int i, const void *p)
|
||||
{
|
||||
cout << "got event: type=" << type << " index=" << i << endl;
|
||||
}
|
||||
} mycb;
|
||||
void mainLoop(int argc, int quitKey)
|
||||
{
|
||||
cout << "Hold the Q key to quit:\n";
|
||||
input->setEvent(&mycb);
|
||||
while(!input->isDown(quitKey))
|
||||
{
|
||||
input->capture();
|
||||
usleep(20000);
|
||||
|
||||
if(argc == 1)
|
||||
{
|
||||
cout << "You are running in script mode, aborting. Run this test with a parameter (any at all) to test the input loop properly\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete input;
|
||||
cout << "\nBye bye!\n";
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
#include "common.cpp"
|
||||
|
||||
#include "../servers/ois_driver.hpp"
|
||||
#include <Ogre.h>
|
||||
#include <OIS/OIS.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
bool isFile(const char *name)
|
||||
{
|
||||
boost::filesystem::path cfg_file_path(name);
|
||||
return boost::filesystem::exists(cfg_file_path);
|
||||
}
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace OIS;
|
||||
|
||||
Root *root;
|
||||
RenderWindow *window;
|
||||
|
||||
void setupOgre()
|
||||
{
|
||||
// Disable logging
|
||||
new LogManager;
|
||||
Log *log = LogManager::getSingleton().createLog("");
|
||||
log->setDebugOutputEnabled(false);
|
||||
|
||||
bool useConfig = isFile("ogre.cfg");
|
||||
|
||||
// Set up Root
|
||||
root = new Root("plugins.cfg", "ogre.cfg", "");
|
||||
|
||||
// Configure
|
||||
if(!useConfig)
|
||||
root->showConfigDialog();
|
||||
else
|
||||
root->restoreConfig();
|
||||
|
||||
// Initialize OGRE window
|
||||
window = root->initialise(true, "test", "");
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
setupOgre();
|
||||
input = new OISDriver(window);
|
||||
|
||||
mainLoop(argc, KC_Q);
|
||||
|
||||
delete root;
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
Hold the Q key to quit:
|
||||
got event: type=3 index=-1
|
||||
You are running in script mode, aborting. Run this test with a parameter (any at all) to test the input loop properly
|
||||
|
||||
Bye bye!
|
@ -0,0 +1,5 @@
|
||||
Hold the Q key to quit:
|
||||
got event: type=-1 index=-1
|
||||
You are running in script mode, aborting. Run this test with a parameter (any at all) to test the input loop properly
|
||||
|
||||
Bye bye!
|
@ -0,0 +1,12 @@
|
||||
# Defines plugins to load
|
||||
|
||||
# Define plugin folder
|
||||
PluginFolder=/usr/local/lib/OGRE/
|
||||
|
||||
# Define plugins
|
||||
Plugin=RenderSystem_GL
|
||||
Plugin=Plugin_ParticleFX
|
||||
Plugin=Plugin_OctreeSceneManager
|
||||
# Plugin=Plugin_CgProgramManager
|
||||
|
||||
|
@ -0,0 +1,16 @@
|
||||
#include "common.cpp"
|
||||
|
||||
#include "../servers/sdl_driver.hpp"
|
||||
#include <SDL.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
SDL_SetVideoMode(640, 480, 0, SDL_SWSURFACE);
|
||||
input = new SDLDriver();
|
||||
|
||||
mainLoop(argc, SDLK_q);
|
||||
|
||||
SDL_Quit();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
make || exit
|
||||
|
||||
mkdir -p output
|
||||
|
||||
PROGS=*_test
|
||||
|
||||
for a in $PROGS; do
|
||||
if [ -f "output/$a.out" ]; then
|
||||
echo "Running $a:"
|
||||
./$a | diff output/$a.out -
|
||||
else
|
||||
echo "Creating $a.out"
|
||||
./$a > "output/$a.out"
|
||||
git add "output/$a.out"
|
||||
fi
|
||||
done
|
Loading…
Reference in New Issue