1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "twine/input.h"
24 #include "backends/keymapper/keymapper.h"
25 #include "common/events.h"
26 #include "common/keyboard.h"
27 #include "common/system.h"
28 #include "twine/scene/actor.h"
29 #include "twine/twine.h"
30 
31 namespace TwinE {
32 
33 const char *mainKeyMapId = "mainKeyMap";
34 const char *uiKeyMapId = "uiKeyMap";
35 const char *cutsceneKeyMapId = "cutsceneKeyMap";
36 const char *holomapKeyMapId = "holomapKeyMap";
37 
ScopedKeyMap(TwinEEngine * engine,const char * id)38 ScopedKeyMap::ScopedKeyMap(TwinEEngine* engine, const char *id) : _engine(engine) {
39 	_changed = _engine->_input->enableAdditionalKeyMap(id, true);
40 	_keymap = id;
41 }
42 
~ScopedKeyMap()43 ScopedKeyMap::~ScopedKeyMap() {
44 	if (_changed) {
45 		_engine->_input->enableAdditionalKeyMap(_keymap.c_str(), false);
46 	}
47 }
48 
Input(TwinEEngine * engine)49 Input::Input(TwinEEngine *engine) : _engine(engine) {}
50 
isActionActive(TwinEActionType actionType,bool onlyFirstTime) const51 bool Input::isActionActive(TwinEActionType actionType, bool onlyFirstTime) const {
52 	if (onlyFirstTime) {
53 		return _actionStates[actionType] == 1;
54 	}
55 	return _actionStates[actionType] > 0;
56 }
57 
toggleActionIfActive(TwinEActionType actionType)58 bool Input::toggleActionIfActive(TwinEActionType actionType) {
59 	if (_actionStates[actionType] > 0) {
60 		_actionStates[actionType] = 0;
61 		return true;
62 	}
63 	return false;
64 }
65 
toggleAbortAction()66 bool Input::toggleAbortAction() {
67 	bool abortState = false;
68 	abortState |= toggleActionIfActive(TwinEActionType::CutsceneAbort);
69 	abortState |= toggleActionIfActive(TwinEActionType::UIAbort);
70 	abortState |= toggleActionIfActive(TwinEActionType::Escape);
71 	abortState |= toggleActionIfActive(TwinEActionType::HolomapAbort);
72 	return abortState;
73 }
74 
isQuickBehaviourActionActive() const75 bool Input::isQuickBehaviourActionActive() const {
76 	return isActionActive(TwinEActionType::QuickBehaviourNormal) || isActionActive(TwinEActionType::QuickBehaviourAthletic) || isActionActive(TwinEActionType::QuickBehaviourAggressive) || isActionActive(TwinEActionType::QuickBehaviourDiscreet);
77 }
78 
isMoveOrTurnActionActive() const79 bool Input::isMoveOrTurnActionActive() const {
80 	return isActionActive(TwinEActionType::TurnLeft) || isActionActive(TwinEActionType::TurnRight) || isActionActive(TwinEActionType::MoveBackward) || isActionActive(TwinEActionType::MoveForward);
81 }
82 
isHeroActionActive() const83 bool Input::isHeroActionActive() const {
84 	return isActionActive(TwinEActionType::ExecuteBehaviourAction) || isActionActive(TwinEActionType::SpecialAction);
85 }
86 
resetHeroActions()87 bool Input::resetHeroActions() {
88 	return toggleActionIfActive(TwinEActionType::ExecuteBehaviourAction) || toggleActionIfActive(TwinEActionType::SpecialAction);
89 }
90 
enableAdditionalKeyMap(const char * id,bool enable)91 bool Input::enableAdditionalKeyMap(const char *id, bool enable) {
92 	Common::Keymapper *keymapper = g_system->getEventManager()->getKeymapper();
93 	Common::Keymap *keymap = keymapper->getKeymap(id);
94 	if (keymap == nullptr) {
95 		return false;
96 	}
97 	const bool changed = keymap->isEnabled() != enable;
98 	keymap->setEnabled(enable);
99 	return changed;
100 }
101 
enableKeyMap(const char * id)102 void Input::enableKeyMap(const char *id) {
103 	if (_currentKeyMap == id) {
104 		return;
105 	}
106 
107 	Common::Keymapper *keymapper = g_system->getEventManager()->getKeymapper();
108 	const Common::KeymapArray &keymaps = keymapper->getKeymaps();
109 	for (Common::Keymap *keymap : keymaps) {
110 		const Common::String& keymapId = keymap->getId();
111 		if (keymapId == mainKeyMapId || keymapId == uiKeyMapId || keymapId == cutsceneKeyMapId || keymapId == holomapKeyMapId) {
112 			keymap->setEnabled(keymapId == id);
113 		}
114 	}
115 	_currentKeyMap = id;
116 	debug("enable keymap %s", id);
117 }
118 
processCustomEngineEventStart(const Common::Event & event)119 void Input::processCustomEngineEventStart(const Common::Event &event) {
120 	if (!_engine->_cfgfile.Debug) {
121 		switch (event.customType) {
122 		case TwinEActionType::DebugGridCameraPressUp:
123 		case TwinEActionType::DebugGridCameraPressDown:
124 		case TwinEActionType::DebugGridCameraPressLeft:
125 		case TwinEActionType::DebugGridCameraPressRight:
126 		case TwinEActionType::DebugPlaceActorAtCenterOfScreen:
127 		case TwinEActionType::DebugMenu:
128 		case TwinEActionType::DebugMenuActivate:
129 		case TwinEActionType::NextRoom:
130 		case TwinEActionType::PreviousRoom:
131 		case TwinEActionType::ApplyCellingGrid:
132 		case TwinEActionType::IncreaseCellingGridIndex:
133 		case TwinEActionType::DecreaseCellingGridIndex:
134 			break;
135 		default:
136 			_actionStates[event.customType] = 1 + event.kbdRepeat;
137 			break;
138 		}
139 	} else {
140 		_actionStates[event.customType] = 1 + event.kbdRepeat;
141 	}
142 	debug(3, "twine custom event type start: %i", event.customType);
143 }
144 
processCustomEngineEventEnd(const Common::Event & event)145 void Input::processCustomEngineEventEnd(const Common::Event &event) {
146 	_actionStates[event.customType] = 0;
147 	debug(3, "twine custom event type end: %i", event.customType);
148 }
149 
readKeys()150 void Input::readKeys() {
151 	Common::Event event;
152 	while (g_system->getEventManager()->pollEvent(event)) {
153 		switch (event.type) {
154 		case Common::EVENT_CUSTOM_ENGINE_ACTION_END:
155 			processCustomEngineEventEnd(event);
156 			break;
157 		case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
158 			processCustomEngineEventStart(event);
159 			break;
160 		default:
161 			break;
162 		}
163 	}
164 }
165 
getMousePositions() const166 Common::Point Input::getMousePositions() const {
167 	return g_system->getEventManager()->getMousePos();
168 }
169 
isMouseHovering(const Common::Rect & rect) const170 bool Input::isMouseHovering(const Common::Rect &rect) const {
171 	if (!_engine->_cfgfile.Mouse) {
172 		return false;
173 	}
174 	const Common::Point &point = getMousePositions();
175 	return rect.contains(point);
176 }
177 
178 } // namespace TwinE
179