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  * Additional copyright for this file:
8  * Copyright (C) 1995 Presto Studios, Inc.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19 
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  *
24  */
25 
26 #include "buried/buried.h"
27 #include "buried/gameui.h"
28 #include "buried/graphics.h"
29 #include "buried/inventory_window.h"
30 #include "buried/navarrow.h"
31 #include "buried/navdata.h"
32 #include "buried/resources.h"
33 #include "buried/scene_view.h"
34 
35 #include "common/keyboard.h"
36 #include "graphics/surface.h"
37 
38 namespace Buried {
39 
NavArrowWindow(BuriedEngine * vm,Window * parent)40 NavArrowWindow::NavArrowWindow(BuriedEngine *vm, Window *parent) : Window(vm, parent) {
41 	_background = _vm->_gfx->getBitmap(IDB_ARROW_BACKGROUND);
42 
43 	_arrowBitmaps[0][0] = IDB_ARROW_UP_CLEAR;
44 	_arrowBitmaps[0][1] = IDB_ARROW_UP_LIT;
45 	_arrowBitmaps[0][2] = IDB_ARROW_UP_HIGHLIGHTED;
46 	_arrowBitmaps[1][0] = IDB_ARROW_LEFT_CLEAR;
47 	_arrowBitmaps[1][1] = IDB_ARROW_LEFT_LIT;
48 	_arrowBitmaps[1][2] = IDB_ARROW_LEFT_HIGHLIGHTED;
49 	_arrowBitmaps[2][0] = IDB_ARROW_RIGHT_CLEAR;
50 	_arrowBitmaps[2][1] = IDB_ARROW_RIGHT_LIT;
51 	_arrowBitmaps[2][2] = IDB_ARROW_RIGHT_HIGHLIGHTED;
52 	_arrowBitmaps[3][0] = IDB_ARROW_DOWN_CLEAR;
53 	_arrowBitmaps[3][1] = IDB_ARROW_DOWN_LIT;
54 	_arrowBitmaps[3][2] = IDB_ARROW_DOWN_HIGHLIGHTED;
55 	_arrowBitmaps[4][0] = IDB_ARROW_FORWARD_CLEAR;
56 	_arrowBitmaps[4][1] = IDB_ARROW_FORWARD_LIT;
57 	_arrowBitmaps[4][2] = IDB_ARROW_FORWARD_HIGHLIGHTED;
58 
59 	for (int i = 0; i < NUM_ARROWS; i++)
60 		_arrowStatus[i] = BUTTON_DISABLED;
61 
62 	rebuildArrows();
63 
64 	_rect = Common::Rect(510, 292, 640, 418);
65 }
66 
~NavArrowWindow()67 NavArrowWindow::~NavArrowWindow() {
68 	_background->free();
69 	delete _background;
70 }
71 
updateArrow(int button,int newStatus)72 bool NavArrowWindow::updateArrow(int button, int newStatus) {
73 	_arrowStatus[button] = newStatus;
74 
75 	rebuildArrows();
76 	invalidateWindow(false);
77 	return true;
78 }
79 
updateAllArrows(int left,int up,int right,int down,int forward)80 bool NavArrowWindow::updateAllArrows(int left, int up, int right, int down, int forward) {
81 	// clone2727 says: This is wrong. Left and up are swapped.
82 	// I can only imagine what bugs this causes.
83 	_arrowStatus[0] = left;
84 	_arrowStatus[1] = up;
85 	_arrowStatus[2] = right;
86 	_arrowStatus[3] = down;
87 	_arrowStatus[4] = forward;
88 
89 	rebuildArrows();
90 	invalidateWindow(false);
91 	return true;
92 }
93 
updateAllArrows(const LocationStaticData & locationStaticData)94 bool NavArrowWindow::updateAllArrows(const LocationStaticData &locationStaticData) {
95 	_arrowStatus[0] = (locationStaticData.destUp.destinationScene.timeZone >= 0) ? BUTTON_ENABLED : BUTTON_DISABLED;
96 	_arrowStatus[1] = (locationStaticData.destLeft.destinationScene.timeZone >= 0) ? BUTTON_ENABLED : BUTTON_DISABLED;
97 	_arrowStatus[2] = (locationStaticData.destRight.destinationScene.timeZone >= 0) ? BUTTON_ENABLED : BUTTON_DISABLED;
98 	_arrowStatus[3] = (locationStaticData.destDown.destinationScene.timeZone >= 0) ? BUTTON_ENABLED : BUTTON_DISABLED;
99 	_arrowStatus[4] = (locationStaticData.destForward.destinationScene.timeZone >= 0) ? BUTTON_ENABLED : BUTTON_DISABLED;
100 
101 	rebuildArrows();
102 	invalidateWindow(false);
103 	return true;
104 }
105 
drawArrow(int xDst,int yDst,int arrow)106 bool NavArrowWindow::drawArrow(int xDst, int yDst, int arrow) {
107 	Graphics::Surface *arrowBitmap = _vm->_gfx->getBitmap(_arrowBitmaps[arrow][_arrowStatus[arrow]]);
108 
109 	for (int ySrc = 0; ySrc < arrowBitmap->h; ySrc++)
110 		memcpy(_background->getBasePtr(xDst, yDst + ySrc), arrowBitmap->getBasePtr(0, ySrc), arrowBitmap->w * arrowBitmap->format.bytesPerPixel);
111 
112 	arrowBitmap->free();
113 	delete arrowBitmap;
114 	return true;
115 }
116 
rebuildArrows()117 bool NavArrowWindow::rebuildArrows() {
118 	_background->free();
119 	delete _background;
120 	_background = _vm->_gfx->getBitmap(IDB_ARROW_BACKGROUND);
121 
122 	drawArrow(37, 2, 0);
123 	drawArrow(2, 39, 1);
124 	drawArrow(64, 38, 2);
125 	drawArrow(38, 68, 3);
126 
127 	Graphics::Surface *centerArrow = _vm->_gfx->getBitmap(_arrowBitmaps[4][_arrowStatus[4]]);
128 	_vm->_gfx->opaqueTransparentBlit(_background, 39, 49, centerArrow->w, centerArrow->h, centerArrow, 0, 0, (_arrowStatus[4] == BUTTON_DISABLED) ? 50 : 85, 255, 255, 255);
129 	centerArrow->free();
130 	delete centerArrow;
131 	return true;
132 }
133 
onLButtonDown(const Common::Point & point,uint flags)134 void NavArrowWindow::onLButtonDown(const Common::Point &point, uint flags) {
135 	Common::Rect leftButton(1, 43, 40, 78);
136 	Common::Rect upButton(40, 1, 76, 45);
137 	Common::Rect rightButton(63, 45, 130, 71);
138 	Common::Rect downButton(42, 71, 78, 124);
139 	Common::Rect forwardButton(39, 49, 101, 91);
140 
141 	((GameUIWindow *)_parent)->_inventoryWindow->destroyInfoWindow();
142 	((GameUIWindow *)_parent)->_inventoryWindow->destroyBurnedLetterWindow();
143 
144 	// clone2727: This logic was broken in the original. retVal wasn't initialized.
145 	bool retVal = false;
146 
147 	// Did we click anywhere near the forward button?
148 	if (forwardButton.contains(point)) {
149 		// If we only clicked on the forward arrow, then take care of it here
150 		if (!rightButton.contains(point) && !downButton.contains(point)) {
151 			if (_arrowStatus[4] == BUTTON_ENABLED)
152 				((GameUIWindow *)_parent)->_sceneViewWindow->moveInDirection(kDirectionForward);
153 		} else {
154 			if (rightButton.contains(point)) {
155 				Graphics::Surface *centerArrow = _vm->_gfx->getBitmap(_arrowBitmaps[4][_arrowStatus[4]]);
156 
157 				if (_vm->_gfx->checkPointAgainstMaskedBitmap(centerArrow, 39, 49, point, 255, 255, 255)) {
158 					if (_arrowStatus[4] == BUTTON_ENABLED)
159 						retVal = ((GameUIWindow *)_parent)->_sceneViewWindow->moveInDirection(kDirectionForward);
160 				} else {
161 					if (_arrowStatus[2] == BUTTON_ENABLED)
162 						retVal = ((GameUIWindow *)_parent)->_sceneViewWindow->moveInDirection(kDirectionRight);
163 				}
164 
165 				centerArrow->free();
166 				delete centerArrow;
167 			}
168 
169 			if (downButton.contains(point)) {
170 				Graphics::Surface *centerArrow = _vm->_gfx->getBitmap(_arrowBitmaps[4][_arrowStatus[4]]);
171 
172 				if (_vm->_gfx->checkPointAgainstMaskedBitmap(centerArrow, 39, 49, point, 255, 255, 255)) {
173 					if (_arrowStatus[4] == BUTTON_ENABLED)
174 						retVal = ((GameUIWindow *)_parent)->_sceneViewWindow->moveInDirection(kDirectionForward);
175 				} else {
176 					if (_arrowStatus[3] == BUTTON_ENABLED)
177 						retVal = ((GameUIWindow *)_parent)->_sceneViewWindow->moveInDirection(kDirectionDown);
178 				}
179 
180 				centerArrow->free();
181 				delete centerArrow;
182 			}
183 		}
184 	} else {
185 		if (upButton.contains(point) && _arrowStatus[0] == BUTTON_ENABLED)
186 			retVal = ((GameUIWindow *)_parent)->_sceneViewWindow->moveInDirection(kDirectionUp);
187 
188 		if (leftButton.contains(point) && _arrowStatus[1] == BUTTON_ENABLED)
189 			retVal = ((GameUIWindow *)_parent)->_sceneViewWindow->moveInDirection(kDirectionLeft);
190 
191 		if (rightButton.contains(point) && _arrowStatus[2] == BUTTON_ENABLED)
192 			retVal = ((GameUIWindow *)_parent)->_sceneViewWindow->moveInDirection(kDirectionRight);
193 
194 		if (downButton.contains(point) && _arrowStatus[3] == BUTTON_ENABLED)
195 			retVal = ((GameUIWindow *)_parent)->_sceneViewWindow->moveInDirection(kDirectionDown);
196 	}
197 
198 	if (retVal) {
199 		rebuildArrows();
200 		invalidateWindow(false);
201 	}
202 }
203 
onKeyUp(const Common::KeyState & key,uint flags)204 void NavArrowWindow::onKeyUp(const Common::KeyState &key, uint flags) {
205 	switch (key.keycode) {
206 	case Common::KEYCODE_KP4:
207 	case Common::KEYCODE_LEFT:
208 		if (_arrowStatus[1] == BUTTON_ENABLED)
209 			((GameUIWindow *)_parent)->_sceneViewWindow->moveInDirection(kDirectionLeft);
210 		break;
211 	case Common::KEYCODE_KP6:
212 	case Common::KEYCODE_RIGHT:
213 		if (_arrowStatus[2] == BUTTON_ENABLED)
214 			((GameUIWindow *)_parent)->_sceneViewWindow->moveInDirection(kDirectionRight);
215 		break;
216 	case Common::KEYCODE_KP2:
217 	case Common::KEYCODE_DOWN:
218 		if (_arrowStatus[3] == BUTTON_ENABLED)
219 			((GameUIWindow *)_parent)->_sceneViewWindow->moveInDirection(kDirectionDown);
220 		break;
221 	case Common::KEYCODE_KP8:
222 	case Common::KEYCODE_UP:
223 		if (_arrowStatus[0] == BUTTON_ENABLED)
224 			((GameUIWindow *)_parent)->_sceneViewWindow->moveInDirection(kDirectionUp);
225 		break;
226 	case Common::KEYCODE_KP5:
227 		if (_arrowStatus[4] == BUTTON_ENABLED)
228 			((GameUIWindow *)_parent)->_sceneViewWindow->moveInDirection(kDirectionForward);
229 		break;
230 	default:
231 		break;
232 	}
233 }
234 
onPaint()235 void NavArrowWindow::onPaint() {
236 	Common::Rect absoluteRect = getAbsoluteRect();
237 	_vm->_gfx->blit(_background, absoluteRect.left, absoluteRect.top);
238 }
239 
onEnable(bool enable)240 void NavArrowWindow::onEnable(bool enable) {
241 	if (enable)
242 		_vm->removeMouseMessages(this);
243 }
244 
245 } // End of namespace Buried
246