CInput.h 8.31 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * CInput.h
 *
 *  Created on: 20.03.2009
 *      Author: gerstrong
 */

#ifndef CINPUT_H_
#define CINPUT_H_

#include <SDL.h>
#include <string>
#include <list>
14
#include <vector>
15
#include <base/utils/Geometry.h>
16
#include <base/GsEventContainer.h>
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
#include <base/InputEvents.h>

#include <base/Singleton.h>
#include <base/GsVirtualinput.h>


#define gInput	CInput::get()

// key defines, locations in keytable[]
enum keys{
	// Ascii keys
	KSPACE = 32,
	KEXCLAIM,
	KDBLQUOTE,
	KHASH,
	KDOLLAR,
	KPERCENT,
	KAMPERSAND,
	KQUOTE,
	KLEFTPAREN,
	KRIGHTPAREN,
	KAST,
	KPLUS,
	KCOMMA,
	KMINUS,
	KPERIOD,
	KSLASH,
	KNUM0,
	KNUM1,
	KNUM2,
	KNUM3,
	KNUM4,
	KNUM5,
	KNUM6,
	KNUM7,
	KNUM8,
	KNUM9,
	KCOLON,
	KSEMICOLON,
	KLESS,
	KEQUAL,
	KGREATER,
	KQUESTION,
	KAT,
	KLEFTBRACKET = 91,
	KBACKSLASH,
	KRIGHTBRACKET,
	KCARET,
	KUNDERSCORE,
	KBACKQUOTE,
	KA,
	KB,
	KC,
	KD,
	KE,
	KF,
	KG,
	KH,
	KI,
	KJ,
	KK,
	KL,
	KM,
	KN,
	KO,
	KP,
	KQ,
	KR,
	KS,
	KT,
	KU,
	KV,
	KW,
	KX,
	KY,
	KZ,
	KLEFTBRACE,
	KLINE,
	KRIGHTBRACE,
	KTILDE,
	
	// Non Ascii Keys
	KSHIFT,
	KPGUP,
	KPGDN,
	
	KQUIT,
	KLEFT,
	KRIGHT,
	KUP,
	KDOWN,
	KCTRL,           // simply, CTRL, mapped to JUMP or FIRE
	KALT,            // simply, ALT, mapped to POGO or fire
	KENTER,
	KF1,
	KF2,
	KF3,
	KF4,
	KF5,
	KF6,
	KF7,
	KF8,
	KF9,
	KF10,
	
	KTAB,
	
	KBCKSPCE,
};

const unsigned int KEYTABLE_SIZE = 160;

#define NUM_INPUTS			4

enum EType
{
	ETYPE_KEYBOARD, ETYPE_JOYAXIS,
	ETYPE_JOYBUTTON, ETYPE_JOYHAT,
};

struct stInputCommand
{
	bool active;
	bool lastactive;
	bool firsttimeactive;

#if SDL_VERSION_ATLEAST(2, 0, 0)
	SDL_Keycode 	keysym;
#else
    SDLKey 	keysym;
#endif

	unsigned int joyeventtype;
	int which;
	int joyaxis;
	unsigned short joybutton;
	int joyvalue;	// in which direction the axis needs to be moved
	int joymotion;	// in which direction the axis is really moved
	int joyhatval;	// in which direction the hat is really moved
};

class CInput : public GsSingleton<CInput>
{
public:
    CInput();

163
    virtual ~CInput();
gerstrong@gmail.com's avatar
gerstrong@gmail.com committed
164

165 166 167
    /**
     * @brief transMouseRelCoord    transforms a mouse click from the screen coordinates to the relative coordinates
     * @param Pos       Resulting relative coordinate to handle
168
     * @param rotPt     pointer
169
     * @param activeArea    Area which is seen and interacted.
170
     * @param tiltedScreen  is the screen tilted.
171 172
     */
    void transMouseRelCoord(Vector2D<float> &Pos,
173
                            const Vector2D<int> pointer,
174 175
                            const GsRect<Uint16> &activeArea,
                            const bool tiltedScreen);
176

177 178 179 180 181
    /**
     * @brief flushFingerEvents If some registered finger get stuck, this method cleans up
     */
    void flushFingerEvents();

182 183 184
    /**
     * @brief	Called every logic cycle. This triggers the events that occur and process them through various functions
     */
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
	void pollEvents();

	bool getHoldedKey(int key);
	bool getPressedKey(int key);
	bool getPulsedKey(int key, int msec);
	bool getPressedIsTypingKey(void);
	bool getPressedIsNumKey(void);
	std::string getPressedTypingKey(void);
	std::string getPressedNumKey(void);
	bool getPressedAnyKey(void);
	void sendKey(int key);

	bool mouseClicked();
	bool getPressedAnyCommand();
	bool getPulsedCommand(int command, int msec);
	bool getPulsedCommand(int player, int command, int msec);
	bool isJoystickAssgmnt(const int player, const int command);
	bool getHoldedCommand(int player, int command);
	int getJoyValue(int player, int command);
	bool getHoldedCommand(int command);
	bool getPressedCommand(int command);
	bool getPressedCommand(int player, int command);
	bool getPressedAnyCommand(const int player);
	bool getPressedAnyButtonCommand(const int player);
    bool getExitEvent()
    {  return m_exit;  }

	bool getTwoButtonFiring(int player);
	void setTwoButtonFiring(int player, bool value);

	bool isAnalog(const int player);
	void enableAnalog(const int player, const bool value);

    bool SuperPogo(const int player) { return mSuperPogo[player]; }
	void setSuperPogo(const int player, const bool value) { mSuperPogo[player] = value; }

	bool ImpossiblePogo(const int player) { return mImpPogo[player]; }
	void setImpossiblePogo(const int player, const bool value) { mImpPogo[player] = value; }

	bool AutoGun(const int player) { return mFullyAutomatic[player]; }
	void setAutoGun(const int player, const bool value) { mFullyAutomatic[player] = value; }

227 228
    void ponder();

229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
    /**
     * @brief render will render stuff the input want's to get on the screen.
     *        These are usually overlay where you can touch or click, like virtual gamepads.
     */
    void render();


	/**
	 * \brief	This checks what event has been assigned to the chosen command and builds a string calling it
	 * 			a standardized way.
	 * \param	command		command where you are looking for the event
	 * \param	input		number of input chosen. it's normal the number of the player
	 * \return 	returns the assigned event as a std::string
	 * \note 	getEventShortName is the short name version for menu prints
	 */ 
	std::string getEventName(int command, unsigned char input);
	std::string getEventShortName(int command, unsigned char input);
	
	std::string getNewMappedEvent(int &rPos, unsigned char &rInp);
	void readNewEvent();

    void waitForAnyInput();
	
	void setupNewEvent(Uint8 device, int position);

	void setupInputCommand( stInputCommand *pInput, int action, const std::string &string );

	void loadControlconfig();
	void resetControls(int player);
	bool startJoyDriver();
	void saveControlconfig();

    void flushCommands();
	void flushCommand(int command);
	void flushCommand(int player, int command);


    /**
     * @brief setCommand    Sets a given command.
     * @param player        player to which the command wil be setCommand;
     * @param command       Command object to be set
     * @param active        Will the command be set active or unactive
     */
    void setCommand(const int player, const int command, const bool active)
    {
        InputCommand[player][command].active = active;
    }


    void flushKeys();
    void flushEvents();
    void flushAll();

	void renderOverlay(); // for mouse wrapper gfx or other stuff

    void shutdown();

	bool MappingInput()
	{ return remapper.mappingInput; }

    /**
     * @brief readSDLEventVec Use this for engine which want to access the SDL Events directly
     */
    bool readSDLEventVec(std::vector<SDL_Event> &evVec);

    /**
     * @brief pushBackButtonEventExtEng Use this if want to add the event that normally would
     *        make open the menu. This event will be processed by the engine for other stuff
     */
    void pushBackButtonEventExtEng();

300
#ifdef VIRTUALPAD
301 302 303
    // One virtual input overlay can be active be processed. This is useful for game to ported on mobile devices
    std::unique_ptr<GsVirtualInput> mpVirtPad;

304 305 306 307 308 309 310 311
    /**
     * @brief setInVPadConfigState Want to open the vpad configuration?
     *        Then open this!
     */
    void setInVPadConfigState()
    {
        mVPadConfigState = true;
    }
312
#endif
313

314 315
private:

gerstrong@gmail.com's avatar
gerstrong@gmail.com committed
316 317 318 319 320 321 322 323 324 325
    bool processKeys(int value);
    void processJoystickAxis();
    void processJoystickHat();
    void processJoystickButton(int value);

    void processMouse();
    void processMouse(SDL_Event& ev);
    void processMouse(int x, int y, bool down, int index);


326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
    // Input Events
    CEventContainer m_EventList;


    // SDL_Event Vector
    //
    /**
     * @brief mSDLEventVec  A vector which stores after every poll process the Event that were triggered.
     *        For the Dosbox fusion this is needed, since our system can only use polling once otherwise it might get confused.
     */
    std::vector<SDL_Event> mSDLEventVec;
    std::vector<SDL_Event> mBackEventBuffer;

	SDL_Event Event;
	std::list<SDL_Joystick*> mp_Joysticks;

	stInputCommand InputCommand[NUM_INPUTS][MAX_COMMANDS];
	bool TwoButtonFiring[NUM_INPUTS];
	bool mAnalogAxesMovement[NUM_INPUTS];
	bool mSuperPogo[NUM_INPUTS];
	bool mImpPogo[NUM_INPUTS];
	bool mFullyAutomatic[NUM_INPUTS];

	bool m_exit;
	int m_cmdpulse;
	short m_joydeadzone;

353
#ifdef VIRTUALPAD
354
    bool mVPadConfigState = false;
355
#endif
356

357 358 359 360 361 362 363
	bool immediate_keytable[KEYTABLE_SIZE];
	bool last_immediate_keytable[KEYTABLE_SIZE];
	bool firsttime_immediate_keytable[KEYTABLE_SIZE];
	
	struct rm_type
	{
	    // For mapping new Commands
gerstrong@gmail.com's avatar
gerstrong@gmail.com committed
364 365 366
        bool mappingInput = false;
        Uint8 mapDevice = 0;
        int mapPosition = 0;
367 368
	} remapper;

gerstrong@gmail.com's avatar
gerstrong@gmail.com committed
369
    SDL_sem *mpPollSem = nullptr;
370 371 372 373
};


#endif /* CINPUT_H_ */