aboutsummaryrefslogtreecommitdiff
path: root/engines/gob/hotspots.h
blob: 912ac8a20e52383a20ee01a511c82e4f044a07fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#ifndef GOB_HOTSPOTS_H
#define GOB_HOTSPOTS_H

#include "common/stack.h"

#include "gob/util.h"

namespace Gob {

class Font;
class Script;

class Hotspots {
public:
	static const int kHotspotCount = 250;

	enum Type {
		kTypeNone              =  0,
		kTypeMove              =  1,
		kTypeClick             =  2,
		kTypeInput1NoLeave     =  3,
		kTypeInput1Leave       =  4,
		kTypeInput2NoLeave     =  5,
		kTypeInput2Leave       =  6,
		kTypeInput3NoLeave     =  7,
		kTypeInput3Leave       =  8,
		kTypeInputFloatNoLeave =  9,
		kTypeInputFloatLeave   = 10,
		kTypeEnable2           = 11,
		kTypeEnable1           = 12,
		kTypeClickEnter        = 21
	};

	enum State {
		kStateFilledDisabled = 0xC,
		kStateFilled         = 0x8,
		kStateDisabled       = 0x4,
		kStateType2          = 0x2,
		kStateType1          = 0x1
	};

	Hotspots(GobEngine *vm);
	~Hotspots();

	/** Remove all hotspots. */
	void clear();

	/** Add a hotspot, returning the new index. */
	uint16 add(uint16 id,
			uint16 left,  uint16 top, uint16 right, uint16 bottom,
			uint16 flags, uint16 key,
			uint16 funcEnter, uint16 funcLeave, uint16 funcPos);

	/** Remove a specific hotspot. */
	void remove(uint16 id);
	/** Remove all hotspots in this state. */
	void removeState(uint8 state);

	/** Push the current hotspots onto the stack.
	 *
	 *  @param all   0: Don't push global ones; 1: Push all; 2: Push only the disabled ones
	 *  @param force Force a push although _shouldPush is false
	 */
	void push(uint8 all, bool force = false);
	/** Pop hotspots from the stack. */
	void pop();

	/** Check the current hotspot. */
	uint16 check(uint8 handleMouse, int16 delay, uint16 &id, uint16 &index);
	/** Check the current hotspot. */
	uint16 check(uint8 handleMouse, int16 delay);

	/** Evaluate hotspot changes. */
	void evaluate();

	/** Return the cursor found in the hotspot to the coordinates. */
	int16 findCursor(uint16 x, uint16 y) const;

	/** implementation of oPlaytoons_F_1B code*/
	void oPlaytoons_F_1B();

private:
	struct Hotspot {
		uint16  id;
		uint16  left;
		uint16  top;
		uint16  right;
		uint16  bottom;
		uint16  flags;
		uint16  key;
		uint16  funcEnter;
		uint16  funcLeave;
		uint16  funcPos;
		Script *script;

		Hotspot();
		Hotspot(uint16 i,
				uint16 l, uint16 t, uint16 r, uint16 b, uint16 f, uint16 k,
				uint16 enter, uint16 leave, uint16 pos);

		void clear();

		Type         getType  () const;
		MouseButtons getButton() const;
		uint16       getWindow() const;
		uint8        getCursor() const;
		uint8        getState () const;

		/** Is this hotspot the block end marker? */
		bool isEnd() const;

		bool isInput      () const;
		bool isActiveInput() const;
		bool isInputLeave () const;

		bool isFilled       () const;
		bool isFilledEnabled() const;
		bool isFilledNew    () const;
		bool isDisabled     () const;

		/** Are the specified coordinates in the hotspot? */
		bool isIn(uint16 x, uint16 y) const;
		/** Does the specified button trigger the hotspot? */
		bool buttonMatch(MouseButtons button) const;

		static uint8 getState(uint16 id);

		void disable();
		void enable ();
	};

	struct StackEntry {
		bool     shouldPush;
		Hotspot *hotspots;
		uint32   size;
		uint32   key;
		uint32   id;
		uint32   index;
		uint16   x;
		uint16   y;
	};

	struct InputDesc {
		uint16 fontIndex;
		uint16 backColor;
		uint16 frontColor;
		uint16 length;
		const char *str;
	};

	GobEngine *_vm;

	Hotspot *_hotspots;
	Common::Stack<StackEntry> _stack;

	bool _shouldPush;

	uint16 _currentKey;
	uint16 _currentIndex;
	uint16 _currentId;
	uint16 _currentX;
	uint16 _currentY;

	/** Add a hotspot, returning the new index. */
	uint16 add(const Hotspot &hotspot);

	/** Recalculate all hotspot parameters
	 *
	 *  @param force Force recalculation of all hotspots, including global ones.
	 */
	void recalculate(bool force);

	/** Is this a valid hotspot? */
	bool isValid(uint16 key, uint16 id, uint16 index) const;

	/** Call a hotspot subroutine. */
	void call(uint16 offset);
	/** Handling hotspot enter events. */
	void enter(uint16 index);
	/** Handling hotspot leave events. */
	void leave(uint16 index);

	/** Check whether a specific part of the window forces a certain cursor. */
	int16 windowCursor(int16 &dx, int16 &dy) const;

	/** Which hotspot is the mouse cursor currently at? */
	uint16 checkMouse(Type type, uint16 &id, uint16 &index) const;

	/** Did the current hotspot change in the meantime? */
	bool checkHotspotChanged();

	/** Update events from a specific input. */
	uint16 updateInput(uint16 xPos, uint16 yPos, uint16 width, uint16 height,
			uint16 backColor, uint16 frontColor, char *str, uint16 fontIndex,
			Type type, int16 &duration, uint16 &id, uint16 &index);

	/** Handle all inputs we currently manage. */
	uint16 handleInputs(int16 time, uint16 inputCount, uint16 &curInput,
			InputDesc *inputs, uint16 &id, uint16 &index);

	/** Evaluate adding new hotspots script commands. */
	void evaluateNew(uint16 i, uint16 *ids, InputDesc *inputs,
			uint16 &inputId, bool &hasInput, uint16 &inputCount);
	/** Find the hotspot requested by script commands. */
	bool evaluateFind(uint16 key, int16 timeVal, const uint16 *ids,
			uint16 leaveWindowIndex, uint16 hotspotIndex1, uint16 hotspotIndex2,
			uint16 endIndex, int16 &duration, uint16 &id, uint16 &index, bool &finished);

	// Finding specific hotspots
	/** Find the hotspot index that corresponds to the input index. */
	uint16 inputToHotspot(uint16 input) const;
	/** Find the input index that corresponds to the hotspot index. */
	uint16 hotspotToInput(uint16 hotspot) const;
	/** Find the input that was clicked on. */
	uint16 findClickedInput(uint16 index) const;
	/** Find the first input hotspot with a leave function. */
	bool findFirstInputLeave(uint16 &id, uint16 &inputId, uint16 &index) const;
	/** Find the hotspot with the matching key, case sensitively. */
	bool findKey(uint16 key, uint16 &id, uint16 &index) const;
	/** Find the hotspot with the matching key, case insensitively. */
	bool findKeyCaseInsensitive(uint16 key, uint16 &id, uint16 &index) const;
	/** Find the nth plain (without Type1 or Type2 state) hotspot. */
	bool findNthPlain(uint16 n, uint16 startIndex, uint16 &id, uint16 &index) const;

	/** Leave the nth plain (without Type1 or Type2 state) hotspot. */
	bool leaveNthPlain(uint16 n, uint16 startIndex, int16 timeVal, const uint16 *ids,
			uint16 &id, uint16 &index, int16 &duration);

	// Hotspot ID variable access
	void setCurrentHotspot(const uint16 *ids, uint16 id) const;
	uint32 getCurrentHotspot() const;

	// String input functions
	void cleanFloatString(const Hotspot &spot) const;
	void checkStringMatch(const Hotspot &spot, const InputDesc &input,
			uint16 inputPos) const;
	void matchInputStrings(const InputDesc *inputs) const;

	uint16 convertSpecialKey(uint16 key) const;

	/** Calculate the graphical cursor position. */
	void getTextCursorPos(const Font &font, const char *str,
			uint32 pos, uint16 x, uint16 y, uint16 width, uint16 height,
			uint16 &cursorX, uint16 &cursorY, uint16 &cursorWidth, uint16 &cursorHeight) const;

	/** Fill that rectangle with the color. */
	void fillRect(uint16 x, uint16 y, uint16 width, uint16 height, uint16 color) const;
	/** Print the given text. */
	void printText(uint16 x, uint16 y, const char *str, uint16 fontIndex, uint16 color) const;

	/** Go through all inputs we manage and redraw their texts. */
	void updateAllTexts(const InputDesc *inputs) const;
};

} // End of namespace Gob

#endif // GOB_HOTSPOTS_H