Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F132739
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
25 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/util/events.cpp b/util/events.cpp
index 780fdafe..a2523699 100644
--- a/util/events.cpp
+++ b/util/events.cpp
@@ -1,624 +1,639 @@
#ifdef USE_SDL
#include <SDL.h>
#endif
#ifdef USE_ALLEGRO5
#include <allegro5/allegro.h>
#endif
#include <vector>
#include <map>
#include "graphics/bitmap.h"
#include "events.h"
#include "exceptions/shutdown_exception.h"
#include "configuration.h"
#include "debug.h"
#include "funcs.h"
#include "thread.h"
#include "init.h"
#include "parameter.h"
#include "input/keyboard.h"
#include "input/joystick.h"
#include "input/input-manager.h"
#include "input/input-source.h"
#include "system.h"
using std::map;
namespace Util{
int do_shutdown = 0;
bool shutdown(){
return do_shutdown > 0;
}
EventManager::EventManager():
bufferKeys(false),
deferResize(false){
resize.enable = false;
#ifdef USE_ALLEGRO5
queue = al_create_event_queue();
if (al_is_keyboard_installed()){
al_register_event_source(queue, al_get_keyboard_event_source());
}
+ if (al_is_joystick_installed()){
+ al_register_event_source(queue, al_get_joystick_event_source());
+ }
if (Graphics::the_display != NULL){
al_register_event_source(queue, al_get_display_event_source(Graphics::the_display));
}
#endif
}
#ifdef USE_SDL
static void handleKeyDown(Keyboard & keyboard, const SDL_Event & event){
keyboard.press(event.key.keysym.sym, event.key.keysym.unicode);
}
static void handleKeyUp(Keyboard & keyboard, const SDL_Event & event){
keyboard.release(event.key.keysym.sym);
}
static void handleJoystickButtonUp(map<int, ReferenceCount<Joystick> > joysticks, const SDL_Event & event){
int device = event.jbutton.which;
int button = event.jbutton.button;
ReferenceCount<Joystick> joystick = joysticks[device];
if (joystick != NULL){
joystick->releaseButton(button);
}
}
static void handleJoystickHat(map<int, ReferenceCount<Joystick> > joysticks, const SDL_Event & event){
int device = event.jhat.which;
int motion = event.jhat.value;
ReferenceCount<Joystick> joystick = joysticks[device];
if (joystick != NULL){
joystick->hatMotion(motion);
}
#if 0
/* should up/down control left/right -- flip these values? */
#if WII
const int axis_up_down = 0;
const int axis_left_right = 1;
const int up = 1;
const int down = -1;
const int left = -1;
const int right = 1;
#else
const int axis_up_down = 1;
const int axis_left_right = 0;
const int up = -1;
const int down = 1;
const int left = -1;
const int right = 1;
#endif
switch (motion){
case SDL_HAT_CENTERED: break;
case SDL_HAT_UP: joystick->axisMotion(axis_up_down, up); break;
case SDL_HAT_DOWN: joystick->axisMotion(axis_up_down, down); break;
case SDL_HAT_RIGHT: joystick->axisMotion(axis_left_right, right); break;
case SDL_HAT_LEFT: joystick->axisMotion(axis_left_right, left); break;
default: break;
}
#endif
}
static void handleJoystickButtonDown(map<int, ReferenceCount<Joystick> > joysticks, const SDL_Event & event){
int device = event.jbutton.which;
int button = event.jbutton.button;
ReferenceCount<Joystick> joystick = joysticks[device];
if (joystick != NULL){
joystick->pressButton(button);
}
}
static void handleJoystickAxis(map<int, ReferenceCount<Joystick> > joysticks, const SDL_Event & event){
int device = event.jaxis.which;
int axis = event.jaxis.axis;
int value = event.jaxis.value;
ReferenceCount<Joystick> joystick = joysticks[device];
if (joystick != NULL){
joystick->axisMotion(axis, value);
}
}
void EventManager::runSDL(Keyboard & keyboard, map<int, ReferenceCount<Joystick> > joysticks){
keyboard.poll();
for (map<int, ReferenceCount<Joystick> >::iterator it = joysticks.begin(); it != joysticks.end(); it++){
ReferenceCount<Joystick> joystick = it->second;
if (joystick != NULL){
joystick->poll();
}
}
SDL_Event event;
/* FIXME: android gets into an infinite loop while reading events */
#ifdef ANDROID
// int good = SDL_PollEvent(&event);
// for (int check = 0; check < 10 && good; check++, good = SDL_PollEvent(&event)){
// if (SDL_PollEvent(&event) == 1){
while (SDL_PollEvent(&event) == 1){
#else
while (SDL_PollEvent(&event) == 1){
#endif
switch (event.type){
case SDL_QUIT : {
dispatch(CloseWindow);
break;
}
case SDL_KEYDOWN : {
handleKeyDown(keyboard, event);
// dispatch(Key, event.key.keysym.sym);
break;
}
case SDL_KEYUP : {
handleKeyUp(keyboard, event);
break;
}
case SDL_JOYBUTTONDOWN: {
handleJoystickButtonDown(joysticks, event);
break;
}
case SDL_JOYHATMOTION : {
handleJoystickHat(joysticks, event);
break;
}
case SDL_JOYBUTTONUP: {
handleJoystickButtonUp(joysticks, event);
break;
}
case SDL_JOYAXISMOTION: {
handleJoystickAxis(joysticks, event);
break;
}
case SDL_VIDEORESIZE : {
int width = event.resize.w;
int height = event.resize.h;
/* to keep the perspective correct
* 640/480 = 1.33333
*/
/*
double ratio = (double) 640 / (double) 480;
if (width > height){
height = (int)((double) width / ratio);
} else {
width = (int)((double) height * ratio);
}
*/
dispatch(ResizeScreen, width, height);
break;
}
default : {
break;
}
}
}
}
#endif
#ifdef USE_ALLEGRO
void EventManager::runAllegro(Keyboard & keyboard, map<int, ReferenceCount<Joystick> > joystick){
keyboard.poll();
}
#endif
#ifdef USE_ALLEGRO5
static void handleKeyDown(Keyboard & keyboard, const ALLEGRO_EVENT & event){
keyboard.press(event.keyboard.keycode, event.keyboard.unichar);
}
static void handleKeyUp(Keyboard & keyboard, const ALLEGRO_EVENT & event){
keyboard.release(event.keyboard.keycode);
}
static void handleResize(const ALLEGRO_EVENT & event){
double width = event.display.width;
double height = event.display.height;
/*
if (width < 640){
width = 640;
}
if (height < 480){
height = 480;
}
*/
/* to keep the perspective correct
* 640/480 = 1.33333
*/
/*
double ratio = (double) 640 / (double) 480;
if (width > height){
height = width / ratio;
} else {
width = height * ratio;
}
*/
ALLEGRO_DISPLAY * display = event.display.source;
al_acknowledge_resize(display);
Configuration::setScreenWidth((int) width);
Configuration::setScreenHeight((int) height);
al_resize_display(display, (int) width, (int) height);
Graphics::getScreenBuffer()->clear();
/*
ALLEGRO_TRANSFORM transformation;
al_identity_transform(&transformation);
// al_scale_transform(&transformation, (double) al_get_display_width(display) / (double) GFX_X, (double) al_get_display_height(display) / (double) GFX_Y);
al_scale_transform(&transformation, (double) width / (double) GFX_X, (double) height / (double) GFX_Y);
al_set_target_bitmap(Graphics::getScreenBuffer()->getData()->getBitmap());
al_use_transform(&transformation);
*/
}
-void EventManager::runAllegro5(Keyboard & keyboard, map<int, ReferenceCount<Joystick> > joystick){
+void EventManager::runAllegro5(Keyboard & keyboard, const map<int, ReferenceCount<Joystick> > & joysticks){
keyboard.poll();
+ for (map<int, ReferenceCount<Joystick> >::const_iterator it = joysticks.begin(); it != joysticks.end(); it++){
+ ReferenceCount<Joystick> joystick = it->second;
+ if (joystick != NULL){
+ joystick->poll();
+ }
+ }
+
ALLEGRO_EVENT event;
while (al_get_next_event(queue, &event)){
switch (event.type){
/*
case ALLEGRO_EVENT_KEY_DOWN: {
Global::debug(0) << "Key down " << event.keyboard.keycode << std::endl;
handleKeyDown(keyboard, event);
break;
}
*/
case ALLEGRO_EVENT_DISPLAY_RESIZE: {
handleResize(event);
break;
}
case ALLEGRO_EVENT_KEY_UP: {
handleKeyUp(keyboard, event);
break;
}
case ALLEGRO_EVENT_KEY_CHAR : {
// Global::debug(0) << "Key char " << event.keyboard.keycode << " unicode " << event.keyboard.unichar << std::endl;
handleKeyDown(keyboard, event);
break;
}
+ case ALLEGRO_EVENT_JOYSTICK_CONFIGURATION: {
+ /* FIXME: tell input manager to reconfigure joysticks */
+ // al_reconfigure_joysticks();
+ break;
+ }
}
}
/*
if (joystick){
joystick->poll();
}
SDL_Event event;
while (SDL_PollEvent(&event) == 1){
switch (event.type){
case SDL_QUIT : {
dispatch(CloseWindow);
break;
}
case SDL_KEYDOWN : {
handleKeyDown(keyboard, event);
// dispatch(Key, event.key.keysym.sym);
break;
}
case SDL_KEYUP : {
handleKeyUp(keyboard, event);
break;
}
case SDL_JOYBUTTONDOWN: {
if (joystick != NULL){
handleJoystickButtonDown(joystick, event);
}
break;
}
case SDL_JOYHATMOTION : {
if (joystick != NULL){
handleJoystickHat(joystick, event);
}
break;
}
case SDL_JOYBUTTONUP: {
if (joystick != NULL){
handleJoystickButtonUp(joystick, event);
}
break;
}
case SDL_JOYAXISMOTION: {
if (joystick != NULL){
handleJoystickAxis(joystick, event);
}
break;
}
case SDL_VIDEORESIZE : {
int width = event.resize.w;
int height = event.resize.h;
/ * to keep the perspective correct
* 640/480 = 1.33333
* /
if (width > height){
height = (int)((double) width / 1.3333333333);
} else {
width = (int)((double) height * 1.3333333333);
}
dispatch(ResizeScreen, width, height);
break;
}
default : {
break;
}
}
}
*/
}
#endif
void EventManager::run(Keyboard & keyboard, std::map<int, ReferenceCount<Joystick> > joysticks){
#ifdef USE_SDL
runSDL(keyboard, joysticks);
#elif USE_ALLEGRO
runAllegro(keyboard, joysticks);
#elif USE_ALLEGRO5
runAllegro5(keyboard, joysticks);
#endif
}
/* kill the program if the user requests */
void EventManager::waitForThread(WaitThread & thread){
// Keyboard dummy;
while (!thread.isRunning()){
try{
/* input manager will run the event manager */
InputManager::poll();
// run(dummy);
} catch (const ShutdownException & death){
thread.kill();
throw death;
}
Util::rest(10);
}
}
EventManager::~EventManager(){
#ifdef USE_ALLEGRO5
al_destroy_event_queue(queue);
#endif
}
void EventManager::enableKeyBuffer(){
bufferKeys = true;
}
void EventManager::disableKeyBuffer(){
bufferKeys = false;
}
void EventManager::dispatch(Event type, int arg1){
switch (type){
case Key : {
if (bufferKeys){
keys.push_back(KeyType(arg1));
}
break;
}
default : {
break;
}
}
}
void EventManager::dispatch(Event type, int arg1, int arg2){
switch (type){
case ResizeScreen : {
if (deferResize){
resize.type = ResizeScreen;
resize.width = arg1;
resize.height = arg2;
resize.enable = true;
} else {
Global::debug(1) << "Resizing screen to " << arg1 << ", " << arg2 << std::endl;
if (Graphics::setGraphicsMode(0, arg1, arg2) == 0){
Configuration::setScreenWidth(arg1);
Configuration::setScreenHeight(arg2);
}
}
break;
}
default: break;
}
}
void EventManager::dispatch(Event type){
switch (type){
case CloseWindow : {
throw ShutdownException();
}
default : break;
}
}
void EventManager::deferResizeEvents(bool defer){
deferResize = defer;
if (!deferResize && resize.enable){
dispatch(resize.type, resize.width, resize.height);
resize.enable = false;
}
}
class LoopDone: public std::exception {
public:
LoopDone(){
}
~LoopDone() throw () {
}
};
Logic::~Logic(){
}
Draw::Draw():
frames(0),
second_counter(Global::second_counter),
fps(0){
}
void Draw::drawFirst(const Graphics::Bitmap & screen){
draw(screen);
}
Draw::~Draw(){
}
double Draw::getFps() const {
return fps;
}
void Draw::updateFrames(){
if (second_counter != Global::second_counter){
int difference = Global::second_counter - second_counter;
double alpha = 0.2;
/* unlikely, but just in case */
if (difference == 0){
difference = 1;
}
fps = (alpha * fps) + ((1 - alpha) * (double) frames / difference);
// fps[fps_index] = (double) frames / (double) difference;
// fps_index = (fps_index+1) % max_fps_index;
second_counter = Global::second_counter;
frames = 0;
}
frames += 1;
}
static void changeScreenMode(){
Configuration::setFullscreen(!Configuration::getFullscreen());
int gfx = (Configuration::getFullscreen() ? Global::FULLSCREEN : Global::WINDOWED);
Graphics::setGraphicsMode(gfx, Graphics::Bitmap::getScreenWidth(), Graphics::Bitmap::getScreenHeight());
}
static void checkFullscreen(){
InputMap<int> input;
input.set(Keyboard::Key_F11, 0, true, 5);
std::vector<InputMap<int>::InputEvent> events = InputManager::getEvents(input, InputSource());
for (std::vector<InputMap<int>::InputEvent>::iterator it = events.begin(); it != events.end(); it++){
InputMap<int>::InputEvent event = *it;
if (!event.enabled){
continue;
}
if (event.out == 5){
changeScreenMode();
}
}
}
static Graphics::Bitmap blackBars(const Graphics::Bitmap & screen){
double width = screen.getWidth();
double height = screen.getHeight();
double ratio = (double) 640 / (double) 480;
width = (double) height * ratio;
if (width > screen.getWidth()){
width = screen.getWidth();
height = width / ratio;
}
int x = (screen.getWidth() - width) / 2;
int y = (screen.getHeight() - height) / 2;
return Graphics::Bitmap(screen, x, y, (int) width, (int) height);
}
static void doStandardLoop(Logic & logic, Draw & draw){
if (Graphics::screenParameter.current() == NULL){
throw Exception::Base(__FILE__, __LINE__);
}
const Graphics::Bitmap & screen = *Graphics::screenParameter.current();
screen.clear();
draw.drawFirst(blackBars(screen));
screen.BlitToScreen();
Global::speed_counter4 = 0;
double runCounter = 0;
try{
const int maxCount = 20;
int frameCount = 0;
uint64_t frameTime = 0;
int logicCount = 0;
uint64_t logicTime = 0;
while (!logic.done()){
if (Global::speed_counter4 > 0){
// Global::debug(0) << "Speed counter " << Global::speed_counter4 << std::endl;
runCounter += logic.ticks(Global::speed_counter4);
Global::speed_counter4 = 0;
bool need_draw = false;
while (runCounter >= 1.0){
need_draw = true;
InputManager::poll();
checkFullscreen();
runCounter -= 1;
logicCount += 1;
uint64_t now = System::currentMilliseconds();
logic.run();
uint64_t later = System::currentMilliseconds();
logicTime += (later - now);
if (logicCount >= maxCount){
// Global::debug(0) << "Logic average " << (logicTime / logicCount) << "ms" << std::endl;
logicCount = 0;
logicTime = 0;
}
if (shutdown()){
throw ShutdownException();
}
if (logic.done()){
/* quit the loop immediately */
throw LoopDone();
}
}
if (need_draw){
frameCount += 1;
draw.updateFrames();
uint64_t now = System::currentMilliseconds();
draw.draw(blackBars(screen));
screen.BlitToScreen();
uint64_t later = System::currentMilliseconds();
frameTime += (later - now);
if (frameCount >= maxCount){
// Global::debug(0) << "Draw average " << (frameTime / frameCount) << "ms" << std::endl;
frameCount = 0;
frameTime = 0;
}
}
}
while (Global::speed_counter4 == 0){
/* if the fps is limited then don't keep redrawing */
if (Global::rateLimit){
rest(1);
} else {
draw.updateFrames();
draw.draw(blackBars(screen));
screen.BlitToScreen();
}
}
}
} catch (const LoopDone & done){
}
}
void standardLoop(Logic & logic, Draw & draw){
/* if a screen already exists (because we have nested standardLoops) then
* leave this parameter alone, otherwise set a new parameter.
*/
/*
if (Parameter<Graphics::Bitmap*>::current() == NULL){
doStandardLoop(logic, draw);
} else {
doStandardLoop(logic, draw);
}
*/
doStandardLoop(logic, draw);
}
}
diff --git a/util/events.h b/util/events.h
index f225f643..705825ed 100644
--- a/util/events.h
+++ b/util/events.h
@@ -1,133 +1,133 @@
#ifndef _paintown_events_h
#define _paintown_events_h
/* handles global events from the system such as
* window manager events (press X button)
* keyboard/mouse/joystick input (for some backends like SDL)
*/
#include <vector>
#include <map>
#include "pointer.h"
#ifdef USE_ALLEGRO5
struct ALLEGRO_EVENT_SOURCE;
struct ALLEGRO_EVENT_QUEUE;
#endif
#ifdef USE_SDL
#include <SDL.h>
#endif
class Keyboard;
class Joystick;
namespace Graphics{
class Bitmap;
}
namespace Util{
class WaitThread;
class EventManager{
public:
EventManager();
virtual void run(Keyboard & keyboard, std::map<int, ReferenceCount<Joystick> > joysticks);
virtual void waitForThread(WaitThread & thread);
virtual ~EventManager();
#ifdef USE_SDL
typedef SDLKey KeyType;
#else
typedef int KeyType;
#endif
inline const std::vector<KeyType> & getBufferedKeys() const {
return keys;
}
void deferResizeEvents(bool defer);
void enableKeyBuffer();
void disableKeyBuffer();
private:
enum Event{
CloseWindow,
ResizeScreen,
Key
};
struct ResizeEvent{
Event type;
int width;
int height;
bool enable;
};
virtual void dispatch(Event type, int arg1, int arg2);
virtual void dispatch(Event type, int arg1);
virtual void dispatch(Event type);
#ifdef USE_SDL
virtual void runSDL(Keyboard &, std::map<int, ReferenceCount<Joystick> >);
#endif
#ifdef USE_ALLEGRO
virtual void runAllegro(Keyboard & keyboard, std::map<int, ReferenceCount<Joystick> >);
#endif
#ifdef USE_ALLEGRO5
- virtual void runAllegro5(Keyboard & keyboard, std::map<int, ReferenceCount<Joystick> >);
+ virtual void runAllegro5(Keyboard & keyboard, const std::map<int, ReferenceCount<Joystick> > &);
ALLEGRO_EVENT_QUEUE * queue;
#endif
std::vector<KeyType> keys;
bool bufferKeys;
bool deferResize;
/* Only need the last event */
ResizeEvent resize;
};
/* implement these classes to get the standard run loop */
class Logic{
public:
/* run a cycle of logic */
virtual void run() = 0;
/* the run loop should finish */
virtual bool done() = 0;
/* return a number of logic ticks for a given number of ticks on
* a real system.
*/
virtual double ticks(double systemTicks) = 0;
virtual ~Logic();
};
class Draw{
public:
Draw();
/* give the drawer a chance to draw stuff to the screen before any logic occurs.
* default implementation is to do nothing.
*/
virtual void drawFirst(const Graphics::Bitmap & screen);
/* standard draw method after logic has run */
virtual void draw(const Graphics::Bitmap & screen) = 0;
virtual ~Draw();
/* called by the standardLoop */
virtual void updateFrames();
virtual double getFps() const;
protected:
int frames;
unsigned int second_counter;
double fps;
};
void standardLoop(Logic & logic, Draw & draw);
/* true if the game should shutdown immediately */
bool shutdown();
extern int do_shutdown;
}
#endif
diff --git a/util/input/allegro5/joystick.cpp b/util/input/allegro5/joystick.cpp
index ff6b75ae..9f9d2345 100644
--- a/util/input/allegro5/joystick.cpp
+++ b/util/input/allegro5/joystick.cpp
@@ -1,29 +1,72 @@
#ifdef USE_ALLEGRO5
#include "../joystick.h"
#include "joystick.h"
+#include "util/debug.h"
#include <allegro5/allegro.h>
Allegro5Joystick::Allegro5Joystick(int id):
id(id){
+ queue = al_create_event_queue();
+ if (al_is_joystick_installed()){
+ al_register_event_source(queue, al_get_joystick_event_source());
+ }
+}
+
+void Allegro5Joystick::axis(int stick, int axis, float position){
+ Global::debug(0) << "stick " << stick << " axis " << axis << " position " << position << std::endl;
+}
+
+void Allegro5Joystick::buttonDown(int button){
+ Global::debug(0) << "Button down " << button << std::endl;
+}
+
+void Allegro5Joystick::buttonUp(int button){
+ Global::debug(0) << "Button up " << button << std::endl;
}
void Allegro5Joystick::poll(){
+ events.clear();
+ ALLEGRO_EVENT event;
+ while (al_get_next_event(queue, &event)){
+ switch (event.type){
+ case ALLEGRO_EVENT_JOYSTICK_AXIS: {
+ if (event.joystick.id == al_get_joystick(id)){
+ axis(event.joystick.stick, event.joystick.axis, event.joystick.pos);
+ }
+ break;
+ }
+ case ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN: {
+ if (event.joystick.id == al_get_joystick(id)){
+ buttonDown(event.joystick.button);
+ }
+ break;
+ }
+ case ALLEGRO_EVENT_JOYSTICK_BUTTON_UP: {
+ if (event.joystick.id == al_get_joystick(id)){
+ buttonUp(event.joystick.button);
+ }
+ break;
+ }
+ }
+ }
}
int Allegro5Joystick::getDeviceId() const {
return id;
}
std::string Allegro5Joystick::getName() const {
return al_get_joystick_name(al_get_joystick(id));
}
Allegro5Joystick::~Allegro5Joystick(){
+ al_destroy_event_queue(queue);
+ queue = NULL;
}
int Joystick::numberOfJoysticks(){
return al_get_num_joysticks();
}
#endif
diff --git a/util/input/allegro5/joystick.h b/util/input/allegro5/joystick.h
index 49918f2b..05bab633 100644
--- a/util/input/allegro5/joystick.h
+++ b/util/input/allegro5/joystick.h
@@ -1,21 +1,29 @@
#ifndef _paintown_allegro5_joystick_h
#define _paintown_allegro5_joystick_h
#include "../joystick.h"
#include <string>
+struct ALLEGRO_EVENT_QUEUE;
+
class Allegro5Joystick: public Joystick {
public:
virtual void poll();
virtual int getDeviceId() const;
virtual std::string getName() const;
virtual ~Allegro5Joystick();
friend class Joystick;
+
protected:
+ void axis(int stick, int axis, float position);
+ void buttonDown(int button);
+ void buttonUp(int button);
+
Allegro5Joystick(int id);
int id;
+ ALLEGRO_EVENT_QUEUE * queue;
};
#endif
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jun 16, 1:00 AM (2 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
71606
Default Alt Text
(25 KB)
Attached To
Mode
R75 R-Tech1
Attached
Detach File
Event Timeline