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 "neverhood/console.h"
24 #include "neverhood/scene.h"
25 #include "neverhood/smackerplayer.h"
26 
27 namespace Neverhood {
28 
Scene(NeverhoodEngine * vm,Module * parentModule)29 Scene::Scene(NeverhoodEngine *vm, Module *parentModule)
30 	: Entity(vm, 0), _parentModule(parentModule), _dataResource(vm), _hitRects(NULL),
31 	_mouseCursorWasVisible(true) {
32 
33 	_isKlaymenBusy = false;
34 	_doConvertMessages = false;
35 	_messageList = NULL;
36 	_rectType = 0;
37 	_mouseClickPos.x = 0;
38 	_mouseClickPos.y = 0;
39 	_mouseClicked = false;
40 	_rectList = NULL;
41 	_klaymen = NULL;
42 	_mouseCursor = NULL;
43 	_palette = NULL;
44 	_background = NULL;
45 	clearHitRects();
46 	clearCollisionSprites();
47 	_vm->_screen->setFps(24);
48 	_vm->_screen->setSmackerDecoder(NULL);
49 	_canAcceptInput = true;
50 	_messageList2 = NULL;
51 	_smackerPlayer = NULL;
52 	_isMessageListBusy = false;
53 	_messageValue = -1;
54 	_messageListStatus = 0;
55 	_messageListCount = 0;
56 	_messageListIndex = 0;
57 
58 	_backgroundFileHash = _cursorFileHash = 0;
59 
60 	SetUpdateHandler(&Scene::update);
61 	SetMessageHandler(&Scene::handleMessage);
62 
63 	_vm->_screen->clearRenderQueue();
64 }
65 
~Scene()66 Scene::~Scene() {
67 
68 	_vm->_screen->setSmackerDecoder(NULL);
69 
70 	if (_palette) {
71 		removeEntity(_palette);
72 		delete _palette;
73 	}
74 
75 	// Delete all entities
76 	for (Common::Array<Entity*>::iterator iter = _entities.begin(); iter != _entities.end(); iter++)
77 		delete *iter;
78 
79 	// Don't delete surfaces since they always belong to an entity
80 
81 	// Purge the resources after each scene
82 	_vm->_res->purgeResources();
83 
84 }
85 
draw()86 void Scene::draw() {
87 	if (_smackerPlayer) {
88 		if (_smackerPlayer->getSurface())
89 			_smackerPlayer->getSurface()->draw();
90 	} else {
91 		for (Common::Array<BaseSurface*>::iterator iter = _surfaces.begin(); iter != _surfaces.end(); iter++)
92 			(*iter)->draw();
93 	}
94 }
95 
addEntity(Entity * entity)96 void Scene::addEntity(Entity *entity) {
97 	int index = 0, insertIndex = -1;
98 	for (Common::Array<Entity*>::iterator iter = _entities.begin(); iter != _entities.end(); iter++) {
99 		if ((*iter)->getPriority() > entity->getPriority()) {
100 			insertIndex = index;
101 			break;
102 		}
103 		index++;
104 	}
105 	if (insertIndex >= 0)
106 		_entities.insert_at(insertIndex, entity);
107 	else
108 		_entities.push_back(entity);
109 }
110 
removeEntity(Entity * entity)111 bool Scene::removeEntity(Entity *entity) {
112 	for (uint index = 0; index < _entities.size(); index++)
113 		if (_entities[index] == entity) {
114 			_entities.remove_at(index);
115 			return true;
116 		}
117 	return false;
118 }
119 
addSurface(BaseSurface * surface)120 void Scene::addSurface(BaseSurface *surface) {
121 	if (surface) {
122 		int index = 0, insertIndex = -1;
123 		for (Common::Array<BaseSurface*>::iterator iter = _surfaces.begin(); iter != _surfaces.end(); iter++) {
124 			if ((*iter)->getPriority() > surface->getPriority()) {
125 				insertIndex = index;
126 				break;
127 			}
128 			index++;
129 		}
130 		if (insertIndex >= 0)
131 			_surfaces.insert_at(insertIndex, surface);
132 		else
133 			_surfaces.push_back(surface);
134 	}
135 }
136 
removeSurface(BaseSurface * surface)137 bool Scene::removeSurface(BaseSurface *surface) {
138 	for (uint index = 0; index < _surfaces.size(); index++) {
139 		if (_surfaces[index] == surface) {
140 			_surfaces.remove_at(index);
141 			return true;
142 		}
143 	}
144 	return false;
145 }
146 
printSurfaces(Console * con)147 void Scene::printSurfaces(Console *con) {
148 	for (uint index = 0; index < _surfaces.size(); index++) {
149 		NDrawRect drawRect = _surfaces[index]->getDrawRect();
150 		NRect clipRect = _surfaces[index]->getClipRect();
151 		int priority = _surfaces[index]->getPriority();
152 		con->debugPrintf("%d ('%s'): Priority %d, draw rect (%d, %d, %d, %d), clip rect (%d, %d, %d, %d)\n",
153 			index, _surfaces[index]->getName().c_str(), priority,
154 			drawRect.x, drawRect.y, drawRect.x2(), drawRect.y2(),
155 			clipRect.x1, clipRect.y1, clipRect.x2, clipRect.y2);
156 	}
157 }
158 
addSprite(Sprite * sprite)159 Sprite *Scene::addSprite(Sprite *sprite) {
160 	addEntity(sprite);
161 	addSurface(sprite->getSurface());
162 	return sprite;
163 }
164 
removeSprite(Sprite * sprite)165 void Scene::removeSprite(Sprite *sprite) {
166 	removeSurface(sprite->getSurface());
167 	removeEntity(sprite);
168 }
169 
setSurfacePriority(BaseSurface * surface,int priority)170 void Scene::setSurfacePriority(BaseSurface *surface, int priority) {
171 	surface->setPriority(priority);
172 	if (removeSurface(surface))
173 		addSurface(surface);
174 }
175 
setSpriteSurfacePriority(Sprite * sprite,int priority)176 void Scene::setSpriteSurfacePriority(Sprite *sprite, int priority) {
177 	if (sprite)
178 		setSurfacePriority(sprite->getSurface(), priority);
179 }
180 
deleteSprite(Sprite ** sprite)181 void Scene::deleteSprite(Sprite **sprite) {
182 	removeCollisionSprite(*sprite);
183 	removeSurface((*sprite)->getSurface());
184 	removeEntity(*sprite);
185 	delete *sprite;
186 	*sprite = NULL;
187 }
188 
addBackground(Background * background)189 Background *Scene::addBackground(Background *background) {
190 	addEntity(background);
191 	addSurface(background->getSurface());
192 	return background;
193 }
194 
setBackground(uint32 fileHash)195 void Scene::setBackground(uint32 fileHash) {
196 	_background = addBackground(new Background(_vm, fileHash, 0, 0));
197 	_backgroundFileHash = fileHash;
198 }
199 
changeBackground(uint32 fileHash)200 void Scene::changeBackground(uint32 fileHash) {
201 	_background->load(fileHash);
202 }
203 
setPalette(uint32 fileHash)204 void Scene::setPalette(uint32 fileHash) {
205 	_palette = fileHash ? new Palette(_vm, fileHash) : new Palette(_vm);
206 	_palette->usePalette();
207 }
208 
setHitRects(uint32 id)209 void Scene::setHitRects(uint32 id) {
210 	setHitRects(_vm->_staticData->getHitRectList(id));
211 }
212 
setHitRects(HitRectList * hitRects)213 void Scene::setHitRects(HitRectList *hitRects) {
214 	_hitRects = hitRects;
215 }
216 
insertStaticSprite(uint32 fileHash,int surfacePriority)217 Sprite *Scene::insertStaticSprite(uint32 fileHash, int surfacePriority) {
218 	return addSprite(new StaticSprite(_vm, fileHash, surfacePriority));
219 }
220 
insertScreenMouse(uint32 fileHash,const NRect * mouseRect)221 void Scene::insertScreenMouse(uint32 fileHash, const NRect *mouseRect) {
222 	NRect rect = NRect::make(-1, -1, -1, -1);
223 	if (mouseRect)
224 		rect = *mouseRect;
225 	insertMouse(new Mouse(_vm, fileHash, rect));
226 	_cursorFileHash = fileHash;
227 }
228 
insertPuzzleMouse(uint32 fileHash,int16 x1,int16 x2)229 void Scene::insertPuzzleMouse(uint32 fileHash, int16 x1, int16 x2) {
230 	insertMouse(new Mouse(_vm, fileHash, x1, x2));
231 	_cursorFileHash = fileHash;
232 }
233 
insertNavigationMouse(uint32 fileHash,int type)234 void Scene::insertNavigationMouse(uint32 fileHash, int type) {
235 	insertMouse(new Mouse(_vm, fileHash, type));
236 	_cursorFileHash = fileHash;
237 }
238 
showMouse(bool visible)239 void Scene::showMouse(bool visible) {
240 	_mouseCursor->getSurface()->setVisible(visible);
241 }
242 
changeMouseCursor(uint32 fileHash)243 void Scene::changeMouseCursor(uint32 fileHash) {
244 	_mouseCursor->load(fileHash);
245 	_mouseCursor->updateCursor();
246 }
247 
addSmackerPlayer(SmackerPlayer * smackerPlayer)248 SmackerPlayer *Scene::addSmackerPlayer(SmackerPlayer *smackerPlayer) {
249 	addEntity(smackerPlayer);
250 	addSurface(smackerPlayer->getSurface());
251 	return smackerPlayer;
252 }
253 
update()254 void Scene::update() {
255 
256 	if (_mouseClicked) {
257 		if (_klaymen) {
258 			if (_canAcceptInput &&
259 				_klaymen->hasMessageHandler() &&
260 				sendMessage(_klaymen, 0x1008, 0) != 0 &&
261 				queryPositionSprite(_mouseClickPos.x, _mouseClickPos.y)) {
262 				_mouseClicked = false;
263 			} else if (_canAcceptInput &&
264 				_klaymen->hasMessageHandler() &&
265 				sendMessage(_klaymen, 0x1008, 0) != 0) {
266 				_mouseClicked = !queryPositionRectList(_mouseClickPos.x, _mouseClickPos.y);
267 			}
268 		} else if (queryPositionSprite(_mouseClickPos.x, _mouseClickPos.y)) {
269 			_mouseClicked = false;
270 		}
271 	}
272 
273 	processMessageList();
274 
275 	// Update all entities
276 	for (Common::Array<Entity*>::iterator iter = _entities.begin(); iter != _entities.end(); iter++)
277 		(*iter)->handleUpdate();
278 
279 }
280 
leaveScene(uint32 result)281 void Scene::leaveScene(uint32 result) {
282 	sendMessage(_parentModule, 0x1009, result);
283 }
284 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)285 uint32 Scene::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
286 	switch (messageNum) {
287 	case NM_MOUSE_MOVE:
288 		if (_mouseCursor && _mouseCursor->hasMessageHandler())
289 			sendMessage(_mouseCursor, 0x4002, param);
290 		break;
291 	case NM_MOUSE_CLICK:
292 		_mouseClicked = true;
293 		_mouseClickPos = param.asPoint();
294 		break;
295 	case 0x0006:
296 		sendMessage(_parentModule, 0x1009, param);
297 		break;
298 	case 0x1006:
299 		// Sent by Klaymen when its animation sequence has finished
300 		if (_isKlaymenBusy) {
301 			_isKlaymenBusy = false;
302 			if (_messageListIndex == _messageListCount) {
303 				// If the current message list was processed completely,
304 				// sent Klaymen into the idle state.
305 				sendMessage(_klaymen, NM_KLAYMEN_STAND_IDLE, 0);
306 			} else {
307 				// Else continue with the next message in the current message list
308 				processMessageList();
309 			}
310 		}
311 		break;
312 	case 0x1007:
313 		// This isn't sent by any code, check if it's in a message list
314 		// This cancels the current message list and sets Klaymen into the idle state.
315 		if (_isKlaymenBusy) {
316 			_isKlaymenBusy = false;
317 			_messageList = NULL;
318 			sendMessage(_klaymen, NM_KLAYMEN_STAND_IDLE, 0);
319 		}
320 		break;
321 	case NM_MOUSE_HIDE:
322 		if (_mouseCursor) {
323 			_mouseCursorWasVisible = _mouseCursor->getSurface()->getVisible();
324 			_mouseCursor->getSurface()->setVisible(false);
325 		}
326 		break;
327 	case NM_MOUSE_SHOW:
328 		if (_mouseCursorWasVisible && _mouseCursor) {
329 			_mouseCursor->getSurface()->setVisible(true);
330 		}
331 		break;
332 	case NM_PRIORITY_CHANGE:
333 		// Set the sender's surface priority
334 		setSurfacePriority(((Sprite*)sender)->getSurface(), param.asInteger());
335 		break;
336 	default:
337 		break;
338 	}
339 	return 0;
340 }
341 
queryPositionSprite(int16 mouseX,int16 mouseY)342 bool Scene::queryPositionSprite(int16 mouseX, int16 mouseY) {
343 	for (uint i = 0; i < _collisionSprites.size(); i++) {
344 		Sprite *sprite = _collisionSprites[i];
345 		if (sprite->hasMessageHandler() && sprite->isPointInside(mouseX, mouseY) &&
346 			sendPointMessage(sprite, 0x1011, _mouseClickPos) != 0) {
347 			return true;
348 		}
349 	}
350 	return false;
351 }
352 
queryPositionRectList(int16 mouseX,int16 mouseY)353 bool Scene::queryPositionRectList(int16 mouseX, int16 mouseY) {
354 	int16 klaymenX = _klaymen->getX();
355 	int16 klaymenY = _klaymen->getY();
356 	if (_rectType == 1) {
357 		RectList &rectList = *_rectList;
358 		for (uint i = 0; i < rectList.size(); i++) {
359 			debug(2, "(%d, %d) ? (%d, %d, %d, %d)", klaymenX, klaymenY, rectList[i].rect.x1, rectList[i].rect.y1, rectList[i].rect.x2, rectList[i].rect.y2);
360 			if (rectList[i].rect.contains(klaymenX, klaymenY)) {
361 				for (uint j = 0; j < rectList[i].subRects.size(); j++) {
362 					debug(2, "  (%d, %d) ? (%d, %d, %d, %d)", mouseX, mouseY, rectList[i].subRects[j].rect.x1, rectList[i].subRects[j].rect.y1, rectList[i].subRects[j].rect.x2, rectList[i].subRects[j].rect.y2);
363 					if (rectList[i].subRects[j].rect.contains(mouseX, mouseY)) {
364 						return setMessageList2(rectList[i].subRects[j].messageListId);
365 					}
366 				}
367 			}
368 		}
369 	} else if (_rectType == 2) {
370 		MessageList *messageList = _dataResource.getMessageListAtPos(klaymenX, klaymenY, mouseX, mouseY);
371 		if (messageList && messageList->size())
372 			setMessageList2(messageList, true, true);
373 	}
374 	return true;
375 }
376 
setMessageList(uint32 id,bool canAcceptInput,bool doConvertMessages)377 void Scene::setMessageList(uint32 id, bool canAcceptInput, bool doConvertMessages) {
378 	setMessageList(_vm->_staticData->getMessageList(id), canAcceptInput, doConvertMessages);
379 }
380 
setMessageList(MessageList * messageList,bool canAcceptInput,bool doConvertMessages)381 void Scene::setMessageList(MessageList *messageList, bool canAcceptInput, bool doConvertMessages) {
382 	_messageList = messageList;
383 	_messageListCount = _messageList ? _messageList->size() : 0;
384 	_messageListIndex = 0;
385 	_isKlaymenBusy = false;
386 	_canAcceptInput = canAcceptInput;
387 	_doConvertMessages = doConvertMessages;
388 	_messageListStatus = 1;
389 	sendMessage(_klaymen, 0x101C, 0);
390 }
391 
setMessageList2(uint32 id,bool canAcceptInput,bool doConvertMessages)392 bool Scene::setMessageList2(uint32 id, bool canAcceptInput, bool doConvertMessages) {
393 	return setMessageList2(_vm->_staticData->getMessageList(id), canAcceptInput, doConvertMessages);
394 }
395 
setMessageList2(MessageList * messageList,bool canAcceptInput,bool doConvertMessages)396 bool Scene::setMessageList2(MessageList *messageList, bool canAcceptInput, bool doConvertMessages) {
397 	if (_messageListStatus == 0 ||
398 		(_messageListStatus == 1 && messageList != _messageList2) ||
399 		(_messageListStatus == 2 && messageList == _messageList2)) {
400 		// NOTE Skipped unneeded resource preloading code
401 		_messageValue = -1;
402 		_messageList2 = messageList;
403 		setMessageList(messageList, canAcceptInput, doConvertMessages);
404 		return true;
405 	}
406 	return false;
407 }
408 
isMessageList2(uint32 id)409 bool Scene::isMessageList2(uint32 id) {
410 	return _messageList2 == _vm->_staticData->getMessageList(id);
411 }
412 
processMessageList()413 void Scene::processMessageList() {
414 	debug(7, "Scene::processMessageList() _isMessageListBusy = %d; _isKlaymenBusy = %d", _isMessageListBusy, _isKlaymenBusy);
415 
416 	if (_isMessageListBusy || _isKlaymenBusy)
417 		return;
418 
419 	_isMessageListBusy = true;
420 
421 	if (!_messageList) {
422 		_messageList2 = NULL;
423 		_messageListStatus = 0;
424 	}
425 
426 	if (_messageList && _klaymen) {
427 
428 #if 0
429 		debug("MessageList: %p, %d", (void*)_messageList, _messageList->size());
430 		for (uint i = 0; i < _messageList->size(); ++i) {
431 			if (i == _messageListIndex) debugN("**"); else debugN("  ");
432 			debug("(%08X, %08X)", (*_messageList)[i].messageNum, (*_messageList)[i].messageValue);
433 		}
434 		debug("--------------------------------");
435 #endif
436 
437 		while (_messageList && _messageListIndex < _messageListCount && !_isKlaymenBusy) {
438 			uint32 messageNum = (*_messageList)[_messageListIndex].messageNum;
439 			uint32 messageParam = (*_messageList)[_messageListIndex].messageValue;
440 
441 			++_messageListIndex;
442 			if (_messageListIndex == _messageListCount)
443 				sendMessage(_klaymen, 0x1021, 0);
444 			if (_doConvertMessages)
445 				messageNum = convertMessageNum(messageNum);
446 			if (messageNum == 0x1009 || messageNum == 0x1024) {
447 				sendMessage(_parentModule, messageNum, messageParam);
448 			} else if (messageNum == 0x100A) {
449 				_messageValue = messageParam;
450 				sendMessage(_parentModule, messageNum, messageParam);
451 			} else if (messageNum == 0x4001) {
452 				_isKlaymenBusy = true;
453 				sendPointMessage(_klaymen, 0x4001, _mouseClickPos);
454 			} else if (messageNum == 0x100D) {
455 				if (this->hasMessageHandler() && sendMessage(this, NM_ANIMATION_START, messageParam) != 0)
456 					continue;
457 			} else if (messageNum == 0x101A) {
458 				_messageListStatus = 0;
459 			} else if (messageNum == 0x101B) {
460 				_messageListStatus = 2;
461 			} else if (messageNum == 0x1020) {
462 				_canAcceptInput = false;
463 			} else if (messageNum >= 0x2000 && messageNum <= 0x2FFF) {
464 				if (this->hasMessageHandler() && sendMessage(this, messageNum, messageParam) != 0) {
465 					_isMessageListBusy = false;
466 					return;
467 				}
468 			} else if (messageNum != 0x4003) {
469 				_isKlaymenBusy = true;
470 				if (_klaymen->hasMessageHandler() && sendMessage(_klaymen, messageNum, messageParam) != 0) {
471 					_isKlaymenBusy = false;
472 				}
473 			}
474 			if (_messageListIndex == _messageListCount) {
475 				_canAcceptInput = true;
476 				_messageList = NULL;
477 			}
478 		}
479 	}
480 
481 	_isMessageListBusy = false;
482 
483 }
484 
cancelMessageList()485 void Scene::cancelMessageList() {
486 	_isKlaymenBusy = false;
487 	_messageList = NULL;
488 	_canAcceptInput = true;
489 	sendMessage(_klaymen, NM_KLAYMEN_STAND_IDLE, 0);
490 }
491 
setRectList(uint32 id)492 void Scene::setRectList(uint32 id) {
493 	setRectList(_vm->_staticData->getRectList(id));
494 }
495 
setRectList(RectList * rectList)496 void Scene::setRectList(RectList *rectList) {
497 	_rectList = rectList;
498 	_rectType = 1;
499 }
500 
clearRectList()501 void Scene::clearRectList() {
502 	_rectList = NULL;
503 	_rectType = 0;
504 }
505 
loadHitRectList()506 void Scene::loadHitRectList() {
507 	HitRectList *hitRectList = _dataResource.getHitRectList();
508 	if (hitRectList) {
509 		_hitRectList = *hitRectList;
510 		setHitRects(&_hitRectList);
511 	}
512 }
513 
loadDataResource(uint32 fileHash)514 void Scene::loadDataResource(uint32 fileHash) {
515 	_dataResource.load(fileHash);
516 	_rectType = 2;
517 	if (_klaymen)
518 		_klaymen->loadDataResource(fileHash);
519 }
520 
convertMessageNum(uint32 messageNum)521 uint16 Scene::convertMessageNum(uint32 messageNum) {
522 	switch (messageNum) {
523 	case 0x00004004:
524 		return 0x4001;
525 	case 0x00000083:
526 		return 0x100A;
527 	case 0x044001C8:
528 		return 0x481C;
529 	case 0x02420480:
530 		return 0x4818;
531 	case 0x08004025:
532 		return 0x100D;
533 	case 0x04404281:
534 		return 0x4824;
535 	case 0x08400880:
536 		return 0x4825;
537 	case 0x08209081:
538 		return 0x4823;
539 	case 0x24000060:
540 		return 0x1009;
541 	case 0x42002200:
542 		return 0x4004;
543 	case 0x428D4894:
544 		return 0x101A;
545 	default:
546 		break;
547 	}
548 	return 0x1000;
549 }
550 
clearHitRects()551 void Scene::clearHitRects() {
552 	_hitRects = NULL;
553 }
554 
findHitRectAtPos(int16 x,int16 y)555 HitRect *Scene::findHitRectAtPos(int16 x, int16 y) {
556 	static HitRect kDefaultHitRect = {NRect(), 0x5000};
557 	if (_hitRects)
558 		for (HitRectList::iterator it = _hitRects->begin(); it != _hitRects->end(); it++)
559 			if ((*it).rect.contains(x, y))
560 				return &(*it);
561 	return &kDefaultHitRect;
562 }
563 
addCollisionSprite(Sprite * sprite)564 void Scene::addCollisionSprite(Sprite *sprite) {
565 	int index = 0, insertIndex = -1;
566 	for (Common::Array<Sprite*>::iterator iter = _collisionSprites.begin(); iter != _collisionSprites.end(); iter++) {
567 		if ((*iter)->getPriority() > sprite->getPriority()) {
568 			insertIndex = index;
569 			break;
570 		}
571 		index++;
572 	}
573 	if (insertIndex >= 0)
574 		_collisionSprites.insert_at(insertIndex, sprite);
575 	else
576 		_collisionSprites.push_back(sprite);
577 }
578 
removeCollisionSprite(Sprite * sprite)579 void Scene::removeCollisionSprite(Sprite *sprite) {
580 	for (uint index = 0; index < _collisionSprites.size(); index++) {
581 		if (_collisionSprites[index] == sprite) {
582 			_collisionSprites.remove_at(index);
583 			break;
584 		}
585 	}
586 }
587 
clearCollisionSprites()588 void Scene::clearCollisionSprites() {
589 	_collisionSprites.clear();
590 }
591 
checkCollision(Sprite * sprite,uint16 flags,int messageNum,uint32 messageParam)592 void Scene::checkCollision(Sprite *sprite, uint16 flags, int messageNum, uint32 messageParam) {
593 	for (Common::Array<Sprite*>::iterator iter = _collisionSprites.begin(); iter != _collisionSprites.end(); iter++) {
594 		Sprite *collSprite = *iter;
595 		if ((sprite->getFlags() & flags) && collSprite->checkCollision(sprite->getCollisionBounds())) {
596 			sprite->sendMessage(collSprite, messageNum, messageParam);
597 		}
598 	}
599 }
600 
insertMouse(Mouse * mouseCursor)601 void Scene::insertMouse(Mouse *mouseCursor) {
602 	if (_mouseCursor)
603 		deleteSprite((Sprite**)&_mouseCursor);
604 	_mouseCursor = mouseCursor;
605 	addEntity(_mouseCursor);
606 }
607 
608 // StaticScene
609 
StaticScene(NeverhoodEngine * vm,Module * parentModule,uint32 backgroundFileHash,uint32 cursorFileHash)610 StaticScene::StaticScene(NeverhoodEngine *vm, Module *parentModule, uint32 backgroundFileHash, uint32 cursorFileHash)
611 	: Scene(vm, parentModule) {
612 
613 	SetMessageHandler(&StaticScene::handleMessage);
614 
615 	setBackground(backgroundFileHash);
616 	setPalette(backgroundFileHash);
617 	insertPuzzleMouse(cursorFileHash, 20, 620);
618 }
619 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)620 uint32 StaticScene::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
621 	Scene::handleMessage(messageNum, param, sender);
622 	switch (messageNum) {
623 	case NM_MOUSE_CLICK:
624 		if (param.asPoint().x <= 20 || param.asPoint().x >= 620)
625 			leaveScene(0);
626 		break;
627 	default:
628 		break;
629 	}
630 	return 0;
631 }
632 
633 } // End of namespace Neverhood
634