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 "titanic/events.h"
24 #include "titanic/debugger.h"
25 #include "titanic/game_manager.h"
26 #include "titanic/main_game_window.h"
27 #include "titanic/star_control/star_control.h"
28 #include "titanic/titanic.h"
29 #include "common/events.h"
30 #include "common/scummsys.h"
31 #include "common/system.h"
32 #include "engines/util.h"
33 #include "graphics/screen.h"
34 
35 namespace Titanic {
36 
Events(TitanicEngine * vm)37 Events::Events(TitanicEngine *vm): _vm(vm), _frameCounter(1),
38 		_totalFrames(0), _priorFrameTime(0), _specialButtons(0) {
39 }
40 
41 #define MOVE_CHECK if (moved) eventTarget()->mouseMove(_mousePos)
42 
pollEvents()43 void Events::pollEvents() {
44 	checkForNextFrameCounter();
45 
46 	bool moved = false;
47 	Common::Event event;
48 	while (!_vm->shouldQuit() && g_system->getEventManager()->pollEvent(event)) {
49 		if (event.type != Common::EVENT_MOUSEMOVE) {
50 			MOVE_CHECK;
51 		}
52 
53 		switch (event.type) {
54 		case Common::EVENT_MOUSEMOVE:
55 			_mousePos = event.mouse;
56 			moved = true;
57 			break;
58 		case Common::EVENT_LBUTTONDOWN:
59 			_specialButtons |= MK_LBUTTON;
60 			_mousePos = event.mouse;
61 			eventTarget()->leftButtonDown(_mousePos);
62 			return;
63 		case Common::EVENT_LBUTTONUP:
64 			_specialButtons &= ~MK_LBUTTON;
65 			_mousePos = event.mouse;
66 			eventTarget()->leftButtonUp(_mousePos);
67 			return;
68 		case Common::EVENT_MBUTTONDOWN:
69 			_specialButtons |= MK_MBUTTON;
70 			_mousePos = event.mouse;
71 			eventTarget()->middleButtonDown(_mousePos);
72 			return;
73 		case Common::EVENT_MBUTTONUP:
74 			_specialButtons &= ~MK_MBUTTON;
75 			_mousePos = event.mouse;
76 			eventTarget()->middleButtonUp(_mousePos);
77 			return;
78 		case Common::EVENT_RBUTTONDOWN:
79 			_specialButtons |= MK_LBUTTON | MK_SHIFT;
80 			_mousePos = event.mouse;
81 			eventTarget()->leftButtonDown(_mousePos);
82 			return;
83 		case Common::EVENT_RBUTTONUP:
84 			_specialButtons &= ~(MK_RBUTTON | MK_SHIFT);
85 			_mousePos = event.mouse;
86 			eventTarget()->leftButtonUp(_mousePos);
87 			return;
88 		case Common::EVENT_WHEELUP:
89 		case Common::EVENT_WHEELDOWN:
90 			_mousePos = event.mouse;
91 			eventTarget()->mouseWheel(_mousePos, event.type == Common::EVENT_WHEELUP);
92 			return;
93 		case Common::EVENT_KEYDOWN:
94 			handleKbdSpecial(event.kbd);
95 			eventTarget()->keyDown(event.kbd);
96 			return;
97 		case Common::EVENT_KEYUP:
98 			handleKbdSpecial(event.kbd);
99 			eventTarget()->keyUp(event.kbd);
100 			return;
101 		default:
102 			break;
103 		}
104 	}
105 
106 	MOVE_CHECK;
107 }
108 
109 #undef MOVE_CHECK
110 
pollEventsAndWait()111 void Events::pollEventsAndWait() {
112 	pollEvents();
113 	g_system->delayMillis(10);
114 
115 	CGameManager *gameManager = g_vm->_window->_gameManager;
116 	if (gameManager) {
117 		// Regularly update the sound mixer
118 		gameManager->_sound.updateMixer();
119 
120 		// WORKAROUND: If in the Star Control view, update the camera
121 		// frequently, to accomodate that the original had a higher
122 		// draw rate than the ScummVM implementation does
123 		CViewItem *view = gameManager->getView();
124 		if (view->getFullViewName() == "Bridge.Node 4.N") {
125 			CStarControl *starControl = dynamic_cast<CStarControl *>(
126 				view->findChildInstanceOf(CStarControl::_type));
127 			if (starControl && starControl->_visible)
128 				starControl->updateCamera();
129 		}
130 	}
131 }
132 
checkForNextFrameCounter()133 bool Events::checkForNextFrameCounter() {
134 	// Check for next game frame
135 	uint32 milli = g_system->getMillis();
136 	if ((milli - _priorFrameTime) >= GAME_FRAME_TIME) {
137 		++_frameCounter;
138 		++_totalFrames;
139 		_priorFrameTime = milli;
140 
141 		// Handle any idle updates
142 		eventTarget()->onIdle();
143 
144 		// Give time to the debugger
145 		_vm->_debugger->onFrame();
146 
147 		// Display the frame
148 		_vm->_screen->update();
149 
150 		return true;
151 	}
152 
153 	return false;
154 }
155 
getTicksCount() const156 uint32 Events::getTicksCount() const {
157 	return _frameCounter * GAME_FRAME_TIME;
158 }
159 
getTotalPlayTicks() const160 uint32 Events::getTotalPlayTicks() const {
161 	return _totalFrames;
162 }
163 
setTotalPlayTicks(uint frames)164 void Events::setTotalPlayTicks(uint frames) {
165 	_totalFrames = frames;
166 }
167 
sleep(uint time)168 void Events::sleep(uint time) {
169 	uint32 delayEnd = g_system->getMillis() + time;
170 
171 	while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd)
172 		pollEventsAndWait();
173 }
174 
waitForPress(uint expiry)175 bool Events::waitForPress(uint expiry) {
176 	uint32 delayEnd = g_system->getMillis() + expiry;
177 	CPressTarget pressTarget;
178 	addTarget(&pressTarget);
179 
180 	while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd && !pressTarget._pressed) {
181 		pollEventsAndWait();
182 	}
183 
184 	removeTarget();
185 	return pressTarget._pressed;
186 }
187 
setMousePos(const Common::Point & pt)188 void Events::setMousePos(const Common::Point &pt) {
189 	g_system->warpMouse(pt.x, pt.y);
190 	_mousePos = pt;
191 	eventTarget()->mouseMove(_mousePos);
192 }
193 
handleKbdSpecial(Common::KeyState keyState)194 void Events::handleKbdSpecial(Common::KeyState keyState) {
195 	if (keyState.flags & Common::KBD_CTRL)
196 		_specialButtons |= MK_CONTROL;
197 	else
198 		_specialButtons &= ~MK_CONTROL;
199 
200 	if (keyState.flags & Common::KBD_SHIFT)
201 		_specialButtons |= MK_SHIFT;
202 	else
203 		_specialButtons &= ~MK_SHIFT;
204 }
205 
206 } // End of namespace Titanic
207