1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 
13 #include "cfile/cfile.h"
14 #include "freespace.h"
15 #include "gamesnd/gamesnd.h"
16 #include "globalincs/alphacolors.h"
17 #include "graphics/font.h"
18 #include "io/key.h"
19 #include "io/mouse.h"
20 #include "localization/localize.h"
21 #include "menuui/snazzyui.h"
22 
23 
24 extern int ascii_table[];
25 extern int shifted_ascii_table[];
26 
27 static int Snazzy_mouse_left_was_down;
28 
snazzy_flush()29 void snazzy_flush()
30 {
31 	Snazzy_mouse_left_was_down = 0;
32 }
33 
snazzy_menu_init()34 void snazzy_menu_init()
35 {
36 	game_flush();
37 }
38 
39 // snazzy_menu_do()
40 //
41 // This function will return an identifier that matches the region of the
42 // image the mouse pointer is currently over.  The function works by working
43 // with two images
44 //
45 // 1. An image that is displayed to the player
46 // 2. A second image, not seen, which has masks for certain areas of image 1
47 //
48 // The idea is to read the mouse, and determine if the mouse pointer is currently
49 // over one of these regions.  Since these regions may be many different colors,
50 // the mask is checked instead, since the regions are always a uniform color
51 //
52 //	The action parameter is used to return whether the region is clicked on or simply
53 // has the mouse over it.  The #defines SNAZZY_OVER and SNAZZY_CLICKED are used.
54 //
55 // The purpose of the key_in parameter is to allow the caller to determine if any
56 // keys are pressed while within the snazzy_menu_do().  It is an optional parameter.
57 //
58 
snazzy_menu_do(ubyte * data,int mask_w,int mask_h,int num_regions,MENU_REGION * regions,int * action,int poll_key,int * key)59 int snazzy_menu_do(ubyte *data, int mask_w, int mask_h, int num_regions, MENU_REGION *regions, int *action, int poll_key, int *key)
60 {
61 	GR_DEBUG_SCOPE("Snazzy Menu");
62 
63 	int i, k, x, y, offset;
64 	int choice = -1, mouse_on_choice = -1;
65 	ubyte pixel_value = 0;
66 
67 	Assert(data != NULL);
68 	Assert(num_regions > 0);
69 	Assert(regions != NULL);
70 
71 	gr_reset_clip();  // don't remove
72 	mouse_get_pos_unscaled( &x, &y );
73 
74 	// boundary conditions
75 	if((y < 0) || (y > mask_h - 1) || (x < 0) || (x > mask_w - 1)){
76 		pixel_value = 255;
77 	} else {
78 		// check the pixel value under the mouse
79 		offset = y * mask_w + x;
80 		pixel_value = *(data + (offset));
81 	}
82 
83 	*action = -1;
84 
85 	k = 0;
86 	if ( poll_key ) {
87 		k = game_check_key();
88 		if (key)
89 			*key = k;  // pass keypress back to caller
90 	}
91 
92 //	if (mouse_down_count(MOUSE_LEFT_BUTTON) )	{
93 	if ( !mouse_down(MOUSE_LEFT_BUTTON) && Snazzy_mouse_left_was_down ) {
94 		//nprintf(("Alan", "pixel val: %d\n", pixel_value));
95 		for (i=0; i < num_regions; i++) {
96 			if (pixel_value == regions[i].mask) {
97 				choice = regions[i].mask;
98 				if ( regions[i].click_sound.isValid() ) {
99 					snd_play( gamesnd_get_interface_sound(regions[i].click_sound), 0.0f );
100 				}
101 			}
102 		}	// end for
103 	}
104 
105 	switch ( k ) {
106 		case KEY_ESC:
107 			choice = ESC_PRESSED;
108 			break;
109 
110 		default:
111 			if (k && k >= 0 && static_cast<size_t>(k) < SIZE_OF_ASCII_TABLE) {
112 				for (i = 0; i < num_regions; i++) {
113 					if (!regions[i].key)
114 						continue;
115 					if (ascii_table[k] == regions[i].key || shifted_ascii_table[k] == regions[i].key) {
116 						choice = regions[i].mask;
117 						if (regions[i].click_sound.isValid()) {
118 							snd_play(gamesnd_get_interface_sound(regions[i].click_sound), 0.0f);
119 						}
120 					}
121 				} // end for
122 			}
123 
124 			break;
125 
126 	} // end switch
127 
128 	for (i=0; i<num_regions; i++) {
129 		if (pixel_value == regions[i].mask) {
130 			mouse_on_choice = regions[i].mask;
131 			break;
132 		}
133 	}	// end for
134 
135 	gr_set_color_fast(&Color_white);
136 	font::set_font(font::FONT1);
137 
138 	if ((mouse_on_choice >= 0) && (mouse_on_choice <= (num_regions)) && (i >=0)) {
139 		int w;
140 		gr_get_string_size(&w, NULL, regions[i].text);
141 
142 		gr_printf_menu( (gr_screen.clip_width_unscaled - w) / 2, 450, "%s", regions[i].text );
143 	}
144 
145 	if ( mouse_down(MOUSE_LEFT_BUTTON) ){
146 		Snazzy_mouse_left_was_down = 1;
147 	} else {
148 		Snazzy_mouse_left_was_down = 0;
149 	}
150 
151 	if ( choice > -1 || choice == ESC_PRESSED ) {
152 		*action = SNAZZY_CLICKED;
153 		return choice;
154 	}
155 
156 	if ( mouse_on_choice > -1 ) {
157 		*action = SNAZZY_OVER;
158 		return mouse_on_choice;
159 	}
160 
161 	return -1;
162 }
163 
164 // add_region() will set up a menu region
165 //
166 //
167 //
168 
snazzy_menu_add_region(MENU_REGION * region,const char * text,int mask,int key,interface_snd_id click_sound)169 void snazzy_menu_add_region(MENU_REGION* region, const char* text, int mask, int key, interface_snd_id click_sound)
170 {
171 	region->mask = mask;
172 	region->key = key;
173 	strcpy_s(region->text, text);
174 	region->click_sound = click_sound;
175 }
176 
177 
178 
179 // read_menu_tbl() will parse through menu.tbl and store the different menu region data
180 //
181 //
182 //
183 
read_menu_tbl(const char * menu_name,char * bkg_filename,char * mask_filename,MENU_REGION * regions,int * num_regions,int play_sound)184 void read_menu_tbl(const char* menu_name, char* bkg_filename, char* mask_filename, MENU_REGION* regions, int* num_regions, int play_sound)
185 {
186 	CFILE* fp;
187 	int state=0;
188 	char* p1, *p2, *p3;
189 	//char music_filename[128];
190 
191 	char seps[]   = NOX(" ,\t");
192 	char *token;
193 	char tmp_line[132];
194 
195 	*num_regions=0;
196 
197 	fp = cfopen( NOX("menu.tbl"), "rt" );
198 	if (fp == NULL) {
199 		Error(LOCATION, "menu.tbl could not be opened\n");
200 
201 		return;
202 	}
203 
204 
205 	while (cfgets(tmp_line, 132, fp)) {
206 		p1 = strchr(tmp_line,'\n'); if (p1) *p1 = '\0';
207 		p1 = strchr(tmp_line,';'); if (p1) *p1 = '\0';
208 		p1 = p3 = strchr( tmp_line, '[' );
209 
210 		if (p3 && state == 1) {
211 			cfclose(fp);
212 			return;
213 		}
214 
215 		if ( p1 || p3)	{
216 			if (!state)	{
217 				p2 = strchr( tmp_line, ']' );
218 				if (p2) *p2 = 0;
219 				if (!stricmp( ++p1, menu_name )) state = 1;
220 			} else {
221 				cfclose(fp);
222 				break;
223 			}
224 		} else if (state) {
225 
226 
227 			// parse a region line
228 			p1 = strchr( tmp_line, '\"' );
229 			if (p1) {
230 				p2 = strchr( tmp_line+1, '\"' );
231 				if (!p2) {
232 					nprintf(("Warning","Error parsing menu file\n"));
233 
234 					return;
235 				}
236 				*p2 = 0;
237 				strcpy_s(regions[*num_regions].text,++p1);
238 				p2++;
239 
240 				// get the tokens mask number
241 				token = strtok( p2, seps );
242 				regions[*num_regions].mask = atoi(token);
243 
244 				// get the hot key character
245 				token = strtok( NULL, seps );
246 				regions[*num_regions].key = token[0];
247 
248 				// stuff default click sound (not in menu.tbl)
249 				if ( play_sound ) {
250 					regions[*num_regions].click_sound = InterfaceSounds::IFACE_MOUSE_CLICK;
251 				} else {
252 					regions[*num_regions].click_sound = interface_snd_id();
253 				}
254 
255 				*num_regions = *num_regions + 1;
256 
257 			}
258 				else {
259 				// get the menu filenames
260 
261 				// Establish string and get the first token
262 				token = strtok( tmp_line, seps );
263 				if ( token != NULL )
264 				{
265 					// store the background filename
266 					strcpy(bkg_filename, token);
267 
268 					// get the mask filename
269 					token = strtok( NULL, seps );
270 					strcpy(mask_filename, token);
271 				}
272 			}
273 		}
274 	}
275 	cfclose(fp);
276 }
277 
278 // snazzy_menu_close() is called when the menu using a snazzy interface is exited
279 //
280 //
281 
snazzy_menu_close()282 void snazzy_menu_close()
283 {
284 	game_flush();
285 }
286