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 "common/scummsys.h"
24 #include "graphics/cursorman.h"
25 #include "common/events.h"
26 #include "common/endian.h"
27 #include "engines/util.h"
28 #include "access/access.h"
29 #include "access/events.h"
30 #include "access/player.h"
31 #include "access/amazon/amazon_resources.h"
32
33 #define CURSOR_WIDTH 16
34 #define CURSOR_HEIGHT 16
35
36 namespace Access {
37
EventsManager(AccessEngine * vm)38 EventsManager::EventsManager(AccessEngine *vm) : _vm(vm) {
39 _cursorId = CURSOR_NONE;
40 _normalMouse = CURSOR_CROSSHAIRS;
41 _frameCounter = 10;
42 _priorFrameTime = 0;
43 _leftButton = _rightButton = false;
44 _middleButton = false;
45 _wheelUp = _wheelDown = false;
46 _mouseCol = _mouseRow = 0;
47 _cursorExitFlag = false;
48 _vbCount = 0;
49 _keyCode = Common::KEYCODE_INVALID;
50 _priorTimerTime = 0;
51 }
52
~EventsManager()53 EventsManager::~EventsManager() {
54 _invCursor.free();
55 }
56
forceSetCursor(CursorType cursorId)57 void EventsManager::forceSetCursor(CursorType cursorId) {
58 setNormalCursor(cursorId);
59 setCursor(cursorId);
60 }
61
setNormalCursor(CursorType cursorId)62 void EventsManager::setNormalCursor(CursorType cursorId) {
63 _normalMouse = cursorId;
64 }
65
setCursor(CursorType cursorId)66 void EventsManager::setCursor(CursorType cursorId) {
67 if (cursorId == _cursorId)
68 return;
69 _cursorId = cursorId;
70
71 if (cursorId == CURSOR_INVENTORY) {
72 // Set the cursor
73 CursorMan.replaceCursor(_invCursor.getPixels(), _invCursor.w, _invCursor.h,
74 _invCursor.w / 2, _invCursor.h / 2, 0);
75 } else {
76 // Get a pointer to the mouse data to use, and get the cursor hotspot
77 const byte *srcP = &_vm->_res->CURSORS[cursorId][0];
78 int hotspotX = (int16)READ_LE_UINT16(srcP);
79 int hotspotY = (int16)READ_LE_UINT16(srcP + 2);
80 srcP += 4;
81
82 // Create a surface to build up the cursor on
83 Graphics::Surface cursorSurface;
84 cursorSurface.create(CURSOR_WIDTH, CURSOR_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
85 byte *destP = (byte *)cursorSurface.getPixels();
86 Common::fill(destP, destP + CURSOR_WIDTH * CURSOR_HEIGHT, 0);
87
88 // Loop to build up the cursor
89 for (int y = 0; y < CURSOR_HEIGHT; ++y) {
90 destP = (byte *)cursorSurface.getBasePtr(0, y);
91 int width = CURSOR_WIDTH;
92 int skip = *srcP++;
93 int plot = *srcP++;
94 if (skip >= width)
95 break;
96
97 // Skip over pixels
98 destP += skip;
99 width -= skip;
100
101 // Write out the pixels to plot
102 while (plot > 0 && width > 0) {
103 *destP++ = *srcP++;
104 --plot;
105 --width;
106 }
107 }
108
109 // Set the cursor
110 CursorMan.replaceCursor(cursorSurface.getPixels(), CURSOR_WIDTH, CURSOR_HEIGHT,
111 hotspotX, hotspotY, 0);
112
113 // Free the cursor surface
114 cursorSurface.free();
115 }
116 }
117
setCursorData(Graphics::ManagedSurface * src,const Common::Rect & r)118 void EventsManager::setCursorData(Graphics::ManagedSurface *src, const Common::Rect &r) {
119 _invCursor.create(r.width(), r.height(), Graphics::PixelFormat::createFormatCLUT8());
120 _invCursor.copyRectToSurface(*src, 0, 0, r);
121 }
122
showCursor()123 void EventsManager::showCursor() {
124 CursorMan.showMouse(true);
125 }
126
hideCursor()127 void EventsManager::hideCursor() {
128 CursorMan.showMouse(false);
129 }
130
isCursorVisible()131 bool EventsManager::isCursorVisible() {
132 return CursorMan.isVisible();
133 }
134
pollEvents(bool skipTimers)135 void EventsManager::pollEvents(bool skipTimers) {
136 if (checkForNextFrameCounter()) {
137 nextFrame();
138 }
139
140 if (checkForNextTimerUpdate() && !skipTimers)
141 nextTimer();
142
143 _vm->_sound->checkSoundQueue();
144
145 _wheelUp = _wheelDown = false;
146
147 Common::Event event;
148 while (g_system->getEventManager()->pollEvent(event)) {
149 switch (event.type) {
150 case Common::EVENT_QUIT:
151 case Common::EVENT_RETURN_TO_LAUNCHER:
152 return;
153
154 case Common::EVENT_KEYDOWN:
155 // Check for debugger
156 keyControl(event.kbd.keycode, true);
157 return;
158 case Common::EVENT_KEYUP:
159 keyControl(event.kbd.keycode, false);
160 return;
161 case Common::EVENT_MOUSEMOVE:
162 _mousePos = event.mouse;
163 _mouseCol = _mousePos.x / 8;
164 _mouseRow = _mousePos.y / 8;
165 break;
166 case Common::EVENT_LBUTTONDOWN:
167 _leftButton = true;
168 return;
169 case Common::EVENT_LBUTTONUP:
170 _leftButton = false;
171 return;
172 case Common::EVENT_RBUTTONDOWN:
173 _rightButton = true;
174 return;
175 case Common::EVENT_RBUTTONUP:
176 _rightButton = false;
177 return;
178 case Common::EVENT_MBUTTONDOWN:
179 _middleButton = true;
180 return;
181 case Common::EVENT_MBUTTONUP:
182 _middleButton = false;
183 return;
184 case Common::EVENT_WHEELUP:
185 _wheelUp = true;
186 return;
187 case Common::EVENT_WHEELDOWN:
188 _wheelDown = true;
189 return;
190 default:
191 break;
192 }
193 }
194 }
195
keyControl(Common::KeyCode keycode,bool isKeyDown)196 void EventsManager::keyControl(Common::KeyCode keycode, bool isKeyDown) {
197 Player &player = *_vm->_player;
198
199 if (!isKeyDown) {
200 if (player._move != NONE) {
201 _keyCode = Common::KEYCODE_INVALID;
202 player._move = NONE;
203 }
204 return;
205 }
206
207 _keyCode = keycode;
208
209 switch (keycode) {
210 case Common::KEYCODE_UP:
211 case Common::KEYCODE_KP8:
212 player._move = UP;
213 break;
214 case Common::KEYCODE_DOWN:
215 case Common::KEYCODE_KP2:
216 player._move = DOWN;
217 break;
218 case Common::KEYCODE_LEFT:
219 case Common::KEYCODE_KP4:
220 player._move = LEFT;
221 break;
222 case Common::KEYCODE_RIGHT:
223 case Common::KEYCODE_KP6:
224 player._move = RIGHT;
225 break;
226 case Common::KEYCODE_KP7:
227 player._move = UPLEFT;
228 break;
229 case Common::KEYCODE_KP9:
230 player._move = UPRIGHT;
231 break;
232 case Common::KEYCODE_KP1:
233 player._move = DOWNLEFT;
234 break;
235 case Common::KEYCODE_KP3:
236 player._move = DOWNRIGHT;
237 break;
238 default:
239 break;
240 }
241 }
242
pollEventsAndWait()243 void EventsManager::pollEventsAndWait() {
244 pollEvents();
245 delay();
246 }
247
checkForNextFrameCounter()248 bool EventsManager::checkForNextFrameCounter() {
249 // Check for next game frame
250 uint32 milli = g_system->getMillis();
251 if ((milli - _priorFrameTime) >= GAME_FRAME_TIME) {
252 --_vbCount;
253 ++_frameCounter;
254 _priorFrameTime = milli;
255
256 return true;
257 }
258
259 return false;
260 }
261
checkForNextTimerUpdate()262 bool EventsManager::checkForNextTimerUpdate() {
263 // Check for next timer update
264 uint32 milli = g_system->getMillis();
265 if ((milli - _priorTimerTime) >= GAME_TIMER_TIME) {
266 _priorTimerTime = milli;
267
268 return true;
269 }
270
271 return false;
272 }
273
nextFrame()274 void EventsManager::nextFrame() {
275 _vm->_screen->update();
276 }
277
nextTimer()278 void EventsManager::nextTimer() {
279 _vm->_animation->updateTimers();
280 _vm->_timers.updateTimers();
281 }
282
delay(int time)283 void EventsManager::delay(int time) {
284 g_system->delayMillis(time);
285 }
286
zeroKeys()287 void EventsManager::zeroKeys() {
288 _keyCode = Common::KEYCODE_INVALID;
289 }
290
getKey(Common::KeyState & key)291 bool EventsManager::getKey(Common::KeyState &key) {
292 if (_keyCode == Common::KEYCODE_INVALID) {
293 return false;
294 } else {
295 key = _keyCode;
296 _keyCode = Common::KEYCODE_INVALID;
297 return true;
298 }
299 }
300
isKeyPending() const301 bool EventsManager::isKeyPending() const {
302 return _keyCode != Common::KEYCODE_INVALID;
303 }
304
debounceLeft()305 void EventsManager::debounceLeft() {
306 while (_leftButton && !_vm->shouldQuit()) {
307 pollEventsAndWait();
308 }
309 }
310
clearEvents()311 void EventsManager::clearEvents() {
312 _leftButton = _rightButton = false;
313 zeroKeys();
314 }
315
waitKeyMouse()316 void EventsManager::waitKeyMouse() {
317 while (!_vm->shouldQuit() && !isKeyMousePressed()) {
318 pollEvents(true);
319 delay();
320 }
321 }
322
calcRawMouse()323 Common::Point EventsManager::calcRawMouse() {
324 Common::Point pt;
325 Screen &screen = *_vm->_screen;
326 pt.x = _mousePos.x - screen._windowXAdd +
327 (_vm->_scrollCol * TILE_WIDTH) + _vm->_scrollX;
328 pt.y = _mousePos.y - screen._screenYOff - screen._windowYAdd +
329 (_vm->_scrollRow * TILE_HEIGHT) + _vm->_scrollY;
330
331 return pt;
332 }
333
checkMouseBox1(Common::Array<Common::Rect> & rects)334 int EventsManager::checkMouseBox1(Common::Array<Common::Rect> &rects) {
335 for (uint16 i = 0; i < rects.size(); ++i) {
336 if (rects[i].left == -1)
337 return -1;
338
339 if ((_mousePos.x > rects[i].left) && (_mousePos.x < rects[i].right)
340 && (_mousePos.y > rects[i].top) && (_mousePos.y < rects[i].bottom))
341 return i;
342 }
343
344 return -1;
345 }
346
isKeyMousePressed()347 bool EventsManager::isKeyMousePressed() {
348 bool result = _leftButton || _rightButton || isKeyPending();
349 debounceLeft();
350 zeroKeys();
351
352 return result;
353 }
354
centerMousePos()355 void EventsManager::centerMousePos() {
356 _mousePos = Common::Point(160, 100);
357 }
358
restrictMouse()359 void EventsManager::restrictMouse() {
360 // No implementation in ScummVM
361 }
362
363 } // End of namespace Access
364