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 "pink/pda_mgr.h"
24 #include "pink/pink.h"
25 #include "pink/director.h"
26 #include "pink/objects/actors/pda_button_actor.h"
27 #include "pink/objects/actors/lead_actor.h"
28 #include "pink/objects/pages/pda_page.h"
29 #include "pink/objects/actions/action_play_with_sfx.h"
30 
31 namespace Pink {
32 
33 static const char * const g_countries[] = {"BRI", "EGY", "BHU", "AUS", "IND", "CHI"};
34 static const char * const g_domains[] = {"NAT", "CLO", "HIS", "REL", "PLA", "ART", "FOO", "PEO"};
35 
PDAMgr(PinkEngine * game)36 PDAMgr::PDAMgr(PinkEngine *game)
37 	: _game(game), _lead(nullptr), _page(nullptr), _globalPage(nullptr),
38 	_cursorMgr(game, nullptr), _countryIndex(0), _domainIndex(0),
39 	_iteration(0), _handFrame(0), _leftHandAction(kLeft1) {}
40 
~PDAMgr()41 PDAMgr::~PDAMgr() {
42 	delete _globalPage;
43 	delete _page;
44 }
45 
saveState(Archive & archive)46 void PDAMgr::saveState(Archive &archive) {
47 	if (_page)
48 		archive.writeString(_page->getName());
49 	else
50 		archive.writeString("");
51 }
52 
execute(const Command & command)53 void PDAMgr::execute(const Command &command) {
54 	switch (command.type) {
55 	case Command::kGoToPage:
56 		goToPage(command.arg);
57 		break;
58 	case Command::kGoToPreviousPage:
59 		assert(_previousPages.size() >= 2);
60 		_previousPages.pop();
61 		goToPage(_previousPages.pop());
62 		break;
63 	case Command::kGoToDomain:
64 		goToPage(Common::String::format("%.6s", _page->getName().c_str()));
65 		break;
66 	case Command::kGoToHelp:
67 		warning("Command GoToHelp is not supported and won't be");
68 		break;
69 	case Command::kNavigateToDomain:
70 		goToPage(Common::String(g_countries[_countryIndex]) += g_domains[_domainIndex]);
71 		break;
72 	case Command::kIncrementCountry:
73 		_countryIndex = (_countryIndex + 1) % 6;
74 		updateWheels(1);
75 		updateLocator();
76 		break;
77 	case Command::kDecrementCountry:
78 		_countryIndex = (_countryIndex + 5) % 6;
79 		updateWheels(1);
80 		updateLocator();
81 		break;
82 	case Command::kIncrementDomain:
83 		_domainIndex = (_domainIndex + 1) % 8;
84 		updateWheels(1);
85 		break;
86 	case Command::kDecrementDomain:
87 		_domainIndex = (_domainIndex + 7) % 8;
88 		updateWheels(1);
89 		break;
90 	case Command::kClose:
91 		close();
92 		break;
93 	default:
94 		break;
95 	}
96 }
97 
goToPage(const Common::String pageName)98 void PDAMgr::goToPage(const Common::String pageName) {
99 	if (_page && !_page->getName().compareToIgnoreCase(pageName))
100 		return;
101 
102 	loadGlobal();
103 
104 	delete _page;
105 	_page = new PDAPage(pageName, getGame());
106 
107 	_previousPages.push(_page->getName());
108 
109 	if (_game->isPeril())
110 		initPerilButtons();
111 
112 	_cursorMgr.setPage(_page);
113 	onMouseMove(_game->getEventManager()->getMousePos());
114 }
115 
onLeftButtonClick(Common::Point point)116 void PDAMgr::onLeftButtonClick(Common::Point point) {
117 	Actor* rightHand = _globalPage->findActor(kRightHand);
118 	if (rightHand)
119 		static_cast<ActionStill*>(rightHand->getAction())->setFrame(1);
120 	Actor *actor = _game->getDirector()->getActorByPoint(point);
121 	if (actor)
122 		actor->onLeftClickMessage();
123 }
124 
onLeftButtonUp()125 void PDAMgr::onLeftButtonUp() {
126 	Actor* rightHand = _globalPage->findActor(kRightHand);
127 	if (rightHand)
128 		static_cast<ActionStill*>(rightHand->getAction())->setFrame(0);
129 }
130 
onMouseMove(Common::Point point)131 void PDAMgr::onMouseMove(Common::Point point) {
132 	Actor *actor = _game->getDirector()->getActorByPoint(point);
133 	if (actor && dynamic_cast<PDAButtonActor *>(actor))
134 		actor->onMouseOver(point, &_cursorMgr);
135 	else
136 		_cursorMgr.setCursor(kPDADefaultCursor, point, Common::String());
137 
138 	if (!_game->isPeril())
139 		return;
140 
141 	float k = (float)point.x / (480 - point.y);
142 	Actor *leftHand = _globalPage->findActor(kLeftHand);
143 	if (k > 0.5) {
144 		if (k > 1) {
145 			if (k > 1.5 && _leftHandAction != kLeft4) {
146 				leftHand->setAction(kLeft4Name);
147 				static_cast<ActionStill*>(leftHand->getAction())->setFrame(_handFrame + 1);
148 				_leftHandAction = kLeft4;
149 			} else if (_leftHandAction != kLeft3) {
150 				leftHand->setAction(kLeft3Name);
151 				static_cast<ActionStill*>(leftHand->getAction())->setFrame(_handFrame + 1);
152 				_leftHandAction = kLeft3;
153 			}
154 		} else if (_leftHandAction != kLeft2) {
155 			leftHand->setAction(kLeft2Name);
156 			static_cast<ActionStill*>(leftHand->getAction())->setFrame(_handFrame + 1);
157 			_leftHandAction = kLeft2;
158 		}
159 	} else if (_leftHandAction != kLeft1) {
160 		leftHand->setAction(kLeft1Name);
161 		static_cast<ActionStill*>(leftHand->getAction())->setFrame(_handFrame + 1);
162 		_leftHandAction = kLeft1;
163 	}
164 
165 	if (_iteration == 0) {
166 		_handFrame = (_handFrame + 1) % 4;
167 		static_cast<ActionStill*>(leftHand->getAction())->nextFrameLooped();
168 	}
169 	_iteration = (_iteration + 1) % 4;
170 }
171 
close()172 void PDAMgr::close() {
173 	if (!_globalPage)
174 		return;
175 
176 	delete _globalPage;
177 	delete _page;
178 	_globalPage = nullptr;
179 	_page = nullptr;
180 
181 	_lead->onPDAClose();
182 }
183 
loadGlobal()184 void PDAMgr::loadGlobal() {
185 	if (_globalPage)
186 		return;
187 
188 	delete _globalPage;
189 	_globalPage = new PDAPage("GLOBAL", getGame());
190 }
191 
initPerilButtons()192 void PDAMgr::initPerilButtons() {
193 	Actor *prevPageButton = _globalPage->findActor(kPreviousPageButton);
194 	if (_previousPages.size() < 2)
195 		prevPageButton->setAction(kInactiveAction);
196 	else
197 		prevPageButton->setAction(kIdleAction);
198 
199 	Actor *navigatorButton = _globalPage->findActor(kNavigatorButton);
200 	Actor *domainButton = _globalPage->findActor(kDomainButton);
201 	if (isNavigate(_page->getName())) {
202 		navigatorButton->setAction(kInactiveAction);
203 		domainButton->setAction(kInactiveAction);
204 		updateWheels();
205 	} else {
206 		calculateIndexes();
207 		navigatorButton->setAction(kIdleAction);
208 		if (isDomain(_page->getName()))
209 			domainButton->setAction(kInactiveAction);
210 		else
211 			domainButton->setAction(kIdleAction);
212 	}
213 	updateLocator();
214 }
215 
updateWheels(bool playSfx)216 void PDAMgr::updateWheels(bool playSfx) {
217 	Actor *wheel = _page->findActor(kCountryWheel);
218 	if (playSfx && wheel->getAction()->getName() != g_countries[_countryIndex]) {
219 		wheel->setAction(Common::String(g_countries[_countryIndex]) + kSfx);
220 		static_cast<ActionPlayWithSfx*>(wheel->getAction())->update(); // hack
221 	}
222 	wheel->setAction(g_countries[_countryIndex]);
223 
224 	wheel = _page->findActor(kDomainWheel);
225 	if (playSfx && wheel->getAction()->getName() != g_domains[_domainIndex]) {
226 		wheel->setAction(Common::String(g_domains[_domainIndex]) + kSfx);
227 		static_cast<ActionPlayWithSfx*>(wheel->getAction())->update(); // hack
228 	}
229 	wheel->setAction(g_domains[_domainIndex]);
230 }
231 
isNavigate(const Common::String & name)232 bool PDAMgr::isNavigate(const Common::String &name) {
233 	return !name.compareToIgnoreCase(kNavigatePage);
234 }
235 
isDomain(const Common::String & name)236 bool PDAMgr::isDomain(const Common::String &name) {
237 	return name.size() == 6;
238 }
239 
updateLocator()240 void PDAMgr::updateLocator() {
241 	Actor *locator = _globalPage->findActor(kLocator);
242 	if (locator)
243 		locator->setAction(g_countries[_countryIndex]);
244 }
245 
calculateIndexes()246 void PDAMgr::calculateIndexes() {
247 	Common::String country = Common::String::format("%.3s", _page->getName().c_str());
248 	for (uint i = 0; i < 6; ++i) {
249 		if (country == g_countries[i]) {
250 			_countryIndex = i;
251 			break;
252 		}
253 	}
254 
255 	Common::String domain = _page->getName();
256 	domain.erase(0, 3);
257 	if (domain.size() >= 4)
258 		domain.erase(3);
259 	for (uint i = 0; i < 8; ++i) {
260 		if (domain == g_domains[i]) {
261 			_domainIndex = i;
262 			break;
263 		}
264 	}
265 }
266 
267 } // End of namespace Pink
268