/* ** 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 . */ //////////////////////////////////////////////////////////////////////////////// // // // (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