380 lines
9.6 KiB
C++

/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: MetaEvent.h ///////////////////////////////////////////////////////////
// Author: Steven Johnson, Dec 2001
#pragma once
#ifndef _H_MetaEvent
#define _H_MetaEvent
#include "Common/SubsystemInterface.h"
#include "GameClient/InGameUI.h"
enum MappableKeyCategories
{
CATEGORY_CONTROL = 0,
CATEGORY_INFORMATION,
CATEGORY_INTERFACE,
CATEGORY_SELECTION,
CATEGORY_TAUNT,
CATEGORY_TEAM,
CATEGORY_MISC,
CATEGORY_DEBUG,
CATEGORY_NUM_CATEGORIES // keep this last
};
static const LookupListRec CategoryListName[] =
{
{"CONTROL", CATEGORY_CONTROL},
{"INFORMATION", CATEGORY_INFORMATION},
{"INTERFACE", CATEGORY_INTERFACE},
{"SELECTION", CATEGORY_SELECTION},
{"TAUNT", CATEGORY_TAUNT},
{"TEAM", CATEGORY_TEAM},
{"MISC", CATEGORY_MISC},
{"DEBUG", CATEGORY_DEBUG},
{NULL, 0}// keep this last
};
// -------------------------------------------------------------------------------
// the keys we allow to be mapped to Meta-events.
// note that this is a subset of all the keys available;
// in particular, "modifier" keys and keypad keys aren't
// available. Note that MappableKeyType is a SUBSET of
// KeyDefType; this is extremely important to maintain!
enum MappableKeyType
{
MK_ESC = KEY_ESC,
MK_BACKSPACE = KEY_BACKSPACE,
MK_ENTER = KEY_ENTER,
MK_SPACE = KEY_SPACE,
MK_TAB = KEY_TAB,
MK_F1 = KEY_F1,
MK_F2 = KEY_F2,
MK_F3 = KEY_F3,
MK_F4 = KEY_F4,
MK_F5 = KEY_F5,
MK_F6 = KEY_F6,
MK_F7 = KEY_F7,
MK_F8 = KEY_F8,
MK_F9 = KEY_F9,
MK_F10 = KEY_F10,
MK_F11 = KEY_F11,
MK_F12 = KEY_F12,
MK_A = KEY_A,
MK_B = KEY_B,
MK_C = KEY_C,
MK_D = KEY_D,
MK_E = KEY_E,
MK_F = KEY_F,
MK_G = KEY_G,
MK_H = KEY_H,
MK_I = KEY_I,
MK_J = KEY_J,
MK_K = KEY_K,
MK_L = KEY_L,
MK_M = KEY_M,
MK_N = KEY_N,
MK_O = KEY_O,
MK_P = KEY_P,
MK_Q = KEY_Q,
MK_R = KEY_R,
MK_S = KEY_S,
MK_T = KEY_T,
MK_U = KEY_U,
MK_V = KEY_V,
MK_W = KEY_W,
MK_X = KEY_X,
MK_Y = KEY_Y,
MK_Z = KEY_Z,
MK_1 = KEY_1,
MK_2 = KEY_2,
MK_3 = KEY_3,
MK_4 = KEY_4,
MK_5 = KEY_5,
MK_6 = KEY_6,
MK_7 = KEY_7,
MK_8 = KEY_8,
MK_9 = KEY_9,
MK_0 = KEY_0,
MK_KP1 = KEY_KP1,
MK_KP2 = KEY_KP2,
MK_KP3 = KEY_KP3,
MK_KP4 = KEY_KP4,
MK_KP5 = KEY_KP5,
MK_KP6 = KEY_KP6,
MK_KP7 = KEY_KP7,
MK_KP8 = KEY_KP8,
MK_KP9 = KEY_KP9,
MK_KP0 = KEY_KP0,
MK_MINUS = KEY_MINUS,
MK_EQUAL = KEY_EQUAL,
MK_LBRACKET = KEY_LBRACKET,
MK_RBRACKET = KEY_RBRACKET,
MK_SEMICOLON = KEY_SEMICOLON,
MK_APOSTROPHE = KEY_APOSTROPHE,
MK_TICK = KEY_TICK,
MK_BACKSLASH = KEY_BACKSLASH,
MK_COMMA = KEY_COMMA,
MK_PERIOD = KEY_PERIOD,
MK_SLASH = KEY_SLASH,
MK_UP = KEY_UP,
MK_DOWN = KEY_DOWN,
MK_LEFT = KEY_LEFT,
MK_RIGHT = KEY_RIGHT,
MK_HOME = KEY_HOME,
MK_END = KEY_END,
MK_PGUP = KEY_PGUP,
MK_PGDN = KEY_PGDN,
MK_INS = KEY_INS,
MK_DEL = KEY_DEL,
MK_KPSLASH = KEY_KPSLASH,
MK_NONE = KEY_NONE
};
static const LookupListRec KeyNames[] =
{
{ "KEY_ESC", MK_ESC },
{ "KEY_BACKSPACE", MK_BACKSPACE },
{ "KEY_ENTER", MK_ENTER },
{ "KEY_SPACE", MK_SPACE },
{ "KEY_TAB", MK_TAB },
{ "KEY_F1", MK_F1 },
{ "KEY_F2", MK_F2 },
{ "KEY_F3", MK_F3 },
{ "KEY_F4", MK_F4 },
{ "KEY_F5", MK_F5 },
{ "KEY_F6", MK_F6 },
{ "KEY_F7", MK_F7 },
{ "KEY_F8", MK_F8 },
{ "KEY_F9", MK_F9 },
{ "KEY_F10", MK_F10 },
{ "KEY_F11", MK_F11 },
{ "KEY_F12", MK_F12 },
{ "KEY_A", MK_A },
{ "KEY_B", MK_B },
{ "KEY_C", MK_C },
{ "KEY_D", MK_D },
{ "KEY_E", MK_E },
{ "KEY_F", MK_F },
{ "KEY_G", MK_G },
{ "KEY_H", MK_H },
{ "KEY_I", MK_I },
{ "KEY_J", MK_J },
{ "KEY_K", MK_K },
{ "KEY_L", MK_L },
{ "KEY_M", MK_M },
{ "KEY_N", MK_N },
{ "KEY_O", MK_O },
{ "KEY_P", MK_P },
{ "KEY_Q", MK_Q },
{ "KEY_R", MK_R },
{ "KEY_S", MK_S },
{ "KEY_T", MK_T },
{ "KEY_U", MK_U },
{ "KEY_V", MK_V },
{ "KEY_W", MK_W },
{ "KEY_X", MK_X },
{ "KEY_Y", MK_Y },
{ "KEY_Z", MK_Z },
{ "KEY_1", MK_1 },
{ "KEY_2", MK_2 },
{ "KEY_3", MK_3 },
{ "KEY_4", MK_4 },
{ "KEY_5", MK_5 },
{ "KEY_6", MK_6 },
{ "KEY_7", MK_7 },
{ "KEY_8", MK_8 },
{ "KEY_9", MK_9 },
{ "KEY_0", MK_0 },
{ "KEY_KP1", MK_KP1 },
{ "KEY_KP2", MK_KP2 },
{ "KEY_KP3", MK_KP3 },
{ "KEY_KP4", MK_KP4 },
{ "KEY_KP5", MK_KP5 },
{ "KEY_KP6", MK_KP6 },
{ "KEY_KP7", MK_KP7 },
{ "KEY_KP8", MK_KP8 },
{ "KEY_KP9", MK_KP9 },
{ "KEY_KP0", MK_KP0 },
{ "KEY_MINUS", MK_MINUS },
{ "KEY_EQUAL", MK_EQUAL },
{ "KEY_LBRACKET", MK_LBRACKET },
{ "KEY_RBRACKET", MK_RBRACKET },
{ "KEY_SEMICOLON", MK_SEMICOLON },
{ "KEY_APOSTROPHE", MK_APOSTROPHE },
{ "KEY_TICK", MK_TICK },
{ "KEY_BACKSLASH", MK_BACKSLASH },
{ "KEY_COMMA", MK_COMMA },
{ "KEY_PERIOD", MK_PERIOD },
{ "KEY_SLASH", MK_SLASH },
{ "KEY_UP", MK_UP },
{ "KEY_DOWN", MK_DOWN },
{ "KEY_LEFT", MK_LEFT },
{ "KEY_RIGHT", MK_RIGHT },
{ "KEY_HOME", MK_HOME },
{ "KEY_END", MK_END },
{ "KEY_PGUP", MK_PGUP },
{ "KEY_PGDN", MK_PGDN },
{ "KEY_INS", MK_INS },
{ "KEY_DEL", MK_DEL },
{ "KEY_KPSLASH", MK_KPSLASH },
{ "KEY_NONE", MK_NONE },
{ NULL, 0 } // keep this last!
};
// -------------------------------------------------------------------------------
enum MappableKeyTransition
{
DOWN,
UP,
DOUBLEDOWN // if a key transition is repeated immediately, we generate this.
};
static const LookupListRec TransitionNames[] =
{
{ "DOWN", DOWN },
{ "UP", UP },
{ "DOUBLEDOWN", DOUBLEDOWN },
{ NULL, 0 }// keep this last!
};
// -------------------------------------------------------------------------------
// an easier-to-type subset of the KEY_STATE stuff.
enum MappableKeyModState
{
NONE = 0,
CTRL = KEY_STATE_LCONTROL,
ALT = KEY_STATE_LALT,
SHIFT = KEY_STATE_LSHIFT,
CTRL_ALT = CTRL|ALT,
SHIFT_CTRL = SHIFT|CTRL,
SHIFT_ALT = SHIFT|ALT,
SHIFT_ALT_CTRL = SHIFT|ALT|CTRL
};
static const LookupListRec ModifierNames[] =
{
{ "NONE", NONE },
{ "CTRL", CTRL },
{ "ALT", ALT },
{ "SHIFT", SHIFT },
{ "CTRL_ALT", CTRL_ALT },
{ "SHIFT_CTRL", SHIFT_CTRL },
{ "SHIFT_ALT", SHIFT_ALT },
{ "SHIFT_ALT_CTRL" , SHIFT_ALT_CTRL },
{ NULL, 0 }// keep this last!
};
// -------------------------------------------------------------------------------
// CommandUsableInType sets in what state the commands are allowed.
enum CommandUsableInType
{
COMMANDUSABLE_NONE = 0,
COMMANDUSABLE_SHELL = (1 << 0),
COMMANDUSABLE_GAME = (1 << 1)
};
static const char* TheCommandUsableInNames[] =
{
"SHELL",
"GAME",
NULL
};
// -------------------------------------------------------------------------------
class MetaMapRec : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(MetaMapRec, "MetaMapRec")
public:
MetaMapRec* m_next;
GameMessage::Type m_meta; ///< the meta-event to emit
MappableKeyType m_key; ///< the key we want
MappableKeyTransition m_transition; ///< the state of the key
MappableKeyModState m_modState; ///< the required state of the ctrl-alt-shift keys
CommandUsableInType m_usableIn; ///< the allowed place the command can be used in
// Next fields are added for Key mapping Dialog
MappableKeyCategories m_category; ///< This is the catagory the key falls under
UnicodeString m_description; ///< The description string for the keys
UnicodeString m_displayName; ///< The display name of our command
};
EMPTY_DTOR(MetaMapRec)
//-----------------------------------------------------------------------------
class MetaEventTranslator : public GameMessageTranslator
{
private:
Int m_lastKeyDown; // really a MappableKeyType
Int m_lastModState; // really a MappableKeyModState
enum { NUM_MOUSE_BUTTONS = 3 };
ICoord2D m_mouseDownPosition[NUM_MOUSE_BUTTONS];
Bool m_nextUpShouldCreateDoubleClick[NUM_MOUSE_BUTTONS];
public:
MetaEventTranslator();
~MetaEventTranslator();
virtual GameMessageDisposition translateGameMessage(const GameMessage *msg);
};
//-----------------------------------------------------------------------------
class MetaMap : public SubsystemInterface
{
friend class MetaEventTranslator;
private:
MetaMapRec *m_metaMaps;
protected:
GameMessage::Type findGameMessageMetaType(const char* name);
MetaMapRec *getMetaMapRec(GameMessage::Type t);
public:
MetaMap();
~MetaMap();
void init() { }
void reset() { }
void update() { }
static void parseMetaMap(INI* ini);
const MetaMapRec *getFirstMetaMapRec() const { return m_metaMaps; }
};
extern MetaMap *TheMetaMap;
#endif