Added Mangle::Input with SDL and OIS implementation. WIP.

actorid
Nicolay Korslund 15 years ago
parent eed875ae04
commit 96e456ee09

@ -564,7 +564,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = sound stream vfs
INPUT = sound stream vfs input
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is

@ -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

@ -11,4 +11,5 @@ function run()
run stream
run vfs
run sound
run input
run .

Loading…
Cancel
Save