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