mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Implementation of (very basic) shortcuts system
- Added EShortcut enumeration that contains all in-game shortcuts - CIntObject::keyPressed now receive values from hotkey enumeration - On keypress, SDL key code will be translated to shortcut ID - Removed access to SDL key codes from most of engine
This commit is contained in:
		
							
								
								
									
										8
									
								
								Global.h
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								Global.h
									
									
									
									
									
								
							| @@ -543,10 +543,16 @@ namespace vstd | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	template<typename T> | ||||
| 	T advance_r(const T &obj, int change) | ||||
| 	{ | ||||
| 		return static_cast<T>(static_cast<int>(obj) + change); | ||||
| 	} | ||||
|  | ||||
| 	template<typename T> | ||||
| 	void advance(T &obj, int change) | ||||
| 	{ | ||||
| 		obj = (T)(((int)obj) + change); | ||||
| 		obj = advance_r(obj, change); | ||||
| 	} | ||||
|  | ||||
| 	template <typename Container> | ||||
|   | ||||
| @@ -31,6 +31,7 @@ set(client_SRCS | ||||
| 	gui/CursorHandler.cpp | ||||
| 	gui/InterfaceObjectConfigurable.cpp | ||||
| 	gui/NotificationHandler.cpp | ||||
| 	gui/ShortcutHandler.cpp | ||||
|  | ||||
| 	lobby/CBonusSelection.cpp | ||||
| 	lobby/CCampaignInfoScreen.cpp | ||||
| @@ -159,6 +160,8 @@ set(client_HEADERS | ||||
| 	gui/InterfaceObjectConfigurable.h | ||||
| 	gui/MouseButton.h | ||||
| 	gui/NotificationHandler.h | ||||
| 	gui/Shortcut.h | ||||
| 	gui/ShortcutHandler.h | ||||
| 	gui/TextAlignment.h | ||||
|  | ||||
| 	lobby/CBonusSelection.h | ||||
|   | ||||
| @@ -33,6 +33,7 @@ | ||||
| #include "../gui/CursorHandler.h" | ||||
| #include "../render/IImage.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../windows/settings/SettingsMainWindow.h" | ||||
| @@ -95,7 +96,7 @@ CAdventureMapInterface::CAdventureMapInterface(): | ||||
| 		gems.push_back(std::make_shared<CAnimImage>(ADVOPT.gemG[g], 0, 0, ADVOPT.gemX[g], ADVOPT.gemY[g])); | ||||
| 	} | ||||
|  | ||||
| 	auto makeButton = [&](int textID, std::function<void()> callback, config::ButtonInfo info, int key) -> std::shared_ptr<CButton> | ||||
| 	auto makeButton = [&](int textID, std::function<void()> callback, config::ButtonInfo info, EShortcut key) -> std::shared_ptr<CButton> | ||||
| 	{ | ||||
| 		auto button = std::make_shared<CButton>(Point(info.x, info.y), info.defName, CGI->generaltexth->zelp[textID], callback, key, info.playerColoured); | ||||
| 		for(auto image : info.additionalDefs) | ||||
| @@ -103,16 +104,16 @@ CAdventureMapInterface::CAdventureMapInterface(): | ||||
| 		return button; | ||||
| 	}; | ||||
|  | ||||
| 	kingOverview = makeButton(293, std::bind(&CAdventureMapInterface::fshowOverview,this),     ADVOPT.kingOverview, SDLK_k); | ||||
| 	underground  = makeButton(294, std::bind(&CAdventureMapInterface::fswitchLevel,this),      ADVOPT.underground,  SDLK_u); | ||||
| 	questlog     = makeButton(295, std::bind(&CAdventureMapInterface::fshowQuestlog,this),     ADVOPT.questlog,     SDLK_q); | ||||
| 	sleepWake    = makeButton(296, std::bind(&CAdventureMapInterface::fsleepWake,this),        ADVOPT.sleepWake,    SDLK_w); | ||||
| 	moveHero     = makeButton(297, std::bind(&CAdventureMapInterface::fmoveHero,this),         ADVOPT.moveHero,     SDLK_m); | ||||
| 	spellbook    = makeButton(298, std::bind(&CAdventureMapInterface::fshowSpellbok,this),     ADVOPT.spellbook,    SDLK_c); | ||||
| 	advOptions   = makeButton(299, std::bind(&CAdventureMapInterface::fadventureOPtions,this), ADVOPT.advOptions,   SDLK_a); | ||||
| 	sysOptions   = makeButton(300, std::bind(&CAdventureMapInterface::fsystemOptions,this),    ADVOPT.sysOptions,   SDLK_o); | ||||
| 	nextHero     = makeButton(301, std::bind(&CAdventureMapInterface::fnextHero,this),         ADVOPT.nextHero,     SDLK_h); | ||||
| 	endTurn      = makeButton(302, std::bind(&CAdventureMapInterface::fendTurn,this),          ADVOPT.endTurn,      SDLK_e); | ||||
| 	kingOverview = makeButton(293, std::bind(&CAdventureMapInterface::fshowOverview,this),     ADVOPT.kingOverview, EShortcut::ADVENTURE_KINGDOM_OVERVIEW); | ||||
| 	underground  = makeButton(294, std::bind(&CAdventureMapInterface::fswitchLevel,this),      ADVOPT.underground,  EShortcut::ADVENTURE_TOGGLE_MAP_LEVEL); | ||||
| 	questlog     = makeButton(295, std::bind(&CAdventureMapInterface::fshowQuestlog,this),     ADVOPT.questlog,     EShortcut::ADVENTURE_QUEST_LOG); | ||||
| 	sleepWake    = makeButton(296, std::bind(&CAdventureMapInterface::fsleepWake,this),        ADVOPT.sleepWake,    EShortcut::ADVENTURE_TOGGLE_SLEEP); | ||||
| 	moveHero     = makeButton(297, std::bind(&CAdventureMapInterface::fmoveHero,this),         ADVOPT.moveHero,     EShortcut::ADVENTURE_MOVE_HERO); | ||||
| 	spellbook    = makeButton(298, std::bind(&CAdventureMapInterface::fshowSpellbok,this),     ADVOPT.spellbook,    EShortcut::ADVENTURE_CAST_SPELL); | ||||
| 	advOptions   = makeButton(299, std::bind(&CAdventureMapInterface::fadventureOPtions,this), ADVOPT.advOptions,   EShortcut::ADVENTURE_OPTIONS); | ||||
| 	sysOptions   = makeButton(300, std::bind(&CAdventureMapInterface::fsystemOptions,this),    ADVOPT.sysOptions,   EShortcut::GLOBAL_OPTIONS); | ||||
| 	nextHero     = makeButton(301, std::bind(&CAdventureMapInterface::fnextHero,this),         ADVOPT.nextHero,     EShortcut::ADVENTURE_NEXT_HERO); | ||||
| 	endTurn      = makeButton(302, std::bind(&CAdventureMapInterface::fendTurn,this),          ADVOPT.endTurn,      EShortcut::ADVENTURE_END_TURN); | ||||
|  | ||||
| 	int panelSpaceBottom = GH.screenDimensions().y - resdatabar->pos.h - 4; | ||||
|  | ||||
| @@ -139,7 +140,7 @@ CAdventureMapInterface::CAdventureMapInterface(): | ||||
| 	worldViewBackConfig.y = 343 + 195; | ||||
| 	worldViewBackConfig.playerColoured = false; | ||||
| 	panelWorldView->addChildToPanel( | ||||
| 		makeButton(288, std::bind(&CAdventureMapInterface::fworldViewBack,this), worldViewBackConfig, SDLK_ESCAPE), ACTIVATE | DEACTIVATE); | ||||
| 		makeButton(288, std::bind(&CAdventureMapInterface::fworldViewBack,this), worldViewBackConfig, EShortcut::GLOBAL_CANCEL), ACTIVATE | DEACTIVATE); | ||||
|  | ||||
| 	config::ButtonInfo worldViewPuzzleConfig = config::ButtonInfo(); | ||||
| 	worldViewPuzzleConfig.defName = "VWPUZ.DEF"; | ||||
| @@ -148,7 +149,7 @@ CAdventureMapInterface::CAdventureMapInterface(): | ||||
| 	worldViewPuzzleConfig.playerColoured = false; | ||||
| 	panelWorldView->addChildToPanel( // no help text for this one | ||||
| 		std::make_shared<CButton>(Point(worldViewPuzzleConfig.x, worldViewPuzzleConfig.y), worldViewPuzzleConfig.defName, std::pair<std::string, std::string>(), | ||||
| 				std::bind(&CPlayerInterface::showPuzzleMap,LOCPLINT), SDLK_p, worldViewPuzzleConfig.playerColoured), ACTIVATE | DEACTIVATE); | ||||
| 				std::bind(&CPlayerInterface::showPuzzleMap,LOCPLINT), EShortcut::ADVENTURE_VIEW_PUZZLE, worldViewPuzzleConfig.playerColoured), ACTIVATE | DEACTIVATE); | ||||
|  | ||||
| 	config::ButtonInfo worldViewScale1xConfig = config::ButtonInfo(); | ||||
| 	worldViewScale1xConfig.defName = "VWMAG1.DEF"; | ||||
| @@ -156,7 +157,7 @@ CAdventureMapInterface::CAdventureMapInterface(): | ||||
| 	worldViewScale1xConfig.y = 23 + 195; | ||||
| 	worldViewScale1xConfig.playerColoured = false; | ||||
| 	panelWorldView->addChildToPanel( // help text is wrong for this button | ||||
| 		makeButton(291, std::bind(&CAdventureMapInterface::fworldViewScale1x,this), worldViewScale1xConfig, SDLK_1), ACTIVATE | DEACTIVATE); | ||||
| 		makeButton(291, std::bind(&CAdventureMapInterface::fworldViewScale1x,this), worldViewScale1xConfig, EShortcut::SELECT_INDEX_1), ACTIVATE | DEACTIVATE); | ||||
|  | ||||
| 	config::ButtonInfo worldViewScale2xConfig = config::ButtonInfo(); | ||||
| 	worldViewScale2xConfig.defName = "VWMAG2.DEF"; | ||||
| @@ -164,7 +165,7 @@ CAdventureMapInterface::CAdventureMapInterface(): | ||||
| 	worldViewScale2xConfig.y = 23 + 195; | ||||
| 	worldViewScale2xConfig.playerColoured = false; | ||||
| 	panelWorldView->addChildToPanel( // help text is wrong for this button | ||||
| 		makeButton(291, std::bind(&CAdventureMapInterface::fworldViewScale2x,this), worldViewScale2xConfig, SDLK_2), ACTIVATE | DEACTIVATE); | ||||
| 		makeButton(291, std::bind(&CAdventureMapInterface::fworldViewScale2x,this), worldViewScale2xConfig, EShortcut::SELECT_INDEX_2), ACTIVATE | DEACTIVATE); | ||||
|  | ||||
| 	config::ButtonInfo worldViewScale4xConfig = config::ButtonInfo(); | ||||
| 	worldViewScale4xConfig.defName = "VWMAG4.DEF"; | ||||
| @@ -172,7 +173,7 @@ CAdventureMapInterface::CAdventureMapInterface(): | ||||
| 	worldViewScale4xConfig.y = 23 + 195; | ||||
| 	worldViewScale4xConfig.playerColoured = false; | ||||
| 	panelWorldView->addChildToPanel( // help text is wrong for this button | ||||
| 		makeButton(291, std::bind(&CAdventureMapInterface::fworldViewScale4x,this), worldViewScale4xConfig, SDLK_4), ACTIVATE | DEACTIVATE); | ||||
| 		makeButton(291, std::bind(&CAdventureMapInterface::fworldViewScale4x,this), worldViewScale4xConfig, EShortcut::SELECT_INDEX_4), ACTIVATE | DEACTIVATE); | ||||
|  | ||||
| 	config::ButtonInfo worldViewUndergroundConfig = config::ButtonInfo(); | ||||
| 	worldViewUndergroundConfig.defName = "IAM010.DEF"; | ||||
| @@ -180,7 +181,7 @@ CAdventureMapInterface::CAdventureMapInterface(): | ||||
| 	worldViewUndergroundConfig.x = GH.screenDimensions().x - 115; | ||||
| 	worldViewUndergroundConfig.y = 343 + 195; | ||||
| 	worldViewUndergroundConfig.playerColoured = true; | ||||
| 	worldViewUnderground = makeButton(294, std::bind(&CAdventureMapInterface::fswitchLevel,this), worldViewUndergroundConfig, SDLK_u); | ||||
| 	worldViewUnderground = makeButton(294, std::bind(&CAdventureMapInterface::fswitchLevel,this), worldViewUndergroundConfig, EShortcut::ADVENTURE_TOGGLE_MAP_LEVEL); | ||||
| 	panelWorldView->addChildColorableButton(worldViewUnderground); | ||||
|  | ||||
| 	onCurrentPlayerChanged(LOCPLINT->playerID); | ||||
| @@ -392,7 +393,6 @@ void CAdventureMapInterface::updateButtons() | ||||
| 	{ | ||||
| 		bool state = LOCPLINT->localState->isHeroSleeping(hero); | ||||
| 		sleepWake->setIndex(state ? 1 : 0, true); | ||||
| 		sleepWake->assignedKeys = {state ? SDLK_w : SDLK_z}; | ||||
| 		sleepWake->redraw(); | ||||
| 	} | ||||
| } | ||||
| @@ -607,17 +607,20 @@ void CAdventureMapInterface::centerOnObject(const CGObjectInstance * obj) | ||||
| 	terrain->onCenteredObject(obj); | ||||
| } | ||||
|  | ||||
| void CAdventureMapInterface::keyPressed(const SDL_Keycode & key) | ||||
| void CAdventureMapInterface::keyPressed(EShortcut key) | ||||
| { | ||||
| 	if (state != EGameState::MAKING_TURN) | ||||
| 		return; | ||||
|  | ||||
| 	//fake mouse use to trigger onTileHovered() | ||||
| 	GH.fakeMouseMove(); | ||||
|  | ||||
| 	const CGHeroInstance *h = LOCPLINT->localState->getCurrentHero(); //selected hero | ||||
| 	const CGTownInstance *t = LOCPLINT->localState->getCurrentTown(); //selected town | ||||
|  | ||||
| 	switch(key) | ||||
| 	{ | ||||
| 	case SDLK_g: | ||||
| 	case EShortcut::ADVENTURE_THIEVES_GUILD: | ||||
| 		if(GH.topInt()->type & BLOCK_ADV_HOTKEYS) | ||||
| 			return; | ||||
|  | ||||
| @@ -634,40 +637,40 @@ void CAdventureMapInterface::keyPressed(const SDL_Keycode & key) | ||||
| 				LOCPLINT->showInfoDialog(CGI->generaltexth->translate("vcmi.adventureMap.noTownWithTavern")); | ||||
| 		} | ||||
| 		return; | ||||
| 	case SDLK_i: | ||||
| 	case EShortcut::ADVENTURE_VIEW_SCENARIO: | ||||
| 		if(isActive()) | ||||
| 			CAdventureOptions::showScenarioInfo(); | ||||
| 		return; | ||||
| 	case SDLK_s: | ||||
| 	case EShortcut::GAME_SAVE_GAME: | ||||
| 		if(isActive()) | ||||
| 			GH.pushIntT<CSavingScreen>(); | ||||
| 		return; | ||||
| 	case SDLK_l: | ||||
| 	case EShortcut::GAME_LOAD_GAME: | ||||
| 		if(isActive()) | ||||
| 			LOCPLINT->proposeLoadingGame(); | ||||
| 		return; | ||||
| 	case SDLK_d: | ||||
| 	case EShortcut::ADVENTURE_DIG_GRAIL: | ||||
| 		{ | ||||
| 			if(h && isActive() && LOCPLINT->makingTurn) | ||||
| 				LOCPLINT->tryDiggging(h); | ||||
| 			return; | ||||
| 		} | ||||
| 	case SDLK_p: | ||||
| 	case EShortcut::ADVENTURE_VIEW_PUZZLE: | ||||
| 		if(isActive()) | ||||
| 			LOCPLINT->showPuzzleMap(); | ||||
| 		return; | ||||
| 	case SDLK_v: | ||||
| 	case EShortcut::ADVENTURE_VIEW_WORLD: | ||||
| 		if(isActive()) | ||||
| 			LOCPLINT->viewWorldMap(); | ||||
| 		return; | ||||
| 	case SDLK_r: | ||||
| 	case EShortcut::GAME_RESTART_GAME: | ||||
| 		if(isActive() && GH.isKeyboardCtrlDown()) | ||||
| 		{ | ||||
| 			LOCPLINT->showYesNoDialog(CGI->generaltexth->translate("vcmi.adventureMap.confirmRestartGame"), | ||||
| 				[](){ GH.pushUserEvent(EUserEvent::RESTART_GAME); }, nullptr); | ||||
| 		} | ||||
| 		return; | ||||
| 	case SDLK_SPACE: //space - try to revisit current object with selected hero | ||||
| 	case EShortcut::ADVENTURE_VISIT_OBJECT: //space - try to revisit current object with selected hero | ||||
| 		{ | ||||
| 			if(!isActive()) | ||||
| 				return; | ||||
| @@ -677,7 +680,7 @@ void CAdventureMapInterface::keyPressed(const SDL_Keycode & key) | ||||
| 			} | ||||
| 		} | ||||
| 		return; | ||||
| 	case SDLK_RETURN: | ||||
| 	case EShortcut::ADVENTURE_VIEW_SELECTED: | ||||
| 		{ | ||||
| 			if(!isActive() || !LOCPLINT->localState->getCurrentArmy()) | ||||
| 				return; | ||||
| @@ -687,7 +690,7 @@ void CAdventureMapInterface::keyPressed(const SDL_Keycode & key) | ||||
| 				LOCPLINT->openTownWindow(t); | ||||
| 			return; | ||||
| 		} | ||||
| 	case SDLK_ESCAPE: | ||||
| 	case EShortcut::GLOBAL_CANCEL: | ||||
| 		{ | ||||
| 			//FIXME: this case is never executed since AdvMapInt is disabled while in spellcasting mode | ||||
| 			if(!isActive() || GH.topInt().get() != this || !spellBeingCasted) | ||||
| @@ -696,7 +699,7 @@ void CAdventureMapInterface::keyPressed(const SDL_Keycode & key) | ||||
| 			abortCastingMode(); | ||||
| 			return; | ||||
| 		} | ||||
| 	case SDLK_t: | ||||
| 	case EShortcut::GAME_MARKETPLACE: | ||||
| 		{ | ||||
| 			//act on key down if marketplace windows is not already opened | ||||
| 			if(GH.topInt()->type & BLOCK_ADV_HOTKEYS) | ||||
| @@ -720,77 +723,55 @@ void CAdventureMapInterface::keyPressed(const SDL_Keycode & key) | ||||
| 				else //if not - complain | ||||
| 					LOCPLINT->showInfoDialog(CGI->generaltexth->translate("vcmi.adventureMap.noTownWithMarket")); | ||||
| 			} | ||||
| 			else if(isActive()) //no ctrl, advmapint is on the top => switch to town | ||||
| 	case EShortcut::ADVENTURE_NEXT_TOWN: | ||||
| 			if(isActive() && !GH.isKeyboardCtrlDown()) //no ctrl, advmapint is on the top => switch to town | ||||
| 			{ | ||||
| 				townList->selectNext(); | ||||
| 			} | ||||
| 			return; | ||||
| 		} | ||||
| 	case SDLK_LALT: | ||||
| 	case SDLK_RALT: | ||||
| 		{ | ||||
| 			//fake mouse use to trigger onTileHovered() | ||||
| 			GH.fakeMouseMove(); | ||||
| 			return; | ||||
| 		} | ||||
| 	default: | ||||
| 		{ | ||||
| 			auto direction = keyToMoveDirection(key); | ||||
|  | ||||
| 			if (!direction) | ||||
| 				return; | ||||
|  | ||||
| 			if(!h || !isActive()) | ||||
| 				return; | ||||
|  | ||||
| 			if (CGI->mh->hasOngoingAnimations()) | ||||
| 				return; | ||||
|  | ||||
| 			if(*direction == Point(0,0)) | ||||
| 			{ | ||||
| 				centerOnObject(h); | ||||
| 				return; | ||||
| 			} | ||||
|  | ||||
| 			int3 dst = h->visitablePos() + int3(direction->x, direction->y, 0); | ||||
|  | ||||
| 			if (!CGI->mh->isInMap((dst))) | ||||
| 				return; | ||||
|  | ||||
| 			if ( !LOCPLINT->localState->setPath(h, dst)) | ||||
| 				return; | ||||
|  | ||||
| 			const CGPath & path = LOCPLINT->localState->getPath(h); | ||||
|  | ||||
| 			if (path.nodes.size() > 2) | ||||
| 				onHeroChanged(h); | ||||
| 			else | ||||
| 			if(!path.nodes[0].turns) | ||||
| 				LOCPLINT->moveHero(h, path); | ||||
| 		} | ||||
| 		return; | ||||
| 	case EShortcut::ADVENTURE_MOVE_HERO_SW: return hotkeyMoveHeroDirectional({-1, +1}); | ||||
| 	case EShortcut::ADVENTURE_MOVE_HERO_SS: return hotkeyMoveHeroDirectional({ 0, +1}); | ||||
| 	case EShortcut::ADVENTURE_MOVE_HERO_SE: return hotkeyMoveHeroDirectional({+1, +1}); | ||||
| 	case EShortcut::ADVENTURE_MOVE_HERO_WW: return hotkeyMoveHeroDirectional({-1,  0}); | ||||
| 	case EShortcut::ADVENTURE_MOVE_HERO_EE: return hotkeyMoveHeroDirectional({+1,  0}); | ||||
| 	case EShortcut::ADVENTURE_MOVE_HERO_NW: return hotkeyMoveHeroDirectional({-1, -1}); | ||||
| 	case EShortcut::ADVENTURE_MOVE_HERO_NN: return hotkeyMoveHeroDirectional({ 0, -1}); | ||||
| 	case EShortcut::ADVENTURE_MOVE_HERO_NE: return hotkeyMoveHeroDirectional({+1, -1}); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| std::optional<Point> CAdventureMapInterface::keyToMoveDirection(const SDL_Keycode & key) | ||||
| void CAdventureMapInterface::hotkeyMoveHeroDirectional(Point direction) | ||||
| { | ||||
| 	switch (key) { | ||||
| 		case SDLK_DOWN:  return Point( 0, +1); | ||||
| 		case SDLK_LEFT:  return Point(-1,  0); | ||||
| 		case SDLK_RIGHT: return Point(+1,  0); | ||||
| 		case SDLK_UP:    return Point( 0, -1); | ||||
| 	const CGHeroInstance *h = LOCPLINT->localState->getCurrentHero(); //selected hero | ||||
|  | ||||
| 		case SDLK_KP_1: return Point(-1, +1); | ||||
| 		case SDLK_KP_2: return Point( 0, +1); | ||||
| 		case SDLK_KP_3: return Point(+1, +1); | ||||
| 		case SDLK_KP_4: return Point(-1,  0); | ||||
| 		case SDLK_KP_5: return Point( 0,  0); | ||||
| 		case SDLK_KP_6: return Point(+1,  0); | ||||
| 		case SDLK_KP_7: return Point(-1, -1); | ||||
| 		case SDLK_KP_8: return Point( 0, -1); | ||||
| 		case SDLK_KP_9: return Point(+1, -1); | ||||
| 	if(!h || !isActive()) | ||||
| 		return; | ||||
|  | ||||
| 	if (CGI->mh->hasOngoingAnimations()) | ||||
| 		return; | ||||
|  | ||||
| 	if(direction == Point(0,0)) | ||||
| 	{ | ||||
| 		centerOnObject(h); | ||||
| 		return; | ||||
| 	} | ||||
| 	return std::nullopt; | ||||
|  | ||||
| 	int3 dst = h->visitablePos() + int3(direction.x, direction.y, 0); | ||||
|  | ||||
| 	if (!CGI->mh->isInMap((dst))) | ||||
| 		return; | ||||
|  | ||||
| 	if ( !LOCPLINT->localState->setPath(h, dst)) | ||||
| 		return; | ||||
|  | ||||
| 	const CGPath & path = LOCPLINT->localState->getPath(h); | ||||
|  | ||||
| 	if (path.nodes.size() > 2) | ||||
| 		onHeroChanged(h); | ||||
| 	else | ||||
| 		if(!path.nodes[0].turns) | ||||
| 			LOCPLINT->moveHero(h, path); | ||||
| } | ||||
|  | ||||
| void CAdventureMapInterface::onSelectionChanged(const CArmedInstance *sel) | ||||
|   | ||||
| @@ -116,6 +116,8 @@ private: | ||||
| 	void fnextHero(); | ||||
| 	void fendTurn(); | ||||
|  | ||||
| 	void hotkeyMoveHeroDirectional(Point direction); | ||||
|  | ||||
| 	bool isActive(); | ||||
| 	void adjustActiveness(bool aiTurnStart); //should be called every time at AI/human turn transition; blocks GUI during AI turn | ||||
|  | ||||
| @@ -130,7 +132,7 @@ private: | ||||
|  | ||||
| 	const CGObjectInstance *getActiveObject(const int3 &tile); | ||||
|  | ||||
| 	std::optional<Point> keyToMoveDirection(const SDL_Keycode & key); | ||||
| 	std::optional<Point> keyToMoveDirection(EShortcut key); | ||||
|  | ||||
| 	void endingTurn(); | ||||
|  | ||||
| @@ -149,7 +151,7 @@ protected: | ||||
| 	void show(SDL_Surface * to) override; | ||||
| 	void showAll(SDL_Surface * to) override; | ||||
|  | ||||
| 	void keyPressed(const SDL_Keycode & key) override; | ||||
| 	void keyPressed(EShortcut key) override; | ||||
|  | ||||
| public: | ||||
| 	CAdventureMapInterface(); | ||||
|   | ||||
| @@ -17,6 +17,7 @@ | ||||
| #include "../lobby/CCampaignInfoScreen.h" | ||||
| #include "../lobby/CScenarioInfoScreen.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../widgets/Buttons.h" | ||||
|  | ||||
| #include "../../CCallback.h" | ||||
| @@ -27,19 +28,18 @@ CAdventureOptions::CAdventureOptions() | ||||
| { | ||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); | ||||
|  | ||||
| 	viewWorld = std::make_shared<CButton>(Point(24, 23), "ADVVIEW.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_v); | ||||
| 	viewWorld = std::make_shared<CButton>(Point(24, 23), "ADVVIEW.DEF", CButton::tooltip(), [&](){ close(); }, EShortcut::ADVENTURE_VIEW_WORLD); | ||||
| 	viewWorld->addCallback( [] { LOCPLINT->viewWorldMap(); }); | ||||
|  | ||||
| 	exit = std::make_shared<CButton>(Point(204, 313), "IOK6432.DEF", CButton::tooltip(), std::bind(&CAdventureOptions::close, this), SDLK_RETURN); | ||||
| 	exit->assignedKeys.insert(SDLK_ESCAPE); | ||||
| 	exit = std::make_shared<CButton>(Point(204, 313), "IOK6432.DEF", CButton::tooltip(), std::bind(&CAdventureOptions::close, this), EShortcut::GLOBAL_RETURN); | ||||
|  | ||||
| 	scenInfo = std::make_shared<CButton>(Point(24, 198), "ADVINFO.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_i); | ||||
| 	scenInfo = std::make_shared<CButton>(Point(24, 198), "ADVINFO.DEF", CButton::tooltip(), [&](){ close(); }, EShortcut::ADVENTURE_VIEW_SCENARIO); | ||||
| 	scenInfo->addCallback(CAdventureOptions::showScenarioInfo); | ||||
|  | ||||
| 	puzzle = std::make_shared<CButton>(Point(24, 81), "ADVPUZ.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_p); | ||||
| 	puzzle = std::make_shared<CButton>(Point(24, 81), "ADVPUZ.DEF", CButton::tooltip(), [&](){ close(); }, EShortcut::ADVENTURE_VIEW_PUZZLE); | ||||
| 	puzzle->addCallback(std::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT)); | ||||
|  | ||||
| 	dig = std::make_shared<CButton>(Point(24, 139), "ADVDIG.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_d); | ||||
| 	dig = std::make_shared<CButton>(Point(24, 139), "ADVDIG.DEF", CButton::tooltip(), [&](){ close(); }, EShortcut::ADVENTURE_DIG_GRAIL); | ||||
| 	if(const CGHeroInstance *h = LOCPLINT->localState->getCurrentHero()) | ||||
| 		dig->addCallback(std::bind(&CPlayerInterface::tryDiggging, LOCPLINT, h)); | ||||
| 	else | ||||
|   | ||||
| @@ -17,6 +17,7 @@ | ||||
| #include "../PlayerLocalState.h" | ||||
| #include "../ClientCommandManager.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../render/Colors.h" | ||||
|  | ||||
| #include "../../CCallback.h" | ||||
| @@ -108,30 +109,29 @@ void CInGameConsole::print(const std::string & txt) | ||||
| 	GH.totalRedraw(); // FIXME: ingame console has no parent widget set | ||||
| } | ||||
|  | ||||
| void CInGameConsole::keyPressed (const SDL_Keycode & key) | ||||
| void CInGameConsole::keyPressed (EShortcut key) | ||||
| { | ||||
| 	if (LOCPLINT->cingconsole != this) | ||||
| 		return; | ||||
|  | ||||
| 	if(!captureAllKeys && key != SDLK_TAB) | ||||
| 	if(!captureAllKeys && key != EShortcut::GAME_ACTIVATE_CONSOLE) | ||||
| 		return; //because user is not entering any text | ||||
|  | ||||
| 	switch(key) | ||||
| 	{ | ||||
| 	case SDLK_TAB: | ||||
| 	case SDLK_ESCAPE: | ||||
| 		{ | ||||
| 			if(captureAllKeys) | ||||
| 			{ | ||||
| 				endEnteringText(false); | ||||
| 			} | ||||
| 			else if(SDLK_TAB == key) | ||||
| 			{ | ||||
| 				startEnteringText(); | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 	case SDLK_RETURN: //enter key | ||||
| 	case EShortcut::GLOBAL_CANCEL: | ||||
| 		if(captureAllKeys) | ||||
| 			endEnteringText(false); | ||||
| 		break; | ||||
|  | ||||
| 	case EShortcut::GAME_ACTIVATE_CONSOLE: | ||||
| 		if(captureAllKeys) | ||||
| 			endEnteringText(false); | ||||
| 		else | ||||
| 			startEnteringText(); | ||||
| 		break; | ||||
|  | ||||
| 	case EShortcut::GLOBAL_CONFIRM: | ||||
| 		{ | ||||
| 			if(!enteredText.empty() && captureAllKeys) | ||||
| 			{ | ||||
| @@ -145,7 +145,7 @@ void CInGameConsole::keyPressed (const SDL_Keycode & key) | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 	case SDLK_BACKSPACE: | ||||
| 	case EShortcut::GLOBAL_BACKSPACE: | ||||
| 		{ | ||||
| 			if(enteredText.size() > 1) | ||||
| 			{ | ||||
| @@ -155,7 +155,7 @@ void CInGameConsole::keyPressed (const SDL_Keycode & key) | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 	case SDLK_UP: //up arrow | ||||
| 	case EShortcut::SELECT_UP: | ||||
| 		{ | ||||
| 			if(previouslyEntered.empty()) | ||||
| 				break; | ||||
| @@ -174,7 +174,7 @@ void CInGameConsole::keyPressed (const SDL_Keycode & key) | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 	case SDLK_DOWN: //down arrow | ||||
| 	case EShortcut::SELECT_DOWN: | ||||
| 		{ | ||||
| 			if(prevEntDisp != -1 && prevEntDisp+1 < previouslyEntered.size()) | ||||
| 			{ | ||||
| @@ -190,10 +190,6 @@ void CInGameConsole::keyPressed (const SDL_Keycode & key) | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 	default: | ||||
| 		{ | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -47,7 +47,7 @@ public: | ||||
| 	void tick(uint32_t msPassed) override; | ||||
| 	void show(SDL_Surface * to) override; | ||||
| 	void showAll(SDL_Surface * to) override; | ||||
| 	void keyPressed(const SDL_Keycode & key) override; | ||||
| 	void keyPressed(EShortcut key) override; | ||||
| 	void textInputed(const std::string & enteredText) override; | ||||
| 	void textEdited(const std::string & enteredText) override; | ||||
|  | ||||
|   | ||||
| @@ -243,7 +243,7 @@ std::set<BattleHex> BattleFieldController::getMovementRangeForHoveredStack() | ||||
| 	if (!owner.stacksController->getActiveStack()) | ||||
| 		return result; | ||||
|  | ||||
| 	if (!settings["battle"]["movementHighlightOnHover"].Bool()) | ||||
| 	if (!settings["battle"]["movementHighlightOnHover"].Bool() && !GH.isKeyboardShiftDown()) | ||||
| 		return result; | ||||
|  | ||||
| 	auto hoveredHex = getHoveredHex(); | ||||
|   | ||||
| @@ -24,6 +24,7 @@ | ||||
| #include "../CVideoHandler.h" | ||||
| #include "../gui/CursorHandler.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../render/Canvas.h" | ||||
| #include "../render/IImage.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| @@ -406,12 +407,12 @@ BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface | ||||
| 	background->colorize(owner.playerID); | ||||
| 	pos = center(background->pos); | ||||
|  | ||||
| 	exit = std::make_shared<CButton>(Point(384, 505), "iok6432.def", std::make_pair("", ""), [&](){ bExitf();}, SDLK_RETURN); | ||||
| 	exit = std::make_shared<CButton>(Point(384, 505), "iok6432.def", std::make_pair("", ""), [&](){ bExitf();}, EShortcut::GLOBAL_CONFIRM); | ||||
| 	exit->setBorderColor(Colors::METALLIC_GOLD); | ||||
| 	 | ||||
| 	if(allowReplay) | ||||
| 	{ | ||||
| 		repeat = std::make_shared<CButton>(Point(24, 505), "icn6432.def", std::make_pair("", ""), [&](){ bRepeatf();}, SDLK_ESCAPE); | ||||
| 		repeat = std::make_shared<CButton>(Point(24, 505), "icn6432.def", std::make_pair("", ""), [&](){ bRepeatf();}, EShortcut::GLOBAL_CANCEL); | ||||
| 		repeat->setBorderColor(Colors::METALLIC_GOLD); | ||||
| 		labels.push_back(std::make_shared<CLabel>(232, 520, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->translate("vcmi.battleResultsWindow.applyResultsLabel"))); | ||||
| 	} | ||||
|   | ||||
| @@ -21,6 +21,7 @@ | ||||
| #include "../CMusicHandler.h" | ||||
| #include "../gui/CursorHandler.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../windows/CSpellWindow.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/Images.h" | ||||
| @@ -182,7 +183,7 @@ void BattleWindow::deactivate() | ||||
| 	LOCPLINT->cingconsole->deactivate(); | ||||
| } | ||||
|  | ||||
| void BattleWindow::keyPressed(const SDL_Keycode & key) | ||||
| void BattleWindow::keyPressed(EShortcut key) | ||||
| { | ||||
| 	if (owner.openingPlaying()) | ||||
| 	{ | ||||
| @@ -190,35 +191,18 @@ void BattleWindow::keyPressed(const SDL_Keycode & key) | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if(key == SDLK_q) | ||||
| 	if(key == EShortcut::BATTLE_TOGGLE_QUEUE) | ||||
| 	{ | ||||
| 		toggleQueueVisibility(); | ||||
| 	} | ||||
| 	else if(key == SDLK_f) | ||||
| 	else if(key == EShortcut::BATTLE_USE_CREATURE_SPELL) | ||||
| 	{ | ||||
| 		owner.actionsController->enterCreatureCastingMode(); | ||||
| 	} | ||||
| 	else if(key == SDLK_ESCAPE) | ||||
| 	else if(key == EShortcut::GLOBAL_CANCEL) | ||||
| 	{ | ||||
| 		owner.actionsController->endCastingSpell(); | ||||
| 	} | ||||
| 	else if(GH.isKeyboardShiftDown()) | ||||
| 	{ | ||||
| 		// save and activate setting | ||||
| 		Settings movementHighlightOnHover = settings.write["battle"]["movementHighlightOnHover"]; | ||||
| 		movementHighlightOnHoverCache = movementHighlightOnHover->Bool(); | ||||
| 		movementHighlightOnHover->Bool() = true; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void BattleWindow::keyReleased(const SDL_Keycode & key) | ||||
| { | ||||
| 	if(!GH.isKeyboardShiftDown()) | ||||
| 	{ | ||||
| 		// set back to initial state | ||||
| 		Settings movementHighlightOnHover = settings.write["battle"]["movementHighlightOnHover"]; | ||||
| 		movementHighlightOnHover->Bool() = movementHighlightOnHoverCache; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void BattleWindow::clickRight(tribool down, bool previousState) | ||||
|   | ||||
| @@ -84,8 +84,7 @@ public: | ||||
|  | ||||
| 	void activate() override; | ||||
| 	void deactivate() override; | ||||
| 	void keyPressed(const SDL_Keycode & key) override; | ||||
| 	void keyReleased(const SDL_Keycode& key) override; | ||||
| 	void keyPressed(EShortcut key) override; | ||||
| 	void clickRight(tribool down, bool previousState) override; | ||||
| 	void show(SDL_Surface *to) override; | ||||
| 	void showAll(SDL_Surface *to) override; | ||||
| @@ -98,9 +97,5 @@ public: | ||||
|  | ||||
| 	/// Set possible alternative options. If more than 1 - the last will be considered as default option | ||||
| 	void setAlternativeActions(const std::list<PossiblePlayerBattleAction> &); | ||||
|  | ||||
| private: | ||||
| 	/// used to save the state of this setting on toggle. | ||||
| 	bool movementHighlightOnHoverCache; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -13,6 +13,7 @@ | ||||
|  | ||||
| #include "CIntObject.h" | ||||
| #include "CursorHandler.h" | ||||
| #include "ShortcutHandler.h" | ||||
|  | ||||
| #include "../CGameInfo.h" | ||||
| #include "../render/Colors.h" | ||||
| @@ -27,6 +28,7 @@ | ||||
| #include <SDL_render.h> | ||||
| #include <SDL_timer.h> | ||||
| #include <SDL_events.h> | ||||
| #include <SDL_keycode.h> | ||||
|  | ||||
| #ifdef VCMI_APPLE | ||||
| #include <dispatch/dispatch.h> | ||||
| @@ -93,6 +95,7 @@ void CGuiHandler::processLists(const ui16 activityFlag, std::function<void (std: | ||||
|  | ||||
| void CGuiHandler::init() | ||||
| { | ||||
| 	shortcutsHandler = std::make_unique<ShortcutHandler>(); | ||||
| 	mainFPSmng = new CFramerateManager(); | ||||
| 	mainFPSmng->init(settings["video"]["targetfps"].Integer()); | ||||
| 	isPointerRelativeMode = settings["general"]["userRelativePointer"].Bool(); | ||||
| @@ -356,6 +359,10 @@ void CGuiHandler::handleCurrentEvent( SDL_Event & current ) | ||||
| 	if(current.type == SDL_KEYDOWN || current.type == SDL_KEYUP) | ||||
| 	{ | ||||
| 		SDL_KeyboardEvent key = current.key; | ||||
|  | ||||
| 		if (key.repeat != 0) | ||||
| 			return; // ignore periodic event resends | ||||
|  | ||||
| 		if(current.type == SDL_KEYDOWN && key.keysym.sym >= SDLK_F1 && key.keysym.sym <= SDLK_F15 && settings["session"]["spectate"].Bool()) | ||||
| 		{ | ||||
| 			//TODO: we need some central place for all interface-independent hotkeys | ||||
| @@ -397,32 +404,35 @@ void CGuiHandler::handleCurrentEvent( SDL_Event & current ) | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		//translate numpad keys | ||||
| 		if(key.keysym.sym == SDLK_KP_ENTER) | ||||
| 		{ | ||||
| 			key.keysym.sym = SDLK_RETURN; | ||||
| 			key.keysym.scancode = SDL_SCANCODE_RETURN; | ||||
| 		} | ||||
| 		auto shortcutsVector = shortcutsHandler->translateKeycode(key.keysym.sym); | ||||
|  | ||||
| 		bool keysCaptured = false; | ||||
| 		for(auto i = keyinterested.begin(); i != keyinterested.end() && continueEventHandling; i++) | ||||
| 		{ | ||||
| 			if((*i)->captureThisKey(key.keysym.sym)) | ||||
| 			for (EShortcut shortcut : shortcutsVector) | ||||
| 			{ | ||||
| 				keysCaptured = true; | ||||
| 				break; | ||||
| 				if((*i)->captureThisKey(shortcut)) | ||||
| 				{ | ||||
| 					keysCaptured = true; | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		std::list<CIntObject*> miCopy = keyinterested; | ||||
| 		for(auto i = miCopy.begin(); i != miCopy.end() && continueEventHandling; i++) | ||||
| 			if(vstd::contains(keyinterested,*i) && (!keysCaptured || (*i)->captureThisKey(key.keysym.sym))) | ||||
| 		{ | ||||
| 			for (EShortcut shortcut : shortcutsVector) | ||||
| 			{ | ||||
| 				if (key.state == SDL_PRESSED && key.repeat == 0) // function like key_DOWN, and not like a periodic key_Pressed check  | ||||
| 					(**i).keyPressed(key.keysym.sym); | ||||
| 				if (key.state == SDL_RELEASED) | ||||
| 					(**i).keyReleased(key.keysym.sym); | ||||
| 				if(vstd::contains(keyinterested,*i) && (!keysCaptured || (*i)->captureThisKey(shortcut))) | ||||
| 				{ | ||||
| 					if (key.state == SDL_PRESSED) | ||||
| 						(**i).keyPressed(shortcut); | ||||
| 					if (key.state == SDL_RELEASED) | ||||
| 						(**i).keyReleased(shortcut); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	else if(current.type == SDL_MOUSEMOTION) | ||||
| 	{ | ||||
| @@ -704,6 +714,10 @@ CGuiHandler::~CGuiHandler() | ||||
| 	delete terminate_cond; | ||||
| } | ||||
|  | ||||
| ShortcutHandler & CGuiHandler::getShortcutsHandler() | ||||
| { | ||||
| 	return *shortcutsHandler; | ||||
| } | ||||
|  | ||||
| void CGuiHandler::moveCursorToPosition(const Point & position) | ||||
| { | ||||
| @@ -770,69 +784,6 @@ void CGuiHandler::drawFPSCounter() | ||||
| 	graphics->fonts[FONT_BIG]->renderTextLeft(screen, fps, Colors::YELLOW, Point(10, 10)); | ||||
| } | ||||
|  | ||||
| SDL_Keycode CGuiHandler::arrowToNum(SDL_Keycode key) | ||||
| { | ||||
| 	switch(key) | ||||
| 	{ | ||||
| 	case SDLK_DOWN: | ||||
| 		return SDLK_KP_2; | ||||
| 	case SDLK_UP: | ||||
| 		return SDLK_KP_8; | ||||
| 	case SDLK_LEFT: | ||||
| 		return SDLK_KP_4; | ||||
| 	case SDLK_RIGHT: | ||||
| 		return SDLK_KP_6; | ||||
| 	default: | ||||
| 		throw std::runtime_error("Wrong key!"); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| SDL_Keycode CGuiHandler::numToDigit(SDL_Keycode key) | ||||
| { | ||||
|  | ||||
| #define REMOVE_KP(keyName) case SDLK_KP_ ## keyName : return SDLK_ ## keyName; | ||||
| 	switch(key) | ||||
| 	{ | ||||
| 		REMOVE_KP(0) | ||||
| 		REMOVE_KP(1) | ||||
| 		REMOVE_KP(2) | ||||
| 		REMOVE_KP(3) | ||||
| 		REMOVE_KP(4) | ||||
| 		REMOVE_KP(5) | ||||
| 		REMOVE_KP(6) | ||||
| 		REMOVE_KP(7) | ||||
| 		REMOVE_KP(8) | ||||
| 		REMOVE_KP(9) | ||||
| 		REMOVE_KP(PERIOD) | ||||
| 		REMOVE_KP(MINUS) | ||||
| 		REMOVE_KP(PLUS) | ||||
| 		REMOVE_KP(EQUALS) | ||||
|  | ||||
| 	case SDLK_KP_MULTIPLY: | ||||
| 		return SDLK_ASTERISK; | ||||
| 	case SDLK_KP_DIVIDE: | ||||
| 		return SDLK_SLASH; | ||||
| 	case SDLK_KP_ENTER: | ||||
| 		return SDLK_RETURN; | ||||
| 	default: | ||||
| 		return SDLK_UNKNOWN; | ||||
| 	} | ||||
| #undef REMOVE_KP | ||||
| } | ||||
|  | ||||
| bool CGuiHandler::isNumKey(SDL_Keycode key, bool number) | ||||
| { | ||||
| 	if(number) | ||||
| 		return key >= SDLK_KP_1 && key <= SDLK_KP_0; | ||||
| 	else | ||||
| 		return (key >= SDLK_KP_1 && key <= SDLK_KP_0) || key == SDLK_KP_MINUS || key == SDLK_KP_PLUS || key == SDLK_KP_EQUALS; | ||||
| } | ||||
|  | ||||
| bool CGuiHandler::isArrowKey(SDL_Keycode key) | ||||
| { | ||||
| 	return key == SDLK_UP || key == SDLK_DOWN || key == SDLK_LEFT || key == SDLK_RIGHT; | ||||
| } | ||||
|  | ||||
| bool CGuiHandler::amIGuiThread() | ||||
| { | ||||
| 	return inGuiThread.get() && *inGuiThread; | ||||
|   | ||||
| @@ -12,8 +12,6 @@ | ||||
| #include "MouseButton.h" | ||||
| #include "../../lib/Point.h" | ||||
|  | ||||
| #include <SDL_keycode.h> | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
|  | ||||
| template <typename T> struct CondSh; | ||||
| @@ -24,6 +22,7 @@ VCMI_LIB_NAMESPACE_END | ||||
| union SDL_Event; | ||||
| struct SDL_MouseMotionEvent; | ||||
|  | ||||
| class ShortcutHandler; | ||||
| class CFramerateManager; | ||||
| class IStatusBar; | ||||
| class CIntObject; | ||||
| @@ -79,6 +78,8 @@ private: | ||||
|  | ||||
| 	std::vector<std::shared_ptr<IShowActivatable>> disposed; | ||||
|  | ||||
| 	std::unique_ptr<ShortcutHandler> shortcutsHandler; | ||||
|  | ||||
| 	std::atomic<bool> continueEventHandling; | ||||
| 	using CIntObjectList = std::list<CIntObject *>; | ||||
|  | ||||
| @@ -113,6 +114,8 @@ public: | ||||
| 	/// returns current position of mouse cursor, relative to vcmi window | ||||
| 	const Point & getCursorPosition() const; | ||||
|  | ||||
| 	ShortcutHandler & getShortcutsHandler(); | ||||
|  | ||||
| 	Point screenDimensions() const; | ||||
|  | ||||
| 	/// returns true if at least one mouse button is pressed | ||||
| @@ -173,10 +176,6 @@ public: | ||||
| 	void breakEventHandling(); //current event won't be propagated anymore | ||||
| 	void drawFPSCounter(); // draws the FPS to the upper left corner of the screen | ||||
|  | ||||
| 	static SDL_Keycode arrowToNum(SDL_Keycode key); //converts arrow key to according numpad key | ||||
| 	static SDL_Keycode numToDigit(SDL_Keycode key);//converts numpad digit key to normal digit key | ||||
| 	static bool isNumKey(SDL_Keycode key, bool number = true); //checks if key is on numpad (numbers - check only for numpad digits) | ||||
| 	static bool isArrowKey(SDL_Keycode key); | ||||
| 	static bool amIGuiThread(); | ||||
| 	static void pushUserEvent(EUserEvent usercode); | ||||
| 	static void pushUserEvent(EUserEvent usercode, void * userdata); | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
| #include "CIntObject.h" | ||||
|  | ||||
| #include "CGuiHandler.h" | ||||
| #include "Shortcut.h" | ||||
| #include "../renderSDL/SDL_Extensions.h" | ||||
| #include "../windows/CMessage.h" | ||||
| #include "../CMT.h" | ||||
| @@ -305,28 +306,23 @@ const Rect & CIntObject::center(const Point & p, bool propagate) | ||||
| 	return pos; | ||||
| } | ||||
|  | ||||
| bool CIntObject::captureThisKey(const SDL_Keycode & key) | ||||
| bool CIntObject::captureThisKey(EShortcut key) | ||||
| { | ||||
| 	return captureAllKeys; | ||||
| } | ||||
|  | ||||
| CKeyShortcut::CKeyShortcut() | ||||
| 	: assignedKey(EShortcut::NONE) | ||||
| {} | ||||
|  | ||||
| CKeyShortcut::CKeyShortcut(int key) | ||||
| CKeyShortcut::CKeyShortcut(EShortcut key) | ||||
| 	: assignedKey(key) | ||||
| { | ||||
| 	if (key != SDLK_UNKNOWN) | ||||
| 		assignedKeys.insert(key); | ||||
| } | ||||
|  | ||||
| CKeyShortcut::CKeyShortcut(std::set<int> Keys) | ||||
| 	:assignedKeys(Keys) | ||||
| {} | ||||
|  | ||||
| void CKeyShortcut::keyPressed(const SDL_Keycode & key) | ||||
| void CKeyShortcut::keyPressed(EShortcut key) | ||||
| { | ||||
| 	if(vstd::contains(assignedKeys,key) | ||||
| 	 || vstd::contains(assignedKeys, CGuiHandler::numToDigit(key))) | ||||
| 	if( assignedKey == key && assignedKey != EShortcut::NONE) | ||||
| 	{ | ||||
| 		bool prev = mouseState(MouseButton::LEFT); | ||||
| 		updateMouseState(MouseButton::LEFT, true); | ||||
| @@ -335,10 +331,9 @@ void CKeyShortcut::keyPressed(const SDL_Keycode & key) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CKeyShortcut::keyReleased(const SDL_Keycode & key) | ||||
| void CKeyShortcut::keyReleased(EShortcut key) | ||||
| { | ||||
| 	if(vstd::contains(assignedKeys,key) | ||||
| 	 || vstd::contains(assignedKeys, CGuiHandler::numToDigit(key))) | ||||
| 	if( assignedKey == key && assignedKey != EShortcut::NONE) | ||||
| 	{ | ||||
| 		bool prev = mouseState(MouseButton::LEFT); | ||||
| 		updateMouseState(MouseButton::LEFT, false); | ||||
|   | ||||
| @@ -16,8 +16,7 @@ | ||||
| struct SDL_Surface; | ||||
| class CGuiHandler; | ||||
| class CPicture; | ||||
|  | ||||
| using SDL_Keycode = int32_t; | ||||
| enum class EShortcut; | ||||
|  | ||||
| using boost::logic::tribool; | ||||
|  | ||||
| @@ -111,9 +110,9 @@ public: | ||||
|  | ||||
| 	//keyboard handling | ||||
| 	bool captureAllKeys; //if true, only this object should get info about pressed keys | ||||
| 	virtual void keyPressed(const SDL_Keycode & key){} | ||||
| 	virtual void keyReleased(const SDL_Keycode & key){} | ||||
| 	virtual bool captureThisKey(const SDL_Keycode & key); //allows refining captureAllKeys against specific events (eg. don't capture ENTER) | ||||
| 	virtual void keyPressed(EShortcut key){} | ||||
| 	virtual void keyReleased(EShortcut key){} | ||||
| 	virtual bool captureThisKey(EShortcut key); //allows refining captureAllKeys against specific events (eg. don't capture ENTER) | ||||
|  | ||||
| 	virtual void textInputed(const std::string & enteredText){}; | ||||
| 	virtual void textEdited(const std::string & enteredText){}; | ||||
| @@ -190,12 +189,11 @@ public: | ||||
| class CKeyShortcut : public virtual CIntObject | ||||
| { | ||||
| public: | ||||
| 	std::set<int> assignedKeys; | ||||
| 	EShortcut assignedKey; | ||||
| 	CKeyShortcut(); | ||||
| 	CKeyShortcut(int key); | ||||
| 	CKeyShortcut(std::set<int> Keys); | ||||
| 	void keyPressed(const SDL_Keycode & key) override; | ||||
| 	void keyReleased(const SDL_Keycode & key) override; | ||||
| 	CKeyShortcut(EShortcut key); | ||||
| 	void keyPressed(EShortcut key) override; | ||||
| 	void keyReleased(EShortcut key) override; | ||||
|  | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -15,6 +15,8 @@ | ||||
| #include "../CGameInfo.h" | ||||
| #include "../CPlayerInterface.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/ShortcutHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| @@ -25,18 +27,6 @@ | ||||
|  | ||||
| #include "../../lib/CGeneralTextHandler.h" | ||||
|  | ||||
| static std::map<std::string, int> KeycodeMap{ | ||||
| 	{"up", SDLK_UP}, | ||||
| 	{"down", SDLK_DOWN}, | ||||
| 	{"left", SDLK_LEFT}, | ||||
| 	{"right", SDLK_RIGHT}, | ||||
| 	{"space", SDLK_SPACE}, | ||||
| 	{"escape", SDLK_ESCAPE}, | ||||
| 	{"backspace", SDLK_BACKSPACE}, | ||||
| 	{"enter", SDLK_RETURN} | ||||
| }; | ||||
|  | ||||
|  | ||||
| InterfaceObjectConfigurable::InterfaceObjectConfigurable(const JsonNode & config, int used, Point offset): | ||||
| 	InterfaceObjectConfigurable(used, offset) | ||||
| { | ||||
| @@ -211,27 +201,20 @@ std::pair<std::string, std::string> InterfaceObjectConfigurable::readHintText(co | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| int InterfaceObjectConfigurable::readKeycode(const JsonNode & config) const | ||||
| EShortcut InterfaceObjectConfigurable::readKeycode(const JsonNode & config) const | ||||
| { | ||||
| 	logGlobal->debug("Reading keycode"); | ||||
| 	if(config.getType() == JsonNode::JsonType::DATA_INTEGER) | ||||
| 		return config.Integer(); | ||||
| 	 | ||||
| 	if(config.getType() == JsonNode::JsonType::DATA_STRING) | ||||
|  | ||||
| 	if(config.getType() != JsonNode::JsonType::DATA_STRING) | ||||
| 	{ | ||||
| 		auto s = config.String(); | ||||
| 		if(s.size() == 1) //keyboard symbol | ||||
| 			return s[0]; | ||||
|  | ||||
| 		if (KeycodeMap.count(s)) | ||||
| 			return KeycodeMap[s]; | ||||
|  | ||||
| 		logGlobal->error("Invalid keycode '%s' in interface configuration!", config.String()); | ||||
| 		return SDLK_UNKNOWN; | ||||
| 		logGlobal->error("Invalid keycode format in interface configuration! Expected string!", config.String()); | ||||
| 		return EShortcut::NONE; | ||||
| 	} | ||||
|  | ||||
| 	logGlobal->error("Invalid keycode format in interface configuration! Expected string or integer!", config.String()); | ||||
| 	return SDLK_UNKNOWN; | ||||
| 	EShortcut result = GH.getShortcutsHandler().findShortcut(config.String()); | ||||
| 	if (result == EShortcut::NONE) | ||||
| 		logGlobal->error("Invalid keycode '%s' in interface configuration!", config.String()); | ||||
| 	return result;; | ||||
| } | ||||
|  | ||||
| std::shared_ptr<CPicture> InterfaceObjectConfigurable::buildPicture(const JsonNode & config) const | ||||
| @@ -340,13 +323,8 @@ std::shared_ptr<CButton> InterfaceObjectConfigurable::buildButton(const JsonNode | ||||
| 		button->addCallback(std::bind(callbacks.at(config["callback"].String()), 0)); | ||||
| 	if(!config["hotkey"].isNull()) | ||||
| 	{ | ||||
| 		if(config["hotkey"].getType() == JsonNode::JsonType::DATA_VECTOR) | ||||
| 		{ | ||||
| 			for(auto k : config["hotkey"].Vector()) | ||||
| 				button->assignedKeys.insert(readKeycode(k)); | ||||
| 		} | ||||
| 		else | ||||
| 			button->assignedKeys.insert(readKeycode(config["hotkey"])); | ||||
| 		if(config["hotkey"].getType() == JsonNode::JsonType::DATA_STRING) | ||||
| 			button->assignedKey = readKeycode(config["hotkey"]); | ||||
| 	} | ||||
| 	return button; | ||||
| } | ||||
|   | ||||
| @@ -64,7 +64,7 @@ protected: | ||||
| 	EFonts readFont(const JsonNode &) const; | ||||
| 	std::string readText(const JsonNode &) const; | ||||
| 	std::pair<std::string, std::string> readHintText(const JsonNode &) const; | ||||
| 	int readKeycode(const JsonNode &) const; | ||||
| 	EShortcut readKeycode(const JsonNode &) const; | ||||
| 	 | ||||
| 	//basic widgets | ||||
| 	std::shared_ptr<CPicture> buildPicture(const JsonNode &) const; | ||||
|   | ||||
							
								
								
									
										140
									
								
								client/gui/Shortcut.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								client/gui/Shortcut.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | ||||
| /* | ||||
|  * Shortcut.h, part of VCMI engine | ||||
|  * | ||||
|  * Authors: listed in file AUTHORS in main folder | ||||
|  * | ||||
|  * License: GNU General Public License v2.0 or later | ||||
|  * Full text of license available in license.txt file, in main folder | ||||
|  * | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| enum class EShortcut | ||||
| { | ||||
| 	NONE, | ||||
|  | ||||
| 	GLOBAL_CONFIRM,    // Enter | ||||
| 	GLOBAL_CANCEL,     // Escape | ||||
| 	GLOBAL_RETURN,     // Enter, Escape | ||||
| 	GLOBAL_FULLSCREEN, // F4 | ||||
| 	GLOBAL_OPTIONS, | ||||
| 	GLOBAL_BACKSPACE, | ||||
| 	GLOBAL_MOVE_FOCUS, | ||||
|  | ||||
| 	SELECT_LEFT, | ||||
| 	SELECT_RIGHT, | ||||
| 	SELECT_UP, | ||||
| 	SELECT_DOWN, | ||||
| 	SELECT_FIRST, | ||||
| 	SELECT_LAST, | ||||
| 	SELECT_PAGE_UP, | ||||
| 	SELECT_PAGE_DOWN, | ||||
|  | ||||
| 	SELECT_INDEX_1, | ||||
| 	SELECT_INDEX_2, | ||||
| 	SELECT_INDEX_3, | ||||
| 	SELECT_INDEX_4, | ||||
| 	SELECT_INDEX_5, | ||||
| 	SELECT_INDEX_6, | ||||
| 	SELECT_INDEX_7, | ||||
| 	SELECT_INDEX_8, | ||||
|  | ||||
| 	MAIN_MENU_NEW, | ||||
| 	MAIN_MENU_LOAD, | ||||
| 	MAIN_MENU_SCORES, | ||||
| 	MAIN_MENU_CREDITS, | ||||
| 	MAIN_MENU_BACK, | ||||
| 	MAIN_MENU_QUIT, | ||||
| 	MAIN_MENU_SINGLEPLAYER, | ||||
| 	MAIN_MENU_MULTIPLAYER, | ||||
| 	MAIN_MENU_CAMPAIGN, | ||||
| 	MAIN_MENU_TUTORIAL, | ||||
| 	MAIN_MENU_CAMPAIGN_SOD, | ||||
| 	MAIN_MENU_CAMPAIGN_ROE, | ||||
| 	MAIN_MENU_CAMPAIGN_AB, | ||||
| 	MAIN_MENU_CAMPAIGN_CUSTOM, | ||||
|  | ||||
| 	LOBBY_BEGIN_GAME, // b, Return | ||||
| 	LOBBY_LOAD_GAME,  // l, Return | ||||
| 	LOBBY_SAVE_GAME,  // s, Return | ||||
| 	LOBBY_RANDOM_MAP, | ||||
| 	LOBBY_HIDE_CHAT, | ||||
| 	LOBBY_ADDITIONAL_OPTIONS, | ||||
| 	LOBBY_SELECT, | ||||
|  | ||||
| 	GAME_END_TURN, | ||||
| 	GAME_LOAD_GAME, | ||||
| 	GAME_SAVE_GAME, | ||||
| 	GAME_RESTART_GAME, | ||||
| 	GAME_TO_MAIN_MENU, | ||||
| 	GAME_QUIT_GAME, | ||||
| 	GAME_MARKETPLACE, | ||||
| 	GAME_THIEVES_GUILD, | ||||
| 	GAME_ACTIVATE_CONSOLE, | ||||
|  | ||||
| 	ADVENTURE_OPTIONS, | ||||
| 	ADVENTURE_TOGGLE_GRID, | ||||
| 	ADVENTURE_TOGGLE_SLEEP, | ||||
| 	ADVENTURE_MOVE_HERO, | ||||
| 	ADVENTURE_VISIT_OBJECT, | ||||
| 	ADVENTURE_MOVE_HERO_SW, | ||||
| 	ADVENTURE_MOVE_HERO_SS, | ||||
| 	ADVENTURE_MOVE_HERO_SE, | ||||
| 	ADVENTURE_MOVE_HERO_WW, | ||||
| 	ADVENTURE_MOVE_HERO_EE, | ||||
| 	ADVENTURE_MOVE_HERO_NW, | ||||
| 	ADVENTURE_MOVE_HERO_NN, | ||||
| 	ADVENTURE_MOVE_HERO_NE, | ||||
| 	ADVENTURE_VIEW_SELECTED, | ||||
| 	ADVENTURE_NEXT_OBJECT, | ||||
| 	ADVENTURE_NEXT_TOWN, | ||||
| 	ADVENTURE_NEXT_HERO, | ||||
| 	ADVENTURE_FIRST_TOWN, | ||||
| 	ADVENTURE_FIRST_HERO, | ||||
| 	ADVENTURE_VIEW_SCENARIO, | ||||
| 	ADVENTURE_DIG_GRAIL, | ||||
| 	ADVENTURE_VIEW_PUZZLE, | ||||
| 	ADVENTURE_VIEW_WORLD, | ||||
| 	ADVENTURE_TOGGLE_MAP_LEVEL, | ||||
| 	ADVENTURE_KINGDOM_OVERVIEW, | ||||
| 	ADVENTURE_QUEST_LOG, | ||||
| 	ADVENTURE_CAST_SPELL, | ||||
| 	ADVENTURE_END_TURN, | ||||
| 	ADVENTURE_THIEVES_GUILD, | ||||
|  | ||||
| 	BATTLE_TOGGLE_QUEUE, | ||||
| 	BATTLE_USE_CREATURE_SPELL, | ||||
| 	BATTLE_SURRENDER, | ||||
| 	BATTLE_RETREAT, | ||||
| 	BATTLE_AUTOCOMBAT, | ||||
| 	BATTLE_CAST_SPELL, | ||||
| 	BATTLE_WAIT, | ||||
| 	BATTLE_DEFEND, | ||||
| 	BATTLE_CONSOLE_UP, | ||||
| 	BATTLE_CONSOLE_DOWN, | ||||
| 	BATTLE_TACTICS_NEXT, | ||||
| 	BATTLE_TACTICS_END, | ||||
|  | ||||
| 	TOWN_OPEN_TAVERN, | ||||
| 	TOWN_SWAP_ARMIES, | ||||
|  | ||||
| 	RECRUITMENT_MAX, | ||||
| 	RECRUITMENT_MIN, | ||||
| 	RECRUITMENT_UPGRADE, // U | ||||
| 	RECRUITMENT_UPGRADE_ALL, // A, U | ||||
|  | ||||
| 	KINGDOM_HEROES, | ||||
| 	KINGDOM_TOWNS, | ||||
|  | ||||
| 	HERO_DISMISS, | ||||
| 	HERO_COMMANDER, | ||||
| 	HERO_LOOSE_FORMATION, | ||||
| 	HERO_TIGHT_FORMATION, | ||||
| 	HERO_TOGGLE_TACTICS, // b | ||||
|  | ||||
| 	SPELLBOOK_TAB_ADVENTURE, | ||||
| 	SPELLBOOK_TAB_COMBAT, | ||||
|  | ||||
| 	AFTER_LAST | ||||
| }; | ||||
|  | ||||
							
								
								
									
										356
									
								
								client/gui/ShortcutHandler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										356
									
								
								client/gui/ShortcutHandler.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,356 @@ | ||||
| /* | ||||
|  * ShortcutHandler.cpp, part of VCMI engine | ||||
|  * | ||||
|  * Authors: listed in file AUTHORS in main folder | ||||
|  * | ||||
|  * License: GNU General Public License v2.0 or later | ||||
|  * Full text of license available in license.txt file, in main folder | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "StdInc.h" | ||||
|  | ||||
| #include "ShortcutHandler.h" | ||||
| #include "Shortcut.h" | ||||
| #include <SDL_keycode.h> | ||||
|  | ||||
| std::vector<EShortcut> ShortcutHandler::translateKeycode(SDL_Keycode key) | ||||
| { | ||||
| 	static const std::multimap<SDL_Keycode, EShortcut> keyToShortcut = { | ||||
| 		{SDLK_RETURN,    EShortcut::GLOBAL_CONFIRM            }, | ||||
| 		{SDLK_KP_ENTER,  EShortcut::GLOBAL_CONFIRM            }, | ||||
| 		{SDLK_ESCAPE,    EShortcut::GLOBAL_CANCEL             }, | ||||
| 		{SDLK_RETURN,    EShortcut::GLOBAL_RETURN             }, | ||||
| 		{SDLK_KP_ENTER,  EShortcut::GLOBAL_RETURN             }, | ||||
| 		{SDLK_ESCAPE,    EShortcut::GLOBAL_RETURN             }, | ||||
| 		{SDLK_F4,        EShortcut::GLOBAL_FULLSCREEN         }, | ||||
| 		{SDLK_BACKSPACE, EShortcut::GLOBAL_BACKSPACE          }, | ||||
| 		{SDLK_TAB,       EShortcut::GLOBAL_MOVE_FOCUS         }, | ||||
| 		{SDLK_o,         EShortcut::GLOBAL_OPTIONS            }, | ||||
| 		{SDLK_LEFT,      EShortcut::SELECT_LEFT               }, | ||||
| 		{SDLK_RIGHT,     EShortcut::SELECT_RIGHT              }, | ||||
| 		{SDLK_UP,        EShortcut::SELECT_UP                 }, | ||||
| 		{SDLK_DOWN,      EShortcut::SELECT_DOWN               }, | ||||
| 		{SDLK_HOME,      EShortcut::SELECT_FIRST              }, | ||||
| 		{SDLK_END,       EShortcut::SELECT_LAST               }, | ||||
| 		{SDLK_PAGEUP,    EShortcut::SELECT_PAGE_UP            }, | ||||
| 		{SDLK_PAGEDOWN,  EShortcut::SELECT_PAGE_DOWN          }, | ||||
| 		{SDLK_1,         EShortcut::SELECT_INDEX_1            }, | ||||
| 		{SDLK_2,         EShortcut::SELECT_INDEX_2            }, | ||||
| 		{SDLK_3,         EShortcut::SELECT_INDEX_3            }, | ||||
| 		{SDLK_4,         EShortcut::SELECT_INDEX_4            }, | ||||
| 		{SDLK_5,         EShortcut::SELECT_INDEX_5            }, | ||||
| 		{SDLK_6,         EShortcut::SELECT_INDEX_6            }, | ||||
| 		{SDLK_7,         EShortcut::SELECT_INDEX_7            }, | ||||
| 		{SDLK_8,         EShortcut::SELECT_INDEX_8            }, | ||||
| 		{SDLK_n,         EShortcut::MAIN_MENU_NEW             }, | ||||
| 		{SDLK_l,         EShortcut::MAIN_MENU_LOAD            }, | ||||
| 		{SDLK_h,         EShortcut::MAIN_MENU_SCORES          }, | ||||
| 		{SDLK_c,         EShortcut::MAIN_MENU_CREDITS         }, | ||||
| 		{SDLK_q,         EShortcut::MAIN_MENU_QUIT            }, | ||||
| 		{SDLK_b,         EShortcut::MAIN_MENU_BACK            }, | ||||
| 		{SDLK_s,         EShortcut::MAIN_MENU_SINGLEPLAYER    }, | ||||
| 		{SDLK_m,         EShortcut::MAIN_MENU_MULTIPLAYER     }, | ||||
| 		{SDLK_c,         EShortcut::MAIN_MENU_CAMPAIGN        }, | ||||
| 		{SDLK_t,         EShortcut::MAIN_MENU_TUTORIAL        }, | ||||
| 		{SDLK_s,         EShortcut::MAIN_MENU_CAMPAIGN_SOD    }, | ||||
| 		{SDLK_r,         EShortcut::MAIN_MENU_CAMPAIGN_ROE    }, | ||||
| 		{SDLK_a,         EShortcut::MAIN_MENU_CAMPAIGN_AB     }, | ||||
| 		{SDLK_c,         EShortcut::MAIN_MENU_CAMPAIGN_CUSTOM }, | ||||
| 		{SDLK_b,         EShortcut::LOBBY_BEGIN_GAME          }, | ||||
| 		{SDLK_RETURN,    EShortcut::LOBBY_BEGIN_GAME          }, | ||||
| 		{SDLK_KP_ENTER,  EShortcut::LOBBY_BEGIN_GAME          }, | ||||
| 		{SDLK_l,         EShortcut::LOBBY_LOAD_GAME           }, | ||||
| 		{SDLK_RETURN,    EShortcut::LOBBY_LOAD_GAME           }, | ||||
| 		{SDLK_KP_ENTER,  EShortcut::LOBBY_LOAD_GAME           }, | ||||
| 		{SDLK_s,         EShortcut::LOBBY_SAVE_GAME           }, | ||||
| 		{SDLK_r,         EShortcut::LOBBY_RANDOM_MAP          }, | ||||
| 		{SDLK_h,         EShortcut::LOBBY_HIDE_CHAT           }, | ||||
| 		{SDLK_a,         EShortcut::LOBBY_ADDITIONAL_OPTIONS  }, | ||||
| 		{SDLK_s,         EShortcut::LOBBY_SELECT              }, | ||||
| 		{SDLK_e,         EShortcut::GAME_END_TURN             }, | ||||
| 		{SDLK_l,         EShortcut::GAME_LOAD_GAME            }, | ||||
| 		{SDLK_s,         EShortcut::GAME_SAVE_GAME            }, | ||||
| 		{SDLK_r,         EShortcut::GAME_RESTART_GAME         }, | ||||
| 		{SDLK_m,         EShortcut::GAME_TO_MAIN_MENU         }, | ||||
| 		{SDLK_q,         EShortcut::GAME_QUIT_GAME            }, | ||||
| 		{SDLK_t,         EShortcut::GAME_MARKETPLACE          }, | ||||
| 		{SDLK_g,         EShortcut::GAME_THIEVES_GUILD        }, | ||||
| 		{SDLK_TAB,       EShortcut::GAME_ACTIVATE_CONSOLE     }, | ||||
| 		{SDLK_o,         EShortcut::ADVENTURE_OPTIONS         }, | ||||
| 		{SDLK_F6,        EShortcut::ADVENTURE_TOGGLE_GRID     }, | ||||
| 		{SDLK_z,         EShortcut::ADVENTURE_TOGGLE_SLEEP    }, | ||||
| 		{SDLK_w,         EShortcut::ADVENTURE_TOGGLE_SLEEP    }, | ||||
| 		{SDLK_m,         EShortcut::ADVENTURE_MOVE_HERO       }, | ||||
| 		{SDLK_SPACE,     EShortcut::ADVENTURE_VISIT_OBJECT    }, | ||||
| 		{SDLK_KP_1,      EShortcut::ADVENTURE_MOVE_HERO_SW    }, | ||||
| 		{SDLK_KP_2,      EShortcut::ADVENTURE_MOVE_HERO_SS    }, | ||||
| 		{SDLK_KP_3,      EShortcut::ADVENTURE_MOVE_HERO_SE    }, | ||||
| 		{SDLK_KP_4,      EShortcut::ADVENTURE_MOVE_HERO_WW    }, | ||||
| 		{SDLK_KP_6,      EShortcut::ADVENTURE_MOVE_HERO_EE    }, | ||||
| 		{SDLK_KP_7,      EShortcut::ADVENTURE_MOVE_HERO_NW    }, | ||||
| 		{SDLK_KP_8,      EShortcut::ADVENTURE_MOVE_HERO_NN    }, | ||||
| 		{SDLK_KP_9,      EShortcut::ADVENTURE_MOVE_HERO_NE    }, | ||||
| 		{SDLK_RETURN,    EShortcut::ADVENTURE_VIEW_SELECTED   }, | ||||
| 		{SDLK_KP_ENTER,  EShortcut::ADVENTURE_VIEW_SELECTED   }, | ||||
|  //		{SDLK_,          EShortcut::ADVENTURE_NEXT_OBJECT     }, | ||||
| 		{SDLK_t,         EShortcut::ADVENTURE_NEXT_TOWN       }, | ||||
| 		{SDLK_h,         EShortcut::ADVENTURE_NEXT_HERO       }, | ||||
|  //		{SDLK_,          EShortcut::ADVENTURE_FIRST_TOWN      }, | ||||
|   //		{SDLK_,          EShortcut::ADVENTURE_FIRST_HERO      }, | ||||
| 		{SDLK_i,         EShortcut::ADVENTURE_VIEW_SCENARIO   }, | ||||
| 		{SDLK_d,         EShortcut::ADVENTURE_DIG_GRAIL       }, | ||||
| 		{SDLK_p,         EShortcut::ADVENTURE_VIEW_PUZZLE     }, | ||||
| 		{SDLK_v,         EShortcut::ADVENTURE_VIEW_WORLD      }, | ||||
| 		{SDLK_u,         EShortcut::ADVENTURE_TOGGLE_MAP_LEVEL}, | ||||
| 		{SDLK_k,         EShortcut::ADVENTURE_KINGDOM_OVERVIEW}, | ||||
| 		{SDLK_q,         EShortcut::ADVENTURE_QUEST_LOG       }, | ||||
| 		{SDLK_c,         EShortcut::ADVENTURE_CAST_SPELL      }, | ||||
| 		{SDLK_e,         EShortcut::ADVENTURE_END_TURN        }, | ||||
| 		{SDLK_g,         EShortcut::ADVENTURE_THIEVES_GUILD   }, | ||||
| 		{SDLK_q,         EShortcut::BATTLE_TOGGLE_QUEUE       }, | ||||
| 		{SDLK_c,         EShortcut::BATTLE_USE_CREATURE_SPELL }, | ||||
| 		{SDLK_s,         EShortcut::BATTLE_SURRENDER          }, | ||||
| 		{SDLK_r,         EShortcut::BATTLE_RETREAT            }, | ||||
| 		{SDLK_a,         EShortcut::BATTLE_AUTOCOMBAT         }, | ||||
| 		{SDLK_c,         EShortcut::BATTLE_CAST_SPELL         }, | ||||
| 		{SDLK_w,         EShortcut::BATTLE_WAIT               }, | ||||
| 		{SDLK_d,         EShortcut::BATTLE_DEFEND             }, | ||||
| 		{SDLK_SPACE,     EShortcut::BATTLE_DEFEND             }, | ||||
| 		{SDLK_UP,        EShortcut::BATTLE_CONSOLE_UP         }, | ||||
| 		{SDLK_DOWN,      EShortcut::BATTLE_CONSOLE_DOWN       }, | ||||
| 		{SDLK_SPACE,     EShortcut::BATTLE_TACTICS_NEXT       }, | ||||
| 		{SDLK_RETURN,    EShortcut::BATTLE_TACTICS_END        }, | ||||
| 		{SDLK_KP_ENTER,  EShortcut::BATTLE_TACTICS_END        }, | ||||
| 		{SDLK_t,         EShortcut::TOWN_OPEN_TAVERN          }, | ||||
| 		{SDLK_SPACE,     EShortcut::TOWN_SWAP_ARMIES          }, | ||||
| 		{SDLK_END,       EShortcut::RECRUITMENT_MAX           }, | ||||
| 		{SDLK_HOME,      EShortcut::RECRUITMENT_MIN           }, | ||||
| 		{SDLK_u,         EShortcut::RECRUITMENT_UPGRADE       }, | ||||
| 		{SDLK_a,         EShortcut::RECRUITMENT_UPGRADE_ALL   }, | ||||
| 		{SDLK_u,         EShortcut::RECRUITMENT_UPGRADE_ALL   }, | ||||
| 		{SDLK_h,         EShortcut::KINGDOM_HEROES            }, | ||||
| 		{SDLK_t,         EShortcut::KINGDOM_TOWNS             }, | ||||
| 		{SDLK_d,         EShortcut::HERO_DISMISS              }, | ||||
| 		{SDLK_c,         EShortcut::HERO_COMMANDER            }, | ||||
| 		{SDLK_l,         EShortcut::HERO_LOOSE_FORMATION      }, | ||||
| 		{SDLK_t,         EShortcut::HERO_TIGHT_FORMATION      }, | ||||
| 		{SDLK_b,         EShortcut::HERO_TOGGLE_TACTICS       }, | ||||
| 		{SDLK_a,         EShortcut::SPELLBOOK_TAB_ADVENTURE   }, | ||||
| 		{SDLK_c,         EShortcut::SPELLBOOK_TAB_COMBAT      } | ||||
| 	}; | ||||
|  | ||||
| 	auto range = keyToShortcut.equal_range(key); | ||||
|  | ||||
| 	// FIXME: some code expects calls to keyPressed / captureThisKey even without defined hotkeys | ||||
| 	if (range.first == range.second) | ||||
| 		return {EShortcut::NONE}; | ||||
|  | ||||
| 	std::vector<EShortcut> result; | ||||
|  | ||||
| 	for (auto it = range.first; it != range.second; ++it) | ||||
| 		result.push_back(it->second); | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| EShortcut ShortcutHandler::findShortcut(const std::string & identifier ) | ||||
| { | ||||
| 	static const std::map<std::string, EShortcut> shortcutNames = { | ||||
| 		{"globalConfirm",            EShortcut::GLOBAL_CONFIRM            }, | ||||
| 		{"globalCancel",             EShortcut::GLOBAL_CANCEL             }, | ||||
| 		{"globalReturn",             EShortcut::GLOBAL_RETURN             }, | ||||
| 		{"globalFullscreen",         EShortcut::GLOBAL_FULLSCREEN         }, | ||||
| 		{"globalOptions",            EShortcut::GLOBAL_OPTIONS            }, | ||||
| 		{"globalBackspace",          EShortcut::GLOBAL_BACKSPACE          }, | ||||
| 		{"globalMoveFocus",          EShortcut::GLOBAL_MOVE_FOCUS         }, | ||||
| 		{"selectLeft",               EShortcut::SELECT_LEFT               }, | ||||
| 		{"selectRight",              EShortcut::SELECT_RIGHT              }, | ||||
| 		{"selectUp",                 EShortcut::SELECT_UP                 }, | ||||
| 		{"selectDown",               EShortcut::SELECT_DOWN               }, | ||||
| 		{"selectFirst",              EShortcut::SELECT_FIRST              }, | ||||
| 		{"selectLast",               EShortcut::SELECT_LAST               }, | ||||
| 		{"selectPageUp",             EShortcut::SELECT_PAGE_UP            }, | ||||
| 		{"selectPageDown",           EShortcut::SELECT_PAGE_DOWN          }, | ||||
| 		{"selectIndex1",             EShortcut::SELECT_INDEX_1            }, | ||||
| 		{"selectIndex2",             EShortcut::SELECT_INDEX_2            }, | ||||
| 		{"selectIndex3",             EShortcut::SELECT_INDEX_3            }, | ||||
| 		{"selectIndex4",             EShortcut::SELECT_INDEX_4            }, | ||||
| 		{"selectIndex5",             EShortcut::SELECT_INDEX_5            }, | ||||
| 		{"selectIndex6",             EShortcut::SELECT_INDEX_6            }, | ||||
| 		{"selectIndex7",             EShortcut::SELECT_INDEX_7            }, | ||||
| 		{"selectIndex8",             EShortcut::SELECT_INDEX_8            }, | ||||
| 		{"mainMenuNew",              EShortcut::MAIN_MENU_NEW             }, | ||||
| 		{"mainMenuLoad",             EShortcut::MAIN_MENU_LOAD            }, | ||||
| 		{"mainMenuScores",           EShortcut::MAIN_MENU_SCORES          }, | ||||
| 		{"mainMenuCredits",          EShortcut::MAIN_MENU_CREDITS         }, | ||||
| 		{"mainMenuQuit",             EShortcut::MAIN_MENU_QUIT            }, | ||||
| 		{"mainMenuBack",             EShortcut::MAIN_MENU_BACK            }, | ||||
| 		{"mainMenuSingleplayer",     EShortcut::MAIN_MENU_SINGLEPLAYER    }, | ||||
| 		{"mainMenuMultiplayer",      EShortcut::MAIN_MENU_MULTIPLAYER     }, | ||||
| 		{"mainMenuCampaign",         EShortcut::MAIN_MENU_CAMPAIGN        }, | ||||
| 		{"mainMenuTutorial",         EShortcut::MAIN_MENU_TUTORIAL        }, | ||||
| 		{"mainMenuCampaignSod",      EShortcut::MAIN_MENU_CAMPAIGN_SOD    }, | ||||
| 		{"mainMenuCampaignRoe",      EShortcut::MAIN_MENU_CAMPAIGN_ROE    }, | ||||
| 		{"mainMenuCampaignAb",       EShortcut::MAIN_MENU_CAMPAIGN_AB     }, | ||||
| 		{"mainMenuCampaignCustom",   EShortcut::MAIN_MENU_CAMPAIGN_CUSTOM }, | ||||
| 		{"lobbyBeginGame",           EShortcut::LOBBY_BEGIN_GAME          }, | ||||
| 		{"lobbyLoadGame",            EShortcut::LOBBY_LOAD_GAME           }, | ||||
| 		{"lobbySaveGame",            EShortcut::LOBBY_SAVE_GAME           }, | ||||
| 		{"lobbyRandomMap",           EShortcut::LOBBY_RANDOM_MAP          }, | ||||
| 		{"lobbyHideChat",            EShortcut::LOBBY_HIDE_CHAT           }, | ||||
| 		{"lobbyAdditionalOptions",   EShortcut::LOBBY_ADDITIONAL_OPTIONS  }, | ||||
| 		{"lobbySelect",              EShortcut::LOBBY_SELECT              }, | ||||
| 		{"gameEndTurn",              EShortcut::GAME_END_TURN             }, | ||||
| 		{"gameLoadGame",             EShortcut::GAME_LOAD_GAME            }, | ||||
| 		{"gameSaveGame",             EShortcut::GAME_SAVE_GAME            }, | ||||
| 		{"gameRestartGame",          EShortcut::GAME_RESTART_GAME         }, | ||||
| 		{"gameMainMenu",             EShortcut::GAME_TO_MAIN_MENU         }, | ||||
| 		{"gameQuitGame",             EShortcut::GAME_QUIT_GAME            }, | ||||
| 		{"gameMarketplace",          EShortcut::GAME_MARKETPLACE          }, | ||||
| 		{"gameThievesGuild",         EShortcut::GAME_THIEVES_GUILD        }, | ||||
| 		{"gameActivateConsole",      EShortcut::GAME_ACTIVATE_CONSOLE     }, | ||||
| 		{"adventureOptions",         EShortcut::ADVENTURE_OPTIONS         }, | ||||
| 		{"adventureToggleGrid",      EShortcut::ADVENTURE_TOGGLE_GRID     }, | ||||
| 		{"adventureToggleSleep",     EShortcut::ADVENTURE_TOGGLE_SLEEP    }, | ||||
| 		{"adventureMoveHero",        EShortcut::ADVENTURE_MOVE_HERO       }, | ||||
| 		{"adventureVisitObject",     EShortcut::ADVENTURE_VISIT_OBJECT    }, | ||||
| 		{"adventureMoveHeroSW",      EShortcut::ADVENTURE_MOVE_HERO_SW    }, | ||||
| 		{"adventureMoveHeroSS",      EShortcut::ADVENTURE_MOVE_HERO_SS    }, | ||||
| 		{"adventureMoveHeroSE",      EShortcut::ADVENTURE_MOVE_HERO_SE    }, | ||||
| 		{"adventureMoveHeroWW",      EShortcut::ADVENTURE_MOVE_HERO_WW    }, | ||||
| 		{"adventureMoveHeroEE",      EShortcut::ADVENTURE_MOVE_HERO_EE    }, | ||||
| 		{"adventureMoveHeroNW",      EShortcut::ADVENTURE_MOVE_HERO_NW    }, | ||||
| 		{"adventureMoveHeroNN",      EShortcut::ADVENTURE_MOVE_HERO_NN    }, | ||||
| 		{"adventureMoveHeroNE",      EShortcut::ADVENTURE_MOVE_HERO_NE    }, | ||||
| 		{"adventureViewSelected",    EShortcut::ADVENTURE_VIEW_SELECTED   }, | ||||
| 		{"adventureNextObject",      EShortcut::ADVENTURE_NEXT_OBJECT     }, | ||||
| 		{"adventureNextTown",        EShortcut::ADVENTURE_NEXT_TOWN       }, | ||||
| 		{"adventureNextHero",        EShortcut::ADVENTURE_NEXT_HERO       }, | ||||
| 		{"adventureFirstTown",       EShortcut::ADVENTURE_FIRST_TOWN      }, | ||||
| 		{"adventureFirstHero",       EShortcut::ADVENTURE_FIRST_HERO      }, | ||||
| 		{"adventureViewScenario",    EShortcut::ADVENTURE_VIEW_SCENARIO   }, | ||||
| 		{"adventureDigGrail",        EShortcut::ADVENTURE_DIG_GRAIL       }, | ||||
| 		{"adventureViewPuzzle",      EShortcut::ADVENTURE_VIEW_PUZZLE     }, | ||||
| 		{"adventureViewWorld",       EShortcut::ADVENTURE_VIEW_WORLD      }, | ||||
| 		{"adventureToggleMapLevel",  EShortcut::ADVENTURE_TOGGLE_MAP_LEVEL}, | ||||
| 		{"adventureKingdomOverview", EShortcut::ADVENTURE_KINGDOM_OVERVIEW}, | ||||
| 		{"adventureQuestLog",        EShortcut::ADVENTURE_QUEST_LOG       }, | ||||
| 		{"adventureCastSpell",       EShortcut::ADVENTURE_CAST_SPELL      }, | ||||
| 		{"adventureEndTurn",         EShortcut::ADVENTURE_END_TURN        }, | ||||
| 		{"adventureThievesGuild",    EShortcut::ADVENTURE_THIEVES_GUILD   }, | ||||
| 		{"battleToggleQueue",        EShortcut::BATTLE_TOGGLE_QUEUE       }, | ||||
| 		{"battleUseCreatureSpell",   EShortcut::BATTLE_USE_CREATURE_SPELL }, | ||||
| 		{"battleSurrender",          EShortcut::BATTLE_SURRENDER          }, | ||||
| 		{"battleRetreat",            EShortcut::BATTLE_RETREAT            }, | ||||
| 		{"battleAutocombat",         EShortcut::BATTLE_AUTOCOMBAT         }, | ||||
| 		{"battleCastSpell",          EShortcut::BATTLE_CAST_SPELL         }, | ||||
| 		{"battleWait",               EShortcut::BATTLE_WAIT               }, | ||||
| 		{"battleDefend",             EShortcut::BATTLE_DEFEND             }, | ||||
| 		{"battleConsoleUp",          EShortcut::BATTLE_CONSOLE_UP         }, | ||||
| 		{"battleConsoleDown",        EShortcut::BATTLE_CONSOLE_DOWN       }, | ||||
| 		{"battleTacticsNext",        EShortcut::BATTLE_TACTICS_NEXT       }, | ||||
| 		{"battleTacticsEnd",         EShortcut::BATTLE_TACTICS_END        }, | ||||
| 		{"townOpenTavern",           EShortcut::TOWN_OPEN_TAVERN          }, | ||||
| 		{"townSwapArmies",           EShortcut::TOWN_SWAP_ARMIES          }, | ||||
| 		{"recruitmentMax",           EShortcut::RECRUITMENT_MAX           }, | ||||
| 		{"recruitmentMin",           EShortcut::RECRUITMENT_MIN           }, | ||||
| 		{"recruitmentUpgrade",       EShortcut::RECRUITMENT_UPGRADE       }, | ||||
| 		{"recruitmentUpgradeAll",    EShortcut::RECRUITMENT_UPGRADE_ALL   }, | ||||
| 		{"kingdomHeroes",            EShortcut::KINGDOM_HEROES            }, | ||||
| 		{"kingdomTowns",             EShortcut::KINGDOM_TOWNS             }, | ||||
| 		{"heroDismiss",              EShortcut::HERO_DISMISS              }, | ||||
| 		{"heroCommander",            EShortcut::HERO_COMMANDER            }, | ||||
| 		{"heroLooseFormation",       EShortcut::HERO_LOOSE_FORMATION      }, | ||||
| 		{"heroTightFormation",       EShortcut::HERO_TIGHT_FORMATION      }, | ||||
| 		{"heroToggleTactics",        EShortcut::HERO_TOGGLE_TACTICS       }, | ||||
| 		{"spellbookTabAdventure",    EShortcut::SPELLBOOK_TAB_ADVENTURE   }, | ||||
| 		{"spellbookTabCombat",       EShortcut::SPELLBOOK_TAB_COMBAT      } | ||||
| 	}; | ||||
|  | ||||
| 	if (shortcutNames.count(identifier)) | ||||
| 		return shortcutNames.at(identifier); | ||||
| 	return EShortcut::NONE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
							
								
								
									
										24
									
								
								client/gui/ShortcutHandler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								client/gui/ShortcutHandler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| /* | ||||
|  * ShortcutHandler.h, part of VCMI engine | ||||
|  * | ||||
|  * Authors: listed in file AUTHORS in main folder | ||||
|  * | ||||
|  * License: GNU General Public License v2.0 or later | ||||
|  * Full text of license available in license.txt file, in main folder | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| enum class EShortcut; | ||||
| using SDL_Keycode = int32_t; | ||||
|  | ||||
| class ShortcutHandler | ||||
| { | ||||
| public: | ||||
| 	/// returns list of shortcuts assigned to provided SDL keycode | ||||
| 	std::vector<EShortcut> translateKeycode(SDL_Keycode key); | ||||
|  | ||||
| 	/// attempts to find shortcut by its unique identifier. Returns EShortcut::NONE on failure | ||||
| 	EShortcut findShortcut(const std::string & identifier ); | ||||
| }; | ||||
| @@ -33,6 +33,7 @@ | ||||
| #include "../render/IImage.h" | ||||
| #include "../render/CAnimation.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
|  | ||||
| #include "../../lib/filesystem/Filesystem.h" | ||||
| #include "../../lib/CGeneralTextHandler.h" | ||||
| @@ -67,9 +68,9 @@ CBonusSelection::CBonusSelection() | ||||
|  | ||||
| 	panelBackground = std::make_shared<CPicture>("CAMPBRF.BMP", 456, 6); | ||||
|  | ||||
| 	buttonStart = std::make_shared<CButton>(Point(475, 536), "CBBEGIB.DEF", CButton::tooltip(), std::bind(&CBonusSelection::startMap, this), SDLK_RETURN); | ||||
| 	buttonRestart = std::make_shared<CButton>(Point(475, 536), "CBRESTB.DEF", CButton::tooltip(), std::bind(&CBonusSelection::restartMap, this), SDLK_RETURN); | ||||
| 	buttonBack = std::make_shared<CButton>(Point(624, 536), "CBCANCB.DEF", CButton::tooltip(), std::bind(&CBonusSelection::goBack, this), SDLK_ESCAPE); | ||||
| 	buttonStart = std::make_shared<CButton>(Point(475, 536), "CBBEGIB.DEF", CButton::tooltip(), std::bind(&CBonusSelection::startMap, this), EShortcut::GLOBAL_CONFIRM); | ||||
| 	buttonRestart = std::make_shared<CButton>(Point(475, 536), "CBRESTB.DEF", CButton::tooltip(), std::bind(&CBonusSelection::restartMap, this), EShortcut::GLOBAL_CONFIRM); | ||||
| 	buttonBack = std::make_shared<CButton>(Point(624, 536), "CBCANCB.DEF", CButton::tooltip(), std::bind(&CBonusSelection::goBack, this), EShortcut::GLOBAL_CANCEL); | ||||
|  | ||||
| 	campaignName = std::make_shared<CLabel>(481, 28, FONT_BIG, ETextAlignment::TOPLEFT, Colors::YELLOW, CSH->si->getCampaignName()); | ||||
|  | ||||
|   | ||||
| @@ -17,6 +17,7 @@ | ||||
| #include "../CServerHandler.h" | ||||
|  | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../windows/InfoWindows.h" | ||||
|  | ||||
| @@ -40,17 +41,17 @@ CLobbyScreen::CLobbyScreen(ESelectionScreen screenType) | ||||
| 	{ | ||||
| 		tabSel->callOnSelect = std::bind(&IServerAPI::setMapInfo, CSH, _1, nullptr); | ||||
|  | ||||
| 		buttonSelect = std::make_shared<CButton>(Point(411, 80), "GSPBUTT.DEF", CGI->generaltexth->zelp[45], 0, SDLK_s); | ||||
| 		buttonSelect = std::make_shared<CButton>(Point(411, 80), "GSPBUTT.DEF", CGI->generaltexth->zelp[45], 0, EShortcut::LOBBY_SELECT); | ||||
| 		buttonSelect->addCallback([&]() | ||||
| 		{ | ||||
| 			toggleTab(tabSel); | ||||
| 			CSH->setMapInfo(tabSel->getSelectedMapInfo()); | ||||
| 		}); | ||||
|  | ||||
| 		buttonOptions = std::make_shared<CButton>(Point(411, 510), "GSPBUTT.DEF", CGI->generaltexth->zelp[46], std::bind(&CLobbyScreen::toggleTab, this, tabOpt), SDLK_a); | ||||
| 		buttonOptions = std::make_shared<CButton>(Point(411, 510), "GSPBUTT.DEF", CGI->generaltexth->zelp[46], std::bind(&CLobbyScreen::toggleTab, this, tabOpt), EShortcut::LOBBY_ADDITIONAL_OPTIONS); | ||||
| 	}; | ||||
|  | ||||
| 	buttonChat = std::make_shared<CButton>(Point(619, 83), "GSPBUT2.DEF", CGI->generaltexth->zelp[48], std::bind(&CLobbyScreen::toggleChat, this), SDLK_h); | ||||
| 	buttonChat = std::make_shared<CButton>(Point(619, 83), "GSPBUT2.DEF", CGI->generaltexth->zelp[48], std::bind(&CLobbyScreen::toggleChat, this), EShortcut::LOBBY_HIDE_CHAT); | ||||
| 	buttonChat->addTextOverlay(CGI->generaltexth->allTexts[532], FONT_SMALL); | ||||
|  | ||||
| 	switch(screenType) | ||||
| @@ -60,7 +61,7 @@ CLobbyScreen::CLobbyScreen(ESelectionScreen screenType) | ||||
| 		tabOpt = std::make_shared<OptionsTab>(); | ||||
| 		tabRand = std::make_shared<RandomMapTab>(); | ||||
| 		tabRand->mapInfoChanged += std::bind(&IServerAPI::setMapInfo, CSH, _1, _2); | ||||
| 		buttonRMG = std::make_shared<CButton>(Point(411, 105), "GSPBUTT.DEF", CGI->generaltexth->zelp[47], 0, SDLK_r); | ||||
| 		buttonRMG = std::make_shared<CButton>(Point(411, 105), "GSPBUTT.DEF", CGI->generaltexth->zelp[47], 0, EShortcut::LOBBY_RANDOM_MAP); | ||||
| 		buttonRMG->addCallback([&]() | ||||
| 		{ | ||||
| 			toggleTab(tabRand); | ||||
| @@ -69,30 +70,28 @@ CLobbyScreen::CLobbyScreen(ESelectionScreen screenType) | ||||
|  | ||||
| 		card->iconDifficulty->addCallback(std::bind(&IServerAPI::setDifficulty, CSH, _1)); | ||||
|  | ||||
| 		buttonStart = std::make_shared<CButton>(Point(411, 535), "SCNRBEG.DEF", CGI->generaltexth->zelp[103], std::bind(&CLobbyScreen::startScenario, this, true), SDLK_b); | ||||
| 		buttonStart = std::make_shared<CButton>(Point(411, 535), "SCNRBEG.DEF", CGI->generaltexth->zelp[103], std::bind(&CLobbyScreen::startScenario, this, true), EShortcut::LOBBY_BEGIN_GAME); | ||||
| 		initLobby(); | ||||
| 		break; | ||||
| 	} | ||||
| 	case ESelectionScreen::loadGame: | ||||
| 	{ | ||||
| 		tabOpt = std::make_shared<OptionsTab>(); | ||||
| 		buttonStart = std::make_shared<CButton>(Point(411, 535), "SCNRLOD.DEF", CGI->generaltexth->zelp[103], std::bind(&CLobbyScreen::startScenario, this, true), SDLK_l); | ||||
| 		buttonStart = std::make_shared<CButton>(Point(411, 535), "SCNRLOD.DEF", CGI->generaltexth->zelp[103], std::bind(&CLobbyScreen::startScenario, this, true), EShortcut::LOBBY_LOAD_GAME); | ||||
| 		initLobby(); | ||||
| 		break; | ||||
| 	} | ||||
| 	case ESelectionScreen::campaignList: | ||||
| 		tabSel->callOnSelect = std::bind(&IServerAPI::setMapInfo, CSH, _1, nullptr); | ||||
| 		buttonStart = std::make_shared<CButton>(Point(411, 535), "SCNRLOD.DEF", CButton::tooltip(), std::bind(&CLobbyScreen::startCampaign, this), SDLK_b); | ||||
| 		buttonStart = std::make_shared<CButton>(Point(411, 535), "SCNRLOD.DEF", CButton::tooltip(), std::bind(&CLobbyScreen::startCampaign, this), EShortcut::LOBBY_BEGIN_GAME); | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	buttonStart->assignedKeys.insert(SDLK_RETURN); | ||||
|  | ||||
| 	buttonBack = std::make_shared<CButton>(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [&]() | ||||
| 	{ | ||||
| 		CSH->sendClientDisconnecting(); | ||||
| 		close(); | ||||
| 	}, SDLK_ESCAPE); | ||||
| 	}, EShortcut::GLOBAL_CANCEL); | ||||
| } | ||||
|  | ||||
| CLobbyScreen::~CLobbyScreen() | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| #include "../CGameInfo.h" | ||||
| #include "../CPlayerInterface.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/TextControls.h" | ||||
|  | ||||
| @@ -39,8 +40,7 @@ CSavingScreen::CSavingScreen() | ||||
| 	tabSel->toggleMode(); | ||||
|  | ||||
| 	tabSel->callOnSelect = std::bind(&CSavingScreen::changeSelection, this, _1); | ||||
| 	buttonStart = std::make_shared<CButton>(Point(411, 535), "SCNRSAV.DEF", CGI->generaltexth->zelp[103], std::bind(&CSavingScreen::saveGame, this), SDLK_s); | ||||
| 	buttonStart->assignedKeys.insert(SDLK_RETURN); | ||||
| 	buttonStart = std::make_shared<CButton>(Point(411, 535), "SCNRSAV.DEF", CGI->generaltexth->zelp[103], std::bind(&CSavingScreen::saveGame, this), EShortcut::LOBBY_SAVE_GAME); | ||||
| } | ||||
|  | ||||
| const CMapInfo * CSavingScreen::getMapInfo() | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| #include "../CGameInfo.h" | ||||
| #include "../CPlayerInterface.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../widgets/Buttons.h" | ||||
|  | ||||
| #include "../../CCallback.h" | ||||
| @@ -43,7 +44,7 @@ CScenarioInfoScreen::CScenarioInfoScreen() | ||||
| 	card->changeSelection(); | ||||
|  | ||||
| 	card->iconDifficulty->setSelected(getCurrentDifficulty()); | ||||
| 	buttonBack = std::make_shared<CButton>(Point(584, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [=](){ close();}, SDLK_ESCAPE); | ||||
| 	buttonBack = std::make_shared<CButton>(Point(584, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [=](){ close();}, EShortcut::GLOBAL_CANCEL); | ||||
| } | ||||
|  | ||||
| CScenarioInfoScreen::~CScenarioInfoScreen() | ||||
|   | ||||
| @@ -25,6 +25,7 @@ | ||||
| #include "../CPlayerInterface.h" | ||||
| #include "../CServerHandler.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../mainmenu/CMainMenu.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| @@ -84,7 +85,7 @@ CSelectionBase::CSelectionBase(ESelectionScreen type) | ||||
| 	} | ||||
| 	pos = background->center(); | ||||
| 	card = std::make_shared<InfoCard>(); | ||||
| 	buttonBack = std::make_shared<CButton>(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [=](){ close();}, SDLK_ESCAPE); | ||||
| 	buttonBack = std::make_shared<CButton>(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [=](){ close();}, EShortcut::GLOBAL_CANCEL); | ||||
| } | ||||
|  | ||||
| void CSelectionBase::toggleTab(std::shared_ptr<CIntObject> tab) | ||||
| @@ -318,9 +319,9 @@ CChatBox::CChatBox(const Rect & rect) | ||||
| 	chatHistory->label->color = Colors::GREEN; | ||||
| } | ||||
|  | ||||
| void CChatBox::keyPressed(const SDL_Keycode & key) | ||||
| void CChatBox::keyPressed(EShortcut key) | ||||
| { | ||||
| 	if(key == SDLK_RETURN && inputBox->getText().size()) | ||||
| 	if(key == EShortcut::GLOBAL_CONFIRM && inputBox->getText().size()) | ||||
| 	{ | ||||
| 		CSH->sendMessage(inputBox->getText()); | ||||
| 		inputBox->setText(""); | ||||
|   | ||||
| @@ -120,7 +120,7 @@ public: | ||||
|  | ||||
| 	CChatBox(const Rect & rect); | ||||
|  | ||||
| 	void keyPressed(const SDL_Keycode & key) override; | ||||
| 	void keyPressed(EShortcut key) override; | ||||
| 	void addNewMessage(const std::string & text); | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -17,6 +17,7 @@ | ||||
| #include "../CPlayerInterface.h" | ||||
| #include "../CServerHandler.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| @@ -281,27 +282,27 @@ void SelectionTab::clickLeft(tribool down, bool previousState) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void SelectionTab::keyPressed(const SDL_Keycode & key) | ||||
| void SelectionTab::keyPressed(EShortcut key) | ||||
| { | ||||
| 	int moveBy = 0; | ||||
| 	switch(key) | ||||
| 	{ | ||||
| 	case SDLK_UP: | ||||
| 	case EShortcut::SELECT_UP: | ||||
| 		moveBy = -1; | ||||
| 		break; | ||||
| 	case SDLK_DOWN: | ||||
| 	case EShortcut::SELECT_DOWN: | ||||
| 		moveBy = +1; | ||||
| 		break; | ||||
| 	case SDLK_PAGEUP: | ||||
| 	case EShortcut::SELECT_PAGE_UP: | ||||
| 		moveBy = -(int)listItems.size() + 1; | ||||
| 		break; | ||||
| 	case SDLK_PAGEDOWN: | ||||
| 	case EShortcut::SELECT_PAGE_DOWN: | ||||
| 		moveBy = +(int)listItems.size() - 1; | ||||
| 		break; | ||||
| 	case SDLK_HOME: | ||||
| 	case EShortcut::SELECT_FIRST: | ||||
| 		select(-slider->getValue()); | ||||
| 		return; | ||||
| 	case SDLK_END: | ||||
| 	case EShortcut::SELECT_LAST: | ||||
| 		select((int)curItems.size() - slider->getValue()); | ||||
| 		return; | ||||
| 	default: | ||||
|   | ||||
| @@ -66,7 +66,7 @@ public: | ||||
| 	void toggleMode(); | ||||
|  | ||||
| 	void clickLeft(tribool down, bool previousState) override; | ||||
| 	void keyPressed(const SDL_Keycode & key) override; | ||||
| 	void keyPressed(EShortcut key) override; | ||||
|  | ||||
| 	void onDoubleClick() override; | ||||
|  | ||||
|   | ||||
| @@ -19,6 +19,7 @@ | ||||
| #include "../CPlayerInterface.h" | ||||
| #include "../CServerHandler.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| @@ -77,7 +78,7 @@ std::shared_ptr<CButton> CCampaignScreen::createExitButton(const JsonNode & butt | ||||
| 	if(!button["help"].isNull() && button["help"].Float() > 0) | ||||
| 		help = CGI->generaltexth->zelp[(size_t)button["help"].Float()]; | ||||
|  | ||||
| 	return std::make_shared<CButton>(Point((int)button["x"].Float(), (int)button["y"].Float()), button["name"].String(), help, [=](){ close();}, (int)button["hotkey"].Float()); | ||||
| 	return std::make_shared<CButton>(Point((int)button["x"].Float(), (int)button["y"].Float()), button["name"].String(), help, [=](){ close();}, EShortcut::GLOBAL_CANCEL); | ||||
| } | ||||
|  | ||||
| CCampaignScreen::CCampaignButton::CCampaignButton(const JsonNode & config) | ||||
|   | ||||
| @@ -19,6 +19,8 @@ | ||||
| #include "../gui/CursorHandler.h" | ||||
| #include "../windows/GUIClasses.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/ShortcutHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| @@ -230,7 +232,9 @@ std::shared_ptr<CButton> CMenuEntry::createButton(CMenuScreen * parent, const Js | ||||
| 	if(posy < 0) | ||||
| 		posy = pos.h + posy; | ||||
|  | ||||
| 	auto result = std::make_shared<CButton>(Point(posx, posy), button["name"].String(), help, command, (int)button["hotkey"].Float()); | ||||
| 	EShortcut shortcut = GH.getShortcutsHandler().findShortcut(button["shortcut"].String()); | ||||
|  | ||||
| 	auto result = std::make_shared<CButton>(Point(posx, posy), button["name"].String(), help, command, shortcut); | ||||
|  | ||||
| 	if (button["center"].Bool()) | ||||
| 		result->moveBy(Point(-result->pos.w/2, -result->pos.h/2)); | ||||
| @@ -382,7 +386,7 @@ CMultiMode::CMultiMode(ESelectionScreen ScreenType) | ||||
| 	buttonHotseat = std::make_shared<CButton>(Point(373, 78), "MUBHOT.DEF", CGI->generaltexth->zelp[266], std::bind(&CMultiMode::hostTCP, this)); | ||||
| 	buttonHost = std::make_shared<CButton>(Point(373, 78 + 57 * 1), "MUBHOST.DEF", CButton::tooltip("Host TCP/IP game", ""), std::bind(&CMultiMode::hostTCP, this)); | ||||
| 	buttonJoin = std::make_shared<CButton>(Point(373, 78 + 57 * 2), "MUBJOIN.DEF", CButton::tooltip("Join TCP/IP game", ""), std::bind(&CMultiMode::joinTCP, this)); | ||||
| 	buttonCancel = std::make_shared<CButton>(Point(373, 424), "MUBCANC.DEF", CGI->generaltexth->zelp[288], [=](){ close();}, SDLK_ESCAPE); | ||||
| 	buttonCancel = std::make_shared<CButton>(Point(373, 424), "MUBCANC.DEF", CGI->generaltexth->zelp[288], [=](){ close();}, EShortcut::GLOBAL_CANCEL); | ||||
| } | ||||
|  | ||||
| void CMultiMode::hostTCP() | ||||
| @@ -422,8 +426,8 @@ CMultiPlayers::CMultiPlayers(const std::string & firstPlayer, ESelectionScreen S | ||||
| 		inputNames[i]->cb += std::bind(&CMultiPlayers::onChange, this, _1); | ||||
| 	} | ||||
|  | ||||
| 	buttonOk = std::make_shared<CButton>(Point(95, 338), "MUBCHCK.DEF", CGI->generaltexth->zelp[560], std::bind(&CMultiPlayers::enterSelectionScreen, this), SDLK_RETURN); | ||||
| 	buttonCancel = std::make_shared<CButton>(Point(205, 338), "MUBCANC.DEF", CGI->generaltexth->zelp[561], [=](){ close();}, SDLK_ESCAPE); | ||||
| 	buttonOk = std::make_shared<CButton>(Point(95, 338), "MUBCHCK.DEF", CGI->generaltexth->zelp[560], std::bind(&CMultiPlayers::enterSelectionScreen, this), EShortcut::GLOBAL_CONFIRM); | ||||
| 	buttonCancel = std::make_shared<CButton>(Point(205, 338), "MUBCANC.DEF", CGI->generaltexth->zelp[561], [=](){ close();}, EShortcut::GLOBAL_CANCEL); | ||||
| 	statusBar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(7, 381, 348, 18), 7, 381)); | ||||
|  | ||||
| 	inputNames[0]->setText(firstPlayer, true); | ||||
| @@ -471,14 +475,14 @@ CSimpleJoinScreen::CSimpleJoinScreen(bool host) | ||||
| 		inputAddress->cb += std::bind(&CSimpleJoinScreen::onChange, this, _1); | ||||
| 		inputPort->cb += std::bind(&CSimpleJoinScreen::onChange, this, _1); | ||||
| 		inputPort->filters += std::bind(&CTextInput::numberFilter, _1, _2, 0, 65535); | ||||
| 		buttonOk = std::make_shared<CButton>(Point(26, 142), "MUBCHCK.DEF", CGI->generaltexth->zelp[560], std::bind(&CSimpleJoinScreen::connectToServer, this), SDLK_RETURN); | ||||
| 		buttonOk = std::make_shared<CButton>(Point(26, 142), "MUBCHCK.DEF", CGI->generaltexth->zelp[560], std::bind(&CSimpleJoinScreen::connectToServer, this), EShortcut::GLOBAL_CONFIRM); | ||||
|  | ||||
| 		inputAddress->giveFocus(); | ||||
| 	} | ||||
| 	inputAddress->setText(host ? CServerHandler::localhostAddress : CSH->getHostAddress(), true); | ||||
| 	inputPort->setText(std::to_string(CSH->getHostPort()), true); | ||||
|  | ||||
| 	buttonCancel = std::make_shared<CButton>(Point(142, 142), "MUBCANC.DEF", CGI->generaltexth->zelp[561], std::bind(&CSimpleJoinScreen::leaveScreen, this), SDLK_ESCAPE); | ||||
| 	buttonCancel = std::make_shared<CButton>(Point(142, 142), "MUBCANC.DEF", CGI->generaltexth->zelp[561], std::bind(&CSimpleJoinScreen::leaveScreen, this), EShortcut::GLOBAL_CANCEL); | ||||
| 	statusBar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(7, 186, 218, 18), 7, 186)); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -19,6 +19,7 @@ | ||||
| #include "../battle/BattleInterface.h" | ||||
| #include "../battle/BattleInterfaceClasses.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../windows/InfoWindows.h" | ||||
| #include "../render/CAnimation.h" | ||||
| #include "../renderSDL/SDL_Extensions.h" | ||||
| @@ -223,7 +224,7 @@ void CButton::hover (bool on) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| CButton::CButton(Point position, const std::string &defName, const std::pair<std::string, std::string> &help, CFunctionList<void()> Callback, int key, bool playerColoredButton): | ||||
| CButton::CButton(Point position, const std::string &defName, const std::pair<std::string, std::string> &help, CFunctionList<void()> Callback, EShortcut key, bool playerColoredButton): | ||||
|     CKeyShortcut(key), | ||||
|     callback(Callback) | ||||
| { | ||||
| @@ -345,7 +346,7 @@ void CToggleBase::addCallback(std::function<void(bool)> function) | ||||
| } | ||||
|  | ||||
| CToggleButton::CToggleButton(Point position, const std::string &defName, const std::pair<std::string, std::string> &help, | ||||
|                              CFunctionList<void(bool)> callback, int key, bool playerColoredButton): | ||||
| 							 CFunctionList<void(bool)> callback, EShortcut key, bool playerColoredButton): | ||||
|   CButton(position, defName, help, 0, key, playerColoredButton), | ||||
|   CToggleBase(callback) | ||||
| { | ||||
| @@ -800,37 +801,37 @@ void CSlider::wheelScrolled(bool down, bool in) | ||||
| 	moveTo(value + 3 * (positive ? +scrollStep : -scrollStep)); | ||||
| } | ||||
|  | ||||
| void CSlider::keyPressed(const SDL_Keycode & key) | ||||
| void CSlider::keyPressed(EShortcut key) | ||||
| { | ||||
| 	int moveDest = value; | ||||
| 	switch(key) | ||||
| 	{ | ||||
| 	case SDLK_UP: | ||||
| 	case EShortcut::SELECT_UP: | ||||
| 		if (!horizontal) | ||||
| 			moveDest = value - scrollStep; | ||||
| 		break; | ||||
| 	case SDLK_LEFT: | ||||
| 	case EShortcut::SELECT_LEFT: | ||||
| 		if (horizontal) | ||||
| 			moveDest = value - scrollStep; | ||||
| 		break; | ||||
| 	case SDLK_DOWN: | ||||
| 	case EShortcut::SELECT_DOWN: | ||||
| 		if (!horizontal) | ||||
| 			moveDest = value + scrollStep; | ||||
| 		break; | ||||
| 	case SDLK_RIGHT: | ||||
| 	case EShortcut::SELECT_RIGHT: | ||||
| 		if (horizontal) | ||||
| 			moveDest = value + scrollStep; | ||||
| 		break; | ||||
| 	case SDLK_PAGEUP: | ||||
| 	case EShortcut::SELECT_PAGE_UP: | ||||
| 		moveDest = value - capacity + scrollStep; | ||||
| 		break; | ||||
| 	case SDLK_PAGEDOWN: | ||||
| 	case EShortcut::SELECT_PAGE_DOWN: | ||||
| 		moveDest = value + capacity - scrollStep; | ||||
| 		break; | ||||
| 	case SDLK_HOME: | ||||
| 	case EShortcut::SELECT_FIRST: | ||||
| 		moveDest = 0; | ||||
| 		break; | ||||
| 	case SDLK_END: | ||||
| 	case EShortcut::SELECT_LAST: | ||||
| 		moveDest = amount - capacity; | ||||
| 		break; | ||||
| 	default: | ||||
|   | ||||
| @@ -101,7 +101,7 @@ public: | ||||
|  | ||||
| 	/// Constructor | ||||
| 	CButton(Point position, const std::string & defName, const std::pair<std::string, std::string> & help, | ||||
| 	        CFunctionList<void()> Callback = 0, int key=0, bool playerColoredButton = false ); | ||||
| 			CFunctionList<void()> Callback = 0, EShortcut key = {}, bool playerColoredButton = false ); | ||||
|  | ||||
| 	/// Appearance modifiers | ||||
| 	void setIndex(size_t index, bool playerColoredButton=false); | ||||
| @@ -157,7 +157,7 @@ class CToggleButton : public CButton, public CToggleBase | ||||
|  | ||||
| public: | ||||
| 	CToggleButton(Point position, const std::string &defName, const std::pair<std::string, std::string> &help, | ||||
| 	              CFunctionList<void(bool)> Callback = 0, int key=0, bool playerColoredButton = false ); | ||||
| 				  CFunctionList<void(bool)> Callback = 0, EShortcut key = {}, bool playerColoredButton = false ); | ||||
| 	void clickLeft(tribool down, bool previousState) override; | ||||
|  | ||||
| 	// bring overrides into scope | ||||
| @@ -276,7 +276,7 @@ public: | ||||
|  | ||||
| 	void addCallback(std::function<void(int)> callback); | ||||
|  | ||||
| 	void keyPressed(const SDL_Keycode & key) override; | ||||
| 	void keyPressed(EShortcut key) override; | ||||
| 	void wheelScrolled(bool down, bool in) override; | ||||
| 	void clickLeft(tribool down, bool previousState) override; | ||||
| 	void mouseMoved (const Point & cursorPosition) override; | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
| #include "CArtifactHolder.h" | ||||
|  | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
|  | ||||
| #include "CComponent.h" | ||||
|  | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
|  | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/CursorHandler.h" | ||||
| #include "../gui/EShortcut.h | ||||
|  | ||||
| #include "Buttons.h" | ||||
|  | ||||
| @@ -82,8 +83,8 @@ void CArtifactsOfHeroBase::init( | ||||
| 		artPlace->leftClickCallback = lClickCallback; | ||||
| 		artPlace->rightClickCallback = rClickCallback; | ||||
| 	} | ||||
| 	leftBackpackRoll = std::make_shared<CButton>(Point(379, 364), "hsbtns3.def", CButton::tooltip(), [scrollHandler]() { scrollHandler(-1); }, SDLK_LEFT); | ||||
| 	rightBackpackRoll = std::make_shared<CButton>(Point(632, 364), "hsbtns5.def", CButton::tooltip(), [scrollHandler]() { scrollHandler(+1); }, SDLK_RIGHT); | ||||
| 	leftBackpackRoll = std::make_shared<CButton>(Point(379, 364), "hsbtns3.def", CButton::tooltip(), [scrollHandler]() { scrollHandler(-1); }, EShortcut::SELECT_LEFT); | ||||
| 	rightBackpackRoll = std::make_shared<CButton>(Point(632, 364), "hsbtns5.def", CButton::tooltip(), [scrollHandler]() { scrollHandler(+1); }, EShortcut::SELECT_RIGHT); | ||||
| 	leftBackpackRoll->block(true); | ||||
| 	rightBackpackRoll->block(true); | ||||
| } | ||||
|   | ||||
| @@ -19,6 +19,7 @@ | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/CursorHandler.h" | ||||
| #include "../gui/TextAlignment.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../renderSDL/SDL_Extensions.h" | ||||
| #include "../windows/CMessage.h" | ||||
| #include "../windows/InfoWindows.h" | ||||
| @@ -488,11 +489,12 @@ CComponentBox::CComponentBox(std::vector<std::shared_ptr<CSelectableComponent>> | ||||
|  | ||||
| 	assert(!components.empty()); | ||||
|  | ||||
| 	int key = SDLK_1; | ||||
| 	auto key = EShortcut::SELECT_INDEX_1; | ||||
| 	for(auto & comp : _components) | ||||
| 	{ | ||||
| 		comp->onSelect = std::bind(&CComponentBox::selectionChanged, this, comp); | ||||
| 		comp->assignedKeys.insert(key++); | ||||
| 		comp->assignedKey = key; | ||||
| 		vstd::advance(key, 1); | ||||
| 	} | ||||
| 	selectionChanged(_components.front()); | ||||
| } | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
|  | ||||
| #include "../CPlayerInterface.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../windows/CMessage.h" | ||||
| #include "../adventureMap/CInGameConsole.h" | ||||
| #include "../renderSDL/SDL_Extensions.h" | ||||
| @@ -555,12 +556,12 @@ void CTextInput::clickLeft(tribool down, bool previousState) | ||||
| 		giveFocus(); | ||||
| } | ||||
|  | ||||
| void CTextInput::keyPressed(const SDL_Keycode & key) | ||||
| void CTextInput::keyPressed(EShortcut key) | ||||
| { | ||||
| 	if(!focus) | ||||
| 		return; | ||||
|  | ||||
| 	if(key == SDLK_TAB) | ||||
| 	if(key == EShortcut::GLOBAL_MOVE_FOCUS) | ||||
| 	{ | ||||
| 		moveFocus(); | ||||
| 		GH.breakEventHandling(); | ||||
| @@ -571,9 +572,7 @@ void CTextInput::keyPressed(const SDL_Keycode & key) | ||||
|  | ||||
| 	switch(key) | ||||
| 	{ | ||||
| 	case SDLK_DELETE: // have index > ' ' so it won't be filtered out by default section | ||||
| 		return; | ||||
| 	case SDLK_BACKSPACE: | ||||
| 	case EShortcut::GLOBAL_BACKSPACE: | ||||
| 		if(!newText.empty()) | ||||
| 		{ | ||||
| 			TextOperations::trimRightUnicode(newText); | ||||
| @@ -608,9 +607,9 @@ void CTextInput::setText(const std::string & nText, bool callCb) | ||||
| 		cb(text); | ||||
| } | ||||
|  | ||||
| bool CTextInput::captureThisKey(const SDL_Keycode & key) | ||||
| bool CTextInput::captureThisKey(EShortcut key) | ||||
| { | ||||
| 	if(key == SDLK_RETURN || key == SDLK_KP_ENTER || key == SDLK_ESCAPE) | ||||
| 	if(key == EShortcut::GLOBAL_RETURN) | ||||
| 		return false; | ||||
|  | ||||
| 	return true; | ||||
|   | ||||
| @@ -225,9 +225,9 @@ public: | ||||
| 	CTextInput(const Rect & Pos, std::shared_ptr<IImage> srf); | ||||
|  | ||||
| 	void clickLeft(tribool down, bool previousState) override; | ||||
| 	void keyPressed(const SDL_Keycode & key) override; | ||||
| 	void keyPressed(EShortcut key) override; | ||||
|  | ||||
| 	bool captureThisKey(const SDL_Keycode & key) override; | ||||
| 	bool captureThisKey(EShortcut key) override; | ||||
|  | ||||
| 	void textInputed(const std::string & enteredText) override; | ||||
| 	void textEdited(const std::string & enteredText) override; | ||||
|   | ||||
| @@ -21,6 +21,7 @@ | ||||
| #include "../CPlayerInterface.h" | ||||
| #include "../PlayerLocalState.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| @@ -1184,8 +1185,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst | ||||
| 	income = std::make_shared<CLabel>(195, 443, FONT_SMALL, ETextAlignment::CENTER); | ||||
| 	icon = std::make_shared<CAnimImage>("ITPT", 0, 0, 15, 387); | ||||
|  | ||||
| 	exit = std::make_shared<CButton>(Point(744, 544), "TSBTNS", CButton::tooltip(CGI->generaltexth->tcommands[8]), [&](){close();}, SDLK_RETURN); | ||||
| 	exit->assignedKeys.insert(SDLK_ESCAPE); | ||||
| 	exit = std::make_shared<CButton>(Point(744, 544), "TSBTNS", CButton::tooltip(CGI->generaltexth->tcommands[8]), [&](){close();}, EShortcut::GLOBAL_RETURN); | ||||
| 	exit->setImageOrder(4, 5, 6, 7); | ||||
|  | ||||
| 	auto split = std::make_shared<CButton>(Point(744, 382), "TSBTNS", CButton::tooltip(CGI->generaltexth->tcommands[3]), [&]() | ||||
| @@ -1308,20 +1308,20 @@ void CCastleInterface::recreateIcons() | ||||
|  | ||||
| } | ||||
|  | ||||
| void CCastleInterface::keyPressed(const SDL_Keycode & key) | ||||
| void CCastleInterface::keyPressed(EShortcut key) | ||||
| { | ||||
| 	switch(key) | ||||
| 	{ | ||||
| 	case SDLK_UP: | ||||
| 	case EShortcut::SELECT_UP: | ||||
| 		townlist->selectPrev(); | ||||
| 		break; | ||||
| 	case SDLK_DOWN: | ||||
| 	case EShortcut::SELECT_DOWN: | ||||
| 		townlist->selectNext(); | ||||
| 		break; | ||||
| 	case SDLK_SPACE: | ||||
| 	case EShortcut::TOWN_SWAP_ARMIES: | ||||
| 		heroes->swapArmies(); | ||||
| 		break; | ||||
| 	case SDLK_t: | ||||
| 	case EShortcut::TOWN_OPEN_TAVERN: | ||||
| 		if(town->hasBuilt(BuildingID::TAVERN)) | ||||
| 			LOCPLINT->showTavernWindow(town); | ||||
| 		break; | ||||
| @@ -1420,8 +1420,7 @@ CHallInterface::CHallInterface(const CGTownInstance * Town): | ||||
| 	statusbar = CGStatusBar::create(statusbarBackground); | ||||
|  | ||||
| 	title = std::make_shared<CLabel>(399, 12, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, town->town->buildings.at(BuildingID(town->hallLevel()+BuildingID::VILLAGE_HALL))->getNameTranslated()); | ||||
| 	exit = std::make_shared<CButton>(Point(748, 556), "TPMAGE1.DEF", CButton::tooltip(CGI->generaltexth->hcommands[8]), [&](){close();}, SDLK_RETURN); | ||||
| 	exit->assignedKeys.insert(SDLK_ESCAPE); | ||||
| 	exit = std::make_shared<CButton>(Point(748, 556), "TPMAGE1.DEF", CButton::tooltip(CGI->generaltexth->hcommands[8]), [&](){close();}, EShortcut::GLOBAL_RETURN); | ||||
|  | ||||
| 	auto & boxList = town->town->clientInfo.hallSlots; | ||||
| 	boxes.resize(boxList.size()); | ||||
| @@ -1486,11 +1485,11 @@ CBuildWindow::CBuildWindow(const CGTownInstance *Town, const CBuilding * Buildin | ||||
| 		std::string tooltipYes = boost::str(boost::format(CGI->generaltexth->allTexts[595]) % building->getNameTranslated()); | ||||
| 		std::string tooltipNo  = boost::str(boost::format(CGI->generaltexth->allTexts[596]) % building->getNameTranslated()); | ||||
|  | ||||
| 		buy = std::make_shared<CButton>(Point(45, 446), "IBUY30", CButton::tooltip(tooltipYes), [&](){ buyFunc(); }, SDLK_RETURN); | ||||
| 		buy = std::make_shared<CButton>(Point(45, 446), "IBUY30", CButton::tooltip(tooltipYes), [&](){ buyFunc(); }, EShortcut::GLOBAL_CONFIRM); | ||||
| 		buy->setBorderColor(Colors::METALLIC_GOLD); | ||||
| 		buy->block(state!=7 || LOCPLINT->playerID != town->tempOwner); | ||||
|  | ||||
| 		cancel = std::make_shared<CButton>(Point(290, 445), "ICANCEL", CButton::tooltip(tooltipNo), [&](){ close();}, SDLK_ESCAPE); | ||||
| 		cancel = std::make_shared<CButton>(Point(290, 445), "ICANCEL", CButton::tooltip(tooltipNo), [&](){ close();}, EShortcut::GLOBAL_CANCEL); | ||||
| 		cancel->setBorderColor(Colors::METALLIC_GOLD); | ||||
| 	} | ||||
| } | ||||
| @@ -1596,8 +1595,7 @@ CFortScreen::CFortScreen(const CGTownInstance * town): | ||||
| 	title = std::make_shared<CLabel>(400, 12, FONT_BIG, ETextAlignment::CENTER, Colors::WHITE, fortBuilding->getNameTranslated()); | ||||
|  | ||||
| 	std::string text = boost::str(boost::format(CGI->generaltexth->fcommands[6]) % fortBuilding->getNameTranslated()); | ||||
| 	exit = std::make_shared<CButton>(Point(748, 556), "TPMAGE1", CButton::tooltip(text), [&](){ close(); }, SDLK_RETURN); | ||||
| 	exit->assignedKeys.insert(SDLK_ESCAPE); | ||||
| 	exit = std::make_shared<CButton>(Point(748, 556), "TPMAGE1", CButton::tooltip(text), [&](){ close(); }, EShortcut::GLOBAL_RETURN); | ||||
|  | ||||
| 	std::vector<Point> positions = | ||||
| 	{ | ||||
| @@ -1785,8 +1783,7 @@ CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner,std::string imagem) | ||||
| 	auto statusbarBackground = std::make_shared<CPicture>(background->getSurface(), barRect, 7, 556); | ||||
| 	statusbar = CGStatusBar::create(statusbarBackground); | ||||
|  | ||||
| 	exit = std::make_shared<CButton>(Point(748, 556), "TPMAGE1.DEF", CButton::tooltip(CGI->generaltexth->allTexts[593]), [&](){ close(); }, SDLK_RETURN); | ||||
| 	exit->assignedKeys.insert(SDLK_ESCAPE); | ||||
| 	exit = std::make_shared<CButton>(Point(748, 556), "TPMAGE1.DEF", CButton::tooltip(CGI->generaltexth->allTexts[593]), [&](){ close(); }, EShortcut::GLOBAL_RETURN); | ||||
|  | ||||
| 	static const std::vector<std::vector<Point> > positions = | ||||
| 	{ | ||||
| @@ -1866,10 +1863,10 @@ CBlacksmithDialog::CBlacksmithDialog(bool possible, CreatureID creMachineID, Art | ||||
| 	                std::to_string(aid.toArtifact(CGI->artifacts())->getPrice())); | ||||
|  | ||||
| 	std::string text = boost::str(boost::format(CGI->generaltexth->allTexts[595]) % creature->getNameSingularTranslated()); | ||||
| 	buy = std::make_shared<CButton>(Point(42, 312), "IBUY30.DEF", CButton::tooltip(text), [&](){ close(); }, SDLK_RETURN); | ||||
| 	buy = std::make_shared<CButton>(Point(42, 312), "IBUY30.DEF", CButton::tooltip(text), [&](){ close(); }, EShortcut::GLOBAL_CONFIRM); | ||||
|  | ||||
| 	text = boost::str(boost::format(CGI->generaltexth->allTexts[596]) % creature->getNameSingularTranslated()); | ||||
| 	cancel = std::make_shared<CButton>(Point(224, 312), "ICANCEL.DEF", CButton::tooltip(text), [&](){ close(); }, SDLK_ESCAPE); | ||||
| 	cancel = std::make_shared<CButton>(Point(224, 312), "ICANCEL.DEF", CButton::tooltip(text), [&](){ close(); }, EShortcut::GLOBAL_CANCEL); | ||||
|  | ||||
| 	if(possible) | ||||
| 		buy->addCallback([=](){ LOCPLINT->cb->buyArtifact(LOCPLINT->cb->getHero(hid),aid); }); | ||||
|   | ||||
| @@ -246,7 +246,7 @@ public: | ||||
|  | ||||
| 	void castleTeleport(int where); | ||||
| 	void townChange(); | ||||
| 	void keyPressed(const SDL_Keycode & key) override; | ||||
| 	void keyPressed(EShortcut key) override; | ||||
|  | ||||
| 	void close(); | ||||
| 	void addBuilding(BuildingID bid); | ||||
|   | ||||
| @@ -22,6 +22,7 @@ | ||||
| #include "../widgets/TextControls.h" | ||||
| #include "../widgets/ObjectLists.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../renderSDL/SDL_Extensions.h" | ||||
|  | ||||
| #include "../../CCallback.h" | ||||
| @@ -284,7 +285,7 @@ CStackWindow::ButtonsSection::ButtonsSection(CStackWindow * owner, int yOffset) | ||||
| 		{ | ||||
| 			LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[12], onDismiss, nullptr); | ||||
| 		}; | ||||
| 		dismiss = std::make_shared<CButton>(Point(5, 5),"IVIEWCR2.DEF", CGI->generaltexth->zelp[445], onClick, SDLK_d); | ||||
| 		dismiss = std::make_shared<CButton>(Point(5, 5),"IVIEWCR2.DEF", CGI->generaltexth->zelp[445], onClick, EShortcut::HERO_DISMISS); | ||||
| 	} | ||||
|  | ||||
| 	if(parent->info->upgradeInfo && !parent->info->commander) | ||||
| @@ -321,14 +322,12 @@ CStackWindow::ButtonsSection::ButtonsSection(CStackWindow * owner, int yOffset) | ||||
| 					LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[314], resComps); | ||||
| 				} | ||||
| 			}; | ||||
| 			auto upgradeBtn = std::make_shared<CButton>(Point(221 + (int)buttonIndex * 40, 5), "stackWindow/upgradeButton", CGI->generaltexth->zelp[446], onClick, SDLK_1); | ||||
| 			auto upgradeBtn = std::make_shared<CButton>(Point(221 + (int)buttonIndex * 40, 5), "stackWindow/upgradeButton", CGI->generaltexth->zelp[446], onClick); | ||||
|  | ||||
| 			upgradeBtn->addOverlay(std::make_shared<CAnimImage>("CPRSMALL", VLC->creh->objects[upgradeInfo.info.newID[buttonIndex]]->getIconIndex())); | ||||
|  | ||||
| 			if(buttonsToCreate == 1) // single upgrade avaialbe | ||||
| 			{ | ||||
| 				upgradeBtn->assignedKeys.insert(SDLK_u); | ||||
| 			} | ||||
| 				upgradeBtn->assignedKey = EShortcut::RECRUITMENT_UPGRADE; | ||||
|  | ||||
| 			upgrade[buttonIndex] = upgradeBtn; | ||||
| 		} | ||||
| @@ -356,8 +355,7 @@ CStackWindow::ButtonsSection::ButtonsSection(CStackWindow * owner, int yOffset) | ||||
| 		parent->switchButtons[parent->activeTab]->disable(); | ||||
| 	} | ||||
|  | ||||
| 	exit = std::make_shared<CButton>(Point(382, 5), "hsbtns.def", CGI->generaltexth->zelp[447], [=](){ parent->close(); }, SDLK_RETURN); | ||||
| 	exit->assignedKeys.insert(SDLK_ESCAPE); | ||||
| 	exit = std::make_shared<CButton>(Point(382, 5), "hsbtns.def", CGI->generaltexth->zelp[447], [=](){ parent->close(); }, EShortcut::GLOBAL_RETURN); | ||||
| } | ||||
|  | ||||
| CStackWindow::CommanderMainSection::CommanderMainSection(CStackWindow * owner, int yOffset) | ||||
| @@ -457,8 +455,8 @@ CStackWindow::CommanderMainSection::CommanderMainSection(CStackWindow * owner, i | ||||
|  | ||||
| 		abilities = std::make_shared<CListBox>(onCreate, Point(38, 3+pos.h), Point(63, 0), 6, abilitiesCount); | ||||
|  | ||||
| 		leftBtn = std::make_shared<CButton>(Point(10,  pos.h + 6), "hsbtns3.def", CButton::tooltip(), [=](){ abilities->moveToPrev(); }, SDLK_LEFT); | ||||
| 		rightBtn = std::make_shared<CButton>(Point(411, pos.h + 6), "hsbtns5.def", CButton::tooltip(), [=](){ abilities->moveToNext(); }, SDLK_RIGHT); | ||||
| 		leftBtn = std::make_shared<CButton>(Point(10,  pos.h + 6), "hsbtns3.def", CButton::tooltip(), [=](){ abilities->moveToPrev(); }, EShortcut::SELECT_LEFT); | ||||
| 		rightBtn = std::make_shared<CButton>(Point(411, pos.h + 6), "hsbtns5.def", CButton::tooltip(), [=](){ abilities->moveToNext(); }, EShortcut::SELECT_RIGHT); | ||||
|  | ||||
| 		if(abilitiesCount <= 6) | ||||
| 		{ | ||||
|   | ||||
| @@ -19,6 +19,7 @@ | ||||
|  | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/TextAlignment.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| @@ -119,22 +120,21 @@ CHeroWindow::CHeroWindow(const CGHeroInstance * hero) | ||||
|  | ||||
| 	statusbar = CGStatusBar::create(7, 559, "ADROLLVR.bmp", 660); | ||||
|  | ||||
| 	quitButton = std::make_shared<CButton>(Point(609, 516), "hsbtns.def", CButton::tooltip(heroscrn[17]), [=](){ close(); }, SDLK_RETURN); | ||||
| 	quitButton->assignedKeys.insert(SDLK_ESCAPE); | ||||
| 	quitButton = std::make_shared<CButton>(Point(609, 516), "hsbtns.def", CButton::tooltip(heroscrn[17]), [=](){ close(); }, EShortcut::GLOBAL_RETURN); | ||||
|  | ||||
| 	dismissLabel = std::make_shared<CTextBox>(CGI->generaltexth->jktexts[8], Rect(370, 430, 65, 35), 0, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE); | ||||
| 	dismissButton = std::make_shared<CButton>(Point(454, 429), "hsbtns2.def", CButton::tooltip(heroscrn[28]), [=](){ dismissCurrent(); }, SDLK_d); | ||||
| 	dismissButton = std::make_shared<CButton>(Point(454, 429), "hsbtns2.def", CButton::tooltip(heroscrn[28]), [=](){ dismissCurrent(); }, EShortcut::HERO_DISMISS); | ||||
|  | ||||
| 	questlogLabel = std::make_shared<CTextBox>(CGI->generaltexth->jktexts[9], Rect(510, 430, 65, 35), 0, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE); | ||||
| 	questlogButton = std::make_shared<CButton>(Point(314, 429), "hsbtns4.def", CButton::tooltip(heroscrn[0]), [=](){ LOCPLINT->showQuestLog(); }, SDLK_q); | ||||
| 	questlogButton = std::make_shared<CButton>(Point(314, 429), "hsbtns4.def", CButton::tooltip(heroscrn[0]), [=](){ LOCPLINT->showQuestLog(); }, EShortcut::ADVENTURE_QUEST_LOG); | ||||
|  | ||||
| 	formations = std::make_shared<CToggleGroup>(0); | ||||
| 	formations->addToggle(0, std::make_shared<CToggleButton>(Point(481, 483), "hsbtns6.def", std::make_pair(heroscrn[23], heroscrn[29]), 0, SDLK_t)); | ||||
| 	formations->addToggle(1, std::make_shared<CToggleButton>(Point(481, 519), "hsbtns7.def", std::make_pair(heroscrn[24], heroscrn[30]), 0, SDLK_l)); | ||||
| 	formations->addToggle(0, std::make_shared<CToggleButton>(Point(481, 483), "hsbtns6.def", std::make_pair(heroscrn[23], heroscrn[29]), 0, EShortcut::HERO_TIGHT_FORMATION)); | ||||
| 	formations->addToggle(1, std::make_shared<CToggleButton>(Point(481, 519), "hsbtns7.def", std::make_pair(heroscrn[24], heroscrn[30]), 0, EShortcut::HERO_LOOSE_FORMATION)); | ||||
|  | ||||
| 	if(hero->commander) | ||||
| 	{ | ||||
| 		commanderButton = std::make_shared<CButton>(Point(317, 18), "buttons/commander", CButton::tooltipLocalized("vcmi.heroWindow.openCommander"), [&](){ commanderWindow(); }, SDLK_c); | ||||
| 		commanderButton = std::make_shared<CButton>(Point(317, 18), "buttons/commander", CButton::tooltipLocalized("vcmi.heroWindow.openCommander"), [&](){ commanderWindow(); }, EShortcut::HERO_COMMANDER); | ||||
| 	} | ||||
|  | ||||
| 	//right list of heroes | ||||
| @@ -224,7 +224,7 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded) | ||||
| 	specImage->setFrame(curHero->type->imageIndex); | ||||
| 	specName->setText(curHero->type->getSpecialtyNameTranslated()); | ||||
|  | ||||
| 	tacticsButton = std::make_shared<CToggleButton>(Point(539, 483), "hsbtns8.def", std::make_pair(heroscrn[26], heroscrn[31]), 0, SDLK_b); | ||||
| 	tacticsButton = std::make_shared<CToggleButton>(Point(539, 483), "hsbtns8.def", std::make_pair(heroscrn[26], heroscrn[31]), 0, EShortcut::HERO_TOGGLE_TACTICS); | ||||
| 	tacticsButton->addHoverText(CButton::HIGHLIGHTED, CGI->generaltexth->heroscrn[25]); | ||||
|  | ||||
| 	dismissButton->addHoverText(CButton::NORMAL, boost::str(boost::format(CGI->generaltexth->heroscrn[16]) % curHero->getNameTranslated() % curHero->type->heroClass->getNameTranslated())); | ||||
|   | ||||
| @@ -17,6 +17,7 @@ | ||||
| #include "../CPlayerInterface.h" | ||||
| #include "../adventureMap/CResDataBar.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| @@ -613,15 +614,14 @@ void CKingdomInterface::generateButtons() | ||||
|  | ||||
| 	//Main control buttons | ||||
| 	btnHeroes = std::make_shared<CButton>(Point(748, 28+footerPos), "OVBUTN1.DEF", CButton::tooltip(CGI->generaltexth->overview[11], CGI->generaltexth->overview[6]), | ||||
| 		std::bind(&CKingdomInterface::activateTab, this, 0), SDLK_h); | ||||
| 		std::bind(&CKingdomInterface::activateTab, this, 0), EShortcut::KINGDOM_HEROES); | ||||
| 	btnHeroes->block(true); | ||||
|  | ||||
| 	btnTowns = std::make_shared<CButton>(Point(748, 64+footerPos), "OVBUTN6.DEF", CButton::tooltip(CGI->generaltexth->overview[12], CGI->generaltexth->overview[7]), | ||||
| 		std::bind(&CKingdomInterface::activateTab, this, 1), SDLK_t); | ||||
| 		std::bind(&CKingdomInterface::activateTab, this, 1), EShortcut::KINGDOM_TOWNS); | ||||
|  | ||||
| 	btnExit = std::make_shared<CButton>(Point(748,99+footerPos), "OVBUTN1.DEF", CButton::tooltip(CGI->generaltexth->allTexts[600]), | ||||
| 		std::bind(&CKingdomInterface::close, this), SDLK_RETURN); | ||||
| 	btnExit->assignedKeys.insert(SDLK_ESCAPE); | ||||
| 		std::bind(&CKingdomInterface::close, this), EShortcut::GLOBAL_RETURN); | ||||
| 	btnExit->setImageOrder(3, 4, 5, 6); | ||||
|  | ||||
| 	//Object list control buttons | ||||
|   | ||||
| @@ -16,6 +16,7 @@ | ||||
| #include "../adventureMap/CResDataBar.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/TextAlignment.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../mapView/MapView.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/Images.h" | ||||
| @@ -35,8 +36,7 @@ CPuzzleWindow::CPuzzleWindow(const int3 & GrailPos, double discoveredRatio) | ||||
|  | ||||
| 	CCS->soundh->playSound(soundBase::OBELISK); | ||||
|  | ||||
| 	quitb = std::make_shared<CButton>(Point(670, 538), "IOK6432.DEF", CButton::tooltip(CGI->generaltexth->allTexts[599]), std::bind(&CPuzzleWindow::close, this), SDLK_RETURN); | ||||
| 	quitb->assignedKeys.insert(SDLK_ESCAPE); | ||||
| 	quitb = std::make_shared<CButton>(Point(670, 538), "IOK6432.DEF", CButton::tooltip(CGI->generaltexth->allTexts[599]), std::bind(&CPuzzleWindow::close, this), EShortcut::GLOBAL_RETURN); | ||||
| 	quitb->setBorderColor(Colors::METALLIC_GOLD); | ||||
|  | ||||
| 	mapView = std::make_shared<PuzzleMapView>(Point(8,9), Point(591, 544), grailPos); | ||||
|   | ||||
| @@ -14,6 +14,7 @@ | ||||
| #include "../CPlayerInterface.h" | ||||
|  | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../adventureMap/CAdventureMapInterface.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| @@ -127,7 +128,7 @@ CQuestLog::CQuestLog (const std::vector<QuestInfo> & Quests) | ||||
| 	minimap = std::make_shared<CQuestMinimap>(Rect(12, 12, 169, 169)); | ||||
| 	// TextBox have it's own 4 pixel padding from top at least for English. To achieve 10px from both left and top only add 6px margin | ||||
| 	description = std::make_shared<CTextBox>("", Rect(205, 18, 385, DESCRIPTION_HEIGHT_MAX), CSlider::BROWN, FONT_MEDIUM, ETextAlignment::TOPLEFT, Colors::WHITE); | ||||
| 	ok = std::make_shared<CButton>(Point(539, 398), "IOKAY.DEF", CGI->generaltexth->zelp[445], std::bind(&CQuestLog::close, this), SDLK_RETURN); | ||||
| 	ok = std::make_shared<CButton>(Point(539, 398), "IOKAY.DEF", CGI->generaltexth->zelp[445], std::bind(&CQuestLog::close, this), EShortcut::GLOBAL_CONFIRM); | ||||
| 	// Both button and lable are shifted to -2px by x and y to not make them actually look like they're on same line with quests list and ok button | ||||
| 	hideCompleteButton = std::make_shared<CToggleButton>(Point(10, 396), "sysopchk.def", CButton::tooltipLocalized("vcmi.questLog.hideComplete"), std::bind(&CQuestLog::toggleComplete, this, _1)); | ||||
| 	hideCompleteLabel = std::make_shared<CLabel>(46, 398, FONT_MEDIUM, ETextAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->translate("vcmi.questLog.hideComplete.hover")); | ||||
|   | ||||
| @@ -23,6 +23,7 @@ | ||||
|  | ||||
| #include "../battle/BattleInterface.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| @@ -409,27 +410,24 @@ void CSpellWindow::turnPageRight() | ||||
| 		CCS->videoh->openAndPlayVideo("PGTRNRGH.SMK", pos.x+13, pos.y+15); | ||||
| } | ||||
|  | ||||
| void CSpellWindow::keyPressed(const SDL_Keycode & key) | ||||
| void CSpellWindow::keyPressed(EShortcut key) | ||||
| { | ||||
| 	if(key == SDLK_ESCAPE ||  key == SDLK_RETURN) | ||||
| 	switch(key) | ||||
| 	{ | ||||
| 		fexitb(); | ||||
| 		return; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		switch(key) | ||||
| 		{ | ||||
| 		case SDLK_LEFT: | ||||
| 		case EShortcut::GLOBAL_RETURN: | ||||
| 			fexitb(); | ||||
| 			break; | ||||
|  | ||||
| 		case EShortcut::SELECT_LEFT: | ||||
| 			fLcornerb(); | ||||
| 			break; | ||||
| 		case SDLK_RIGHT: | ||||
| 		case EShortcut::SELECT_RIGHT: | ||||
| 			fRcornerb(); | ||||
| 			break; | ||||
| 		case SDLK_UP: | ||||
| 		case SDLK_DOWN: | ||||
| 		case EShortcut::SELECT_UP: | ||||
| 		case EShortcut::SELECT_DOWN: | ||||
| 		{ | ||||
| 			bool down = key == SDLK_DOWN; | ||||
| 			bool down = key == EShortcut::SELECT_DOWN; | ||||
| 			static const int schoolsOrder[] = { 0, 3, 1, 2, 4 }; | ||||
| 			int index = -1; | ||||
| 			while(schoolsOrder[++index] != selectedTab); | ||||
| @@ -439,38 +437,12 @@ void CSpellWindow::keyPressed(const SDL_Keycode & key) | ||||
| 				selectSchool(schoolsOrder[index]); | ||||
| 			break; | ||||
| 		} | ||||
| 		case SDLK_c: | ||||
| 		case EShortcut::SPELLBOOK_TAB_COMBAT: | ||||
| 			fbattleSpellsb(); | ||||
| 			break; | ||||
| 		case SDLK_a: | ||||
| 		case EShortcut::SPELLBOOK_TAB_ADVENTURE: | ||||
| 			fadvSpellsb(); | ||||
| 			break; | ||||
| 		default://to get rid of warnings | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		//alt + 1234567890-= casts spell from 1 - 12 slot | ||||
| 		if(GH.isKeyboardAltDown()) | ||||
| 		{ | ||||
| 			SDL_Keycode hlpKey = key; | ||||
| 			if(CGuiHandler::isNumKey(hlpKey, false)) | ||||
| 			{ | ||||
| 				if(hlpKey == SDLK_KP_PLUS) | ||||
| 					hlpKey = SDLK_EQUALS; | ||||
| 				else | ||||
| 					hlpKey = CGuiHandler::numToDigit(hlpKey); | ||||
| 			} | ||||
|  | ||||
| 			static const SDL_Keycode spellSelectors[] = {SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5, SDLK_6, SDLK_7, SDLK_8, SDLK_9, SDLK_0, SDLK_MINUS, SDLK_EQUALS}; | ||||
|  | ||||
| 			int index = -1; | ||||
| 			while(++index < std::size(spellSelectors) && spellSelectors[index] != hlpKey); | ||||
| 			if(index >= std::size(spellSelectors)) | ||||
| 				return; | ||||
|  | ||||
| 			//try casting spell | ||||
| 			spellAreas[index]->clickLeft(false, true); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -112,7 +112,7 @@ public: | ||||
| 	void selectSchool(int school); //schools: 0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic, 4 - all schools | ||||
| 	int pagesWithinCurrentTab(); | ||||
|  | ||||
| 	void keyPressed(const SDL_Keycode & key) override; | ||||
| 	void keyPressed(EShortcut key) override; | ||||
|  | ||||
| 	void show(SDL_Surface * to) override; | ||||
| }; | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| #include "../widgets/Images.h" | ||||
| #include "../renderSDL/SDL_Extensions.h" | ||||
| #include "../gui/TextAlignment.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| #include "../windows/InfoWindows.h" | ||||
| @@ -728,8 +729,7 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket * Market, const CGHeroInsta | ||||
| 	initItems(false); | ||||
| 	initItems(true); | ||||
|  | ||||
| 	ok = std::make_shared<CButton>(Point(516, 520), "IOK6432.DEF", CGI->generaltexth->zelp[600], [&](){ close(); }, SDLK_RETURN); | ||||
| 	ok->assignedKeys.insert(SDLK_ESCAPE); | ||||
| 	ok = std::make_shared<CButton>(Point(516, 520), "IOK6432.DEF", CGI->generaltexth->zelp[600], [&](){ close(); }, EShortcut::GLOBAL_RETURN); | ||||
| 	deal = std::make_shared<CButton>(Point(307, 520), "TPMRKB.DEF", CGI->generaltexth->zelp[595], [&](){ makeDeal(); } ); | ||||
| 	deal->block(true); | ||||
|  | ||||
| @@ -1170,8 +1170,7 @@ CAltarWindow::CAltarWindow(const IMarket * Market, const CGHeroInstance * Hero, | ||||
|  | ||||
| 	statusBar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); | ||||
|  | ||||
| 	ok = std::make_shared<CButton>(Point(516, 520), "IOK6432.DEF", CGI->generaltexth->zelp[568], [&](){ close();}, SDLK_RETURN); | ||||
| 	ok->assignedKeys.insert(SDLK_ESCAPE); | ||||
| 	ok = std::make_shared<CButton>(Point(516, 520), "IOK6432.DEF", CGI->generaltexth->zelp[568], [&](){ close();}, EShortcut::GLOBAL_RETURN); | ||||
|  | ||||
| 	deal = std::make_shared<CButton>(Point(269, 520), "ALTSACR.DEF", CGI->generaltexth->zelp[585], std::bind(&CAltarWindow::makeDeal,this)); | ||||
|  | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| #include "CCreatureWindow.h" | ||||
|  | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../gui/TextAlignment.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| @@ -32,12 +33,12 @@ void CreaturePurchaseCard::initButtons() | ||||
|  | ||||
| void CreaturePurchaseCard::initMaxButton() | ||||
| { | ||||
| 	maxButton = std::make_shared<CButton>(Point(pos.x + 52, pos.y + 180), "QuickRecruitmentWindow/QuickRecruitmentAllButton.def", CButton::tooltip(), std::bind(&CSlider::moveToMax,slider), SDLK_LSHIFT); | ||||
| 	maxButton = std::make_shared<CButton>(Point(pos.x + 52, pos.y + 180), "QuickRecruitmentWindow/QuickRecruitmentAllButton.def", CButton::tooltip(), std::bind(&CSlider::moveToMax,slider), EShortcut::RECRUITMENT_MAX); | ||||
| } | ||||
|  | ||||
| void CreaturePurchaseCard::initMinButton() | ||||
| { | ||||
| 	minButton = std::make_shared<CButton>(Point(pos.x, pos.y + 180), "QuickRecruitmentWindow/QuickRecruitmentNoneButton.def", CButton::tooltip(), std::bind(&CSlider::moveToMin,slider), SDLK_LCTRL); | ||||
| 	minButton = std::make_shared<CButton>(Point(pos.x, pos.y + 180), "QuickRecruitmentWindow/QuickRecruitmentNoneButton.def", CButton::tooltip(), std::bind(&CSlider::moveToMin,slider), EShortcut::RECRUITMENT_MIN); | ||||
| } | ||||
|  | ||||
| void CreaturePurchaseCard::initCreatureSwitcherButton() | ||||
|   | ||||
| @@ -28,6 +28,7 @@ | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/CursorHandler.h" | ||||
| #include "../gui/TextAlignment.h" | ||||
| #include "../gui/Shortcut.h" | ||||
|  | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| @@ -210,9 +211,9 @@ CRecruitmentWindow::CRecruitmentWindow(const CGDwelling * Dwelling, int Level, c | ||||
|  | ||||
| 	slider = std::make_shared<CSlider>(Point(176,279),135,std::bind(&CRecruitmentWindow::sliderMoved,this, _1),0,0,0,true); | ||||
|  | ||||
| 	maxButton = std::make_shared<CButton>(Point(134, 313), "IRCBTNS.DEF", CGI->generaltexth->zelp[553], std::bind(&CSlider::moveToMax, slider), SDLK_m); | ||||
| 	buyButton = std::make_shared<CButton>(Point(212, 313), "IBY6432.DEF", CGI->generaltexth->zelp[554], std::bind(&CRecruitmentWindow::buy, this), SDLK_RETURN); | ||||
| 	cancelButton = std::make_shared<CButton>(Point(290, 313), "ICN6432.DEF", CGI->generaltexth->zelp[555], std::bind(&CRecruitmentWindow::close, this), SDLK_ESCAPE); | ||||
| 	maxButton = std::make_shared<CButton>(Point(134, 313), "IRCBTNS.DEF", CGI->generaltexth->zelp[553], std::bind(&CSlider::moveToMax, slider), EShortcut::RECRUITMENT_MAX); | ||||
| 	buyButton = std::make_shared<CButton>(Point(212, 313), "IBY6432.DEF", CGI->generaltexth->zelp[554], std::bind(&CRecruitmentWindow::buy, this), EShortcut::GLOBAL_CONFIRM); | ||||
| 	cancelButton = std::make_shared<CButton>(Point(290, 313), "ICN6432.DEF", CGI->generaltexth->zelp[555], std::bind(&CRecruitmentWindow::close, this), EShortcut::GLOBAL_CANCEL); | ||||
|  | ||||
| 	title = std::make_shared<CLabel>(243, 32, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW); | ||||
| 	availableValue = std::make_shared<CLabel>(205, 253, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE); | ||||
| @@ -313,8 +314,8 @@ CSplitWindow::CSplitWindow(const CCreature * creature, std::function<void(int, i | ||||
| 	int leftMax = total - rightMin; | ||||
| 	int rightMax = total - leftMin; | ||||
|  | ||||
| 	ok = std::make_shared<CButton>(Point(20, 263), "IOK6432", CButton::tooltip(), std::bind(&CSplitWindow::apply, this), SDLK_RETURN); | ||||
| 	cancel = std::make_shared<CButton>(Point(214, 263), "ICN6432", CButton::tooltip(), std::bind(&CSplitWindow::close, this), SDLK_ESCAPE); | ||||
| 	ok = std::make_shared<CButton>(Point(20, 263), "IOK6432", CButton::tooltip(), std::bind(&CSplitWindow::apply, this), EShortcut::GLOBAL_CONFIRM); | ||||
| 	cancel = std::make_shared<CButton>(Point(214, 263), "ICN6432", CButton::tooltip(), std::bind(&CSplitWindow::close, this), EShortcut::GLOBAL_CANCEL); | ||||
|  | ||||
| 	int sliderPosition = total - leftMin - rightMin; | ||||
|  | ||||
| @@ -403,7 +404,7 @@ CLevelWindow::CLevelWindow(const CGHeroInstance * hero, PrimarySkill::PrimarySki | ||||
| 	} | ||||
|  | ||||
| 	portrait = std::make_shared<CAnimImage>("PortraitsLarge", hero->portrait, 0, 170, 66); | ||||
| 	ok = std::make_shared<CButton>(Point(297, 413), "IOKAY", CButton::tooltip(), std::bind(&CLevelWindow::close, this), SDLK_RETURN); | ||||
| 	ok = std::make_shared<CButton>(Point(297, 413), "IOKAY", CButton::tooltip(), std::bind(&CLevelWindow::close, this), EShortcut::GLOBAL_CONFIRM); | ||||
|  | ||||
| 	//%s has gained a level. | ||||
| 	mainTitle = std::make_shared<CLabel>(192, 33, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, boost::str(boost::format(CGI->generaltexth->allTexts[444]) % hero->getNameTranslated())); | ||||
| @@ -459,9 +460,9 @@ CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj) | ||||
| 	rumor = std::make_shared<CTextBox>(rumorText, Rect(32, 190, 330, 68), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE); | ||||
|  | ||||
| 	statusbar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); | ||||
| 	cancel = std::make_shared<CButton>(Point(310, 428), "ICANCEL.DEF", CButton::tooltip(CGI->generaltexth->tavernInfo[7]), std::bind(&CTavernWindow::close, this), SDLK_ESCAPE); | ||||
| 	recruit = std::make_shared<CButton>(Point(272, 355), "TPTAV01.DEF", CButton::tooltip(), std::bind(&CTavernWindow::recruitb, this), SDLK_RETURN); | ||||
| 	thiefGuild = std::make_shared<CButton>(Point(22, 428), "TPTAV02.DEF", CButton::tooltip(CGI->generaltexth->tavernInfo[5]), std::bind(&CTavernWindow::thievesguildb, this), SDLK_t); | ||||
| 	cancel = std::make_shared<CButton>(Point(310, 428), "ICANCEL.DEF", CButton::tooltip(CGI->generaltexth->tavernInfo[7]), std::bind(&CTavernWindow::close, this), EShortcut::GLOBAL_CANCEL); | ||||
| 	recruit = std::make_shared<CButton>(Point(272, 355), "TPTAV01.DEF", CButton::tooltip(), std::bind(&CTavernWindow::recruitb, this), EShortcut::GLOBAL_CONFIRM); | ||||
| 	thiefGuild = std::make_shared<CButton>(Point(22, 428), "TPTAV02.DEF", CButton::tooltip(CGI->generaltexth->tavernInfo[5]), std::bind(&CTavernWindow::thievesguildb, this), EShortcut::ADVENTURE_THIEVES_GUILD); | ||||
|  | ||||
| 	if(LOCPLINT->cb->getResourceAmount(EGameResID::GOLD) < GameConstants::HERO_GOLD_COST) //not enough gold | ||||
| 	{ | ||||
| @@ -982,7 +983,7 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, | ||||
| 		luck[b] = std::make_shared<MoraleLuckBox>(false,  Rect(Point(212 + 490 * b, 39), Point(32, 32)), true); | ||||
| 	} | ||||
|  | ||||
| 	quit = std::make_shared<CButton>(Point(732, 567), "IOKAY.DEF", CGI->generaltexth->zelp[600], std::bind(&CExchangeWindow::close, this), SDLK_RETURN); | ||||
| 	quit = std::make_shared<CButton>(Point(732, 567), "IOKAY.DEF", CGI->generaltexth->zelp[600], std::bind(&CExchangeWindow::close, this), EShortcut::GLOBAL_CONFIRM); | ||||
| 	if(queryID.getNum() > 0) | ||||
| 		quit->addCallback([=](){ LOCPLINT->cb->selectionMade(0, queryID); }); | ||||
|  | ||||
| @@ -1098,8 +1099,8 @@ CShipyardWindow::CShipyardWindow(const TResources & cost, int state, BoatId boat | ||||
| 	goldPic = std::make_shared<CAnimImage>("RESOURCE",GameResID(EGameResID::GOLD), 0, 100, 244); | ||||
| 	woodPic = std::make_shared<CAnimImage>("RESOURCE", GameResID(EGameResID::WOOD), 0, 196, 244); | ||||
|  | ||||
| 	quit = std::make_shared<CButton>(Point(224, 312), "ICANCEL", CButton::tooltip(CGI->generaltexth->allTexts[599]), std::bind(&CShipyardWindow::close, this), SDLK_ESCAPE); | ||||
| 	build = std::make_shared<CButton>(Point(42, 312), "IBUY30", CButton::tooltip(CGI->generaltexth->allTexts[598]), std::bind(&CShipyardWindow::close, this), SDLK_RETURN); | ||||
| 	quit = std::make_shared<CButton>(Point(224, 312), "ICANCEL", CButton::tooltip(CGI->generaltexth->allTexts[599]), std::bind(&CShipyardWindow::close, this), EShortcut::GLOBAL_CANCEL); | ||||
| 	build = std::make_shared<CButton>(Point(42, 312), "IBUY30", CButton::tooltip(CGI->generaltexth->allTexts[598]), std::bind(&CShipyardWindow::close, this), EShortcut::GLOBAL_CONFIRM); | ||||
| 	build->addCallback(onBuy); | ||||
|  | ||||
| 	for(auto i = EGameResID::WOOD; i <= EGameResID::GOLD; vstd::advance(i, 1)) | ||||
| @@ -1199,9 +1200,9 @@ CTransformerWindow::CTransformerWindow(const CGHeroInstance * _hero, const CGTow | ||||
| 			items.push_back(std::make_shared<CItem>(this, army->getStackCount(SlotID(i)), i)); | ||||
| 	} | ||||
|  | ||||
| 	all = std::make_shared<CButton>(Point(146, 416), "ALTARMY.DEF", CGI->generaltexth->zelp[590], [&](){ addAll(); }, SDLK_a); | ||||
| 	convert = std::make_shared<CButton>(Point(269, 416), "ALTSACR.DEF", CGI->generaltexth->zelp[591], [&](){ makeDeal(); }, SDLK_RETURN); | ||||
| 	cancel = std::make_shared<CButton>(Point(392, 416), "ICANCEL.DEF", CGI->generaltexth->zelp[592], [&](){ close(); },SDLK_ESCAPE); | ||||
| 	all = std::make_shared<CButton>(Point(146, 416), "ALTARMY.DEF", CGI->generaltexth->zelp[590], [&](){ addAll(); }, EShortcut::RECRUITMENT_UPGRADE_ALL); | ||||
| 	convert = std::make_shared<CButton>(Point(269, 416), "ALTSACR.DEF", CGI->generaltexth->zelp[591], [&](){ makeDeal(); }, EShortcut::GLOBAL_CONFIRM); | ||||
| 	cancel = std::make_shared<CButton>(Point(392, 416), "ICANCEL.DEF", CGI->generaltexth->zelp[592], [&](){ close(); },EShortcut::GLOBAL_CANCEL); | ||||
| 	statusbar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); | ||||
|  | ||||
| 	titleLeft = std::make_shared<CLabel>(153, 29,FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[485]);//holding area | ||||
| @@ -1315,7 +1316,7 @@ CUniversityWindow::CUniversityWindow(const CGHeroInstance * _hero, const IMarket | ||||
| 	for(int i=0; i<goods.size(); i++)//prepare clickable items | ||||
| 		items.push_back(std::make_shared<CItem>(this, goods[i], 54+i*104, 234)); | ||||
|  | ||||
| 	cancel = std::make_shared<CButton>(Point(200, 313), "IOKAY.DEF", CGI->generaltexth->zelp[632], [&](){ close(); }, SDLK_RETURN); | ||||
| 	cancel = std::make_shared<CButton>(Point(200, 313), "IOKAY.DEF", CGI->generaltexth->zelp[632], [&](){ close(); }, EShortcut::GLOBAL_CONFIRM); | ||||
| 	statusbar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); | ||||
| } | ||||
|  | ||||
| @@ -1353,10 +1354,10 @@ CUnivConfirmWindow::CUnivConfirmWindow(CUniversityWindow * owner_, int SKILL, bo | ||||
| 	boost::replace_first(text, "%s", CGI->skillh->getByIndex(SKILL)->getNameTranslated()); | ||||
| 	boost::replace_first(text, "%d", "2000"); | ||||
|  | ||||
| 	confirm = std::make_shared<CButton>(Point(148, 299), "IBY6432.DEF", CButton::tooltip(hoverText, text), [=](){makeDeal(SKILL);}, SDLK_RETURN); | ||||
| 	confirm = std::make_shared<CButton>(Point(148, 299), "IBY6432.DEF", CButton::tooltip(hoverText, text), [=](){makeDeal(SKILL);}, EShortcut::GLOBAL_CONFIRM); | ||||
| 	confirm->block(!available); | ||||
|  | ||||
| 	cancel = std::make_shared<CButton>(Point(252,299), "ICANCEL.DEF", CGI->generaltexth->zelp[631], [&](){ close(); }, SDLK_ESCAPE); | ||||
| 	cancel = std::make_shared<CButton>(Point(252,299), "ICANCEL.DEF", CGI->generaltexth->zelp[631], [&](){ close(); }, EShortcut::GLOBAL_CANCEL); | ||||
| 	statusbar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); | ||||
| } | ||||
|  | ||||
| @@ -1376,7 +1377,7 @@ CGarrisonWindow::CGarrisonWindow(const CArmedInstance * up, const CGHeroInstance | ||||
| 		auto split = std::make_shared<CButton>(Point(88, 314), "IDV6432.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3], ""), [&](){ garr->splitClick(); } ); | ||||
| 		garr->addSplitBtn(split); | ||||
| 	} | ||||
| 	quit = std::make_shared<CButton>(Point(399, 314), "IOK6432.DEF", CButton::tooltip(CGI->generaltexth->tcommands[8], ""), [&](){ close(); }, SDLK_RETURN); | ||||
| 	quit = std::make_shared<CButton>(Point(399, 314), "IOK6432.DEF", CButton::tooltip(CGI->generaltexth->tcommands[8], ""), [&](){ close(); }, EShortcut::GLOBAL_CONFIRM); | ||||
|  | ||||
| 	std::string titleText; | ||||
| 	if(down->tempOwner == up->tempOwner) | ||||
| @@ -1426,7 +1427,7 @@ CHillFortWindow::CHillFortWindow(const CGHeroInstance * visitor, const CGObjectI | ||||
|  | ||||
| 	for(int i = 0; i < slotsCount; i++) | ||||
| 	{ | ||||
| 		upgrade[i] = std::make_shared<CButton>(Point(107 + i * 76, 171), "", CButton::tooltip(getTextForSlot(SlotID(i))), [=](){ makeDeal(SlotID(i)); }, SDLK_1 + i); | ||||
| 		upgrade[i] = std::make_shared<CButton>(Point(107 + i * 76, 171), "", CButton::tooltip(getTextForSlot(SlotID(i))), [=](){ makeDeal(SlotID(i)); }, vstd::advance_r(EShortcut::SELECT_INDEX_1, i)); | ||||
| 		for(auto image : { "APHLF1R.DEF", "APHLF1Y.DEF", "APHLF1G.DEF" }) | ||||
| 			upgrade[i]->addImage(image); | ||||
|  | ||||
| @@ -1437,11 +1438,11 @@ CHillFortWindow::CHillFortWindow(const CGHeroInstance * visitor, const CGObjectI | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	upgradeAll = std::make_shared<CButton>(Point(30, 231), "", CButton::tooltip(CGI->generaltexth->allTexts[432]), [&](){ makeDeal(SlotID(slotsCount));}, SDLK_0); | ||||
| 	upgradeAll = std::make_shared<CButton>(Point(30, 231), "", CButton::tooltip(CGI->generaltexth->allTexts[432]), [&](){ makeDeal(SlotID(slotsCount));}, EShortcut::RECRUITMENT_UPGRADE_ALL); | ||||
| 	for(auto image : { "APHLF4R.DEF", "APHLF4Y.DEF", "APHLF4G.DEF" }) | ||||
| 		upgradeAll->addImage(image); | ||||
|  | ||||
| 	quit = std::make_shared<CButton>(Point(294, 275), "IOKAY.DEF", CButton::tooltip(), std::bind(&CHillFortWindow::close, this), SDLK_RETURN); | ||||
| 	quit = std::make_shared<CButton>(Point(294, 275), "IOKAY.DEF", CButton::tooltip(), std::bind(&CHillFortWindow::close, this), EShortcut::GLOBAL_CONFIRM); | ||||
| 	statusbar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); | ||||
|  | ||||
| 	garr = std::make_shared<CGarrisonInt>(108, 60, 18, Point(), hero, nullptr); | ||||
| @@ -1617,8 +1618,7 @@ CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner): | ||||
| 	SThievesGuildInfo tgi; //info to be displayed | ||||
| 	LOCPLINT->cb->getThievesGuildInfo(tgi, owner); | ||||
|  | ||||
| 	exitb = std::make_shared<CButton>(Point(748, 556), "TPMAGE1", CButton::tooltip(CGI->generaltexth->allTexts[600]), [&](){ close();}, SDLK_RETURN); | ||||
| 	exitb->assignedKeys.insert(SDLK_ESCAPE); | ||||
| 	exitb = std::make_shared<CButton>(Point(748, 556), "TPMAGE1", CButton::tooltip(CGI->generaltexth->allTexts[600]), [&](){ close();}, EShortcut::GLOBAL_RETURN); | ||||
| 	statusbar = CGStatusBar::create(3, 555, "TStatBar.bmp", 742); | ||||
|  | ||||
| 	resdatabar = std::make_shared<CMinorResDataBar>(); | ||||
| @@ -1814,7 +1814,7 @@ void CObjectListWindow::init(std::shared_ptr<CIntObject> titleWidget_, std::stri | ||||
|  | ||||
| 	title = std::make_shared<CLabel>(152, 27, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW, _title); | ||||
| 	descr = std::make_shared<CLabel>(145, 133, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, _descr); | ||||
| 	exit = std::make_shared<CButton>( Point(228, 402), "ICANCEL.DEF", CButton::tooltip(), std::bind(&CObjectListWindow::exitPressed, this), SDLK_ESCAPE); | ||||
| 	exit = std::make_shared<CButton>( Point(228, 402), "ICANCEL.DEF", CButton::tooltip(), std::bind(&CObjectListWindow::exitPressed, this), EShortcut::GLOBAL_CANCEL); | ||||
|  | ||||
| 	if(titleWidget) | ||||
| 	{ | ||||
| @@ -1827,7 +1827,7 @@ void CObjectListWindow::init(std::shared_ptr<CIntObject> titleWidget_, std::stri | ||||
| 		Point(14, 151), Point(0, 25), 9, items.size(), 0, 1, Rect(262, -32, 256, 256) ); | ||||
| 	list->type |= REDRAW_PARENT; | ||||
|  | ||||
| 	ok = std::make_shared<CButton>(Point(15, 402), "IOKAY.DEF", CButton::tooltip(), std::bind(&CObjectListWindow::elementSelected, this), SDLK_RETURN); | ||||
| 	ok = std::make_shared<CButton>(Point(15, 402), "IOKAY.DEF", CButton::tooltip(), std::bind(&CObjectListWindow::elementSelected, this), EShortcut::GLOBAL_CONFIRM); | ||||
| 	ok->block(!list->size()); | ||||
| } | ||||
|  | ||||
| @@ -1875,28 +1875,28 @@ void CObjectListWindow::changeSelection(size_t which) | ||||
| 	selected = which; | ||||
| } | ||||
|  | ||||
| void CObjectListWindow::keyPressed (const SDL_Keycode & key) | ||||
| void CObjectListWindow::keyPressed (EShortcut key) | ||||
| { | ||||
| 	int sel = static_cast<int>(selected); | ||||
|  | ||||
| 	switch(key) | ||||
| 	{ | ||||
| 	break; case SDLK_UP: | ||||
| 	break; case EShortcut::SELECT_UP: | ||||
| 		sel -=1; | ||||
|  | ||||
| 	break; case SDLK_DOWN: | ||||
| 	break; case EShortcut::SELECT_DOWN: | ||||
| 		sel +=1; | ||||
|  | ||||
| 	break; case SDLK_PAGEUP: | ||||
| 	break; case EShortcut::SELECT_PAGE_UP: | ||||
| 		sel -=9; | ||||
|  | ||||
| 	break; case SDLK_PAGEDOWN: | ||||
| 	break; case EShortcut::SELECT_PAGE_DOWN: | ||||
| 		sel +=9; | ||||
|  | ||||
| 	break; case SDLK_HOME: | ||||
| 	break; case EShortcut::SELECT_FIRST: | ||||
| 		sel = 0; | ||||
|  | ||||
| 	break; case SDLK_END: | ||||
| 	break; case EShortcut::SELECT_LAST: | ||||
| 		sel = static_cast<int>(items.size()); | ||||
|  | ||||
| 	break; default: | ||||
|   | ||||
| @@ -194,7 +194,7 @@ public: | ||||
| 	std::shared_ptr<CIntObject> genItem(size_t index); | ||||
| 	void elementSelected();//call callback and close this window | ||||
| 	void changeSelection(size_t which); | ||||
| 	void keyPressed(const SDL_Keycode & key) override; | ||||
| 	void keyPressed(EShortcut key) override; | ||||
| }; | ||||
|  | ||||
| class CTavernWindow : public CStatusbarWindow | ||||
|   | ||||
| @@ -26,6 +26,7 @@ | ||||
| #include "../windows/CMessage.h" | ||||
| #include "../renderSDL/SDL_Extensions.h" | ||||
| #include "../gui/CursorHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
|  | ||||
| #include "../../CCallback.h" | ||||
|  | ||||
| @@ -79,9 +80,6 @@ CSelWindow::CSelWindow(const std::string &Text, PlayerColor player, int charperl | ||||
|  | ||||
| 	text = std::make_shared<CTextBox>(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE); | ||||
|  | ||||
| 	buttons.front()->assignedKeys.insert(SDLK_RETURN); //first button - reacts on enter | ||||
| 	buttons.back()->assignedKeys.insert(SDLK_ESCAPE); //last button - reacts on escape | ||||
|  | ||||
| 	if (buttons.size() > 1 && askID.getNum() >= 0) //cancel button functionality | ||||
| 	{ | ||||
| 		buttons.back()->addCallback([askID]() { | ||||
| @@ -96,8 +94,8 @@ CSelWindow::CSelWindow(const std::string &Text, PlayerColor player, int charperl | ||||
| 		addChild(comps[i].get()); | ||||
| 		components.push_back(comps[i]); | ||||
| 		comps[i]->onSelect = std::bind(&CSelWindow::selectionChange,this,i); | ||||
| 		if(i<9) | ||||
| 			comps[i]->assignedKeys.insert(SDLK_1+i); | ||||
| 		if(i<8) | ||||
| 			comps[i]->assignedKey = vstd::advance_r(EShortcut::SELECT_INDEX_1,i); | ||||
| 	} | ||||
| 	CMessage::drawIWindow(this, Text, player); | ||||
| } | ||||
| @@ -137,12 +135,6 @@ CInfoWindow::CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo | ||||
| 		text->resize(text->label->textSize); | ||||
| 	} | ||||
|  | ||||
| 	if(buttons.size()) | ||||
| 	{ | ||||
| 		buttons.front()->assignedKeys.insert(SDLK_RETURN); //first button - reacts on enter | ||||
| 		buttons.back()->assignedKeys.insert(SDLK_ESCAPE); //last button - reacts on escape | ||||
| 	} | ||||
|  | ||||
| 	for(auto & comp : comps) | ||||
| 	{ | ||||
| 		comp->recActions = 0xff & ~DISPOSE; | ||||
|   | ||||
| @@ -14,6 +14,7 @@ | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/CreatureCostBox.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../../CCallback.h" | ||||
| #include "../../lib/ResourceSet.h" | ||||
| #include "../../lib/CCreatureHandler.h" | ||||
| @@ -29,20 +30,19 @@ void QuickRecruitmentWindow::setButtons() | ||||
|  | ||||
| void QuickRecruitmentWindow::setCancelButton() | ||||
| { | ||||
| 	cancelButton = std::make_shared<CButton>(Point((pos.w / 2) + 48, 418), "ICN6432.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_ESCAPE); | ||||
| 	cancelButton = std::make_shared<CButton>(Point((pos.w / 2) + 48, 418), "ICN6432.DEF", CButton::tooltip(), [&](){ close(); }, EShortcut::GLOBAL_CANCEL); | ||||
| 	cancelButton->setImageOrder(0, 1, 2, 3); | ||||
| } | ||||
|  | ||||
| void QuickRecruitmentWindow::setBuyButton() | ||||
| { | ||||
| 	buyButton = std::make_shared<CButton>(Point((pos.w / 2) - 32, 418), "IBY6432.DEF", CButton::tooltip(), [&](){ purchaseUnits(); }, SDLK_RETURN); | ||||
| 	cancelButton->assignedKeys.insert(SDLK_ESCAPE); | ||||
| 	buyButton = std::make_shared<CButton>(Point((pos.w / 2) - 32, 418), "IBY6432.DEF", CButton::tooltip(), [&](){ purchaseUnits(); }, EShortcut::GLOBAL_CONFIRM); | ||||
| 	buyButton->setImageOrder(0, 1, 2, 3); | ||||
| } | ||||
|  | ||||
| void QuickRecruitmentWindow::setMaxButton() | ||||
| { | ||||
| 	maxButton = std::make_shared<CButton>(Point((pos.w/2)-112, 418), "IRCBTNS.DEF", CButton::tooltip(), [&](){ maxAllCards(cards); }, SDLK_m); | ||||
| 	maxButton = std::make_shared<CButton>(Point((pos.w/2)-112, 418), "IRCBTNS.DEF", CButton::tooltip(), [&](){ maxAllCards(cards); }, EShortcut::RECRUITMENT_MAX); | ||||
| 	maxButton->setImageOrder(0, 1, 2, 3); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
| 	"roe" : | ||||
| 	{ | ||||
| 		"images" : [ {"x": 0, "y": 0, "name":"CAMPBACK"} ], | ||||
| 		"exitbutton" : {"x": 658, "y": 482, "name":"CMPSCAN", "hotkey" : 27}, | ||||
| 		"exitbutton" : {"x": 658, "y": 482, "name":"CMPSCAN" }, | ||||
| 		"items": | ||||
| 		[ | ||||
| 			{ "x":90,  "y":72,  "file":"DATA/GOOD1.H3C",    "image":"CAMPGD1S", "video":"CGOOD1",   "open": true }, | ||||
| @@ -22,7 +22,7 @@ | ||||
| 			{"x": 34,  "y": 417, "name":"CAMP1FWX"},//one campaign have special inactive image | ||||
| 			{"x": 385, "y": 401, "name":"CAMPNOSC"},//and the last one is not present | ||||
| 		], | ||||
| 		"exitbutton" : {"x": 658, "y": 482, "name":"CMPSCAN", "hotkey" : 27}, | ||||
| 		"exitbutton" : {"x": 658, "y": 482, "name":"CMPSCAN" }, | ||||
| 		"items": | ||||
| 		[ | ||||
| 			{ "x":90,  "y":72,  "file":"DATA/AB.H3C",       "image":"CAMP1AB7", "video":"C1ab7", "open": true }, | ||||
| @@ -36,7 +36,7 @@ | ||||
| 	"sod": | ||||
| 	{ | ||||
| 		"images" : [ {"x": 0, "y": 0, "name":"CAMPBKX2"} ], | ||||
| 		"exitbutton" : {"x": 658, "y": 482, "name":"CMPSCAN", "hotkey" : 27}, | ||||
| 		"exitbutton" : {"x": 658, "y": 482, "name":"CMPSCAN" }, | ||||
| 		"items": | ||||
| 		[ | ||||
| 			{ "x":90,  "y":72,  "file":"DATA/GEM.H3C",      "image":"CAMPNB1", "video":"NEW",     "open": true }, | ||||
| @@ -47,18 +47,5 @@ | ||||
| 			{ "x":34,  "y":417, "file":"DATA/FINAL.H3C",    "image":"CAMPUA1", "video":"UNHOLY",  "open": true }, | ||||
| 			{ "x":404, "y":414, "file":"DATA/SECRET.H3C",  "image":"CAMPSP1", "video":"SPECTRE", "open": true } | ||||
| 		] | ||||
| 	}, | ||||
| 	"wog" :  | ||||
| 	{ | ||||
| 		/// wog campaigns, currently has no assigned button in campaign screen and thus unused | ||||
| 		"images" : [ {"x": 0, "y": 0, "name":"CAMPZALL"} ], | ||||
| 		"exitbutton" : {"x": 658, "y": 482, "name":"CMPSCAN", "hotkey" : 27}, | ||||
| 		"items": | ||||
| 		[ | ||||
| 			{ "x":90,  "y":72,  "file":"DATA/ZC1.H3C", "image":"CAMPZ01", "open": true}, | ||||
| 			{ "x":539, "y":72,  "file":"DATA/ZC2.H3C", "image":"CAMPZ02", "open": true}, | ||||
| 			{ "x":43,  "y":245, "file":"DATA/ZC3.H3C", "image":"CAMPZ03", "open": true}, | ||||
| 			{ "x":311, "y":242, "file":"DATA/ZC4.H3C", "image":"CAMPZ04", "open": true} | ||||
| 		] | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -17,22 +17,22 @@ | ||||
| 				"name" : "main", | ||||
| 				"buttons": | ||||
| 				[ | ||||
| 					{"x": 644, "y":  70, "center" : true, "name":"MMENUNG", "hotkey" : 110, "help": 3, "command": "to new"}, | ||||
| 					{"x": 645, "y": 192, "center" : true, "name":"MMENULG", "hotkey" : 108, "help": 4, "command": "to load"}, | ||||
| 					{"x": 643, "y": 296, "center" : true, "name":"MMENUHS", "hotkey" : 104, "help": 5, "command": "highscores"}, | ||||
| 					{"x": 643, "y": 414, "center" : true, "name":"MMENUCR", "hotkey" : 99,  "help": 6, "command": "to credits"}, | ||||
| 					{"x": 643, "y": 520, "center" : true, "name":"MMENUQT", "hotkey" : 27,  "help": 7, "command": "exit"} | ||||
| 					{"x": 644, "y":  70, "center" : true, "name":"MMENUNG", "shortcut" : "mainMenuNew", "help": 3, "command": "to new"}, | ||||
| 					{"x": 645, "y": 192, "center" : true, "name":"MMENULG", "shortcut" : "mainMenuLoad", "help": 4, "command": "to load"}, | ||||
| 					{"x": 643, "y": 296, "center" : true, "name":"MMENUHS", "shortcut" : "mainMenuScores", "help": 5, "command": "highscores"}, | ||||
| 					{"x": 643, "y": 414, "center" : true, "name":"MMENUCR", "shortcut" : "mainMenuCredits", "help": 6, "command": "to credits"}, | ||||
| 					{"x": 643, "y": 520, "center" : true, "name":"MMENUQT", "shortcut" : "mainMenuQuit", "help": 7, "command": "exit"} | ||||
| 				] | ||||
| 			}, | ||||
| 			{ | ||||
| 				"name" : "new", | ||||
| 				"buttons": | ||||
| 				[ | ||||
| 					{"x": 649, "y":  65, "center" : true, "name":"GTSINGL", "hotkey" : 115, "help": 10, "command": "start single"}, | ||||
| 					{"x": 649, "y": 180, "center" : true, "name":"GTMULTI", "hotkey" : 109, "help": 12, "command": "start multi"}, | ||||
| 					{"x": 646, "y": 298, "center" : true, "name":"GTCAMPN", "hotkey" : 99,  "help": 11, "command": "to campaign"}, | ||||
| 					{"x": 647, "y": 412, "center" : true, "name":"GTTUTOR", "hotkey" : 116, "help": 13, "command": "start tutorial"}, | ||||
| 					{"x": 645, "y": 517, "center" : true, "name":"GTBACK",  "hotkey" : 27,  "help": 14, "command": "to main"} | ||||
| 					{"x": 649, "y":  65, "center" : true, "name":"GTSINGL", "shortcut" : "mainMenuSingleplayer", "help": 10, "command": "start single"}, | ||||
| 					{"x": 649, "y": 180, "center" : true, "name":"GTMULTI", "shortcut" : "mainMenuMultiplayer", "help": 12, "command": "start multi"}, | ||||
| 					{"x": 646, "y": 298, "center" : true, "name":"GTCAMPN", "shortcut" : "mainMenuCampaign", "help": 11, "command": "to campaign"}, | ||||
| 					{"x": 647, "y": 412, "center" : true, "name":"GTTUTOR", "shortcut" : "mainMenuTutorial", "help": 13, "command": "start tutorial"}, | ||||
| 					{"x": 645, "y": 517, "center" : true, "name":"GTBACK",  "shortcut" : "mainMenuBack", "help": 14, "command": "to main"} | ||||
| 				], | ||||
| 				"images": [ {"x": 114, "y": 312, "name":"NEWGAME"} ] | ||||
| 			}, | ||||
| @@ -40,11 +40,11 @@ | ||||
| 				"name" : "load", | ||||
| 				"buttons": | ||||
| 				[ | ||||
| 					{"x": 649, "y":  65, "center" : true, "name":"GTSINGL", "hotkey" : 115, "help": 10, "command": "load single"}, | ||||
| 					{"x": 649, "y": 180, "center" : true, "name":"GTMULTI", "hotkey" : 109, "help": 12, "command": "load multi"}, | ||||
| 					{"x": 646, "y": 298, "center" : true, "name":"GTCAMPN", "hotkey" : 99,  "help": 11, "command": "load campaign"}, | ||||
| 					{"x": 647, "y": 412, "center" : true, "name":"GTTUTOR", "hotkey" : 116, "help": 13, "command": "load tutorial"}, | ||||
| 					{"x": 645, "y": 517, "center" : true, "name":"GTBACK",  "hotkey" : 27,  "help": 14, "command": "to main"} | ||||
| 					{"x": 649, "y":  65, "center" : true, "name":"GTSINGL", "shortcut" : "mainMenuSingleplayer", "help": 10, "command": "load single"}, | ||||
| 					{"x": 649, "y": 180, "center" : true, "name":"GTMULTI", "shortcut" : "mainMenuMultiplayer", "help": 12, "command": "load multi"}, | ||||
| 					{"x": 646, "y": 298, "center" : true, "name":"GTCAMPN", "shortcut" : "mainMenuCampaign", "help": 11, "command": "load campaign"}, | ||||
| 					{"x": 647, "y": 412, "center" : true, "name":"GTTUTOR", "shortcut" : "mainMenuTutorial", "help": 13, "command": "load tutorial"}, | ||||
| 					{"x": 645, "y": 517, "center" : true, "name":"GTBACK",  "shortcut" : "mainMenuBack", "help": 14, "command": "to main"} | ||||
| 				], | ||||
| 				"images": [ {"x": 114, "y": 312, "name":"LOADGAME"} ] | ||||
| 			}, | ||||
| @@ -52,11 +52,11 @@ | ||||
| 				"name" : "campaign", | ||||
| 				"buttons": | ||||
| 				[ | ||||
| 					{"x": 634, "y":  67, "center" : true, "name":"CSSSOD", "hotkey" : 119, "command": "campaigns sod"}, | ||||
| 					{"x": 637, "y": 181, "center" : true, "name":"CSSROE", "hotkey" : 114, "command": "campaigns roe"}, | ||||
| 					{"x": 638, "y": 301, "center" : true, "name":"CSSARM", "hotkey" : 97,  "command": "campaigns ab"}, | ||||
| 					{"x": 638, "y": 413, "center" : true, "name":"CSSCUS", "hotkey" : 99,  "command": "start campaign"}, | ||||
| 					{"x": 639, "y": 518, "center" : true, "name":"CSSEXIT", "hotkey" : 27,  "command": "to new"} | ||||
| 					{"x": 634, "y":  67, "center" : true, "name":"CSSSOD",  "shortcut" : "mainMenuCampaignSod", "command": "campaigns sod"}, | ||||
| 					{"x": 637, "y": 181, "center" : true, "name":"CSSROE",  "shortcut" : "mainMenuCampaignRoe", "command": "campaigns roe"}, | ||||
| 					{"x": 638, "y": 301, "center" : true, "name":"CSSARM",  "shortcut" : "mainMenuCampaignAb", "command": "campaigns ab"}, | ||||
| 					{"x": 638, "y": 413, "center" : true, "name":"CSSCUS",  "shortcut" : "mainMenuCampaign", "command": "start campaign"}, | ||||
| 					{"x": 639, "y": 518, "center" : true, "name":"CSSEXIT", "shortcut" : "mainMenuBack",  "command": "to new"} | ||||
| 				], | ||||
| 			} | ||||
| 		] | ||||
|   | ||||
| @@ -22,7 +22,7 @@ | ||||
| 			"image": "icm003", | ||||
| 			"help": "core.help.381", | ||||
| 			"callback": "options", | ||||
| 			"hotkey": "o" | ||||
| 			"hotkey": "globalOptions" | ||||
| 		}, | ||||
|  | ||||
| 		{ | ||||
| @@ -32,7 +32,7 @@ | ||||
| 			"image": "icm001", | ||||
| 			"help": "core.help.379", | ||||
| 			"callback": "surrender", | ||||
| 			"hotkey": "s" | ||||
| 			"hotkey": "battleSurrender" | ||||
| 		}, | ||||
|  | ||||
| 		{ | ||||
| @@ -42,7 +42,7 @@ | ||||
| 			"image": "icm002", | ||||
| 			"help": "core.help.380", | ||||
| 			"callback": "flee", | ||||
| 			"hotkey": "r" | ||||
| 			"hotkey": "battleRetreat" | ||||
| 		}, | ||||
|  | ||||
| 		{ | ||||
| @@ -52,7 +52,7 @@ | ||||
| 			"image": "icm004", | ||||
| 			"help": "core.help.382", | ||||
| 			"callback": "autofight", | ||||
| 			"hotkey": "a" | ||||
| 			"hotkey": "battleAutocombat" | ||||
| 		}, | ||||
|  | ||||
| 		{ | ||||
| @@ -62,7 +62,7 @@ | ||||
| 			"image": "icm005", | ||||
| 			"help": "core.help.385", | ||||
| 			"callback": "spellbook", | ||||
| 			"hotkey": "c" | ||||
| 			"hotkey": "battleCastSpell" | ||||
| 		}, | ||||
|  | ||||
| 		{ | ||||
| @@ -72,7 +72,7 @@ | ||||
| 			"image": "icm006", | ||||
| 			"help": "core.help.386", | ||||
| 			"callback": "wait", | ||||
| 			"hotkey": "w" | ||||
| 			"hotkey": "battleWait" | ||||
| 		}, | ||||
|  | ||||
| 		{ | ||||
| @@ -82,7 +82,7 @@ | ||||
| 			"image": "icm007", | ||||
| 			"help": "core.help.387", | ||||
| 			"callback": "defence", | ||||
| 			"hotkey": ["d", "space"] | ||||
| 			"hotkey": "battleDefend" | ||||
| 		}, | ||||
|  | ||||
| 		{ | ||||
| @@ -92,7 +92,7 @@ | ||||
| 			"image": "ComSlide", | ||||
| 			"callback": "consoleUp", | ||||
| 			"imageOrder": [0, 1, 0, 0], | ||||
| 			"hotkey": "up" | ||||
| 			"hotkey": "battleConsoleUp" | ||||
| 		}, | ||||
|  | ||||
| 		{ | ||||
| @@ -102,7 +102,7 @@ | ||||
| 			"image": "ComSlide", | ||||
| 			"callback": "consoleDown", | ||||
| 			"imageOrder": [2, 3, 2, 2], | ||||
| 			"hotkey": "down" | ||||
| 			"hotkey": "battleConsoleDown" | ||||
| 		}, | ||||
|  | ||||
| 		{ | ||||
| @@ -118,7 +118,7 @@ | ||||
| 			"position": {"x": 213, "y": 560}, | ||||
| 			"image": "icm011", | ||||
| 			"callback": "tacticNext", | ||||
| 			"hotkey": "space" | ||||
| 			"hotkey": "battleTacticsNext" | ||||
| 		}, | ||||
| 		 | ||||
| 		{ | ||||
| @@ -127,7 +127,7 @@ | ||||
| 			"position": {"x": 419, "y": 560}, | ||||
| 			"image": "icm012", | ||||
| 			"callback": "tacticEnd", | ||||
| 			"hotkey": "enter" | ||||
| 			"hotkey": "battleTacticsEnd" | ||||
| 		} | ||||
| 	] | ||||
| } | ||||
|   | ||||
| @@ -47,7 +47,6 @@ | ||||
| 			"image": "settingsWindow/button32", | ||||
| 			"help": "vcmi.systemOptions.resolutionButton", | ||||
| 			"callback": "setGameResolution", | ||||
| 			"hotkey": "g",			 | ||||
| 			"items": | ||||
| 			[ | ||||
| 				{ | ||||
|   | ||||
| @@ -103,7 +103,7 @@ | ||||
| 			"imageOrder": [1, 0, 2, 3], | ||||
| 			"help": "core.help.321", | ||||
| 			"callback": "loadGame", | ||||
| 			"hotkey": "l" | ||||
| 			"hotkey": "gameLoadGame" | ||||
| 		}, | ||||
| 		{ | ||||
| 			"name": "saveButton", | ||||
| @@ -113,7 +113,7 @@ | ||||
| 			"imageOrder": [1, 0, 2, 3], | ||||
| 			"help": "core.help.322", | ||||
| 			"callback": "saveGame", | ||||
| 			"hotkey": "s" | ||||
| 			"hotkey": "gameSaveGame" | ||||
| 		}, | ||||
| 		{ | ||||
| 			"name": "restartButton", | ||||
| @@ -123,7 +123,7 @@ | ||||
| 			"imageOrder": [1, 0, 2, 3], | ||||
| 			"help": "core.help.323", | ||||
| 			"callback": "restartGame", | ||||
| 			"hotkey": "r" | ||||
| 			"hotkey": "gameRestartGame" | ||||
| 		}, | ||||
| 		{ | ||||
| 			"name": "mainMenuButton", | ||||
| @@ -133,7 +133,7 @@ | ||||
| 			"imageOrder": [1, 0, 2, 3], | ||||
| 			"help": "core.help.320", | ||||
| 			"callback": "returnToMainMenu", | ||||
| 			"hotkey": "m" | ||||
| 			"hotkey": "gameMainMenu" | ||||
| 		}, | ||||
| 		{ | ||||
| 			"name": "quitButton", | ||||
| @@ -143,7 +143,7 @@ | ||||
| 			"imageOrder": [1, 0, 2, 3], | ||||
| 			"help": "core.help.324", | ||||
| 			"callback": "quitGame", | ||||
| 			"hotkey": "q" | ||||
| 			"hotkey": "gameQuitGame" | ||||
| 		}, | ||||
| 		{ | ||||
| 			"name": "closeSettingsButton", | ||||
| @@ -153,7 +153,7 @@ | ||||
| 			"imageOrder": [1, 0, 2, 3], | ||||
| 			"help": "core.help.325", | ||||
| 			"callback": "closeWindow", | ||||
| 			"hotkey": ["escape", "backspace"] | ||||
| 			"hotkey": "globalReturn" | ||||
| 		} | ||||
| 	] | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user