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/mouse.h"
24 #include "graphics/cursorman.h"
25 
26 namespace Neverhood {
27 
Mouse(NeverhoodEngine * vm,uint32 fileHash,const NRect & mouseRect)28 Mouse::Mouse(NeverhoodEngine *vm, uint32 fileHash, const NRect &mouseRect)
29 	: StaticSprite(vm, 2000), _mouseType(kMouseType433),
30 	_mouseCursorResource(vm), _frameNum(0) {
31 
32 	_mouseRect = mouseRect;
33 	init(fileHash);
34 	if (_x >= _mouseRect.x1 && _x <= _mouseRect.x2 &&
35 		_y >= _mouseRect.y1 && _y <= _mouseRect.y2) {
36 		_mouseCursorResource.setCursorNum(1);
37 	} else {
38 		_mouseCursorResource.setCursorNum(4);
39 	}
40 	updateCursor();
41 }
42 
Mouse(NeverhoodEngine * vm,uint32 fileHash,int16 x1,int16 x2)43 Mouse::Mouse(NeverhoodEngine *vm, uint32 fileHash, int16 x1, int16 x2)
44 	: StaticSprite(vm, 2000), _mouseType(kMouseType435),
45 	_mouseCursorResource(vm), _frameNum(0), _x1(x1), _x2(x2) {
46 
47 	init(fileHash);
48 	if (_x <= _x1) {
49 		_mouseCursorResource.setCursorNum(6);
50 	} else if (_x >= _x2) {
51 		_mouseCursorResource.setCursorNum(5);
52 	} else {
53 		_mouseCursorResource.setCursorNum(4);
54 	}
55 	updateCursor();
56 }
57 
Mouse(NeverhoodEngine * vm,uint32 fileHash,int type)58 Mouse::Mouse(NeverhoodEngine *vm, uint32 fileHash, int type)
59 	: StaticSprite(vm, 2000), _mouseType(kMouseTypeNavigation),
60 	_mouseCursorResource(vm), _type(type), _frameNum(0) {
61 
62 	init(fileHash);
63 	_mouseCursorResource.setCursorNum(0);
64 }
65 
~Mouse()66 Mouse::~Mouse() {
67 	CursorMan.showMouse(false);
68 }
69 
init(uint32 fileHash)70 void Mouse::init(uint32 fileHash) {
71 	_mouseCursorResource.load(fileHash);
72 	_x = _vm->getMouseX();
73 	_y = _vm->getMouseY();
74 	createSurface(2000, 32, 32);
75 	SetUpdateHandler(&Mouse::update);
76 	SetMessageHandler(&Mouse::handleMessage);
77 	_drawOffset.x = 0;
78 	_drawOffset.y = 0;
79 	_drawOffset.width = 32;
80 	_drawOffset.height = 32;
81 	_collisionBoundsOffset = _drawOffset;
82 	updateBounds();
83 	_needRefresh = true;
84 	CursorMan.showMouse(false);
85 }
86 
load(uint32 fileHash)87 void Mouse::load(uint32 fileHash) {
88 	_mouseCursorResource.load(fileHash);
89 	_needRefresh = true;
90 }
91 
update()92 void Mouse::update() {
93 	if (CursorMan.isVisible() && !_surface->getVisible()) {
94 		CursorMan.showMouse(false);
95 	} else if (!CursorMan.isVisible() && _surface->getVisible()) {
96 		CursorMan.showMouse(true);
97 	}
98 	updateCursor();
99 	_frameNum++;
100 	if (_frameNum >= 6)
101 		_frameNum = 0;
102 	_needRefresh = _frameNum % 2 == 0;
103 }
104 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)105 uint32 Mouse::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
106 	debug(7, "Mouse::handleMessage(%04X)", messageNum);
107 	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
108 	switch (messageNum) {
109 	case 0x2064:
110 		_x = param.asPoint().x;
111 		_y = param.asPoint().y;
112 		switch (_type) {
113 		case 1:
114 			if (_x >= 320)
115 				messageResult = 1;
116 			else
117 				messageResult = 0;
118 			break;
119 		case 2:
120 		default:
121 			if (_x < 100)
122 				messageResult = 0;
123 			else if (_x > 540)
124 				messageResult = 1;
125 			else
126 				messageResult = 2;
127 			break;
128 		case 3:
129 			if (_x < 100)
130 				messageResult = 0;
131 			else if (_x > 540)
132 				messageResult = 1;
133 			else
134 				messageResult = 4;
135 			break;
136 		case 4:
137 			if (_x < 100)
138 				messageResult = 0;
139 			else if (_x > 540)
140 				messageResult = 1;
141 			else if (_y >= 150)
142 				messageResult = 2;
143 			else
144 				messageResult = 3;
145 			break;
146 		case 5:
147 			if (_y >= 240)
148 				messageResult = 4;
149 			else
150 				messageResult = 3;
151 			break;
152 		}
153 		break;
154 	case 0x4002:
155 		_x = param.asPoint().x;
156 		_y = param.asPoint().y;
157 		updateCursorNum();
158 		updateBounds();
159 		break;
160 	default:
161 		break;
162 	}
163 	return messageResult;
164 }
165 
updateCursor()166 void Mouse::updateCursor() {
167 
168 	if (!_surface)
169 		return;
170 
171 	if (_doDeltaX) {
172 		_surface->getDrawRect().x = filterX(_x - _drawOffset.width - _drawOffset.x + 1);
173 	} else {
174 		_surface->getDrawRect().x = filterX(_x + _drawOffset.x);
175 	}
176 
177 	if (_doDeltaY) {
178 		_surface->getDrawRect().y = filterY(_y - _drawOffset.height - _drawOffset.y + 1);
179 	} else {
180 		_surface->getDrawRect().y = filterY(_y + _drawOffset.y);
181 	}
182 
183 	if (_needRefresh) {
184 		_needRefresh = false;
185 		_drawOffset = _mouseCursorResource.getRect();
186 		_surface->drawMouseCursorResource(_mouseCursorResource, _frameNum / 2);
187 		Graphics::Surface *cursorSurface = _surface->getSurface();
188 		CursorMan.replaceCursor((const byte*)cursorSurface->getPixels(),
189 			cursorSurface->w, cursorSurface->h, -_drawOffset.x, -_drawOffset.y, 0);
190 	}
191 
192 }
193 
updateCursorNum()194 void Mouse::updateCursorNum() {
195 	switch (_mouseType) {
196 	case kMouseType433:
197 		if (_x >= _mouseRect.x1 && _x <= _mouseRect.x2 &&
198 			_y >= _mouseRect.y1 && _y <= _mouseRect.y2) {
199 			_mouseCursorResource.setCursorNum(1);
200 		} else {
201 			_mouseCursorResource.setCursorNum(4);
202 		}
203 		break;
204 	case kMouseType435:
205 		if (_x <= _x1) {
206 			_mouseCursorResource.setCursorNum(6);
207 		} else if (_x >= _x2) {
208 			_mouseCursorResource.setCursorNum(5);
209 		} else {
210 			_mouseCursorResource.setCursorNum(4);
211 		}
212 		break;
213 	case kMouseTypeNavigation:
214 		switch (_type) {
215 		case 1:
216 			if (_x >= 320)
217 				_mouseCursorResource.setCursorNum(5);
218 			else
219 				_mouseCursorResource.setCursorNum(6);
220 			break;
221 		case 2:
222 		default:
223 			if (_x < 100)
224 				_mouseCursorResource.setCursorNum(6);
225 			else if (_x > 540)
226 				_mouseCursorResource.setCursorNum(5);
227 			else
228 				_mouseCursorResource.setCursorNum(0);
229 			break;
230 		case 3:
231 			if (_x < 100)
232 				_mouseCursorResource.setCursorNum(1);
233 			else if (_x > 540)
234 				_mouseCursorResource.setCursorNum(1);
235 			break;
236 		case 4:
237 			if (_x < 100)
238 				_mouseCursorResource.setCursorNum(6);
239 			else if (_x > 540)
240 				_mouseCursorResource.setCursorNum(5);
241 			else if (_y >= 150)
242 				_mouseCursorResource.setCursorNum(0);
243 			else
244 				_mouseCursorResource.setCursorNum(3);
245 			break;
246 		case 5:
247 			if (_y >= 240)
248 				_mouseCursorResource.setCursorNum(2);
249 			else
250 				_mouseCursorResource.setCursorNum(3);
251 			break;
252 		}
253 		break;
254 	default:
255 		break;
256 	}
257 
258 }
259 
260 } // End of namespace Neverhood
261