mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 23:55:38 +00:00
Began refactoring away the GuiComponent system in favor of ES-config's Gui system.
Man, I'm nuts.
This commit is contained in:
parent
3e6adf7be4
commit
4a35c34dc0
|
@ -2,7 +2,7 @@ CXX=g++
|
||||||
CXXFLAGS=-Wall -g -O2
|
CXXFLAGS=-Wall -g -O2
|
||||||
LDFLAGS=
|
LDFLAGS=
|
||||||
|
|
||||||
SRC_SOURCES=AudioManager.cpp InputConfig.cpp Log.cpp FolderData.cpp Font.cpp GameData.cpp GuiComponent.cpp InputManager.cpp main.cpp MathExp.cpp Renderer.cpp Renderer_draw_gl.cpp Renderer_init.cpp Sound.cpp SystemData.cpp XMLReader.cpp components/GuiAnimation.cpp components/GuiBox.cpp components/GuiFastSelect.cpp components/GuiGameList.cpp components/GuiImage.cpp components/GuiInputConfig.cpp components/GuiMenu.cpp components/GuiTheme.cpp pugiXML/pugixml.cpp
|
SRC_SOURCES=AudioManager.cpp InputConfig.cpp Log.cpp FolderData.cpp Font.cpp GameData.cpp Gui.cpp InputManager.cpp main.cpp MathExp.cpp Renderer_draw_gl.cpp Renderer_init.cpp Sound.cpp SystemData.cpp XMLReader.cpp components/GuiAnimation.cpp components/GuiBox.cpp components/GuiFastSelect.cpp components/GuiGameList.cpp components/GuiImage.cpp components/GuiInputConfig.cpp components/GuiMenu.cpp components/GuiTheme.cpp pugiXML/pugixml.cpp
|
||||||
SOURCES=$(addprefix src/,$(SRC_SOURCES))
|
SOURCES=$(addprefix src/,$(SRC_SOURCES))
|
||||||
OBJECTS=$(SOURCES:.cpp=.o)
|
OBJECTS=$(SOURCES:.cpp=.o)
|
||||||
DEPS=$(SOURCES:.cpp=.d)
|
DEPS=$(SOURCES:.cpp=.d)
|
||||||
|
|
11
src/Gui.cpp
Normal file
11
src/Gui.cpp
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include "Gui.h"
|
||||||
|
#include "Window.h"
|
||||||
|
|
||||||
|
Gui::Gui(Window* window) : mWindow(window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Gui::~Gui()
|
||||||
|
{
|
||||||
|
mWindow->removeGui(this);
|
||||||
|
}
|
21
src/Gui.h
Normal file
21
src/Gui.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef _GUI_H_
|
||||||
|
#define _GUI_H_
|
||||||
|
|
||||||
|
#include "InputConfig.h"
|
||||||
|
|
||||||
|
class Window;
|
||||||
|
|
||||||
|
class Gui
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Gui(Window* window);
|
||||||
|
virtual ~Gui();
|
||||||
|
|
||||||
|
virtual void input(InputConfig* config, Input input) = 0;
|
||||||
|
virtual void update(int deltaTime) = 0;
|
||||||
|
virtual void render() = 0;
|
||||||
|
protected:
|
||||||
|
Window* mWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,113 +0,0 @@
|
||||||
#include "GuiComponent.h"
|
|
||||||
#include "Renderer.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include "Log.h"
|
|
||||||
|
|
||||||
std::vector<GuiComponent*> GuiComponent::sComponentVector;
|
|
||||||
|
|
||||||
GuiComponent::GuiComponent()
|
|
||||||
{
|
|
||||||
sComponentVector.push_back(this);
|
|
||||||
|
|
||||||
mOffsetX = 0;
|
|
||||||
mOffsetY = 0;
|
|
||||||
mOpacity = 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
GuiComponent::~GuiComponent()
|
|
||||||
{
|
|
||||||
for(unsigned int i = 0; i < sComponentVector.size(); i++)
|
|
||||||
{
|
|
||||||
if(sComponentVector.at(i) == this)
|
|
||||||
{
|
|
||||||
sComponentVector.erase(sComponentVector.begin() + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiComponent::addChild(GuiComponent* comp)
|
|
||||||
{
|
|
||||||
mChildren.push_back(comp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiComponent::removeChild(GuiComponent* comp)
|
|
||||||
{
|
|
||||||
for(unsigned int i = 0; i < mChildren.size(); i++)
|
|
||||||
{
|
|
||||||
if(mChildren.at(i) == comp)
|
|
||||||
{
|
|
||||||
mChildren.erase(mChildren.begin() + i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(LogError) << "Error - tried to remove GuiComponent child, but couldn't find it!";
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiComponent::clearChildren()
|
|
||||||
{
|
|
||||||
mChildren.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiComponent::processTicks(int deltaTime)
|
|
||||||
{
|
|
||||||
for(unsigned int i = 0; i < sComponentVector.size(); i++)
|
|
||||||
{
|
|
||||||
sComponentVector.at(i)->onTick(deltaTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiComponent::render()
|
|
||||||
{
|
|
||||||
onRender();
|
|
||||||
|
|
||||||
for(unsigned int i = 0; i < mChildren.size(); i++)
|
|
||||||
{
|
|
||||||
mChildren.at(i)->render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiComponent::pause()
|
|
||||||
{
|
|
||||||
onPause();
|
|
||||||
|
|
||||||
for(unsigned int i = 0; i < mChildren.size(); i++)
|
|
||||||
mChildren.at(i)->pause();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiComponent::resume()
|
|
||||||
{
|
|
||||||
onResume();
|
|
||||||
|
|
||||||
for(unsigned int i = 0; i < mChildren.size(); i++)
|
|
||||||
mChildren.at(i)->resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiComponent::init()
|
|
||||||
{
|
|
||||||
onInit();
|
|
||||||
|
|
||||||
for(unsigned int i = 0; i < mChildren.size(); i++)
|
|
||||||
{
|
|
||||||
mChildren.at(i)->init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiComponent::deinit()
|
|
||||||
{
|
|
||||||
onDeinit();
|
|
||||||
|
|
||||||
for(unsigned int i = 0; i < mChildren.size(); i++)
|
|
||||||
{
|
|
||||||
mChildren.at(i)->deinit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiComponent::setOffsetX(int val) { mOffsetX = val; }
|
|
||||||
void GuiComponent::setOffsetY(int val) { mOffsetY = val; }
|
|
||||||
void GuiComponent::setOffset(int x, int y) { mOffsetX = x; mOffsetY = y; }
|
|
||||||
int GuiComponent::getOffsetX() { return mOffsetX; }
|
|
||||||
int GuiComponent::getOffsetY() { return mOffsetY; }
|
|
||||||
|
|
||||||
void GuiComponent::setOpacity(unsigned char opacity) { mOpacity = opacity; }
|
|
||||||
unsigned char GuiComponent::getOpacity() { return mOpacity; }
|
|
|
@ -1,68 +0,0 @@
|
||||||
#ifndef _GUICOMPONENT_H_
|
|
||||||
#define _GUICOMPONENT_H_
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "Renderer.h"
|
|
||||||
#include "InputManager.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
The GuiComponent class is what everything that is rendered, updated by time (ticking), or takes input is subclassed from.
|
|
||||||
GuiComponents have a list of child GuiComponents. Rendering, ticking, pausing/resuming, init/deinit, are all automatically sent to children.
|
|
||||||
You can rely on the parent getting called first - this way, you can control what order components are rendered in.
|
|
||||||
You can also manually call the render/pause/resume/init/deinit methods if you so desire (e.g. want a child to render *before* its parent).
|
|
||||||
|
|
||||||
To make a GuiComponent render/take input, you must register with the Renderer or InputManager respectively (Renderer::registerComponent(comp) or InputManager::registerComponent(comp)).
|
|
||||||
All components are automatically ticked every frame, just add an onTick(int deltaTime) method.
|
|
||||||
onInput calls arrive before onRender calls.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class GuiComponent
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GuiComponent();
|
|
||||||
virtual ~GuiComponent();
|
|
||||||
|
|
||||||
void render();
|
|
||||||
virtual void onRender() { };
|
|
||||||
virtual void onTick(int deltaTime) { };
|
|
||||||
|
|
||||||
void pause();
|
|
||||||
void resume();
|
|
||||||
virtual void onPause() { };
|
|
||||||
virtual void onResume() { };
|
|
||||||
|
|
||||||
void init();
|
|
||||||
void deinit();
|
|
||||||
virtual void onInit() { };
|
|
||||||
virtual void onDeinit() { };
|
|
||||||
|
|
||||||
virtual void onInput(InputManager::InputButton button, bool keyDown) { };
|
|
||||||
|
|
||||||
void addChild(GuiComponent* comp);
|
|
||||||
void removeChild(GuiComponent* comp);
|
|
||||||
void clearChildren();
|
|
||||||
unsigned int getChildCount() { return mChildren.size(); }
|
|
||||||
GuiComponent* getChild(unsigned int i) { return mChildren.at(i); }
|
|
||||||
|
|
||||||
|
|
||||||
int getOffsetX();
|
|
||||||
int getOffsetY();
|
|
||||||
void setOffsetX(int val);
|
|
||||||
void setOffsetY(int val);
|
|
||||||
void setOffset(int x, int y);
|
|
||||||
|
|
||||||
unsigned char getOpacity();
|
|
||||||
void setOpacity(unsigned char opacity);
|
|
||||||
|
|
||||||
static void processTicks(int deltaTime);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int mOffsetX, mOffsetY;
|
|
||||||
|
|
||||||
unsigned char mOpacity;
|
|
||||||
|
|
||||||
static std::vector<GuiComponent*> sComponentVector;
|
|
||||||
std::vector<GuiComponent*> mChildren;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,311 +1,151 @@
|
||||||
#include "InputManager.h"
|
#include "InputManager.h"
|
||||||
#include "GuiComponent.h"
|
#include "InputConfig.h"
|
||||||
|
#include "Window.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
#include "Log.h"
|
|
||||||
|
|
||||||
std::vector<GuiComponent*> InputManager::inputVector;
|
InputManager::InputManager(Window* window) : mWindow(window)
|
||||||
SDL_Event* InputManager::lastEvent = NULL;
|
|
||||||
|
|
||||||
std::map<int, InputManager::InputButton> InputManager::joystickButtonMap, InputManager::joystickAxisPosMap, InputManager::joystickAxisNegMap;
|
|
||||||
std::map<int, int> InputManager::axisState;
|
|
||||||
InputManager::InputButton InputManager::hatState = InputManager::UNKNOWN;
|
|
||||||
std::string InputManager::joystickName = "";
|
|
||||||
|
|
||||||
int InputManager::deadzone = 28000;
|
|
||||||
|
|
||||||
void InputManager::registerComponent(GuiComponent* comp)
|
|
||||||
{
|
{
|
||||||
inputVector.push_back(comp);
|
mJoysticks = NULL;
|
||||||
|
mKeyboardInputConfig = NULL;
|
||||||
|
mNumJoysticks = 0;
|
||||||
|
mNumPlayers = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputManager::unregisterComponent(GuiComponent* comp)
|
InputManager::~InputManager()
|
||||||
{
|
{
|
||||||
for(unsigned int i = 0; i < inputVector.size(); i++)
|
deinit();
|
||||||
{
|
|
||||||
if(inputVector.at(i) == comp)
|
|
||||||
{
|
|
||||||
inputVector.erase(inputVector.begin() + i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InputManager::InputButton InputManager::processEvent(SDL_Event* event)
|
void InputManager::init()
|
||||||
{
|
{
|
||||||
bool keyDown = false;
|
if(mJoysticks != NULL)
|
||||||
InputButton button = UNKNOWN;
|
deinit();
|
||||||
|
|
||||||
lastEvent = event;
|
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
|
||||||
|
|
||||||
//keyboard events
|
mNumJoysticks = SDL_NumJoysticks();
|
||||||
if(event->type == SDL_KEYDOWN || event->type == SDL_KEYUP)
|
mJoysticks = new SDL_Joystick*[mNumJoysticks];
|
||||||
|
mInputConfigs = new InputConfig*[mNumJoysticks];
|
||||||
|
mPrevAxisValues = new std::map<int, int>[mNumJoysticks];
|
||||||
|
|
||||||
|
for(int i = 0; i < mNumJoysticks; i++)
|
||||||
{
|
{
|
||||||
if(event->key.state == SDL_PRESSED)
|
mJoysticks[i] = SDL_JoystickOpen(i);
|
||||||
keyDown = true;
|
mInputConfigs[i] = new InputConfig(i);
|
||||||
|
|
||||||
//get InputButton from the event
|
for(int k = 0; k < SDL_JoystickNumAxes(mJoysticks[i]); k++)
|
||||||
switch(event->key.keysym.sym)
|
|
||||||
{
|
{
|
||||||
case SDLK_LEFT:
|
mPrevAxisValues[i][k] = 0;
|
||||||
button = LEFT;
|
|
||||||
break;
|
|
||||||
case SDLK_RIGHT:
|
|
||||||
button = RIGHT;
|
|
||||||
break;
|
|
||||||
case SDLK_UP:
|
|
||||||
button = UP;
|
|
||||||
break;
|
|
||||||
case SDLK_DOWN:
|
|
||||||
button = DOWN;
|
|
||||||
break;
|
|
||||||
case SDLK_PAGEUP:
|
|
||||||
button = PAGEUP;
|
|
||||||
break;
|
|
||||||
case SDLK_RIGHTBRACKET:
|
|
||||||
button = PAGEUP;
|
|
||||||
break;
|
|
||||||
case SDLK_PAGEDOWN:
|
|
||||||
button = PAGEDOWN;
|
|
||||||
break;
|
|
||||||
case SDLK_LEFTBRACKET:
|
|
||||||
button = PAGEDOWN;
|
|
||||||
break;
|
|
||||||
case SDLK_RETURN:
|
|
||||||
button = BUTTON1;
|
|
||||||
break;
|
|
||||||
case SDLK_ESCAPE:
|
|
||||||
button = BUTTON2;
|
|
||||||
break;
|
|
||||||
case SDLK_F1:
|
|
||||||
button = MENU;
|
|
||||||
break;
|
|
||||||
case SDLK_F2:
|
|
||||||
button = SELECT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
button = UNKNOWN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//catch emergency quit event
|
|
||||||
if(event->key.keysym.sym == SDLK_F4 && keyDown)
|
|
||||||
{
|
|
||||||
//I have no idea if SDL will delete this event, but we're quitting, so I don't think it really matters
|
|
||||||
SDL_Event* quit = new SDL_Event();
|
|
||||||
quit->type = SDL_QUIT;
|
|
||||||
SDL_PushEvent(quit);
|
|
||||||
LOG(LogInfo) << "Pushing quit event.";
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
if(event->type == SDL_JOYBUTTONDOWN || event->type == SDL_JOYBUTTONUP) //joystick button events
|
|
||||||
{
|
|
||||||
if(event->type == SDL_JOYBUTTONDOWN) //defaults to false, so no else
|
|
||||||
keyDown = true;
|
|
||||||
|
|
||||||
button = joystickButtonMap[event->jbutton.button];
|
|
||||||
}else{
|
|
||||||
if(event->type == SDL_JOYHATMOTION)
|
|
||||||
{
|
|
||||||
int hat = event->jhat.value;
|
|
||||||
|
|
||||||
if(hat == 0) //centered
|
|
||||||
{
|
|
||||||
//we need to send a keyUp event for the last hat
|
|
||||||
//keyDown is already false
|
|
||||||
button = hatState;
|
|
||||||
}else{
|
|
||||||
keyDown = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hat & SDL_HAT_LEFT)
|
|
||||||
button = LEFT;
|
|
||||||
if(hat & SDL_HAT_RIGHT)
|
|
||||||
button = RIGHT;
|
|
||||||
|
|
||||||
if(hat & SDL_HAT_UP)
|
|
||||||
button = UP;
|
|
||||||
if(hat & SDL_HAT_DOWN)
|
|
||||||
button = DOWN;
|
|
||||||
|
|
||||||
if(button == hatState && keyDown)
|
|
||||||
{
|
|
||||||
//ignore this hat event since the user most likely just made it a diagonal (but it still is using the old direction)
|
|
||||||
button = UNKNOWN;
|
|
||||||
}else{
|
|
||||||
if(hatState != UNKNOWN && keyDown)
|
|
||||||
{
|
|
||||||
//this will occur if the user went down -> downLeft -> Left or similar
|
|
||||||
button = hatState;
|
|
||||||
keyDown = false;
|
|
||||||
hatState = UNKNOWN;
|
|
||||||
processEvent(event);
|
|
||||||
}else{
|
|
||||||
if(!keyDown)
|
|
||||||
hatState = UNKNOWN;
|
|
||||||
else
|
|
||||||
hatState = button;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}else{
|
|
||||||
if(event->type == SDL_JOYAXISMOTION)
|
|
||||||
{
|
|
||||||
int axis = event->jaxis.axis;
|
|
||||||
int value = event->jaxis.value;
|
|
||||||
|
|
||||||
//if this axis was previously not centered, it can only keyUp
|
|
||||||
if(axisState[axis] != 0)
|
|
||||||
{
|
|
||||||
if(abs(value) < deadzone) //if it has indeed centered
|
|
||||||
{
|
|
||||||
if(axisState[axis] > 0)
|
|
||||||
button = joystickAxisPosMap[axis];
|
|
||||||
else
|
|
||||||
button = joystickAxisNegMap[axis];
|
|
||||||
axisState[axis] = 0;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
if(value > deadzone)
|
|
||||||
{
|
|
||||||
//axisPos keyDown
|
|
||||||
axisState[axis] = 1;
|
|
||||||
keyDown = true;
|
|
||||||
button = joystickAxisPosMap[axis];
|
|
||||||
}else if(value < -deadzone)
|
|
||||||
{
|
|
||||||
axisState[axis] = -1;
|
|
||||||
keyDown = true;
|
|
||||||
button = joystickAxisNegMap[axis];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int i = 0; i < inputVector.size(); i++)
|
mKeyboardInputConfig = new InputConfig(DEVICE_KEYBOARD);
|
||||||
{
|
|
||||||
inputVector.at(i)->onInput(button, keyDown);
|
|
||||||
}
|
|
||||||
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputManager::loadConfig()
|
|
||||||
{
|
|
||||||
LOG(LogDebug) << "Loading input config...";
|
|
||||||
|
|
||||||
//clear any old config
|
|
||||||
joystickButtonMap.clear();
|
|
||||||
joystickAxisPosMap.clear();
|
|
||||||
joystickAxisNegMap.clear();
|
|
||||||
|
|
||||||
std::string path = getConfigPath();
|
|
||||||
|
|
||||||
std::ifstream file(path.c_str());
|
|
||||||
|
|
||||||
joystickName = "";
|
|
||||||
|
|
||||||
while(file.good())
|
|
||||||
{
|
|
||||||
std::string line;
|
|
||||||
std::getline(file, line);
|
|
||||||
|
|
||||||
//skip blank lines and comments
|
|
||||||
if(line.empty() || line[0] == *"#")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
|
|
||||||
//I know I could probably just read from the file stream directly, but I feel it would be harder to catch errors in a readable way
|
|
||||||
std::istringstream stream(line);
|
|
||||||
|
|
||||||
std::string token[3];
|
|
||||||
int tokNum = 0;
|
|
||||||
|
|
||||||
while(std::getline(stream, token[tokNum], ' '))
|
|
||||||
{
|
|
||||||
tokNum++;
|
|
||||||
|
|
||||||
//JOYNAME can have spaces
|
|
||||||
if(tokNum == 1 && token[0] == "JOYNAME")
|
|
||||||
{
|
|
||||||
std::getline(stream, token[1]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tokNum >= 3)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(token[0] == "BUTTON")
|
|
||||||
{
|
|
||||||
joystickButtonMap[atoi(token[1].c_str())] = (InputButton)atoi(token[2].c_str());
|
|
||||||
}else if(token[0] == "AXISPOS")
|
|
||||||
{
|
|
||||||
joystickAxisPosMap[atoi(token[1].c_str())] = (InputButton)atoi(token[2].c_str());
|
|
||||||
}else if(token[0] == "AXISNEG")
|
|
||||||
{
|
|
||||||
joystickAxisNegMap[atoi(token[1].c_str())] = (InputButton)atoi(token[2].c_str());
|
|
||||||
}else if(token[0] == "JOYNAME")
|
|
||||||
{
|
|
||||||
joystickName = token[1];
|
|
||||||
}else{
|
|
||||||
LOG(LogWarning) << "Invalid input type - " << token[0];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(LogDebug) << "Finished loading input config";
|
|
||||||
|
|
||||||
openJoystick();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputManager::openJoystick()
|
|
||||||
{
|
|
||||||
//if any joystick is plugged in
|
|
||||||
if(SDL_NumJoysticks() > 0)
|
|
||||||
{
|
|
||||||
if(!joystickName.empty())
|
|
||||||
{
|
|
||||||
LOG(LogDebug) << " attempting to open joystick of name \"" << joystickName << "\"";
|
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
for(int i = 0; i < SDL_NumJoysticks(); i++)
|
|
||||||
{
|
|
||||||
if(strcmp(SDL_JoystickName(i), joystickName.c_str()) == 0)
|
|
||||||
{
|
|
||||||
LOG(LogDebug) << " found, opening joystick " << joystickName << " at " << i;
|
|
||||||
|
|
||||||
SDL_JoystickOpen(i);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!found)
|
|
||||||
{
|
|
||||||
LOG(LogWarning) << " could not find named joystick! You could try manually removing the joystick name entry in the input config file.";
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
LOG(LogDebug) << " opening first joystick (no name saved)";
|
|
||||||
|
|
||||||
SDL_JoystickOpen(0); //if we don't have a specific joystick in mind, take the first
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
LOG(LogDebug) << " no joysticks detected by SDL_NumJoysticks(), so no joystick opened";
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_JoystickEventState(SDL_ENABLE);
|
SDL_JoystickEventState(SDL_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string InputManager::getConfigPath()
|
void InputManager::deinit()
|
||||||
{
|
{
|
||||||
std::string home = getenv("HOME");
|
SDL_JoystickEventState(SDL_DISABLE);
|
||||||
home += "/.emulationstation/es_input.cfg";
|
|
||||||
return home;
|
if(!SDL_WasInit(SDL_INIT_JOYSTICK))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(mJoysticks != NULL)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < mNumJoysticks; i++)
|
||||||
|
{
|
||||||
|
SDL_JoystickClose(mJoysticks[i]);
|
||||||
|
delete mInputConfigs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
delete mKeyboardInputConfig;
|
||||||
|
|
||||||
|
delete[] mJoysticks;
|
||||||
|
delete[] mInputConfigs;
|
||||||
|
delete[] mPrevAxisValues;
|
||||||
|
mJoysticks = NULL;
|
||||||
|
mKeyboardInputConfig = NULL;
|
||||||
|
mInputConfigs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputManager::getNumJoysticks() { return mNumJoysticks; }
|
||||||
|
|
||||||
|
int InputManager::getNumPlayers() { return mNumPlayers; }
|
||||||
|
void InputManager::setNumPlayers(int num) { mNumPlayers = num; }
|
||||||
|
|
||||||
|
InputConfig* InputManager::getInputConfigByDevice(int device)
|
||||||
|
{
|
||||||
|
if(device == DEVICE_KEYBOARD)
|
||||||
|
return mKeyboardInputConfig;
|
||||||
|
else
|
||||||
|
return mInputConfigs[device];
|
||||||
|
}
|
||||||
|
|
||||||
|
InputConfig* InputManager::getInputConfigByPlayer(int player)
|
||||||
|
{
|
||||||
|
if(mKeyboardInputConfig->getPlayerNum() == player)
|
||||||
|
return mKeyboardInputConfig;
|
||||||
|
|
||||||
|
for(int i = 0; i < mNumJoysticks; i++)
|
||||||
|
{
|
||||||
|
if(mInputConfigs[i]->getPlayerNum() == player)
|
||||||
|
return mInputConfigs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Could not find input config for player number " << player << "!\n";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputManager::parseEvent(const SDL_Event& ev)
|
||||||
|
{
|
||||||
|
switch(ev.type)
|
||||||
|
{
|
||||||
|
case SDL_JOYAXISMOTION:
|
||||||
|
//if it switched boundaries
|
||||||
|
if((abs(ev.jaxis.value) > DEADZONE) != (abs(mPrevAxisValues[ev.jaxis.which][ev.jaxis.axis]) > DEADZONE))
|
||||||
|
{
|
||||||
|
int normValue;
|
||||||
|
if(abs(ev.jaxis.value) <= DEADZONE)
|
||||||
|
normValue = 0;
|
||||||
|
else
|
||||||
|
if(ev.jaxis.value > 0)
|
||||||
|
normValue = 1;
|
||||||
|
else
|
||||||
|
normValue = -1;
|
||||||
|
|
||||||
|
mWindow->input(getInputConfigByDevice(ev.jaxis.which), Input(ev.jaxis.which, TYPE_AXIS, ev.jaxis.axis, normValue, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
mPrevAxisValues[ev.jaxis.which][ev.jaxis.axis] = ev.jaxis.value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_JOYBUTTONDOWN:
|
||||||
|
case SDL_JOYBUTTONUP:
|
||||||
|
mWindow->input(getInputConfigByDevice(ev.jbutton.which), Input(ev.jbutton.which, TYPE_BUTTON, ev.jbutton.button, ev.jbutton.state == SDL_PRESSED, false));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_JOYHATMOTION:
|
||||||
|
mWindow->input(getInputConfigByDevice(ev.jhat.which), Input(ev.jhat.which, TYPE_HAT, ev.jhat.hat, ev.jhat.value, false));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
if(ev.key.keysym.sym == SDLK_F4)
|
||||||
|
{
|
||||||
|
SDL_Event* quit = new SDL_Event();
|
||||||
|
quit->type = SDL_QUIT;
|
||||||
|
SDL_PushEvent(quit);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mWindow->input(getInputConfigByDevice(DEVICE_KEYBOARD), Input(DEVICE_KEYBOARD, TYPE_KEY, ev.key.keysym.sym, 1, false));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_KEYUP:
|
||||||
|
mWindow->input(getInputConfigByDevice(DEVICE_KEYBOARD), Input(DEVICE_KEYBOARD, TYPE_KEY, ev.key.keysym.sym, 0, false));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +1,46 @@
|
||||||
#ifndef _INPUTMANAGER_H_
|
#ifndef _INPUTMANAGER_H_
|
||||||
#define _INPUTMANAGER_H_
|
#define _INPUTMANAGER_H_
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <SDL/SDL.h>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class GuiComponent;
|
class InputConfig;
|
||||||
|
class Window;
|
||||||
|
|
||||||
//The InputManager takes native system input and abstracts it into InputButtons.
|
//you should only ever instantiate one of these, by the way
|
||||||
//GuiComponents can be registered to receive onInput() events.
|
class InputManager
|
||||||
namespace InputManager {
|
{
|
||||||
void registerComponent(GuiComponent* comp);
|
public:
|
||||||
void unregisterComponent(GuiComponent* comp);
|
InputManager(Window* window);
|
||||||
|
~InputManager();
|
||||||
|
|
||||||
void loadConfig();
|
void init();
|
||||||
void openJoystick();
|
void deinit();
|
||||||
|
|
||||||
//enum for identifying input, regardless of configuration
|
void setNumPlayers(int num);
|
||||||
enum InputButton { UNKNOWN, UP, DOWN, LEFT, RIGHT, BUTTON1, BUTTON2, MENU, SELECT, PAGEUP, PAGEDOWN};
|
int getNumPlayers();
|
||||||
|
|
||||||
InputButton processEvent(SDL_Event* event);
|
int getNumJoysticks();
|
||||||
|
|
||||||
extern std::vector<GuiComponent*> inputVector;
|
void parseEvent(const SDL_Event& ev);
|
||||||
extern SDL_Event* lastEvent; //mostly for GuiInputConfig
|
|
||||||
extern int deadzone;
|
|
||||||
std::string getConfigPath();
|
|
||||||
|
|
||||||
extern std::map<int, InputButton> joystickButtonMap;
|
InputConfig* getInputConfigByPlayer(int player);
|
||||||
extern std::map<int, InputButton> joystickAxisPosMap, joystickAxisNegMap;
|
|
||||||
extern std::map<int, int> axisState;
|
private:
|
||||||
extern InputButton hatState;
|
static const int DEADZONE = 23000;
|
||||||
extern std::string joystickName;
|
|
||||||
}
|
Window* mWindow;
|
||||||
|
|
||||||
|
//non-InputManager classes shouldn't use this, as you can easily miss the keyboard
|
||||||
|
InputConfig* getInputConfigByDevice(int device);
|
||||||
|
|
||||||
|
int mNumJoysticks;
|
||||||
|
int mNumPlayers;
|
||||||
|
SDL_Joystick** mJoysticks;
|
||||||
|
InputConfig** mInputConfigs;
|
||||||
|
InputConfig* mKeyboardInputConfig;
|
||||||
|
std::map<int, int>* mPrevAxisValues;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
#include "Renderer.h"
|
|
||||||
#include "GuiComponent.h"
|
|
||||||
|
|
||||||
std::vector<GuiComponent*> renderVector;
|
|
||||||
|
|
||||||
void Renderer::registerComponent(GuiComponent* comp)
|
|
||||||
{
|
|
||||||
renderVector.push_back(comp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::unregisterComponent(GuiComponent* comp)
|
|
||||||
{
|
|
||||||
for(unsigned int i = 0; i < renderVector.size(); i++)
|
|
||||||
{
|
|
||||||
if(renderVector.at(i) == comp)
|
|
||||||
{
|
|
||||||
renderVector.erase(renderVector.begin() + i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::deleteAll()
|
|
||||||
{
|
|
||||||
for(unsigned int i = 0; i < renderVector.size(); i++)
|
|
||||||
{
|
|
||||||
delete renderVector.at(i);
|
|
||||||
}
|
|
||||||
renderVector.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::render()
|
|
||||||
{
|
|
||||||
for(unsigned int i = 0; i < renderVector.size(); i++)
|
|
||||||
{
|
|
||||||
renderVector.at(i)->render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::onInit()
|
|
||||||
{
|
|
||||||
for(unsigned int i = 0; i < renderVector.size(); i++)
|
|
||||||
{
|
|
||||||
renderVector.at(i)->init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::onDeinit()
|
|
||||||
{
|
|
||||||
for(unsigned int i = 0; i < renderVector.size(); i++)
|
|
||||||
{
|
|
||||||
renderVector.at(i)->deinit();
|
|
||||||
}
|
|
||||||
}
|
|
70
src/Window.cpp
Normal file
70
src/Window.cpp
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#include "Window.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
Window::Window()
|
||||||
|
{
|
||||||
|
mInputManager = new InputManager(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Window::~Window()
|
||||||
|
{
|
||||||
|
delete mInputManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::pushGui(Gui* gui)
|
||||||
|
{
|
||||||
|
mGuiStack.push_back(gui);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::removeGui(Gui* gui)
|
||||||
|
{
|
||||||
|
for(unsigned int i = 0; i < mGuiStack.size(); i++)
|
||||||
|
{
|
||||||
|
if(mGuiStack.at(i) == gui)
|
||||||
|
{
|
||||||
|
mGuiStack.erase(mGuiStack.begin() + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Gui* Window::peekGui()
|
||||||
|
{
|
||||||
|
if(mGuiStack.size() == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return mGuiStack.at(mGuiStack.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::render()
|
||||||
|
{
|
||||||
|
if(mGuiStack.size() == 0)
|
||||||
|
std::cout << "guistack empty\n";
|
||||||
|
|
||||||
|
for(unsigned int i = 0; i < mGuiStack.size(); i++)
|
||||||
|
{
|
||||||
|
mGuiStack.at(i)->render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::input(InputConfig* config, Input input)
|
||||||
|
{
|
||||||
|
if(peekGui())
|
||||||
|
this->peekGui()->input(config, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::update(int deltaTime)
|
||||||
|
{
|
||||||
|
if(peekGui())
|
||||||
|
peekGui()->update(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
InputManager* Window::getInputManager()
|
||||||
|
{
|
||||||
|
return mInputManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
asIScriptEngine* Window::getScriptEngine()
|
||||||
|
{
|
||||||
|
return mScriptEngine;
|
||||||
|
}
|
29
src/Window.h
Normal file
29
src/Window.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef _WINDOW_H_
|
||||||
|
#define _WINDOW_H_
|
||||||
|
|
||||||
|
#include "Gui.h"
|
||||||
|
#include "InputManager.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class Window
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Window();
|
||||||
|
~Window();
|
||||||
|
|
||||||
|
void pushGui(Gui* gui);
|
||||||
|
void removeGui(Gui* gui);
|
||||||
|
Gui* peekGui();
|
||||||
|
|
||||||
|
void input(InputConfig* config, Input input);
|
||||||
|
void update(int deltaTime);
|
||||||
|
void render();
|
||||||
|
|
||||||
|
InputManager* getInputManager();
|
||||||
|
|
||||||
|
private:
|
||||||
|
InputManager* mInputManager;
|
||||||
|
std::vector<Gui*> mGuiStack;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue