1 /*
2 OpenUniverse 1.0
3 Copyright (C) 2000 Raul Alonso <amil@las.es>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include "ou.h"
21 #include "gui.h"
22
23 #ifdef HAVE_GLUI
24
25 GLUI *glui_rwin = NULL, *glui_trailwin, *glui_optwin = NULL;
26 GLUI_Listbox *list_source, *list_target;
27 GLUI_Panel *control_panel;
28 GLUI_Translation *head_trans, *roll_trans;
29 GLUI_Checkbox *glui_follow;
30 GLUI_RadioGroup *radio;
31 GLUI_RadioButton *cam1, *cam2, *cam3, *cam4;
32 GLUI_Translation *trans_zoom;
33 int fullscreeninGUI = 0, rebuildStarsDL = 0;
34
35 /*
36 GLUI callback
37 */
38
update_cmode(void)39 void update_cmode(void)
40 {
41 int type;
42
43
44 type = ISASPACECRAFT(currtarget);
45
46 if (type)
47 glui_follow->enable();
48 else
49 glui_follow->disable();
50
51
52 if (follow && type) {
53 cam1->set_name("Behind");
54 cam2->set_name("Top");
55 cam3->set_name("Right");
56 cam4->set_name("Left");
57 list_target->enable();
58 trans_zoom->enable();
59 head_trans->enable();
60 roll_trans->enable();
61 } else {
62 cam1->set_name("Free");
63 cam2->set_name("Linked");
64 cam3->set_name("Body to Body");
65 cam4->set_name("Orbiter");
66 switch (cmode) {
67 case 0:
68 case 1:
69 trans_zoom->disable();
70 head_trans->disable();
71 roll_trans->disable();
72 break;
73 case 2:
74 case 3:
75 trans_zoom->enable();
76 break;
77 }
78 }
79
80
81 }
82
glui_callback(int cmd)83 void glui_callback(int cmd)
84 {
85
86 #define CX(s) (s->ball->down_pt[0]-s->ball->center[0])
87 #define CY(s) (s->ball->down_pt[1]-s->ball->center[1])
88
89 static GLUI_Spinner *spinner;
90 static int i;
91
92 switch (cmd) {
93 case OPT_OPEN:
94 if (glui_optwin) {
95 glui_optwin->show();
96 } else {
97 glui_optwin = GLUI_Master.create_glui("Options");
98 glui_optwin->add_checkbox("Demo", &demomode);
99 glui_optwin->add_checkbox("Pause", &paused);
100 glui_optwin->add_separator();
101 glui_optwin->add_checkbox("Atmosphere", &atmospheres);
102 glui_optwin->add_checkbox("Lighting", &lighting);
103 glui_optwin->add_checkbox("Textures", &texture);
104 glui_optwin->add_checkbox("Stars", &drawstars);
105 glui_optwin->add_checkbox("Milky Way", &milkyway);
106 glui_optwin->add_checkbox("Messier Objects", &messier);
107 glui_optwin->add_separator();
108 glui_optwin->add_checkbox("Info", &info);
109 glui_optwin->add_checkbox("Top View Map", &radar);
110 glui_optwin->add_checkbox("Stars labels", &slabels);
111 glui_optwin->add_checkbox("Bodies labels", &plabels);
112 glui_optwin->add_separator();
113 glui_optwin->add_checkbox("Joystick", &joyactive);
114 glui_optwin->add_separator();
115 glui_optwin->add_checkbox("Real time", &realtime);
116 glui_optwin->add_separator();
117 spinner =
118 glui_optwin->add_spinner("Star brightness:",
119 GLUI_SPINNER_FLOAT, &star_mag,
120 OPT_STARMAG,
121 (GLUI_Update_CB) glui_callback);
122 spinner->set_float_limits(0.0, 10.0);
123 glui_optwin->add_button("Trails", TRAILS_OPEN,
124 (GLUI_Update_CB) glui_callback);
125 glui_optwin->add_button("Close", OPT_HIDE,
126 (GLUI_Update_CB) glui_callback);
127 }
128 break;
129 case OPT_HIDE:
130 glui_optwin->hide();
131 break;
132 case TRAILS_OPEN:
133 if (glui_trailwin) {
134 glui_trailwin->show();
135 } else {
136 glui_trailwin = GLUI_Master.create_glui("Trails");
137 for (i = 0; i < NUMBODIES; i++)
138 if ((planets[i].Type == PLANET) ||
139 (planets[i].Type == ASTEROID) ||
140 (planets[i].Type == COMET))
141 glui_trailwin->add_checkbox(planets[i].Name,
142 &planets[i].
143 TrailEnabled);
144 glui_trailwin->add_button("Close", TRAILS_HIDE,
145 (GLUI_Update_CB) glui_callback);
146 }
147 break;
148 case TRAILS_HIDE:
149 glui_trailwin->hide();
150 break;
151 case CAM_NEAR:
152 Key('n', 0, 0);
153 break;
154 case CAM_CMODE:
155 i = follow && ISASPACECRAFT(currtarget);
156 switch (cmode) {
157 case 0:
158 list_target->disable();
159 control_panel->enable();
160 trans_zoom->disable();
161 break;
162 case 1:
163 transition = 1;
164 if (!i) {
165 list_target->enable();
166 control_panel->disable();
167 }
168 break;
169 case 2:
170 transition = 1;
171 if (!i) {
172 list_target->enable();
173 control_panel->disable();
174 }
175 break;
176 case 3:
177 transition = 1;
178 if (!i) {
179 list_target->enable();
180 control_panel->disable();
181 }
182 break;
183 default:
184 break;
185 }
186 update_cmode();
187 break;
188 case CAM_FOLLOW:
189 update_cmode();
190 break;
191 case CAM_SOURCE:
192 if (currsource == currtarget) {
193 currsource = (currsource + 1) % NUMBODIES;
194 while (planets[currsource].Type >= RING)
195 currsource = (currsource + 1) % NUMBODIES;
196 }
197 transition = 1;
198 break;
199 case CAM_TARGET:
200 if (currsource == currtarget) {
201 currtarget = (currtarget + 1) % NUMBODIES;
202 while (planets[currtarget].Type >= RING)
203 currtarget = (currtarget + 1) % NUMBODIES;
204 }
205 update_cmode();
206 transition = 1;
207 break;
208 case CAM_HEADING:
209 if (ISASPACECRAFT(currtarget)) {
210 planets[currtarget].rot[X] = (int) head_trans->get_x();
211 planets[currtarget].rot[Y] = (int) head_trans->get_y();
212 CLAMP_SELF(planets[currtarget].rot[X], -64, 64);
213 CLAMP_SELF(planets[currtarget].rot[Y], -64, 64);
214 head_trans->set_x((float) planets[currtarget].rot[X]);
215 head_trans->set_y((float) planets[currtarget].rot[Y]);
216 } else {
217 camrot[X] = (int) head_trans->get_x();
218 camrot[Y] = (int) head_trans->get_y();
219 CLAMP_SELF(camrot[X], -64, 64);
220 CLAMP_SELF(camrot[Y], -64, 64);
221 head_trans->set_x((float) camrot[X]);
222 head_trans->set_y((float) camrot[Y]);
223 }
224 break;
225 case CAM_ROLL:
226 if (ISASPACECRAFT(currtarget)) {
227 planets[currtarget].rot[Z] = (int) roll_trans->get_x();
228 CLAMP_SELF(planets[currtarget].rot[Z], -64, 64);
229 roll_trans->set_x((float) planets[currtarget].rot[Z]);
230 } else {
231 camrot[Z] = (int) roll_trans->get_x();
232 CLAMP_SELF(camrot[Z], -64, 64);
233 roll_trans->set_x((float) camrot[Z]);
234 }
235 if (roll_trans->get_y() > 0.0)
236 Special(GLUT_KEY_PAGE_UP, 0, 0);
237 if (roll_trans->get_y() < 0.0)
238 Special(GLUT_KEY_PAGE_DOWN, 0, 0);
239 roll_trans->set_y(0.0);
240 break;
241 case GUI_HIDE:
242 glui_rwin->hide();
243 fullscreeninGUI = 1;
244 Reshape(glutGet((GLenum) GLUT_WINDOW_WIDTH),
245 glutGet((GLenum) GLUT_WINDOW_HEIGHT));
246 break;
247 case GUI_QUIT:
248 Key(27, 0, 0);
249 break;
250 case OPT_STARMAG:
251 rebuildStarsDL = 1;
252 break;
253 default:
254 break;
255 }
256 }
257
258
259 #endif
260
261
GUI_Viewport(int * width,int * height)262 void GUI_Viewport(int *width, int *height)
263 {
264 #ifdef HAVE_GLUI
265 int tx, ty, tw, th;
266
267 if (fullscreeninGUI)
268 glViewport(0, 0, *width, *height);
269 else {
270
271 GLUI_Master.get_viewport_area(&tx, &ty, &tw, &th);
272 GLUI_Master.auto_set_viewport();
273 *width = tw;
274 *height = th;
275 }
276 #else
277 glViewport(0, 0, *width, *height);
278 #endif
279
280 }
281
282
GUI_Init(void)283 void GUI_Init(void)
284 {
285 #ifdef HAVE_GLUI
286 int i;
287 char sbuf[80];
288
289 if (fullscreen)
290 return;
291
292 GLUI_Master.set_glutKeyboardFunc(Key);
293 GLUI_Master.set_glutSpecialFunc(Special);
294 GLUI_Master.set_glutMouseFunc(Mouse);
295 glutIdleFunc(NULL);
296 GLUI_Master.set_glutIdleFunc(Idle);
297
298 glui_rwin =
299 GLUI_Master.create_glui_subwindow(main_window,
300 GLUI_SUBWINDOW_RIGHT);
301 glui_rwin->set_main_gfx_window(main_window);
302
303
304 list_source =
305 glui_rwin->add_listbox("Source:", &currsource, CAM_SOURCE,
306 (GLUI_Update_CB) glui_callback);
307 for (i = 0; i < NUMBODIES; i++)
308 switch (planets[i].Type) {
309 case RING:
310 case ATMOSPHERE:
311 break;
312 case SATELLITE:
313 case ORBITER:
314 sprintf(sbuf, " %s", planets[i].Name);
315 list_source->add_item(i, sbuf);
316 break;
317 default:
318 list_source->add_item(i, planets[i].Name);
319 break;
320
321 }
322 list_source->enabled = true;
323
324
325 list_target =
326 glui_rwin->add_listbox("Target:", &currtarget, CAM_TARGET,
327 (GLUI_Update_CB) glui_callback);
328 for (i = 0; i < NUMBODIES; i++)
329 switch (planets[i].Type) {
330 case RING:
331 case ATMOSPHERE:
332 break;
333 case SATELLITE:
334 case ORBITER:
335 sprintf(sbuf, " %s", planets[i].Name);
336 list_target->add_item(i, sbuf);
337 break;
338 default:
339 list_target->add_item(i, planets[i].Name);
340 break;
341
342 }
343
344 glui_rwin->add_button("Go there!", CAM_NEAR,
345 (GLUI_Update_CB) glui_callback);
346
347 GLUI_Panel *camera_panel = glui_rwin->add_panel("Camera Mode");
348 radio =
349 glui_rwin->add_radiogroup_to_panel(camera_panel, &cmode, CAM_CMODE,
350 (GLUI_Update_CB) glui_callback);
351 cam1 = glui_rwin->add_radiobutton_to_group(radio, "Free");
352 cam2 = glui_rwin->add_radiobutton_to_group(radio, "Linked");
353 cam3 = glui_rwin->add_radiobutton_to_group(radio, "Body to Body");
354 cam4 = glui_rwin->add_radiobutton_to_group(radio, "Orbiter");
355 glui_follow =
356 glui_rwin->add_checkbox_to_panel(camera_panel, "Follow", &follow,
357 CAM_FOLLOW,
358 (GLUI_Update_CB) glui_callback);
359 if (ISASPACECRAFT(currtarget))
360 glui_follow->disable();
361
362 control_panel = glui_rwin->add_panel("", GLUI_PANEL_NONE);
363
364 head_trans =
365 glui_rwin->add_translation_to_panel(control_panel, "Heading",
366 GLUI_TRANSLATION_XY, NULL,
367 CAM_HEADING,
368 (GLUI_Update_CB)
369 glui_callback);
370
371 glui_rwin->add_column_to_panel(control_panel, false);
372
373
374 roll_trans =
375 glui_rwin->add_translation_to_panel(control_panel, "Roll/Speed",
376 GLUI_TRANSLATION_XY, NULL,
377 CAM_ROLL,
378 (GLUI_Update_CB)
379 glui_callback);
380
381 GLUI_Panel *lens_panel = glui_rwin->add_panel("", GLUI_PANEL_NONE);
382
383 /* Insert extra blank spaces to avoid misalignment */
384 GLUI_Translation *trans_fov =
385 glui_rwin->add_translation_to_panel(lens_panel, " FOV ",
386 GLUI_TRANSLATION_Z, &fov);
387 trans_fov->set_speed(0.1);
388 trans_fov->set_z(fov);
389
390 glui_rwin->add_column_to_panel(lens_panel, false);
391
392 trans_zoom =
393 glui_rwin->add_translation_to_panel(lens_panel, " ZOOM ",
394 GLUI_TRANSLATION_Z, &zoom);
395 trans_zoom->set_speed(0.1);
396 trans_zoom->set_z(zoom);
397
398 GLUI_Spinner *glui_tf =
399 glui_rwin->add_spinner("Timefactor:", GLUI_SPINNER_INT,
400 &timefactor);
401
402 glui_tf->set_int_limits(-5000, 5000);
403 glui_tf->set_speed(0.001);
404
405 glui_rwin->add_button("Options", OPT_OPEN,
406 (GLUI_Update_CB) glui_callback);
407 glui_rwin->add_button("Hide GUI", GUI_HIDE,
408 (GLUI_Update_CB) glui_callback);
409 glui_rwin->add_button("Quit", GUI_QUIT,
410 (GLUI_Update_CB) glui_callback);
411 if (!cmode)
412 control_panel->disable();
413
414 update_cmode();
415 #endif
416 }
417