Initial Lime Gamepad API

This commit is contained in:
Joshua Granick
2015-03-18 01:42:56 -07:00
parent f4c9880cce
commit cfbf3f4a3f
15 changed files with 460 additions and 1 deletions

View File

@@ -18,6 +18,7 @@ import lime.ui.Window;
class NativeApplication {
private var gamepadEventInfo = new GamepadEventInfo ();
private var keyEventInfo = new KeyEventInfo ();
private var mouseEventInfo = new MouseEventInfo ();
private var renderEventInfo = new RenderEventInfo (RENDER);
@@ -60,6 +61,7 @@ class NativeApplication {
public function exec ():Int {
lime_gamepad_event_manager_register (handleGamepadEvent, gamepadEventInfo);
lime_key_event_manager_register (handleKeyEvent, keyEventInfo);
lime_mouse_event_manager_register (handleMouseEvent, mouseEventInfo);
lime_render_event_manager_register (handleRenderEvent, renderEventInfo);
@@ -105,6 +107,39 @@ class NativeApplication {
}
private function handleGamepadEvent ():Void {
if (parent.window != null) {
switch (gamepadEventInfo.type) {
case AXIS_MOVE:
parent.window.onGamepadAxisMove.dispatch (gamepadEventInfo.id, gamepadEventInfo.axis, gamepadEventInfo.value);
case BUTTON_DOWN:
parent.window.onGamepadButtonDown.dispatch (gamepadEventInfo.id, gamepadEventInfo.button);
case BUTTON_UP:
parent.window.onGamepadButtonUp.dispatch (gamepadEventInfo.id, gamepadEventInfo.button);
case CONNECT:
parent.window.onGamepadConnect.dispatch (gamepadEventInfo.id);
case DISCONNECT:
parent.window.onGamepadDisconnect.dispatch (gamepadEventInfo.id);
}
}
}
private function handleKeyEvent ():Void {
if (parent.window != null) {
@@ -291,6 +326,7 @@ class NativeApplication {
private static var lime_application_update = System.load ("lime", "lime_application_update", 1);
private static var lime_application_quit = System.load ("lime", "lime_application_quit", 1);
private static var lime_application_get_ticks = System.load ("lime", "lime_application_get_ticks", 0);
private static var lime_gamepad_event_manager_register = System.load ("lime", "lime_gamepad_event_manager_register", 2);
private static var lime_key_event_manager_register = System.load ("lime", "lime_key_event_manager_register", 2);
private static var lime_mouse_event_manager_register = System.load ("lime", "lime_mouse_event_manager_register", 2);
private static var lime_render_event_manager_register = System.load ("lime", "lime_render_event_manager_register", 2);
@@ -302,6 +338,48 @@ class NativeApplication {
}
private class GamepadEventInfo {
public var axis:Int;
public var button:Int;
public var id:Int;
public var type:GamepadEventType;
public var value:Float;
public function new (type:GamepadEventType = null, id:Int = 0, button:Int = 0, axis:Int = 0, value:Float = 0) {
this.type = type;
this.id = id;
this.button = button;
this.axis = axis;
this.value = value;
}
public function clone ():GamepadEventInfo {
return new GamepadEventInfo (type, id, button, axis, value);
}
}
@:enum private abstract GamepadEventType(Int) {
var AXIS_MOVE = 0;
var BUTTON_DOWN = 1;
var BUTTON_UP = 2;
var CONNECT = 3;
var DISCONNECT = 4;
}
private class KeyEventInfo {

View File

@@ -98,6 +98,11 @@ class Application extends Module {
windows.push (window);
window.onGamepadAxisMove.add (onGamepadAxisMove);
window.onGamepadButtonDown.add (onGamepadButtonDown);
window.onGamepadButtonUp.add (onGamepadButtonUp);
window.onGamepadConnect.add (onGamepadConnect);
window.onGamepadDisconnect.add (onGamepadDisconnect);
window.onKeyDown.add (onKeyDown);
window.onKeyUp.add (onKeyUp);
window.onMouseDown.add (onMouseDown);

View File

@@ -18,6 +18,13 @@ interface IModule {
public function init (context:RenderContext):Void;
public function onGamepadAxisMove (id:Int, axis:Int, value:Float):Void;
public function onGamepadButtonDown(id:Int, button:Int):Void;
public function onGamepadButtonUp (id:Int, button:Int):Void;
public function onGamepadConnect (id:Int):Void;
public function onGamepadDisconnect (id:Int):Void;
/**
* Called when a key down event is fired
* @param keyCode The code of the key that was pressed

View File

@@ -25,6 +25,13 @@ class Module implements IModule {
public function init (context:RenderContext):Void { }
public function onGamepadAxisMove (id:Int, axis:Int, value:Float):Void { }
public function onGamepadButtonDown(id:Int, button:Int):Void { }
public function onGamepadButtonUp (id:Int, button:Int):Void { }
public function onGamepadConnect (id:Int):Void { }
public function onGamepadDisconnect (id:Int):Void { }
/**
* Called when a key down event is fired
* @param keyCode The code of the key that was pressed

33
lime/ui/Gamepad.hx Normal file
View File

@@ -0,0 +1,33 @@
package lime.ui;
import lime.system.System;
class Gamepad {
public static function getDeviceName (id:Int):String {
#if (cpp || neko || nodejs)
return lime_gamepad_get_device_name (id);
#else
return null;
#end
}
// Native Methods
#if (cpp || neko || nodejs)
private static var lime_gamepad_get_device_name = System.load ("lime", "lime_gamepad_get_device_name", 1);
#end
}

View File

@@ -15,6 +15,11 @@ class Window {
public var config:Config;
public var fullscreen:Bool;
public var height:Int;
public var onGamepadAxisMove = new Event<Int->Int->Float->Void> ();
public var onGamepadButtonDown = new Event<Int->Int->Void> ();
public var onGamepadButtonUp = new Event<Int->Int->Void> ();
public var onGamepadConnect = new Event<Int->Void> ();
public var onGamepadDisconnect = new Event<Int->Void> ();
public var onKeyDown = new Event<KeyCode->KeyModifier->Void> ();
public var onKeyUp = new Event<KeyCode->KeyModifier->Void> ();
public var onMouseDown = new Event<Float->Float->Int->Void> ();

View File

@@ -145,6 +145,7 @@
<file name="src/backend/sdl/SDLApplication.cpp" />
<file name="src/backend/sdl/SDLWindow.cpp" />
<file name="src/backend/sdl/SDLRenderer.cpp" />
<file name="src/backend/sdl/SDLGamepad.cpp" />
<file name="src/backend/sdl/SDLMouse.cpp" />
<file name="src/backend/sdl/SDLSystem.cpp" />
<file name="src/backend/sdl/SDLJNI.cpp" />
@@ -164,6 +165,7 @@
<file name="src/audio/AudioBuffer.cpp" />
<file name="src/graphics/ImageBuffer.cpp" />
<file name="src/graphics/RenderEvent.cpp" />
<file name="src/ui/GamepadEvent.cpp" />
<file name="src/ui/KeyEvent.cpp" />
<file name="src/ui/MouseEvent.cpp" />
<file name="src/ui/TouchEvent.cpp" />

View File

@@ -0,0 +1,20 @@
#ifndef LIME_UI_GAMEPAD_H
#define LIME_UI_GAMEPAD_H
namespace lime {
class Gamepad {
public:
static const char* GetDeviceName (int id);
};
}
#endif

View File

@@ -0,0 +1,45 @@
#ifndef LIME_UI_GAMEPAD_EVENT_H
#define LIME_UI_GAMEPAD_EVENT_H
#include <hx/CFFI.h>
namespace lime {
enum GamepadEventType {
AXIS_MOVE,
BUTTON_DOWN,
BUTTON_UP,
CONNECT,
DISCONNECT
};
class GamepadEvent {
public:
static AutoGCRoot* callback;
static AutoGCRoot* eventObject;
GamepadEvent ();
static void Dispatch (GamepadEvent* event);
int axis;
double axisValue;
int button;
int id;
GamepadEventType type;
};
}
#endif

View File

@@ -21,6 +21,8 @@
#include <system/System.h>
#include <text/Font.h>
#include <text/TextLayout.h>
#include <ui/Gamepad.h>
#include <ui/GamepadEvent.h>
#include <ui/KeyEvent.h>
#include <ui/Mouse.h>
#include <ui/MouseCursor.h>
@@ -342,6 +344,22 @@ namespace lime {
}
value lime_gamepad_event_manager_register (value callback, value eventObject) {
GamepadEvent::callback = new AutoGCRoot (callback);
GamepadEvent::eventObject = new AutoGCRoot (eventObject);
return alloc_null ();
}
value lime_gamepad_get_device_name (value id) {
return alloc_string (Gamepad::GetDeviceName (val_int (id)));
}
value lime_image_encode (value buffer, value type, value quality) {
ImageBuffer imageBuffer = ImageBuffer (buffer);
@@ -715,6 +733,8 @@ namespace lime {
DEFINE_PRIM (lime_font_render_glyph, 3);
DEFINE_PRIM (lime_font_render_glyphs, 3);
DEFINE_PRIM (lime_font_set_size, 2);
DEFINE_PRIM (lime_gamepad_event_manager_register, 2);
DEFINE_PRIM (lime_gamepad_get_device_name, 1);
DEFINE_PRIM (lime_image_encode, 3);
DEFINE_PRIM (lime_image_load, 1);
DEFINE_PRIM (lime_jni_getenv, 0);

View File

@@ -1,4 +1,5 @@
#include "SDLApplication.h"
#include "SDLGamepad.h"
#ifdef HX_MACOS
#include <CoreFoundation/CoreFoundation.h>
@@ -24,7 +25,7 @@ namespace lime {
SDLApplication::SDLApplication () {
SDL_Init (SDL_INIT_VIDEO | SDL_INIT_TIMER);
SDL_Init (SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER | SDL_INIT_TIMER);
#ifdef EMSCRIPTEN
currentApplication = this;
@@ -38,6 +39,7 @@ namespace lime {
lastUpdate = 0;
nextUpdate = 0;
GamepadEvent gamepadEvent;
KeyEvent keyEvent;
MouseEvent mouseEvent;
RenderEvent renderEvent;
@@ -111,6 +113,15 @@ namespace lime {
RenderEvent::Dispatch (&renderEvent);
break;
case SDL_CONTROLLERAXISMOTION:
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
case SDL_CONTROLLERDEVICEADDED:
case SDL_CONTROLLERDEVICEREMOVED:
ProcessGamepadEvent (event);
break;
case SDL_JOYAXISMOTION:
case SDL_JOYBALLMOTION:
case SDL_JOYBUTTONDOWN:
@@ -191,6 +202,75 @@ namespace lime {
}
void SDLApplication::ProcessGamepadEvent (SDL_Event* event) {
if (GamepadEvent::callback) {
switch (event->type) {
case SDL_CONTROLLERAXISMOTION:
gamepadEvent.type = BUTTON_UP;
gamepadEvent.axis = event->caxis.axis;
gamepadEvent.id = event->caxis.which;
gamepadEvent.axisValue = event->caxis.value / 32768.0;
GamepadEvent::Dispatch (&gamepadEvent);
break;
case SDL_CONTROLLERBUTTONDOWN:
gamepadEvent.type = BUTTON_DOWN;
gamepadEvent.button = event->cbutton.button;
gamepadEvent.id = event->cbutton.which;
GamepadEvent::Dispatch (&gamepadEvent);
break;
case SDL_CONTROLLERBUTTONUP:
gamepadEvent.type = BUTTON_UP;
gamepadEvent.button = event->cbutton.button;
gamepadEvent.id = event->cbutton.which;
GamepadEvent::Dispatch (&gamepadEvent);
break;
case SDL_CONTROLLERDEVICEADDED:
if (SDLGamepad::Connect (event->cdevice.which)) {
gamepadEvent.type = CONNECT;
gamepadEvent.id = SDLGamepad::GetInstanceID (event->cdevice.which);
GamepadEvent::Dispatch (&gamepadEvent);
}
break;
case SDL_CONTROLLERDEVICEREMOVED: {
if (SDLGamepad::Disconnect (event->cdevice.which)) {
gamepadEvent.type = DISCONNECT;
gamepadEvent.id = event->cdevice.which;
GamepadEvent::Dispatch (&gamepadEvent);
}
break;
}
}
}
}
void SDLApplication::ProcessKeyEvent (SDL_Event* event) {
if (KeyEvent::callback) {

View File

@@ -6,6 +6,7 @@
#include <app/Application.h>
#include <app/UpdateEvent.h>
#include <graphics/RenderEvent.h>
#include <ui/GamepadEvent.h>
#include <ui/KeyEvent.h>
#include <ui/MouseEvent.h>
#include <ui/TouchEvent.h>
@@ -35,6 +36,7 @@ namespace lime {
private:
void HandleEvent (SDL_Event* event);
void ProcessGamepadEvent (SDL_Event* event);
void ProcessKeyEvent (SDL_Event* event);
void ProcessMouseEvent (SDL_Event* event);
void ProcessTouchEvent (SDL_Event* event);
@@ -43,6 +45,7 @@ namespace lime {
bool active;
Uint32 currentUpdate;
double framePeriod;
GamepadEvent gamepadEvent;
KeyEvent keyEvent;
Uint32 lastUpdate;
MouseEvent mouseEvent;

View File

@@ -0,0 +1,67 @@
#include "SDLGamepad.h"
namespace lime {
std::map<int, SDL_GameController*> gameControllers = std::map<int, SDL_GameController*> ();
std::map<int, int> gameControllerIDs = std::map<int, int> ();
bool SDLGamepad::Connect (int deviceID) {
if (SDL_IsGameController (deviceID)) {
SDL_GameController *gameController = SDL_GameControllerOpen (deviceID);
if (gameController) {
SDL_Joystick *joystick = SDL_GameControllerGetJoystick (gameController);
int id = SDL_JoystickInstanceID (joystick);
gameControllers[id] = gameController;
gameControllerIDs[deviceID] = id;
return true;
}
}
return false;
}
bool SDLGamepad::Disconnect (int id) {
if (gameControllers.find (id) != gameControllers.end ()) {
SDL_GameController *gameController = gameControllers[id];
SDL_GameControllerClose (gameController);
gameControllers.erase (id);
return true;
}
return false;
}
const char* Gamepad::GetDeviceName (int id) {
return SDL_GameControllerName (gameControllers[id]);
}
int SDLGamepad::GetInstanceID (int deviceID) {
return gameControllerIDs[deviceID];
}
}

View File

@@ -0,0 +1,27 @@
#ifndef LIME_SDL_GAMEPAD_H
#define LIME_SDL_GAMEPAD_H
#include <SDL.h>
#include <ui/Gamepad.h>
#include <map>
namespace lime {
class SDLGamepad {
public:
static bool Connect (int deviceID);
static int GetInstanceID (int deviceID);
static bool Disconnect (int id);
};
}
#endif

View File

@@ -0,0 +1,60 @@
#include <hx/CFFI.h>
#include <ui/GamepadEvent.h>
namespace lime {
AutoGCRoot* GamepadEvent::callback = 0;
AutoGCRoot* GamepadEvent::eventObject = 0;
static double id_axis;
static int id_button;
static int id_id;
static int id_type;
static int id_value;
static bool init = false;
GamepadEvent::GamepadEvent () {
axis = 0;
axisValue = 0;
button = 0;
id = 0;
type = AXIS_MOVE;
}
void GamepadEvent::Dispatch (GamepadEvent* event) {
if (GamepadEvent::callback) {
if (!init) {
id_axis = val_id ("axis");
id_button = val_id ("button");
id_id = val_id ("id");
id_type = val_id ("type");
id_value = val_id ("value");
init = true;
}
value object = (GamepadEvent::eventObject ? GamepadEvent::eventObject->get () : alloc_empty_object ());
alloc_field (object, id_axis, alloc_float (event->axis));
alloc_field (object, id_button, alloc_int (event->button));
alloc_field (object, id_id, alloc_int (event->id));
alloc_field (object, id_type, alloc_int (event->type));
alloc_field (object, id_value, alloc_float (event->axisValue));
val_call0 (GamepadEvent::callback->get ());
}
}
}