FS2_Open
Open source remastering of the Freespace 2 engine
lab.cpp
Go to the documentation of this file.
1 /*
2  * lab.cpp
3  * created by WMCoolmon
4  *
5  * You may not sell or otherwise commercially exploit the source or things you
6  * create based on the source.
7  *
8  */
9 
10 
11 
12 #include "cmdline/cmdline.h"
13 #include "freespace2/freespace.h"
15 #include "graphics/gropengldraw.h"
16 #include "graphics/gropengllight.h"
18 #include "graphics/shadows.h"
19 #include "hud/hudshield.h"
20 #include "io/key.h"
21 #include "io/timer.h"
22 #include "lab/wmcgui.h"
23 #include "lighting/lighting.h"
24 #include "mission/missionparse.h"
26 #include "model/model.h"
27 #include "object/objectsnd.h"
28 #include "playerman/managepilot.h"
29 #include "render/3d.h"
30 #include "ship/ship.h"
32 #include "weapon/beam.h"
33 #include "weapon/weapon.h"
34 
35 // flags
36 #define LAB_FLAG_NORMAL (0) // default
37 #define LAB_FLAG_NO_ROTATION (1<<0) // don't rotate models
38 #define LAB_FLAG_SHOW_INSIGNIA (1<<1) // show ships with insignia applied
39 #define LAB_FLAG_SHOW_DEBRIS (1<<2) // render debris instead of normal LOD
40 #define LAB_FLAG_SUBMODEL_ROTATE (1<<3) // do rotation for any rotating ship subobjects
41 #define LAB_FLAG_LIGHTNING_ARCS (1<<4) // show damage lightning
42 #define LAB_FLAG_UNUSED (1<<5) // feel free to change that to something you need - Valathil
43 #define LAB_FLAG_SHOW_WEAPONS (1<<6) // determines if external weapons models are displayed
44 #define LAB_FLAG_INITIAL_ROTATION (1<<7) // initial rotation setting
45 #define LAB_FLAG_DESTROYED_SUBSYSTEMS (1<<8) // render model as if all subsystems are destroyed
46 
47 // modes
48 #define LAB_MODE_NONE 0 // not showing anything
49 #define LAB_MODE_SHIP 1 // dealing with ships
50 #define LAB_MODE_WEAPON 2 // dealing with weapons
51 
52 
53 // variables
54 static GUIScreen *Lab_screen = NULL;
55 static Window *Lab_toolbar = NULL;
56 static Window *Lab_class_window = NULL;
57 static Window *Lab_class_toolbar = NULL;
58 static Window *Lab_flags_window = NULL;
59 static Window *Lab_render_options_window = NULL;
60 static Window *Lab_variables_window = NULL;
61 static Window *Lab_description_window = NULL;
62 static Text *Lab_description_text = NULL;
63 static TreeItem **Lab_species_nodes = NULL;
64 
65 static bool Lab_in_mission = false;
66 static int Lab_screen_save_bitmap = -1;
67 static shader Lab_shader;
68 
69 static int Lab_insignia_bitmap = -1;
70 static int Lab_insignia_index = -1;
71 
72 static ubyte Lab_mode = LAB_MODE_NONE;
73 static int Lab_selected_index = -1;
74 static int Lab_last_selected_ship = -1;
75 static int Lab_selected_object = -1;
76 static int Lab_last_selected_weapon = -1;
77 
78 static int Lab_model_num = -1;
79 static int Lab_weaponmodel_num[MAX_SHIP_WEAPONS];
80 static int Lab_model_LOD = 0;
81 static int Lab_model_flags = MR_AUTOCENTER | MR_NO_FOGGING;
82 static int Lab_model_debug_flags = 0;
83 static char Lab_model_filename[MAX_FILENAME_LEN];
84 static char Lab_weaponmodel_filename[MAX_SHIP_WEAPONS][MAX_FILENAME_LEN];
85 
86 static int Lab_bitmap_id = -1;
87 static char Lab_bitmap_filename[MAX_FILENAME_LEN];
88 
89 static float Lab_viewer_zoom = 1.2f;
90 static vec3d Lab_viewer_pos = ZERO_VECTOR;
91 static matrix Lab_viewer_orient = IDENTITY_MATRIX;
92 static float Lab_viewer_rotation = 0.0f;
93 static int Lab_viewer_flags = LAB_MODE_NONE;
94 
95 static ship_subsys *Lab_ship_subsys = NULL;
96 static SCP_vector<model_subsystem> Lab_ship_model_subsys;
97 
98 static int Lab_detail_texture_save = 0;
99 
100 static int anim_timer_start = 0;
101 
102 // damage lightning stuff
103 static vec3d Lab_arc_pts[MAX_SHIP_ARCS][2];
104 static int Lab_arc_timestamp[MAX_SHIP_ARCS];
105 static ubyte Lab_arc_type[MAX_SHIP_ARCS];
106 static int Lab_arc_next_time = -1;
107 static bool Lab_arc_disrupted = false;
108 
109 static float Lab_thrust_len = 1.0f;
110 static bool Lab_thrust_afterburn = false;
111 
112 // Trackball_mode:
113 // 1 == rotate (left-mouse)
114 // 2 == pan (shift-left-mouse)
115 // 3 == zoom (right-mouse)
116 static int Trackball_mode = 1;
117 static int Trackball_active = 0;
118 
120 
121 // functions
122 void labviewer_change_ship_lod(Tree *caller);
123 void labviewer_change_ship(Tree *caller);
124 void labviewer_make_desc_window(Button *caller);
127 
128 
129 // ---------------------- General/Utility Functions ----------------------------
131 {
132  if (Lab_ship_subsys != NULL) {
133  delete[] Lab_ship_subsys;
134  Lab_ship_subsys = NULL;
135  }
136 
137  Lab_ship_model_subsys.clear();
138 
139  // whole lot of of get-outs
140  if (Lab_mode != LAB_MODE_SHIP) {
141  return;
142  }
143 
144  if (Lab_selected_index < 0) {
145  return;
146  }
147 
148  if (Lab_selected_index >= static_cast<int>(Ship_info.size())) {
149  Int3();
150  return;
151  }
152 
153  if (Ship_info[Lab_selected_index].n_subsystems <= 0) {
154  return;
155  }
156 
157 
158  uint n_subsystems = Ship_info[Lab_selected_index].n_subsystems;
159 
160  Lab_ship_subsys = new ship_subsys[n_subsystems];
161  for (uint i = 0; i < n_subsystems; i++)
162  Lab_ship_subsys[i].clear();
163 
164  Lab_ship_model_subsys.reserve(n_subsystems);
165  for (uint idx = 0; idx < n_subsystems; idx++) {
166  Lab_ship_model_subsys.push_back( Ship_info[Lab_selected_index].subsystems[idx] );
167  }
168 }
169 
170 void labviewer_change_bitmap(int ship_index = -1, int weapon_index = -1)
171 {
172  if ( (ship_index < 0) && (weapon_index < 0) ) {
173  if (Lab_bitmap_id >= 0) {
174  bm_release(Lab_bitmap_id);
175  if (Lab_last_selected_weapon >= 0) {
176  Weapon_info[Lab_last_selected_weapon].laser_bitmap.first_frame = -1;
177  }
178  Lab_bitmap_id = -1;
179  Lab_last_selected_weapon = -1;
180  }
181 
182  return;
183  }
184 
185  if ( !Lab_in_mission ) {
186  if (ship_index >= 0) {
187  // TODO: Ship stuff!!
188  } else if (weapon_index >= 0) {
189  // release old bitmap if required
190  if ( (Lab_last_selected_weapon >= 0) && (Lab_last_selected_weapon != weapon_index)) {
191  Weapon_info[Lab_last_selected_weapon].laser_bitmap.first_frame = -1;
192  if (Lab_bitmap_id >= 0) {
193  bm_release(Lab_bitmap_id);
194  }
195  }
196  // load up the weapon bitmaps
197  extern void weapon_load_bitmaps(int);
198  weapon_load_bitmaps(weapon_index);
199  Lab_bitmap_id = Weapon_info[weapon_index].laser_bitmap.first_frame;
200  }
201  }
202 
203  if (Lab_bitmap_id >= 0) {
204  bm_get_filename(Lab_bitmap_id, Lab_bitmap_filename);
205  } else {
206  memset( Lab_bitmap_filename, 0, sizeof(Lab_bitmap_filename) );
207  }
208 
210 }
211 
212 void labviewer_change_model(char *model_fname, int lod = 0, int sel_index = -1)
213 {
214  bool change_model = true;
215  int j,l;
216  ship_info *sip = NULL;
217 
218  anim_timer_start = timer_get_milliseconds();
219 
220  if ( (model_fname != NULL) && (Lab_mode == LAB_MODE_SHIP) ) {
221  if ( (Lab_selected_index >= 0) && (Lab_selected_index == sel_index) ) {
222  change_model = false;
223  }
224  }
225 
226  Lab_selected_index = sel_index;
227 
228  if (change_model) {
229  bool valid_ship = ( (Lab_mode == LAB_MODE_SHIP) && (sel_index >= 0) );
230 
231  if (Lab_model_num != -1) {
232  model_page_out_textures(Lab_model_num, true);
233  model_unload(Lab_model_num);
234  Lab_model_num = -1;
235 
236  for (j = 0; j < MAX_SHIP_WEAPONS; j++) {
237  if (Lab_weaponmodel_num[j] >= 0) {
238  model_page_out_textures(Lab_weaponmodel_num[j], true);
239  model_unload(Lab_weaponmodel_num[j]);
240  Lab_weaponmodel_num[j] = -1;
241  }
242  }
243 
244  if (Lab_last_selected_ship >= 0) {
245  ship_page_out_textures(Lab_last_selected_ship, true);
246  }
247  }
248 
250 
251  Lab_viewer_zoom = 1.2f;
252 
253  if (valid_ship) {
254  memcpy( &Lab_viewer_pos, &Ship_info[sel_index].closeup_pos, sizeof(vec3d) );
255  } else {
256  Lab_viewer_pos.xyz.x = Lab_viewer_pos.xyz.y = 0.0f;
257  }
258 
259  // only load a new model if we are supposed to (so that we can use this function to reset states)
260  if (model_fname != NULL) {
261  model_subsystem *subsystems = NULL;
262 
263  if ( !Lab_ship_model_subsys.empty() ) {
264  subsystems = &Lab_ship_model_subsys[0];
265  }
266 
267  Lab_model_num = model_load(model_fname, (valid_ship) ? Ship_info[sel_index].n_subsystems : 0, subsystems, 0);
268 
269  if (Lab_model_num >= 0) {
270  strcpy_s(Lab_model_filename, model_fname);
271  } else {
272  memset( Lab_model_filename, 0, sizeof(Lab_model_filename) );
273  }
274 
275  if (valid_ship) {
276  if (Lab_model_num >= 0) {
277  model_page_in_textures(Lab_model_num, sel_index);
278  }
279 
280  for (int idx = 0; idx < Ship_info[sel_index].n_subsystems; idx++) {
281  model_set_instance_info(&Lab_ship_subsys[idx].submodel_info_1, Lab_ship_model_subsys[idx].turn_rate, 0.5f);
282  }
283  }
284 
285  // do the same for weapon models if necessary
286  if (Lab_mode == LAB_MODE_SHIP) {
287  sip = &Ship_info[Lab_selected_index];
288  l = 0;
289  for (j = 0; j < sip->num_primary_banks; j++) {
291  if (!sip->draw_primary_models[j])
292  continue;
293  Lab_weaponmodel_num[l] = -1;
294  if ( strlen(wip->external_model_name) ){
295  Lab_weaponmodel_num[l] = model_load(wip->external_model_name, 0, NULL);
296  }
297  if (Lab_weaponmodel_num[l] >= 0) {
298  strcpy_s(Lab_weaponmodel_filename[l], wip->external_model_name);
299  } else {
300  memset( Lab_weaponmodel_filename[l], 0, sizeof(Lab_weaponmodel_filename[l]) );
301  }
302  l++;
303  }
304 
305  for (j = 0; j < sip->num_secondary_banks; j++) {
307  if (!sip->draw_secondary_models[j])
308  continue;
309  Lab_weaponmodel_num[l] = -1;
310  if ( strlen(wip->external_model_name) ){
311  Lab_weaponmodel_num[l] = model_load(wip->external_model_name, 0, NULL);
312  }
313  if (Lab_weaponmodel_num[l] >= 0) {
314  strcpy_s(Lab_weaponmodel_filename[l], wip->external_model_name);
315  } else {
316  memset( Lab_weaponmodel_filename[l], 0, sizeof(Lab_weaponmodel_filename[l]) );
317  }
318  l++;
319  }
320  }
321  } else {
322  // clear out the model filename
323  memset( Lab_model_filename, 0, sizeof(Lab_model_filename) );
324  if (Lab_weaponmodel_num[0] >= 0) {
325  for (j = 0; j < MAX_SHIP_WEAPONS; j++) {
326  memset( Lab_weaponmodel_filename[j], 0, sizeof(Lab_weaponmodel_filename[j]) );
327  }
328  }
329  }
330  }
331 
332  if (lod == 99) {
333  Lab_model_LOD = 0;
334  Lab_viewer_flags |= LAB_FLAG_SHOW_DEBRIS;
335  } else {
336  Lab_model_LOD = lod;
337  Lab_viewer_flags &= ~LAB_FLAG_SHOW_DEBRIS;
338  }
339 
340  if (model_fname == NULL) {
341  Lab_last_selected_ship = -1;
342  }
343 
345 }
346 
348 {
349  int i;
350  float mradius = 0.0f;
351  const float MAX_ARC_LENGTH_PERCENTAGE = 0.25f;
352 
353  if (Lab_mode != LAB_MODE_SHIP) {
354  return;
355  }
356 
357 
358  // Kill off old sparks
359  for (i = 0; i < MAX_SHIP_ARCS; i++) {
360  if ( timestamp_valid(Lab_arc_timestamp[i]) && timestamp_elapsed(Lab_arc_timestamp[i]) ) {
361  Lab_arc_timestamp[i] = timestamp(-1);
362  }
363  }
364 
365 
366  if ( !timestamp_valid(Lab_arc_next_time) ) {
367  // start the next fireball up in the next 10 seconds or so...
368  int freq;
369 
370  if (Lab_arc_disrupted) {
371  freq = 150;
372  } else {
373  // 1% hull left
374  freq = 550;
375  }
376 
377  // set the next arc time
378  Lab_arc_next_time = timestamp_rand(freq * 2, freq * 4);
379  }
380 
381  mradius = model_get_radius(Lab_model_num);
382 
383  if ( timestamp_elapsed(Lab_arc_next_time) ) {
384 
385  Lab_arc_next_time = timestamp(-1); // invalid, so it gets restarted next frame
386 
387  int n, n_arcs = ((rand() >> 5) % 3) + 1; // Create 1-3 sparks
388 
389  vec3d v1, v2, v3, v4;
390 
392  submodel_get_two_random_points(Lab_model_num, -1, &v1, &v2);
393  submodel_get_two_random_points(Lab_model_num, -1, &v3, &v4);
394  } else {
395  submodel_get_two_random_points_better(Lab_model_num, -1, &v1, &v2);
396  submodel_get_two_random_points_better(Lab_model_num, -1, &v3, &v4);
397  }
398 
399  // For large ships, cap the length to be 25% of max radius
400  if (mradius > 200.0f) {
401  float max_dist = mradius * MAX_ARC_LENGTH_PERCENTAGE;
402 
403  vec3d tmp;
404  float d;
405 
406  // Cap arc 2->1
407  vm_vec_sub( &tmp, &v1, &v2 );
408  d = vm_vec_mag_quick( &tmp );
409  if ( d > max_dist ) {
410  vm_vec_scale_add( &v1, &v2, &tmp, max_dist / d );
411  }
412 
413  // Cap arc 2->3
414  vm_vec_sub( &tmp, &v3, &v2 );
415  d = vm_vec_mag_quick( &tmp );
416  if ( d > max_dist ) {
417  vm_vec_scale_add( &v3, &v2, &tmp, max_dist / d );
418  }
419 
420 
421  // Cap arc 2->4
422  vm_vec_sub( &tmp, &v4, &v2 );
423  d = vm_vec_mag_quick( &tmp );
424  if ( d > max_dist ) {
425  vm_vec_scale_add( &v4, &v2, &tmp, max_dist / d );
426  }
427  }
428 
429  n = 0;
430 
431  float factor = 1.0f + 0.0025f * mradius;
432  int a = fl2i(factor * 100.0f);
433  int b = fl2i(factor * 1000.0f);
434  int lifetime = (myrand() % ((b) - (a) + 1)) + (a);
435 
436  // Create the arc effects
437  for (i = 0; i < MAX_SHIP_ARCS; i++) {
438  if ( !timestamp_valid(Lab_arc_timestamp[i]) ) {
439  Lab_arc_timestamp[i] = timestamp(lifetime); // live up to a second
440 
441  switch (n) {
442  case 0:
443  Lab_arc_pts[i][0] = v1;
444  Lab_arc_pts[i][1] = v2;
445  break;
446 
447  case 1:
448  Lab_arc_pts[i][0] = v2;
449  Lab_arc_pts[i][1] = v3;
450  break;
451 
452  case 2:
453  Lab_arc_pts[i][0] = v2;
454  Lab_arc_pts[i][1] = v4;
455  break;
456 
457  default:
458  Int3();
459  }
460 
461  // determine what kind of arc to create
462  if (Lab_arc_disrupted) {
463  Lab_arc_type[i] = MARC_TYPE_EMP;
464  } else {
465  Lab_arc_type[i] = MARC_TYPE_NORMAL;
466  }
467 
468  if ( ++n == n_arcs ) {
469  // Don't need to create anymore
470  break;
471  }
472  }
473  }
474  }
475 
476  // maybe move arc points around
477  for (i = 0; i < MAX_SHIP_ARCS; i++) {
478  if ( timestamp_valid(Lab_arc_timestamp[i]) ) {
479  if ( !timestamp_elapsed(Lab_arc_timestamp[i]) ) {
480  // Maybe move a vertex.... 20% of the time maybe?
481  int mr = myrand();
482 
483  if ( mr < (RAND_MAX / 5) ) {
484  vec3d v1, v2;
486  submodel_get_two_random_points(Lab_model_num, -1, &v1, &v2);
487  } else {
488  submodel_get_two_random_points_better(Lab_model_num, -1, &v1, &v2);
489  }
490 
491  vec3d static_one;
492 
493  if (mr % 2) {
494  static_one = Lab_arc_pts[i][0];
495  } else {
496  static_one = Lab_arc_pts[i][1];
497  }
498 
499  // For large ships, cap the length to be 25% of max radius
500  if (mradius > 200.0f) {
501  float max_dist = mradius * MAX_ARC_LENGTH_PERCENTAGE;
502 
503  vec3d tmp;
504  float d;
505 
506  // Cap arc 2->1
507  vm_vec_sub( &tmp, &v1, &static_one );
508  d = vm_vec_mag_quick( &tmp );
509 
510  if (d > max_dist) {
511  vm_vec_scale_add( &v1, &static_one, &tmp, max_dist / d );
512  }
513  }
514 
515  Lab_arc_pts[i][mr % 2] = v1;
516  }
517  }
518  }
519  }
520 
521  for (i = 0; i < MAX_SHIP_ARCS; i++) {
522  if ( timestamp_valid(Lab_arc_timestamp[i]) ) {
523  model_add_arc(Lab_model_num, -1, &Lab_arc_pts[i][0], &Lab_arc_pts[i][1], Lab_arc_type[i]);
524 
525  // maybe add lighting for the arc
526  if (Detail.lighting > 2) {
527  // Move arc endpoints into world coordinates
528  vec3d tmp1, tmp2;
529  vm_vec_unrotate(&tmp1, &Lab_arc_pts[i][0], &Lab_viewer_orient);
530  vm_vec_unrotate(&tmp2, &Lab_arc_pts[i][1], &Lab_viewer_orient);
531 
532  light_add_point( &tmp1, 10.0f, 20.0f, frand(), 1.0f, 1.0f, 1.0f, -1 );
533  light_add_point( &tmp2, 10.0f, 20.0f, frand(), 1.0f, 1.0f, 1.0f, -1 );
534  }
535  }
536  }
537 }
538 
540 {
541  static float thruster_frame = 0.0f;
542  static float thruster_glow_frame = 0.0f;
543  static int thruster_bitmap = -1;
544  static int thruster_glow_bitmap = -1;
545  static float thruster_glow_noise = 1.0f;
546 
547  float rate;
548  int framenum;
549  int secondary_glow_bitmap = -1;
550  int tertiary_glow_bitmap = -1;
551  static int thruster_distortion_bitmap = -1;
552  generic_anim *flame_anim = NULL, *glow_anim = NULL;
553  species_info *species = &Species_info[0];
554  weapon_info *wip = NULL;
555  mst_info mst;
556 
557 
558  if (Lab_mode == LAB_MODE_SHIP) {
559  Assert( sip != NULL );
560  species = &Species_info[sip->species];
561  }
562 
563  if (Lab_mode == LAB_MODE_WEAPON) {
564  wip = &Weapon_info[Lab_selected_index];
565  }
566 
567  // init thruster graphics (species stuff)
568  extern void ship_init_thrusters();
570 
571  if ( Lab_thrust_afterburn && (Lab_mode != LAB_MODE_WEAPON) ) {
572  flame_anim = &sip->thruster_flame_info.afterburn; // select afterburner flame
573  glow_anim = &sip->thruster_glow_info.afterburn; // select afterburner glow
574  secondary_glow_bitmap = sip->thruster_secondary_glow_info.afterburn.bitmap_id;
575  tertiary_glow_bitmap = sip->thruster_tertiary_glow_info.afterburn.bitmap_id;
576  thruster_distortion_bitmap = sip->thruster_distortion_info.afterburn.bitmap_id;
577 
578  rate = 1.5f; // go at 1.5x faster when afterburners on
579  } else {
580  flame_anim = &species->thruster_info.flames.normal; // select normal flame
581  glow_anim = &species->thruster_info.glow.normal; // select normal glow
582 
583  if (Lab_mode == LAB_MODE_WEAPON) {
584  if (wip->thruster_flame.first_frame >= 0)
585  flame_anim = &wip->thruster_flame;
586 
587  if (wip->thruster_glow.first_frame >= 0)
588  glow_anim = &wip->thruster_glow;
589  }
590 
591  if (Lab_mode == LAB_MODE_SHIP) {
592  flame_anim = &sip->thruster_flame_info.normal; // select normal flame
593  glow_anim = &sip->thruster_glow_info.normal; // select normal glow
594  secondary_glow_bitmap = sip->thruster_secondary_glow_info.normal.bitmap_id;
595  tertiary_glow_bitmap = sip->thruster_tertiary_glow_info.normal.bitmap_id;
596  thruster_distortion_bitmap = sip->thruster_distortion_info.normal.bitmap_id;
597  }
598 
599  // If thrust at 0, go at half as fast, full thrust; full framerate
600  // so set rate from 0.5 to 1.0, depending on thrust from 0 to 1
601  // rate = 0.5f + objp->phys_info.forward_thrust / 2.0f;
602  rate = 0.67f * (1.0f + Lab_thrust_len);
603  }
604 
605  Assert( flFrametime > 0.0f );
606 
607  if (flame_anim->first_frame >= 0) {
608  thruster_frame += flFrametime * rate;
609 
610  // Sanity checks
611  if (thruster_frame < 0.0f) {
612  thruster_frame = 0.0f;
613  } else if (thruster_frame > 100.0f) {
614  thruster_frame = 0.0f;
615  }
616 
617  while (thruster_frame > flame_anim->total_time) {
618  thruster_frame -= flame_anim->total_time;
619  }
620 
621  framenum = fl2i( (thruster_frame * flame_anim->num_frames) / flame_anim->total_time );
622 
623  CLAMP(framenum, 0, flame_anim->num_frames-1);
624 
625  // Get the bitmap for this frame
626  thruster_bitmap = flame_anim->first_frame + framenum;
627  } else {
628  thruster_frame = 0.0f;
629  thruster_bitmap = -1;
630  }
631 
632  // Do it for glow bitmaps
633 
634  if (glow_anim->first_frame >= 0) {
635  thruster_glow_frame += flFrametime * rate;
636 
637  // Sanity checks
638  if (thruster_glow_frame < 0.0f) {
639  thruster_glow_frame = 0.0f;
640  } else if (thruster_glow_frame > 100.0f) {
641  thruster_glow_frame = 0.0f;
642  }
643 
644  while (thruster_glow_frame > glow_anim->total_time) {
645  thruster_glow_frame -= glow_anim->total_time;
646  }
647 
648  framenum = fl2i( (thruster_glow_frame * glow_anim->num_frames) / glow_anim->total_time );
649 
650  CLAMP(framenum, 0, glow_anim->num_frames-1);
651 
652  // Get the bitmap for this frame
653  thruster_glow_bitmap = glow_anim->first_frame; // + framenum;
654  thruster_glow_noise = Noise[framenum];
655  } else {
656  thruster_glow_frame = 0.0f;
657  thruster_glow_bitmap = -1;
658  thruster_glow_noise = 1.0f;
659  }
660 
661 
662  // ok, we've worked out the bitmaps, so now we need to set up the thrust info
663  mst.length.xyz.z = Lab_thrust_len;
664  mst.length.xyz.x = 0.0f;
665  mst.length.xyz.y = 0.0f;
666 
667  // Add noise to thruster geometry.
668  if ( Lab_mode == LAB_MODE_SHIP ) {
669  if (!(sip->flags2 & SIF2_NO_THRUSTER_GEO_NOISE)) {
670  mst.length.xyz.z *= (1.0f + frand()/5.0f - 0.1f);
671  mst.length.xyz.y *= (1.0f + frand()/5.0f - 0.1f);
672  mst.length.xyz.x *= (1.0f + frand()/5.0f - 0.1f);
673  }
674  } else {
675  mst.length.xyz.z *= (1.0f + frand()/5.0f - 0.1f);
676  mst.length.xyz.y *= (1.0f + frand()/5.0f - 0.1f);
677  mst.length.xyz.x *= (1.0f + frand()/5.0f - 0.1f);
678  }
679 
680  CLAMP(mst.length.xyz.z, -1.0f, 1.0f);
681  CLAMP(mst.length.xyz.y, -1.0f, 1.0f);
682  CLAMP(mst.length.xyz.x, -1.0f, 1.0f);
683 
684  mst.primary_bitmap = thruster_bitmap;
685  mst.primary_glow_bitmap =thruster_glow_bitmap;
686  mst.secondary_glow_bitmap = secondary_glow_bitmap;
687  mst.tertiary_glow_bitmap = tertiary_glow_bitmap;
688  mst.distortion_bitmap = thruster_distortion_bitmap;
689 
690  mst.use_ab = Lab_thrust_afterburn;
691  mst.glow_noise = thruster_glow_noise * sip->thruster_glow_noise_mult;
692  mst.rotvel = vmd_zero_vector;
693 
694  if (Lab_mode == LAB_MODE_SHIP) {
701  mst.draw_distortion = sip->draw_distortion;
702  }
703 
704  if (Lab_mode == LAB_MODE_WEAPON) {
706  }
707 
708  // set, and go...
709  render_info->set_thruster_info(mst);
710 }
711 
713 
714 void labviewer_render_model(float frametime)
715 {
716  int i, j;
717  float rev_rate;
718  angles rot_angles, view_angles;
719  ship_info *sip = NULL;
720 
721  if ( (Lab_mode == LAB_MODE_SHIP) && (Lab_selected_index >= 0) ) {
722  sip = &Ship_info[Lab_selected_index];
723  }
724 
725  model_render_params render_info;
726 
727  model_clear_instance(Lab_model_num);
728 
729  // get correct revolution rate
730  rev_rate = REVOLUTION_RATE;
731 
732  if (sip != NULL) {
733  if (sip->flags & SIF_BIG_SHIP) {
734  rev_rate *= 1.7f;
735  } else if (sip->flags & SIF_HUGE_SHIP) {
736  rev_rate *= 3.0f;
737  }
738 
739  if (sip->uses_team_colors && !Teamcolor_override) {
740  render_info.set_team_color(Lab_team_color, "none", 0, 0);
741  }
742  }
743 
744  // rotate/pan/zoom the model as much as required for this frame
745  if (Trackball_active) {
746  int dx, dy;
747  matrix mat1, mat2;
748 
749  mouse_get_delta(&dx, &dy);
750 
751  if (dx || dy) {
752  // rotation mode
753  if (Trackball_mode == 1) {
754  vm_trackball(-dx, -dy, &mat1);
755  vm_matrix_x_matrix(&mat2, &mat1, &Lab_viewer_orient);
756  Lab_viewer_orient = mat2;
757  }
758  // pan mode
759  else if (Trackball_mode == 2) {
760  double scale_x = dx * (double)model_get_radius(Lab_model_num) * 0.005;
761  double scale_y = dy * (double)model_get_radius(Lab_model_num) * 0.005;
762 
763  Lab_viewer_pos.xyz.x -= (float)scale_x;
764  Lab_viewer_pos.xyz.y += (float)scale_y;
765  }
766  // zoom mode
767  else if ( dy && (Trackball_mode == 3) ) {
768  float scale_y = dy * 0.01f;
769 
770  Lab_viewer_zoom += scale_y;
771  }
772  }
773  }
774  // otherwise do orient/rotation calculation, if we are supposed to
775  else if ( !(Lab_viewer_flags & LAB_FLAG_NO_ROTATION) ) {
776  Lab_viewer_rotation += PI2 * frametime / rev_rate;
777 
778  while (Lab_viewer_rotation > PI2)
779  Lab_viewer_rotation -= PI2;
780 
781  // setup stuff needed to render the ship
782  view_angles.p = -0.6f;
783  view_angles.b = 0.0f;
784  view_angles.h = 0.0f;
785  vm_angles_2_matrix(&Lab_viewer_orient, &view_angles);
786 
787  rot_angles.p = 0.0f;
788  rot_angles.b = 0.0f;
789  rot_angles.h = Lab_viewer_rotation;
790  vm_rotate_matrix_by_angles(&Lab_viewer_orient, &rot_angles);
791  }
792 
793 
794  // render the ship
795  g3_start_frame(1);
796 
797  if (sip != NULL) {
798  Lab_viewer_pos.xyz.z = sip->closeup_pos.xyz.z;
799 
800  float my_zoom = sip->closeup_zoom * Lab_viewer_zoom;
801  // clamp it down so that we don't get too close or too far away
802  CLAMP(my_zoom, 0.08f, 1.8f);
803 
804  g3_set_view_matrix(&Lab_viewer_pos, &vmd_identity_matrix, my_zoom);
805  } else {
806  // find the largest radius
807  polymodel *pm = model_get(Lab_model_num);
808  float largest_radius = 0.0f;
809 
810  Assert( pm != NULL );
811 
812  for (i = 0; i < pm->n_models; i++) {
813  if ( !pm->submodel[i].is_thruster ) {
814  if (pm->submodel[i].rad > largest_radius) {
815  largest_radius = pm->submodel[i].rad;
816  }
817  }
818  }
819 
820  Lab_viewer_pos.xyz.z = -(largest_radius * 2.0f);
821 
822  CLAMP(Lab_viewer_zoom, 0.08f, 1.8f);
823 
824  g3_set_view_matrix(&Lab_viewer_pos, &vmd_identity_matrix, Lab_viewer_zoom);
825  }
826 
827 
828 
829  // lighting for techroom
830  light_reset();
831  vec3d light_dir = vmd_zero_vector;
832  light_dir.xyz.y = 1.0f;
833  light_dir.xyz.x = 0.0000001f;
834  light_add_directional(&light_dir, 0.65f, 1.0f, 1.0f, 1.0f,-1);
835  int mx, my;
836  mouse_get_pos( &mx, &my );
837  light_dir.xyz.y = 0.0000001f;
838  light_dir.xyz.x = sinf(my/150.0f);
839  light_dir.xyz.z = cosf(my/150.0f);
840  vm_vec_normalize(&light_dir);
841  vm_vec_scale(&light_dir, mx*10.1f);
842  light_add_point(&light_dir,1,mx*10.2f+0.1f, 0.5f, 1.0f, 1.0f, 1.0f,-1);
843 
845  // lighting for techroom
846 
847  render_info.set_color(255, 255, 255);
848  render_info.set_detail_level_lock(Lab_model_LOD);
849 
850  int flagggs = Lab_model_flags;
851 
852  // only render the insignia when the flag is set
853  if (Lab_viewer_flags & LAB_FLAG_SHOW_INSIGNIA) {
854  render_info.set_insignia_bitmap(Lab_insignia_bitmap);
855  }
856 
857  // render special if we are showing debris
858  if (Lab_viewer_flags & LAB_FLAG_SHOW_DEBRIS) {
859  polymodel *pm = model_get(Lab_model_num);
860 
861  if (!Cmdline_nohtl) {
864  }
865 
866  for (i = 0; i < pm->num_debris_objects; i++) {
867  vec3d world_point = ZERO_VECTOR;
868 
869  model_find_world_point(&world_point, &pm->submodel[pm->debris_objects[i]].offset, Lab_model_num, -1, &Lab_viewer_orient, &vmd_zero_vector);
870  Shadow_override = true;
871 
872  render_info.set_flags(Lab_model_flags);
873 
874  submodel_render_immediate(&render_info, Lab_model_num, pm->debris_objects[i], &Lab_viewer_orient, &world_point);
875  Shadow_override = false;
876  }
877  }
878  // render normally otherwise
879  else {
880  // show damage arcs if wanted
881  if ( (sip != NULL) && (Lab_viewer_flags & LAB_FLAG_LIGHTNING_ARCS) ) {
883  }
884 
885  // ship/weapon thrusters
886  if (Lab_model_flags & MR_SHOW_THRUSTERS) {
887  labviewer_add_model_thrusters(&render_info, sip);
888  }
889 
890  // do initial rotation
891  if (sip != NULL) {
892  if (Lab_viewer_flags & LAB_FLAG_INITIAL_ROTATION) {
893  for (i = 0; i < sip->n_subsystems; i++) {
894  if (Lab_ship_model_subsys[i].type == SUBSYSTEM_TURRET) {
895 
896  for (j = 0; j < Lab_ship_model_subsys[i].n_triggers; j++) {
897 
898  // special case for turrets
899  Lab_ship_subsys[i].submodel_info_2.angs.p = Lab_ship_model_subsys[i].triggers[j].angle.xyz.x;
900  Lab_ship_subsys[i].submodel_info_1.angs.h = Lab_ship_model_subsys[i].triggers[j].angle.xyz.y;
901  }
902  if ( Lab_ship_model_subsys[i].subobj_num >= 0 ) {
903  model_set_instance(Lab_model_num, Lab_ship_model_subsys[i].subobj_num, &Lab_ship_subsys[i].submodel_info_1 );
904  }
905  if ( (Lab_ship_model_subsys[i].subobj_num != Lab_ship_model_subsys[i].turret_gun_sobj) && (Lab_ship_model_subsys[i].turret_gun_sobj >= 0) ) {
906  model_set_instance(Lab_model_num, Lab_ship_model_subsys[i].turret_gun_sobj, &Lab_ship_subsys[i].submodel_info_2 );
907  }
908  }
909  }
910  }
911  }
912 
913  // rotate submodels if wanted
914  if ( (sip != NULL) && (Lab_viewer_flags & LAB_FLAG_SUBMODEL_ROTATE) ) {
915  for (i = 0; i < sip->n_subsystems; i++) {
916  if ( !(Lab_ship_model_subsys[i].flags & MSS_FLAG_ROTATES) ) {
917  continue;
918  }
919 
920  model_set_instance(Lab_model_num, Lab_ship_model_subsys[i].subobj_num, &Lab_ship_subsys[i].submodel_info_1 );
921 
922  // if we got this far, we can rotate - so choose which method to use
923  if (Lab_ship_model_subsys[i].flags & MSS_FLAG_STEPPED_ROTATE) {
924  submodel_stepped_rotate(&Lab_ship_model_subsys[i], &Lab_ship_subsys[i].submodel_info_1);
925  } else {
926  submodel_rotate(&Lab_ship_model_subsys[i], &Lab_ship_subsys[i].submodel_info_1 );
927  }
928  }
929  }
930 
931  if( !( flagggs & MR_NO_LIGHTING ) && Cmdline_shadow_quality ) {
932  polymodel *pm = model_get(Lab_model_num);
933 
934  shadows_start_render(&Eye_matrix, &Eye_position, Proj_fov, gr_screen.clip_aspect, -Lab_viewer_pos.xyz.z + pm->rad, -Lab_viewer_pos.xyz.z + pm->rad + 200.0f, -Lab_viewer_pos.xyz.z + pm->rad + 2000.0f, -Lab_viewer_pos.xyz.z + pm->rad + 10000.0f);
935 
936  render_info.set_flags(MR_NO_TEXTURING | MR_NO_LIGHTING | MR_AUTOCENTER);
937 
938  model_render_immediate(&render_info, Lab_model_num, &Lab_viewer_orient, &vmd_zero_vector);
939 
940  //render weapon models if selected
941  if ( Lab_mode == LAB_MODE_SHIP && ( Lab_viewer_flags & LAB_FLAG_SHOW_WEAPONS ) ) {
942  int k,l;
943  g3_start_instance_matrix(&vmd_zero_vector, &Lab_viewer_orient, true);
944  l = 0;
945 
946  // no thrusters for attached missiles
947  int render_flags = MR_NO_TEXTURING | MR_NO_LIGHTING;
948 
949  //primary weapons
950  for (j = 0; j < sip->num_primary_banks; j++) {
951  if (!sip->draw_primary_models[j])
952  continue;
953  if (Lab_weaponmodel_num[l] >= 0) {
954  w_bank *bank = &model_get(Lab_model_num)->gun_banks[j];
955  for(k = 0; k < bank->num_slots; k++) {
956 
957  render_info.set_flags(render_flags);
958  model_render_immediate(&render_info, Lab_weaponmodel_num[l], &vmd_identity_matrix, &bank->pnt[k]);
959  }
960  }
961  l++;
962  }
963  //secondary weapons
964  vec3d secondary_weapon_pos;
965  w_bank* bank;
966 
967  for (j = 0; j < sip->num_secondary_banks; j++) {
968  if (!sip->draw_secondary_models[j])
969  continue;
970  if (Lab_weaponmodel_num[l] >= 0) {
971  bank = &(model_get(Lab_model_num))->missile_banks[j];
973  for(k = 0; k < bank->num_slots; k++) {
974  render_info.set_flags(render_flags);
975  model_render_immediate(&render_info, Lab_weaponmodel_num[l], &vmd_identity_matrix, &bank->pnt[k]);
976  }
977  } else {
978  for(k = 0; k < bank->num_slots; k++)
979  {
980  secondary_weapon_pos = bank->pnt[k];
981  render_info.set_flags(render_flags);
982  model_render_immediate(&render_info, Lab_weaponmodel_num[l], &vmd_identity_matrix, &secondary_weapon_pos);
983  }
984  }
985  }
986  l++;
987  }
988  g3_done_instance(true);
989  }
990 
992  }
993 
994  if (!Cmdline_nohtl) {
997  }
998 
1000 
1001 // render_info.set_animated_effect(
1002 // ANIMATED_SHADER_LOADOUTSELECT_FS1,
1003 // MIN((timer_get_milliseconds()-anim_timer_start)/1500.0f, 2.0f)
1004 // );
1005 
1006  if (sip != NULL) {
1007  if (Lab_viewer_flags & LAB_FLAG_DESTROYED_SUBSYSTEMS) {
1008  model_show_damaged(Lab_model_num, 1);
1009  }
1010  }
1011 
1012  //render weapon models if selected
1013  if (Lab_mode == LAB_MODE_SHIP && (Lab_viewer_flags & LAB_FLAG_SHOW_WEAPONS)) {
1014  int k,l;
1015  g3_start_instance_matrix(&vmd_zero_vector, &Lab_viewer_orient, true);
1016  l = 0;
1017 
1018  // no thrusters for attached missiles
1019  int render_flags = flagggs;
1020  render_flags &= ~MR_SHOW_THRUSTERS;
1021 
1022  //primary weapons
1023  for (j = 0; j < sip->num_primary_banks; j++) {
1024  if (!sip->draw_primary_models[j])
1025  continue;
1026  if (Lab_weaponmodel_num[l] >= 0) {
1027  w_bank *bank = &model_get(Lab_model_num)->gun_banks[j];
1028  for(k = 0; k < bank->num_slots; k++) {
1029  render_info.set_flags(render_flags);
1030  model_render_immediate(&render_info, Lab_weaponmodel_num[l], &vmd_identity_matrix, &bank->pnt[k]);
1031  }
1032  }
1033  l++;
1034  }
1035  //secondary weapons
1036  vec3d secondary_weapon_pos;
1037  w_bank* bank;
1038 
1039  for (j = 0; j < sip->num_secondary_banks; j++) {
1040  if (!sip->draw_secondary_models[j])
1041  continue;
1042  if (Lab_weaponmodel_num[l] >= 0) {
1043  bank = &(model_get(Lab_model_num))->missile_banks[j];
1045  for(k = 0; k < bank->num_slots; k++) {
1046  render_info.set_flags(render_flags);
1047  model_render_immediate(&render_info, Lab_weaponmodel_num[l], &vmd_identity_matrix, &bank->pnt[k]);
1048  }
1049  } else {
1050  for(k = 0; k < bank->num_slots; k++)
1051  {
1052  secondary_weapon_pos = bank->pnt[k];
1053  render_info.set_flags(render_flags);
1054  model_render_immediate(&render_info, Lab_weaponmodel_num[l], &vmd_identity_matrix, &secondary_weapon_pos);
1055  }
1056  }
1057  }
1058  l++;
1059  }
1060  g3_done_instance(true);
1061  }
1062 
1063  render_info.set_debug_flags(Lab_model_debug_flags);
1064  render_info.set_flags(flagggs);
1065  render_info.set_object_number(Lab_selected_object);
1066 
1067  model_render_immediate(&render_info, Lab_model_num, &Lab_viewer_orient, &vmd_zero_vector, MODEL_RENDER_OPAQUE);
1070  bool gpo_save = Glowpoint_override;
1071  Glowpoint_override = true;
1072  model_render_immediate(&render_info, Lab_model_num, &Lab_viewer_orient, &vmd_zero_vector, MODEL_RENDER_TRANS);
1073  Glowpoint_override = gpo_save;
1074  }
1075 
1076  batch_render_all();
1079  if ( !Cmdline_nohtl ) {
1082  }
1083 
1084  g3_end_frame();
1085 }
1086 
1087 void labviewer_render_bitmap(float frametime)
1088 {
1089  static float current_frame = 0.0f;
1090  static float current_glow_frame = 0.0f;
1091  int framenum = 0;
1092 
1093  // if not valid then bail
1094  if ( (Lab_selected_index < 0) || (Lab_mode != LAB_MODE_WEAPON) || (Lab_bitmap_id < 0) ) {
1095  return;
1096  }
1097 
1098 
1099  weapon_info *wip = &Weapon_info[Lab_selected_index];
1100 
1101  if (wip->laser_bitmap.first_frame < 0) {
1102  return;
1103  }
1104 
1105 
1106  float rev_rate = REVOLUTION_RATE;
1107  angles rot_angles, view_angles;
1108 
1109  if (Trackball_active) {
1110  int dx, dy;
1111  matrix mat1, mat2;
1112 
1113  mouse_get_delta(&dx, &dy);
1114 
1115  if (dx || dy) {
1116  // rotation mode
1117  if (Trackball_mode == 1) {
1118  vm_trackball(-dx, -dy, &mat1);
1119  vm_matrix_x_matrix(&mat2, &mat1, &Lab_viewer_orient);
1120  Lab_viewer_orient = mat2;
1121  }
1122  // pan mode
1123  else if (Trackball_mode == 2) {
1124  double scale_x = dx * (double)wip->laser_length * 0.005;
1125  double scale_y = dy * (double)wip->laser_length * 0.005;
1126 
1127  Lab_viewer_pos.xyz.x -= (float)scale_x;
1128  Lab_viewer_pos.xyz.y += (float)scale_y;
1129  }
1130  // zoom mode
1131  else if ( dy && (Trackball_mode == 3) ) {
1132  float scale_y = dy / 100.0f;
1133 
1134  Lab_viewer_zoom += scale_y;
1135  }
1136  }
1137  }
1138  // otherwise do orient/rotation calculation, if we are supposed to
1139  else if ( !(Lab_viewer_flags & LAB_FLAG_NO_ROTATION) ) {
1140  Lab_viewer_rotation += PI2 * frametime / rev_rate;
1141 
1142  while (Lab_viewer_rotation > PI2) {
1143  Lab_viewer_rotation -= PI2;
1144  }
1145 
1146  // setup stuff needed to render the ship
1147  view_angles.p = -0.6f;
1148  view_angles.b = 0.0f;
1149  view_angles.h = 0.0f;
1150  vm_angles_2_matrix(&Lab_viewer_orient, &view_angles);
1151 
1152  rot_angles.p = 0.0f;
1153  rot_angles.b = 0.0f;
1154  rot_angles.h = Lab_viewer_rotation;
1155  vm_rotate_matrix_by_angles(&Lab_viewer_orient, &rot_angles);
1156  }
1157 
1158  g3_start_frame(1);
1159 
1160  Lab_viewer_pos.xyz.z = -(wip->laser_length * 2.0f);
1161 
1162  CLAMP(Lab_viewer_zoom, 0.08f, 1.8f);
1163 
1164  g3_set_view_matrix(&Lab_viewer_pos, &vmd_identity_matrix, Lab_viewer_zoom * 1.3f);
1165 
1166  if ( !Cmdline_nohtl ) {
1169  }
1170 
1171 
1172  // draw the primary laser bitmap
1174 
1175  if (wip->laser_bitmap.num_frames > 1) {
1176  current_frame += frametime;
1177 
1178  // Sanity checks
1179  if (current_frame < 0.0f) {
1180  current_frame = 0.0f;
1181  } else if (current_frame > 100.0f) {
1182  current_frame = 0.0f;
1183  }
1184 
1185  while (current_frame > wip->laser_bitmap.total_time) {
1186  current_frame -= wip->laser_bitmap.total_time;
1187  }
1188 
1189  framenum = fl2i( (current_frame * wip->laser_bitmap.num_frames) / wip->laser_bitmap.total_time );
1190 
1191  CLAMP(framenum, 0, wip->laser_bitmap.num_frames-1);
1192  }
1193 
1194  vec3d headp;
1195  vm_vec_scale_add(&headp, &vmd_zero_vector, &Lab_viewer_orient.vec.fvec, wip->laser_length);
1196 
1198  if(wip->laser_length > 0.0001f)
1200 
1201 
1202  // now draw the laser glow bitmap, if there is one, and if we are supposed to
1203  if ( !(Lab_model_flags & MR_NO_GLOWMAPS) && (wip->laser_glow_bitmap.first_frame >= 0) ) {
1204  vec3d headp2, tailp;
1205  color c;
1206 
1207  float weapon_glow_scale_f = 2.3f;
1208  float weapon_glow_scale_r = 2.3f;
1209  float weapon_glow_scale_l = 1.5f;
1210  float weapon_glow_alpha = 0.85f;
1211 
1212  // get the laser color
1213  if ( (wip->laser_color_2.red == 0) && (wip->laser_color_2.green == 0) && (wip->laser_color_2.blue == 0) ) {
1214  c = wip->laser_color_1;
1215  } else {
1216  // lifetime pct
1217  float pct = 1.0f;
1218 
1219  // otherwise interpolate between the colors
1220  gr_init_color( &c, (int)((float)wip->laser_color_1.red + (((float)wip->laser_color_2.red - (float)wip->laser_color_1.red) * pct)),
1221  (int)((float)wip->laser_color_1.green + (((float)wip->laser_color_2.green - (float)wip->laser_color_1.green) * pct)),
1222  (int)((float)wip->laser_color_1.blue + (((float)wip->laser_color_2.blue - (float)wip->laser_color_1.blue) * pct)) );
1223  }
1224 
1225  vm_vec_scale_add(&headp2, &vmd_zero_vector, &Lab_viewer_orient.vec.fvec, wip->laser_length * weapon_glow_scale_l);
1226  vm_vec_scale_add(&tailp, &vmd_zero_vector, &Lab_viewer_orient.vec.fvec, wip->laser_length * (1 - weapon_glow_scale_l) );
1227 
1228  framenum = 0;
1229 
1230  if (wip->laser_glow_bitmap.num_frames > 1) {
1231  current_glow_frame += frametime;
1232 
1233  // Sanity checks
1234  if (current_glow_frame < 0.0f) {
1235  current_glow_frame = 0.0f;
1236  } else if (current_glow_frame > 100.0f) {
1237  current_glow_frame = 0.0f;
1238  }
1239 
1240  while (current_glow_frame > wip->laser_glow_bitmap.total_time) {
1241  current_glow_frame -= wip->laser_glow_bitmap.total_time;
1242  }
1243 
1244  framenum = fl2i( (current_glow_frame * wip->laser_glow_bitmap.num_frames) / wip->laser_glow_bitmap.total_time );
1245 
1246  CLAMP(framenum, 0, wip->laser_glow_bitmap.num_frames-1);
1247  }
1248 
1250  if(wip->laser_length > 0.0001f)
1251  g3_draw_laser_rgb(&headp2, wip->laser_head_radius * weapon_glow_scale_f, &tailp, wip->laser_tail_radius * weapon_glow_scale_r, c.red, c.green, c.blue, TMAP_FLAG_TEXTURED | TMAP_FLAG_XPARENT | TMAP_FLAG_RGB | TMAP_HTL_3D_UNLIT);
1252  }
1253 
1254  // clean up and move on ...
1255 
1256  if ( !Cmdline_nohtl ) {
1259  }
1260 
1261  g3_end_frame();
1262 }
1263 
1264 void labviewer_do_render(float frametime)
1265 {
1266  int w, h;
1267 
1268  if ( (Lab_model_num < 0) && (Lab_bitmap_id < 0) ) {
1269  gr_get_string_size(&w, &h, "Viewer off");
1272 
1273  return;
1274  }
1275 
1276  // render our particular thing
1277  if (Lab_model_num >= 0) {
1278 
1280 
1281  labviewer_render_model(frametime);
1282 
1284 
1285  // print out the current pof filename, to help with... something
1286  if ( strlen(Lab_model_filename) ) {
1287  gr_get_string_size(&w, &h, Lab_model_filename);
1290  }
1291  } else if (Lab_bitmap_id >= 0) {
1293 
1294  labviewer_render_bitmap(frametime);
1295 
1297 
1298  // print out the current bitmap filename, to help with... something
1299  if ( strlen(Lab_bitmap_filename) ) {
1300  gr_get_string_size(&w, &h, Lab_bitmap_filename);
1303  }
1304  }
1305 
1306  // print FPS at bottom left, might be helpful
1307  extern void game_get_framerate();
1308  extern float frametotal;
1309  extern float Framerate;
1310 
1312 
1314 
1315  if (frametotal != 0.0f) {
1317  } else {
1319  }
1320 
1321  //Print FXAA preset
1324 
1325  //Print bloom intensity
1328 
1329  //Print current Team Color setting, if any
1330  if (Lab_team_color != "<none>")
1331  gr_printf_no_resize(gr_screen.center_offset_x + 2, gr_screen.center_offset_y + gr_screen.center_h - (gr_get_font_height() * 4) - 3, "Use T and Y to cycle through available Team Color settings. Current: %s", Lab_team_color.c_str());
1332 
1333  //Display helpful text
1335  gr_printf_no_resize(gr_screen.center_offset_x + 70, gr_screen.center_offset_y + gr_screen.center_h - gr_get_font_height(), "Use number keys to switch between FXAA presets. B and N can be used to adjust bloom.");
1336 }
1337 
1338 void labviewer_exit(Button *caller)
1339 {
1340  if(Lab_selected_object != -1) {
1341  obj_delete(Lab_selected_object);
1342  }
1344 }
1345 
1346 // ---------------------------- Class Window ----------------------------------
1348 {
1349  if (Lab_class_toolbar) {
1350  Lab_class_toolbar->DeleteChildren();
1351  }
1352 
1353  Lab_class_window = NULL;
1354 
1355  Lab_mode = LAB_MODE_NONE;
1356 
1357  // reset any existing model/bitmap that is showing
1358  labviewer_change_model(NULL);
1360 }
1361 
1363 {
1364  if (Lab_class_window == NULL) {
1365  Lab_class_window = (Window*)Lab_screen->Add(new Window("Class Window", gr_screen.center_offset_x + 50, gr_screen.center_offset_y + 50));
1367  }
1368 
1369  if (Lab_class_toolbar == NULL) {
1370  Lab_class_toolbar = (Window*)Lab_screen->Add(new Window("Class Toolbar", gr_screen.center_offset_x + 0, gr_screen.center_offset_y + Lab_toolbar->GetHeight(), -1, -1, WS_NOTITLEBAR | WS_NONMOVEABLE));
1371  }
1372 
1373  // clear out all existing children
1374  Lab_class_window->ClearContent();
1375  Lab_class_toolbar->ClearContent();
1376 
1377  // set our new title
1378  if (mode == LAB_MODE_SHIP) {
1379  Lab_class_window->SetCaption("Ship Classes");
1380  } else if (mode == LAB_MODE_WEAPON) {
1381  Lab_class_window->SetCaption("Weapon Classes");
1382  }
1383 
1384  // reset any existing model/bitmap that is showing
1385  labviewer_change_model(NULL);
1387 }
1388 
1389 
1390 // ------------------------------ Flags Window --------------------------------
1391 typedef struct lab_flag {
1393  int flag;
1394  bool second;
1395 } lab_flag;
1396 
1397 static SCP_vector<lab_flag> Lab_flags;
1398 
1400 {
1401  if (Lab_flags_window != NULL) {
1402  Lab_flags_window->DeleteChildren();
1403  }
1404 
1405  Lab_flags.clear();
1406 }
1407 
1408 void labviewer_flags_add(int *X, int *Y, char *flag_name, int flag, bool flags2 = false)
1409 {
1410  int x = 0, y = 0;
1411 
1412  Assert( (Lab_flags_window != NULL) && (flag_name != NULL) );
1413 
1414  lab_flag new_flag;
1415 
1416  if (X) {
1417  x = *X;
1418  }
1419 
1420  if (Y) {
1421  y = *Y;
1422  }
1423 
1424  new_flag.cb = (Checkbox*) Lab_flags_window->AddChild(new Checkbox(flag_name, x, y));
1425  new_flag.flag = flag;
1426  new_flag.second = flags2;
1427 
1428  Lab_flags.push_back( new_flag );
1429 
1430  if (X) {
1431  *X += new_flag.cb->GetWidth() + 2;
1432  }
1433 
1434  if (Y) {
1435  *Y += new_flag.cb->GetHeight() + 1;
1436  }
1437 }
1438 
1440 {
1441  int y;
1442 
1443  if (Lab_mode == LAB_MODE_NONE) {
1444  return;
1445  }
1446 
1447  if (Lab_flags_window == NULL) {
1448  return;
1449  }
1450 
1451  // clear out anything that already exists
1453 
1454  y = 0;
1455 
1456  // ship flags ...
1457  if (Lab_mode == LAB_MODE_SHIP) {
1458  labviewer_flags_add(NULL, &y, "SUPPORT", SIF_SUPPORT);
1459  labviewer_flags_add(NULL, &y, "CARGO", SIF_CARGO);
1460  labviewer_flags_add(NULL, &y, "FIGHTER", SIF_FIGHTER);
1461  labviewer_flags_add(NULL, &y, "BOMBER", SIF_BOMBER);
1462  labviewer_flags_add(NULL, &y, "CRUISER", SIF_CRUISER);
1463  labviewer_flags_add(NULL, &y, "CORVETTE", SIF_CORVETTE);
1464  labviewer_flags_add(NULL, &y, "FREIGHTER", SIF_FREIGHTER);
1465  labviewer_flags_add(NULL, &y, "CAPITAL", SIF_CAPITAL);
1466  labviewer_flags_add(NULL, &y, "TRANSPORT", SIF_TRANSPORT);
1467  labviewer_flags_add(NULL, &y, "NAVBUOY", SIF_NAVBUOY);
1468  labviewer_flags_add(NULL, &y, "SENTRYGUN", SIF_SENTRYGUN);
1469  labviewer_flags_add(NULL, &y, "ESCAPEPOD", SIF_ESCAPEPOD);
1470  labviewer_flags_add(NULL, &y, "GAS MINER", SIF_GAS_MINER);
1471  labviewer_flags_add(NULL, &y, "AWACS", SIF_AWACS);
1472  labviewer_flags_add(NULL, &y, "STEALTH", SIF_STEALTH);
1473  labviewer_flags_add(NULL, &y, "SUPERCAP", SIF_SUPERCAP);
1474  labviewer_flags_add(NULL, &y, "KNOSSOS DEVICE", SIF_KNOSSOS_DEVICE);
1475  labviewer_flags_add(NULL, &y, "DRYDOCK", SIF_DRYDOCK);
1476  labviewer_flags_add(NULL, &y, "SHIP COPY", SIF_SHIP_COPY);
1477  labviewer_flags_add(NULL, &y, "BIG DAMAGE", SIF_BIG_DAMAGE);
1478  labviewer_flags_add(NULL, &y, "HAS AWACS", SIF_HAS_AWACS);
1479  labviewer_flags_add(NULL, &y, "NO COLLIDE INVISIBLE", SIF_SHIP_CLASS_DONT_COLLIDE_INVIS);
1480  labviewer_flags_add(NULL, &y, "DO COLLISION CHECK", SIF_NO_COLLIDE);
1481  labviewer_flags_add(NULL, &y, "PLAYER SHIP", SIF_PLAYER_SHIP);
1482  labviewer_flags_add(NULL, &y, "DEFAULT PLAYER SHIP", SIF_DEFAULT_PLAYER_SHIP);
1483  labviewer_flags_add(NULL, &y, "BALLISTIC PRIMARIES", SIF_BALLISTIC_PRIMARIES);
1484  labviewer_flags_add(NULL, &y, "FLASH", SIF2_FLASH, true);
1485  labviewer_flags_add(NULL, &y, "SURFACE SHIELDS", SIF2_SURFACE_SHIELDS, true);
1486  labviewer_flags_add(NULL, &y, "SHOW SHIP MODEL", SIF2_SHOW_SHIP_MODEL, true);
1487  labviewer_flags_add(NULL, &y, "IN TECH DATABASE", SIF_IN_TECH_DATABASE);
1488  labviewer_flags_add(NULL, &y, "IN TECH DATABASE MULTI", SIF_IN_TECH_DATABASE_M);
1489  }
1490  // weapon flags ...
1491  else if (Lab_mode == LAB_MODE_WEAPON) {
1492  labviewer_flags_add(NULL, &y, "HEAT SEEKING", WIF_HOMING_HEAT);
1493  labviewer_flags_add(NULL, &y, "ASPECT SEEKING", WIF_HOMING_ASPECT);
1494  labviewer_flags_add(NULL, &y, "ELECTRONICS", WIF_ELECTRONICS);
1495  labviewer_flags_add(NULL, &y, "PUNCTURE", WIF_PUNCTURE);
1496  labviewer_flags_add(NULL, &y, "SUPERCAP", WIF_SUPERCAP);
1497  labviewer_flags_add(NULL, &y, "COUNTERMEASURE", WIF_CMEASURE);
1498  labviewer_flags_add(NULL, &y, "BIG ONLY", WIF_BIG_ONLY);
1499  labviewer_flags_add(NULL, &y, "HUGE", WIF_HUGE);
1500  labviewer_flags_add(NULL, &y, "PLAYER ALLOWED", WIF_PLAYER_ALLOWED);
1501  labviewer_flags_add(NULL, &y, "PARTICLE SPEW", WIF_PARTICLE_SPEW);
1502  labviewer_flags_add(NULL, &y, "EMP", WIF_EMP);
1503  labviewer_flags_add(NULL, &y, "ENERGY SUCK", WIF_ENERGY_SUCK);
1504  labviewer_flags_add(NULL, &y, "SHUDDER", WIF_SHUDDER);
1505  labviewer_flags_add(NULL, &y, "BALLISTIC", WIF2_BALLISTIC, true);
1506  labviewer_flags_add(NULL, &y, "PIERCE SHIELDS", WIF2_PIERCE_SHIELDS, true);
1507  labviewer_flags_add(NULL, &y, "CYCLE", WIF2_CYCLE, true);
1508  labviewer_flags_add(NULL, &y, "NO LIGHTING", WIF2_MR_NO_LIGHTING, true);
1509  labviewer_flags_add(NULL, &y, "TRANSPARENT", WIF2_TRANSPARENT, true);
1510  labviewer_flags_add(NULL, &y, "IN TECH DATABASE", WIF_IN_TECH_DATABASE);
1511  }
1512 }
1513 
1515 {
1516  size_t i;
1517 
1518  if ( (Lab_selected_index < 0) || (Lab_mode == LAB_MODE_NONE) ) {
1519  return;
1520  }
1521 
1522  // no flags? then don't bother
1523  if (Lab_flags.empty()) {
1524  return;
1525  }
1526 
1527 
1528  if (Lab_mode == LAB_MODE_SHIP) {
1529  ship_info *sip = &Ship_info[Lab_selected_index];
1530 
1531  for (i = 0; i < Lab_flags.size(); i++) {
1532  if (Lab_flags[i].second) {
1533  Lab_flags[i].cb->SetFlag(&sip->flags2, Lab_flags[i].flag);
1534  } else {
1535  Lab_flags[i].cb->SetFlag(&sip->flags, Lab_flags[i].flag);
1536  }
1537  }
1538  } else if (Lab_mode == LAB_MODE_WEAPON) {
1539  weapon_info *wip = &Weapon_info[Lab_selected_index];
1540 
1541  for (i = 0; i < Lab_flags.size(); i++) {
1542  if (Lab_flags[i].second) {
1543  Lab_flags[i].cb->SetFlag(&wip->wi_flags2, Lab_flags[i].flag);
1544  } else {
1545  Lab_flags[i].cb->SetFlag(&wip->wi_flags, Lab_flags[i].flag);
1546  }
1547  }
1548  }
1549 }
1550 
1552 {
1553  Lab_flags_window = NULL;
1554 
1555  Lab_flags.clear();
1556 }
1557 
1559 {
1560  if (Lab_flags_window == NULL) {
1561  Lab_flags_window = (Window*) Lab_screen->Add(new Window("Flags Window", gr_screen.center_offset_x + gr_screen.center_w - 205, gr_screen.center_offset_y + 200));
1563  }
1564 
1565  // set our new title
1566  if (Lab_mode == LAB_MODE_SHIP) {
1567  Lab_flags_window->SetCaption("Ship Flags");
1568  } else if (Lab_mode == LAB_MODE_WEAPON) {
1569  Lab_flags_window->SetCaption("Weapon Flags");
1570  }
1571 
1572  // populate the window with our flags (controls both ships and weapons flags)
1574 
1575  // update content, if we need to
1577 }
1578 
1579 // ----------------------- Variables Window --------------------------------
1580 #define VAR_POS_LEFTWIDTH 150
1581 #define VAR_POS_RIGHTWIDTH 100
1582 #define VAR_POS_RIGHTX 160
1583 
1584 #define VAR_ADD_HEADER(name) { \
1585  ntp = (Text*)Lab_variables_window->AddChild(new Text((name), (name), VAR_POS_RIGHTX/2, y + 8, VAR_POS_RIGHTWIDTH)); \
1586  y += ntp->GetHeight() + 10; \
1587 }
1588 
1589 static SCP_vector<Text*> Lab_variables;
1590 
1592 {
1593  Lab_variables_window = NULL;
1594 
1595  Lab_variables.clear();
1596 }
1597 
1599 {
1600  if (Lab_variables_window != NULL) {
1601  Lab_variables_window->DeleteChildren();
1602  }
1603 
1604  Lab_variables.clear();
1605 }
1606 
1607 void labviewer_variables_add(int *Y, char *var_name)
1608 {
1609  int y = 0;
1610  Text *new_text;
1611 
1612  Assert( (Lab_variables_window != NULL) && (var_name != NULL) );
1613 
1614  if (Y) {
1615  y = *Y;
1616  }
1617 
1618  // variable
1619  Lab_variables_window->AddChild(new Text((var_name), (var_name), 0, y, VAR_POS_LEFTWIDTH));
1620  // edit box
1621  new_text = (Text*)Lab_variables_window->AddChild(new Text(SCP_string((var_name)) + SCP_string("Editbox"), "", VAR_POS_RIGHTX, y, VAR_POS_RIGHTWIDTH, 12, T_EDITTABLE));
1622 
1623  if (Y) {
1624  *Y += new_text->GetHeight() + 2;
1625  }
1626 
1627  Lab_variables.push_back( new_text );
1628 }
1629 
1631 {
1632  Text *ntp;
1633  int y;
1634 
1635  if (Lab_mode == LAB_MODE_NONE) {
1636  return;
1637  }
1638 
1639  if (Lab_variables_window == NULL) {
1640  return;
1641  }
1642 
1643  // clear out anything that already exists
1645 
1646  y = 0;
1647 
1648  // IMPORTANT NOTE: If you add something here, make sure you add it to labviewer_update_variables_window() as well!
1649  // ship vFEWfe<ariables ...
1650  if (Lab_mode == LAB_MODE_SHIP) {
1651  labviewer_variables_add(&y, "Name");
1652  labviewer_variables_add(&y, "Species");
1653  labviewer_variables_add(&y, "Type");
1654  labviewer_variables_add(&y, "Default Team Color");
1655 
1656  // physics
1657  VAR_ADD_HEADER("Physics");
1658  labviewer_variables_add(&y, "Density");
1659  labviewer_variables_add(&y, "Damp");
1660  labviewer_variables_add(&y, "Rotdamp");
1661  labviewer_variables_add(&y, "Max vel (x)");
1662  labviewer_variables_add(&y, "Max vel (y)");
1663  labviewer_variables_add(&y, "Max vel (z)");
1664  labviewer_variables_add(&y, "Warp in speed");
1665  labviewer_variables_add(&y, "Warp out speed");
1666 
1667  // other
1668  VAR_ADD_HEADER("Stats");
1669  labviewer_variables_add(&y, "Shields");
1670  labviewer_variables_add(&y, "Hull");
1671  labviewer_variables_add(&y, "Subsys repair rate");
1672  labviewer_variables_add(&y, "Hull repair rate");
1673  labviewer_variables_add(&y, "Countermeasures");
1674  labviewer_variables_add(&y, "HUD Icon");
1675 
1676  VAR_ADD_HEADER("Power");
1677  labviewer_variables_add(&y, "Power output");
1678  labviewer_variables_add(&y, "Max oclk speed");
1679  labviewer_variables_add(&y, "Max weapon reserve");
1680 
1681  VAR_ADD_HEADER("Afterburner");
1682  labviewer_variables_add(&y, "Fuel");
1683  labviewer_variables_add(&y, "Burn rate");
1684  labviewer_variables_add(&y, "Recharge rate");
1685 
1686  VAR_ADD_HEADER("Explosion");
1687  labviewer_variables_add(&y, "Inner radius");
1688  labviewer_variables_add(&y, "Outer radius");
1689  labviewer_variables_add(&y, "Damage");
1690  labviewer_variables_add(&y, "Blast");
1691  labviewer_variables_add(&y, "Propagates");
1692  labviewer_variables_add(&y, "Shockwave speed");
1693  labviewer_variables_add(&y, "Shockwave count");
1694 
1695  // techroom
1696  VAR_ADD_HEADER("Techroom");
1697  labviewer_variables_add(&y, "Closeup zoom");
1698  labviewer_variables_add(&y, "Closeup pos (x)");
1699  labviewer_variables_add(&y, "Closeup pos (y)");
1700  labviewer_variables_add(&y, "Closeup pos (z)");
1701  }
1702  // weapon variables ...
1703  else if (Lab_mode == LAB_MODE_WEAPON) {
1704  labviewer_variables_add(&y, "Name");
1705  labviewer_variables_add(&y, "Subtype");
1706 
1707  // physics
1708  VAR_ADD_HEADER("Physics");
1709  labviewer_variables_add(&y, "Mass");
1710  labviewer_variables_add(&y, "Max speed");
1711  labviewer_variables_add(&y, "Lifetime");
1712  labviewer_variables_add(&y, "Range");
1713  labviewer_variables_add(&y, "Min Range");
1714 
1715  VAR_ADD_HEADER("Damage");
1716  labviewer_variables_add(&y, "Fire wait");
1717  labviewer_variables_add(&y, "Damage");
1718  labviewer_variables_add(&y, "Armor factor");
1719  labviewer_variables_add(&y, "Shield factor");
1720  labviewer_variables_add(&y, "Subsys factor");
1721 
1722  VAR_ADD_HEADER("Armor");
1723  labviewer_variables_add(&y, "Damage type");
1724 
1725  VAR_ADD_HEADER("Shockwave");
1726  labviewer_variables_add(&y, "Speed");
1727 
1728  VAR_ADD_HEADER("Missiles");
1729  labviewer_variables_add(&y, "Turn time");
1730  labviewer_variables_add(&y, "FOV");
1731  labviewer_variables_add(&y, "Min locktime");
1732  labviewer_variables_add(&y, "Pixels/sec");
1733  labviewer_variables_add(&y, "Catchup pixels/sec");
1734  labviewer_variables_add(&y, "Catchup pixel pen.");
1735  labviewer_variables_add(&y, "Swarm count");
1736  labviewer_variables_add(&y, "Swarm wait");
1737  }
1738 }
1739 
1740 #define VAR_SET_VALUE(value) { \
1741  Assert( i < Lab_variables.size() ); \
1742  Lab_variables[i]->SetText((value)); \
1743  i++; \
1744 }
1745 
1746 #define VAR_SET_VALUE_SAVE(value, max_size) { \
1747  Assert( i < Lab_variables.size() ); \
1748  Lab_variables[i]->SetText((value)); \
1749  if ((max_size) < 1) { \
1750  Assert( (max_size) == 0 ); \
1751  Lab_variables[i]->SetSaveLoc(&(value), T_ST_ONENTER); \
1752  } else { \
1753  Lab_variables[i]->SetSaveLoc(&(value), T_ST_ONENTER, (max_size), 0); \
1754  } \
1755  i++; \
1756 }
1758 
1760 {
1761  uint i = 0;
1762 
1763  if (Lab_mode == LAB_MODE_NONE) {
1764  return;
1765  }
1766 
1767  if (Lab_variables_window == NULL) {
1768  return;
1769  }
1770 
1771  if (Lab_selected_index < 0) {
1772  return;
1773  }
1774 
1775  // IMPORTANT NOTE: If you add something here, make sure you add it to labviewer_populate_variables_window() as well!
1776  // ship variables ...
1777  if (Lab_mode == LAB_MODE_SHIP) {
1778  Assert( Lab_selected_index < static_cast<int>(Ship_info.size()) );
1779  ship_info *sip = &Ship_info[Lab_selected_index];
1780 
1781  VAR_SET_VALUE(sip->name);
1782  VAR_SET_VALUE_SAVE(sip->species, Species_info.size()-1);
1783  VAR_SET_VALUE_SAVE(sip->class_type, Ship_types.size()-1);
1785 
1786  VAR_SET_VALUE_SAVE(sip->density, 0);
1787  VAR_SET_VALUE_SAVE(sip->damp, 0);
1788  VAR_SET_VALUE_SAVE(sip->rotdamp, 0);
1789  VAR_SET_VALUE_SAVE(sip->max_vel.xyz.x, 0);
1790  VAR_SET_VALUE_SAVE(sip->max_vel.xyz.y, 0);
1791  VAR_SET_VALUE_SAVE(sip->max_vel.xyz.z, 0);
1794 
1800  VAR_SET_VALUE_SAVE(sip->shield_icon_index, Hud_shield_filenames.size()-1);
1801 
1805  // VAR_SET_VALUE_SAVE(sip->max_shield_regen_per_second, 0);
1806  // VAR_SET_VALUE_SAVE(sip->max_weapon_regen_per_second, 0);
1807 
1811 
1819 
1821  VAR_SET_VALUE_SAVE(sip->closeup_pos.xyz.x, 0);
1822  VAR_SET_VALUE_SAVE(sip->closeup_pos.xyz.y, 0);
1823  VAR_SET_VALUE_SAVE(sip->closeup_pos.xyz.z, 0);
1824  }
1825  // weapon variables ...
1826  else if (Lab_mode == LAB_MODE_WEAPON) {
1827  Assert( Lab_selected_index < Num_weapon_types );
1828  weapon_info *wip = &Weapon_info[Lab_selected_index];
1829 
1830  VAR_SET_VALUE(wip->name);
1832 
1833  VAR_SET_VALUE_SAVE(wip->mass, 0);
1834  VAR_SET_VALUE_SAVE(wip->max_speed, 0);
1835  VAR_SET_VALUE_SAVE(wip->lifetime, 0);
1838 
1839  VAR_SET_VALUE_SAVE(wip->fire_wait, 0);
1840  VAR_SET_VALUE_SAVE(wip->damage, 0);
1844 
1846 
1848 
1849  VAR_SET_VALUE_SAVE(wip->turn_time, 0);
1850  VAR_SET_VALUE_SAVE(wip->fov, 0);
1856  VAR_SET_VALUE_SAVE(wip->SwarmWait, 0);
1857  }
1858 }
1859 
1861 {
1862  if (Lab_variables_window != NULL) {
1863  return;
1864  }
1865 
1866  Lab_variables_window = (Window*)Lab_screen->Add(new Window("Class Variables", gr_screen.center_offset_x + gr_screen.center_w - (VAR_POS_RIGHTX + VAR_POS_RIGHTWIDTH + 25), gr_screen.center_offset_y + 200));
1867 
1868  // set our new title
1869  if (Lab_mode == LAB_MODE_SHIP) {
1870  Lab_variables_window->SetCaption("Ship Variables");
1871  } else if (Lab_mode == LAB_MODE_WEAPON) {
1872  Lab_variables_window->SetCaption("Weapon Variables");
1873  }
1874 
1875  // populate the window with our flags (controls both ships and weapons flags)
1877 
1878  // update content, if we need to
1880 
1881  Lab_variables_window->SetCloseFunction(labviewer_close_variables_window);
1882 }
1883 
1884 // -------------------- Render Options Window ------------------------------
1886 {
1887  int slider_pos = (int)(caller->GetSelectedItem()->GetData());
1888  Assert( (slider_pos >= 0) && (slider_pos <= MAX_DETAIL_LEVEL) );
1889 
1890  Detail.hardware_textures = slider_pos;
1891 }
1892 
1894 {
1895  Lab_render_options_window = NULL;
1896 }
1897 
1898 #define ADD_RENDER_FLAG(text, flag, var) { \
1899  cbp = (Checkbox*)Lab_render_options_window->AddChild(new Checkbox((text), 2, y)); \
1900  cbp->SetFlag(&(flag), (var)); \
1901  y += cbp->GetHeight() + 2; \
1902 }
1903 
1904 #define ADD_RENDER_BOOL(text, flag) { \
1905  cbp = (Checkbox*)Lab_render_options_window->AddChild(new Checkbox((text), 2, y)); \
1906  cbp->SetBool(&(flag)); \
1907  y += cbp->GetHeight() + 1; \
1908 }
1909 
1911 {
1912  Checkbox *cbp;
1913  Tree *cmp;
1914  TreeItem *ctip;
1915  int y = 0;
1916 
1917  if (Lab_render_options_window != NULL) {
1918  return;
1919  }
1920 
1921  Lab_render_options_window = (Window*)Lab_screen->Add(new Window("Render Options", gr_screen.center_offset_x + gr_screen.center_w - 300, gr_screen.center_offset_y + 200));
1922  Assert( Lab_render_options_window != NULL );
1923 
1924  // add all of the flags that we want/need...
1925 
1926  // viewer flags
1927  ADD_RENDER_FLAG("Disable Model Rotation", Lab_viewer_flags, LAB_FLAG_NO_ROTATION);
1928  ADD_RENDER_FLAG("Show Insignia", Lab_viewer_flags, LAB_FLAG_SHOW_INSIGNIA);
1929  ADD_RENDER_FLAG("Show Damage Lightning", Lab_viewer_flags, LAB_FLAG_LIGHTNING_ARCS);
1930  ADD_RENDER_FLAG("Rotate Subsystems", Lab_viewer_flags, LAB_FLAG_SUBMODEL_ROTATE);
1931  if (is_minimum_GLSL_version()) {
1932  ADD_RENDER_BOOL("Fixed Render Pipeline", GLSL_override);
1933  if (Cmdline_postprocess) {
1934  ADD_RENDER_BOOL("Hide Post Processing", PostProcessing_override);
1935  ADD_RENDER_BOOL("Use FXAA", Cmdline_fxaa);
1936  }
1937  }
1938  // map related flags
1939  ADD_RENDER_BOOL("No Diffuse Map", Basemap_override);
1940  if (Cmdline_glow) {
1941  ADD_RENDER_FLAG("No Glow Map", Lab_model_flags, MR_NO_GLOWMAPS);
1942  }
1943  if (Cmdline_spec) {
1944  ADD_RENDER_BOOL("No Specular Map", Specmap_override);
1945  }
1946  if (Cmdline_env) {
1947  ADD_RENDER_BOOL("No Environment Map", Envmap_override);
1948  }
1949  if (Cmdline_normal) {
1950  ADD_RENDER_BOOL("No Normal Map", Normalmap_override);
1951  }
1952  if (Cmdline_height) {
1953  ADD_RENDER_BOOL("No Height Map", Heightmap_override);
1954  }
1955  ADD_RENDER_BOOL("No Team Colors", Teamcolor_override);
1956  ADD_RENDER_BOOL("No Glow Points", Glowpoint_override);
1957  // model flags
1959  ADD_RENDER_FLAG("Transparent", Lab_model_flags, MR_ALL_XPARENT);
1960  ADD_RENDER_FLAG("No Lighting", Lab_model_flags, MR_NO_LIGHTING);
1961  ADD_RENDER_FLAG("No Z-Buffer", Lab_model_flags, MR_NO_ZBUFFER);
1962  ADD_RENDER_FLAG("No Culling", Lab_model_flags, MR_NO_CULL);
1963  ADD_RENDER_FLAG("Force Clamp", Lab_model_flags, MR_FORCE_CLAMP);
1964  ADD_RENDER_FLAG("Show Full Detail", Lab_model_flags, MR_FULL_DETAIL);
1965  ADD_RENDER_FLAG("Show Pivots", Lab_model_debug_flags, MR_DEBUG_PIVOTS);
1966  ADD_RENDER_FLAG("Show Paths", Lab_model_debug_flags, MR_DEBUG_PATHS);
1967  ADD_RENDER_FLAG("Show Bay Paths", Lab_model_debug_flags, MR_DEBUG_BAY_PATHS);
1968  ADD_RENDER_FLAG("Show Radius", Lab_model_debug_flags, MR_DEBUG_RADIUS);
1969  ADD_RENDER_FLAG("Show Shields", Lab_model_debug_flags, MR_DEBUG_SHIELDS);
1970  ADD_RENDER_FLAG("Show Thrusters", Lab_model_flags, MR_SHOW_THRUSTERS);
1971  ADD_RENDER_FLAG("Show Ship Weapons", Lab_viewer_flags, LAB_FLAG_SHOW_WEAPONS);
1972  ADD_RENDER_FLAG("Initial Rotation", Lab_viewer_flags, LAB_FLAG_INITIAL_ROTATION);
1973  ADD_RENDER_FLAG("Show Destroyed Subsystems", Lab_viewer_flags, LAB_FLAG_DESTROYED_SUBSYSTEMS);
1974 
1975  // start tree
1976  cmp = (Tree*)Lab_render_options_window->AddChild(new Tree("Detail Options Tree", 0, y + 2, NULL, Lab_render_options_window->GetWidth()));
1977 
1978  // 3d hardware texture slider options
1979  ctip = cmp->AddItem(NULL, "3D Hardware Textures", 0, false);
1980 
1981  cmp->AddItem(ctip, "Minimum", 0, false, labviewer_change_detail_texture);
1982  cmp->AddItem(ctip, "Low", 1, false, labviewer_change_detail_texture);
1983  cmp->AddItem(ctip, "Medium", 2, false, labviewer_change_detail_texture);
1984  cmp->AddItem(ctip, "High", 3, false, labviewer_change_detail_texture);
1985  cmp->AddItem(ctip, "Maximum", 4, false, labviewer_change_detail_texture);
1986 
1987  // set close function
1988  Lab_render_options_window->SetCloseFunction(labviewer_close_render_options_window);
1989 }
1990 
1991 // ------------------------- Description Window ------------------------------
1993 {
1994  Lab_description_text = NULL;
1995  Lab_description_window = NULL;
1996 }
1997 
1999 {
2000  if ( (Lab_description_window == NULL) || (Lab_description_text == NULL) ) {
2001  return;
2002  }
2003 
2004  if (Lab_selected_index != -1) {
2005  if (Lab_mode == LAB_MODE_SHIP) {
2006  Lab_description_window->SetCaption(Ship_info[Lab_selected_index].name);
2007 
2008  if (Ship_info[Lab_selected_index].tech_desc != NULL) {
2009  Lab_description_text->SetText(Ship_info[Lab_selected_index].tech_desc);
2010  } else {
2011  Lab_description_text->SetText("No description available.");
2012  }
2013  } else if (Lab_mode == LAB_MODE_WEAPON) {
2014  Lab_description_window->SetCaption(Weapon_info[Lab_selected_index].name);
2015 
2016  if (Weapon_info[Lab_selected_index].tech_desc != NULL) {
2017  Lab_description_text->SetText(Weapon_info[Lab_selected_index].tech_desc);
2018  } else {
2019  Lab_description_text->SetText("No description available.");
2020  }
2021  }
2022  }
2023 }
2024 
2026 {
2027  if (Lab_description_window != NULL) {
2028  return;
2029  }
2030 
2031  Lab_description_window = (Window*)Lab_screen->Add(new Window("Description", gr_screen.center_offset_x + gr_screen.center_w - gr_screen.center_w/3 - 50,
2033  gr_screen.center_h/6));
2034  Lab_description_text = (Text*)Lab_description_window->AddChild(new Text("Description Text", "No ship selected.", 0, 0));
2035 
2037 
2038  Lab_description_window->SetCloseFunction(labviewer_close_desc_window);
2039 }
2040 
2041 // ------------------------ Ships Window -----------------------------------
2043 {
2044  GUIObject *cbp;
2045  TreeItem *ctip, *stip;
2046  int x, idx;
2047 
2048  if (Lab_mode == LAB_MODE_SHIP) {
2049  return;
2050  }
2051 
2052 
2053  // switch the class window to ship mode
2055 
2056  if ( (Lab_class_window == NULL) || (Lab_class_toolbar == NULL) ) {
2057  Int3();
2058  Lab_mode = LAB_MODE_SHIP;
2059  return;
2060  }
2061 
2062 
2063  // populate the class toolbar
2064  x = 0;
2065  cbp = Lab_class_toolbar->AddChild(new Button("Class Description", x, 0, labviewer_make_desc_window));
2066 
2067  x += cbp->GetWidth() + 10;
2068  cbp = Lab_class_toolbar->AddChild(new Button("Class Options", x, 0, labviewer_make_flags_window));
2069 
2070  x += cbp->GetWidth() + 10;
2071  cbp = Lab_class_toolbar->AddChild(new Button("Class Variables", x, 0, labviewer_make_variables_window));
2072 
2073 
2074  // populate ship class window
2075  Tree *cmp = (Tree*)Lab_class_window->AddChild(new Tree("Ship Tree", 0, 0));
2076 
2077  if (Lab_species_nodes != NULL) {
2078  for (idx = 0; idx < (int)Species_info.size(); idx++) {
2079  Lab_species_nodes[idx]->ClearAllItems();
2080  }
2081 
2082  delete [] Lab_species_nodes;
2083  Lab_species_nodes = NULL;
2084  }
2085 
2086  Lab_species_nodes = new TreeItem*[Species_info.size()+1];
2087 
2088  // Add species nodes
2089  for (idx = 0; idx < (int)Species_info.size(); idx++) {
2090  Lab_species_nodes[idx] = cmp->AddItem(NULL, Species_info[idx].species_name, 0, false);
2091  }
2092 
2093  // Just in case. I don't actually think this is possible though.
2094  Lab_species_nodes[Species_info.size()] = cmp->AddItem(NULL, "Other", 0, false);
2095 
2096  // Now add the ships
2097  SCP_string lod_name;
2098  char buf[33];
2099 
2100  for (auto it = Ship_info.cbegin(); it != Ship_info.cend(); ++it) {
2101  if ( (it->species >= 0) && (it->species < (int)Species_info.size()) ) {
2102  stip = Lab_species_nodes[it->species];
2103  } else {
2104  stip = Lab_species_nodes[Species_info.size()];
2105  }
2106 
2107  ctip = cmp->AddItem(stip, it->name, std::distance(Ship_info.cbegin(), it), false, labviewer_change_ship);
2108 
2109  if ( !Lab_in_mission ) {
2110  for (int j = 0; j < it->num_detail_levels; j++) {
2111  sprintf(buf, "%d", j);
2112  lod_name = "LOD ";
2113  lod_name += buf;
2114 
2115  cmp->AddItem(ctip, lod_name, j, false, labviewer_change_ship_lod);
2116  }
2117 
2118  cmp->AddItem(ctip, "Debris", 99, false, labviewer_change_ship_lod);
2119  }
2120  }
2121 
2122  // if any nodes are empty, just add a single "<none>" entry so we know that species doesn't have anything yet
2123  // No the <= is not a mistake :)
2124  for (idx = 0; idx < (int)Species_info.size(); idx++) {
2125  if ( !Lab_species_nodes[idx]->HasChildren() ) {
2126  cmp->AddItem(Lab_species_nodes[idx], "<none>", 0, false, NULL);
2127  }
2128  }
2129 
2130  // if the "Other" entry doesn't contain anything then just delete it
2131  if ( !Lab_species_nodes[Species_info.size()]->HasChildren() ) {
2132  delete Lab_species_nodes[Species_info.size()];
2133  }
2134 
2135 
2136  // and... we're done!
2137  Lab_mode = LAB_MODE_SHIP;
2138 
2139  // populate the flags window, if it exists
2140  // (NOTE: must be done *after* Lab_mode is set properly)
2141  if (Lab_flags_window != NULL) {
2142  Lab_flags_window->SetCaption("Ship Flags");
2143 
2146  }
2147 
2148  if (Lab_description_window != NULL) {
2150  }
2151 
2152  if (Lab_variables_window != NULL) {
2153  Lab_variables_window->SetCaption("Ship Variables");
2154 
2157  }
2158 }
2159 
2161 {
2162  int ship_index = (int)(caller->GetSelectedItem()->GetParentItem()->GetData());
2163  Assert( ship_index >= 0 );
2164 
2165  if (Lab_selected_object == -1)
2166  {
2167  // Goober5000 - The lab loads subsystems into its special lab-specific vector, but normally subsystems are loaded into the Ship_info
2168  // entry. Note also that models are only loaded once each. If a lab model was previously loaded using the "lightweight" method,
2169  // ship_create will not find any of the subsystems it is looking for. So we have to make sure the model is only loaded for the purposes
2170  // of error-checking and then immediately cleared so that it can be subsequently loaded the lab way.
2171 
2172  // reset any existing model/bitmap that is showing
2173  labviewer_change_model(NULL);
2175 
2177  Lab_selected_object = ship_create(&vmd_identity_matrix, &vmd_zero_vector, ship_index);
2178 
2179  // unload the model we just loaded
2180  model_page_out_textures(Ship_info[ship_index].model_num, true);
2181  model_unload(Ship_info[ship_index].model_num);
2182  Ship_info[ship_index].model_num = -1;
2183  }
2184  else
2185  {
2186  obj_delete(Lab_selected_object);
2187  Lab_selected_object = ship_create(&vmd_identity_matrix, &vmd_zero_vector, ship_index);
2188  }
2189 
2190  Lab_last_selected_ship = Lab_selected_index;
2191 
2192  labviewer_change_model(Ship_info[ship_index].pof_file, caller->GetSelectedItem()->GetData(), ship_index);
2193 
2194  if (Ship_info[ship_index].uses_team_colors) {
2195  Lab_team_color = Ship_info[ship_index].default_team_name;
2196  } else {
2197  Lab_team_color = "<none>";
2198  }
2199 
2203 
2204  for (int i = 0; i < MAX_SHIP_ARCS; i++) {
2205  Lab_arc_timestamp[i] = -1;
2206  Lab_arc_type[i] = MARC_TYPE_NORMAL;
2207  Lab_arc_next_time = -1;
2208  }
2209 }
2210 
2212 {
2213  // this is really only for when we are in a mission
2214  if ( !Lab_in_mission ) {
2215  return;
2216  }
2217 
2218  Lab_selected_index = (int)(caller->GetSelectedItem()->GetData());
2219 
2223 }
2224 
2225 // --------------------------- Weapons Window --------------------------------
2227 {
2228  int weap_index = (int)(caller->GetSelectedItem()->GetParentItem()->GetData());
2229  Assert( weap_index >= 0 );
2230 
2231  labviewer_change_model(Weapon_info[weap_index].tech_model, caller->GetSelectedItem()->GetData(), weap_index);
2232 }
2233 
2235 {
2236  int weap_index = (int)(caller->GetSelectedItem()->GetParentItem()->GetData());
2237  Assert( weap_index >= 0 );
2238 
2239  labviewer_change_model(Weapon_info[weap_index].external_model_name, caller->GetSelectedItem()->GetData(), weap_index);
2240 }
2241 
2242 extern void weapon_load_bitmaps(int weapon_index);
2244 {
2245  int weap_index = (int)(caller->GetSelectedItem()->GetData());
2246  Assert( weap_index >= 0 );
2247 
2248  if ( !(Weapon_info[weap_index].wi_flags & WIF_BEAM) ) {
2249  switch (Weapon_info[weap_index].render_type) {
2250  case WRT_POF:
2252  labviewer_change_model(Weapon_info[weap_index].pofbitmap_name, 0, weap_index);
2253  weapon_load_bitmaps(weap_index);
2254  break;
2255 
2256  case WRT_LASER:
2257  labviewer_change_model(NULL);
2258  labviewer_change_bitmap(-1, weap_index);
2259  break;
2260 
2261  default:
2262  labviewer_change_model(NULL);
2264  break;
2265  }
2266  }
2267 
2268  Lab_selected_index = weap_index;
2269  Lab_last_selected_weapon = Lab_selected_index;
2270 
2274 }
2275 
2276 // weapon window create function
2278 {
2279  GUIObject *cbp;
2280  TreeItem *cwip, *stip;
2281  int x;
2282 
2283  if (Lab_mode == LAB_MODE_WEAPON) {
2284  return;
2285  }
2286 
2287 
2288  // switch the class window to weapon mode
2290 
2291  if ( (Lab_class_window == NULL) || (Lab_class_toolbar == NULL) ) {
2292  Int3();
2293  Lab_mode = LAB_MODE_WEAPON;
2294  return;
2295  }
2296 
2297 
2298  // populate the weapons toolbar
2299  x = 0;
2300  cbp = Lab_class_toolbar->AddChild(new Button("Class Description", x, 0, labviewer_make_desc_window));
2301 
2302  x += cbp->GetWidth() + 10;
2303  cbp = Lab_class_toolbar->AddChild(new Button("Class Options", x, 0, labviewer_make_flags_window));
2304 
2305  x += cbp->GetWidth() + 10;
2306  cbp = Lab_class_toolbar->AddChild(new Button("Class Variables", x, 0, labviewer_make_variables_window));
2307 
2308 
2309  // populate the weapons window
2310  Tree *cmp = (Tree*)Lab_class_window->AddChild(new Tree("Weapon Tree", 0, 0));
2311 
2312  // Unfortunately these are hardcoded
2313  TreeItem **type_nodes = new TreeItem*[Num_weapon_subtypes];
2314  int i;
2315 
2316  // Add type nodes
2317  for (i = 0; i < Num_weapon_subtypes; i++) {
2318  type_nodes[i] = cmp->AddItem(NULL, Weapon_subtype_names[i], 0, false);
2319  }
2320 
2321  // Now add the weapons
2322  for (i = 0; i < Num_weapon_types; i++) {
2323  if (Weapon_info[i].subtype == WP_UNUSED) {
2324  continue;
2325  } else if (Weapon_info[i].subtype >= Num_weapon_subtypes) {
2326  Warning(LOCATION, "Invalid weapon subtype found on weapon %s", Weapon_info[i].name);
2327  continue;
2328  }
2329 
2330  if (Weapon_info[i].wi_flags & WIF_BEAM) {
2331  stip = type_nodes[WP_BEAM];
2332  } else {
2333  stip = type_nodes[Weapon_info[i].subtype];
2334  }
2335 
2336  cwip = cmp->AddItem(stip, Weapon_info[i].name, i, false, labviewer_change_weapon);
2337 
2338  if (Weapon_info[i].tech_model[0] != '\0') {
2339  cmp->AddItem(cwip, "Tech Model", 0, false, labviewer_show_tech_model);
2340  }
2341  if (Weapon_info[i].external_model_name[0] != '\0') {
2342  cmp->AddItem(cwip, "External Model", 0, false, labviewer_show_external_model);
2343  }
2344  }
2345 
2346  // Get rid of any empty nodes
2347  for (i = 0; i < Num_weapon_subtypes; i++) {
2348  if ( !type_nodes[i]->HasChildren() ) {
2349  delete type_nodes[i];
2350  }
2351  }
2352  delete[] type_nodes;
2353 
2354  Lab_mode = LAB_MODE_WEAPON;
2355 
2356  // populate the flags window, if it exists
2357  // (NOTE: must be done *after* Lab_mode is set properly)
2358  if (Lab_flags_window != NULL) {
2359  Lab_flags_window->SetCaption("Weapon Flags");
2360 
2363  }
2364 
2365  if (Lab_description_window != NULL) {
2367  }
2368 
2369  if (Lab_variables_window != NULL) {
2370  Lab_variables_window->SetCaption("Weapon Variables");
2371 
2374  }
2375 }
2376 
2377 
2378 
2379 // ----------------------------- Lab functions ---------------------------------
2380 
2381 void lab_init()
2382 {
2383  GUIObject *cbp;
2384  int x,i;
2385 
2387 
2389  Lab_in_mission = true;
2390  } else {
2391  Lab_in_mission = false;
2392  }
2393 
2394  if (Lab_in_mission) {
2395  Lab_screen_save_bitmap = gr_save_screen();
2396  gr_create_shader(&Lab_shader, 0, 0, 0, 127);
2397  } else {
2398  gr_set_clear_color(0, 0, 0);
2399  }
2400 
2401 
2402  //We start by creating the screen/toolbar
2403  Lab_screen = GUI_system.PushScreen(new GUIScreen("Lab"));
2404 
2405  Lab_toolbar = (Window*)Lab_screen->Add(new Window("Toolbar", gr_screen.center_offset_x, gr_screen.center_offset_y, -1, -1, WS_NOTITLEBAR | WS_NONMOVEABLE));
2406 
2407  // start filling the main toolbar
2408  x = 0;
2409  cbp = Lab_toolbar->AddChild(new Button("Ships", x, 0, labviewer_make_ship_window));
2410 
2411  x += cbp->GetWidth() + 10;
2412  cbp = Lab_toolbar->AddChild(new Button("Weapons", x, 0, labviewer_make_weap_window));
2413 
2414  if ( !Lab_in_mission ) {
2415  x += cbp->GetWidth() + 10;
2416  cbp = Lab_toolbar->AddChild(new Button("Render Options", x, 0, labviewer_make_render_options_window));
2417  }
2418 
2419  x += cbp->GetWidth() + 20;
2420  cbp = Lab_toolbar->AddChild(new Button("Exit", x, 0, labviewer_exit));
2421 
2422 
2423  // reset some defaults, just to be sure
2424  Lab_viewer_zoom = 1.2f;
2425  Lab_viewer_pos.xyz.x = Lab_viewer_pos.xyz.y = 0.0f;
2426  Lab_mode = LAB_MODE_NONE;
2427  Lab_thrust_len = 1.0f;
2428  Lab_thrust_afterburn = false;
2429  Lab_arc_next_time = -1;
2430  Lab_arc_disrupted = false;
2431  for (i = 0; i < MAX_SHIP_WEAPONS; i++) {
2432  Lab_weaponmodel_num[i] = -1;
2433  }
2434 
2435  // save detail options
2436  Lab_detail_texture_save = Detail.hardware_textures;
2437  if ( !Lab_in_mission ) {
2438  // load up the list of insignia that we might use on the ships
2440 
2441  // the default insignia bitmap
2442  Lab_insignia_index = 0;
2443  Assert( (Lab_insignia_index < Num_pilot_squad_images) );
2444 
2445  Lab_insignia_bitmap = bm_load_duplicate(Pilot_squad_image_names[Lab_insignia_index]);
2446  }
2447 
2448  // disable post-processing by default in the lab
2449  PostProcessing_override = true;
2450  // disable model rotation by default in the lab
2451  Lab_viewer_flags |= LAB_FLAG_NO_ROTATION;
2452  Lab_viewer_flags |= LAB_FLAG_INITIAL_ROTATION;
2453 }
2454 
2456 void lab_do_frame(float frametime)
2457 {
2458  gr_reset_clip();
2459  gr_clear();
2460 
2461  if (Lab_in_mission) {
2462  gr_restore_screen(Lab_screen_save_bitmap);
2463  gr_set_shader(&Lab_shader);
2465  } else {
2466  labviewer_do_render(frametime);
2467  }
2468 
2469 
2470  bool test1 = ( GUI_system.OnFrame(frametime, !(Trackball_active) ? true : false, false) == GSOF_NOTHINGPRESSED );
2471 
2472  if (test1) {
2473  int key = GUI_system.GetKeyPressed();
2474  int status = GUI_system.GetStatus();
2475 
2476  // set trackball modes
2477  if (status & GST_MOUSE_LEFT_BUTTON) {
2478  Trackball_active = 1;
2479  Trackball_mode = 1; // rotate
2480 
2481  if ( key_get_shift_status() & KEY_SHIFTED ) {
2482  Trackball_mode = 2; // pan
2483  }
2484  } else if (status & GST_MOUSE_RIGHT_BUTTON) {
2485  Trackball_active = 1;
2486  Trackball_mode = 3; // Zoom
2487  } else if ( !mouse_down(MOUSE_LEFT_BUTTON | MOUSE_RIGHT_BUTTON) ) {
2488  // reset trackball modes
2489  Trackball_active = 0;
2490  Trackball_mode = 0;
2491  }
2492 
2493  //Due to switch scoping rules, this has to be declared here
2495  // handle any key presses
2496  switch (key) {
2497  // switch between the current insignia bitmap to render with
2498  case KEY_DIVIDE: {
2499  if ( !(Lab_viewer_flags & LAB_FLAG_SHOW_INSIGNIA) ) {
2500  break;
2501  }
2502 
2503  Lab_insignia_index = (Lab_insignia_index+1) % Num_pilot_squad_images;
2504  Assert( (Lab_insignia_index >= 0) && (Lab_insignia_index < Num_pilot_squad_images) );
2505 
2506  if (Lab_insignia_bitmap >= 0) {
2507  bm_release(Lab_insignia_bitmap);
2508  Lab_insignia_bitmap = -1;
2509  }
2510 
2511  Lab_insignia_bitmap = bm_load_duplicate(Pilot_squad_image_names[Lab_insignia_index]);
2512 
2513  break;
2514  }
2515 
2516  // change between damage lightning effects
2517  case KEY_L:
2518  Lab_arc_disrupted = !Lab_arc_disrupted;
2519  Lab_arc_next_time = -1;
2520  break;
2521 
2522  // Adjust FXAA presets
2523  case KEY_0:
2525  Cmdline_fxaa_preset = 0;
2526  break;
2527  case KEY_1:
2529  Cmdline_fxaa_preset = 1;
2530  break;
2531  case KEY_2:
2533  Cmdline_fxaa_preset = 2;
2534  break;
2535  case KEY_3:
2537  Cmdline_fxaa_preset = 3;
2538  break;
2539  case KEY_4:
2541  Cmdline_fxaa_preset = 4;
2542  break;
2543  case KEY_5:
2545  Cmdline_fxaa_preset = 5;
2546  break;
2547  case KEY_6:
2549  Cmdline_fxaa_preset = 6;
2550  break;
2551  case KEY_7:
2553  Cmdline_fxaa_preset = 7;
2554  break;
2555  case KEY_8:
2557  Cmdline_fxaa_preset = 8;
2558  break;
2559  case KEY_9:
2561  Cmdline_fxaa_preset = 9;
2562  break;
2563 
2564  //adjust bloom intensity
2565  case KEY_B:
2566  if (!PostProcessing_override) {
2568  if (Cmdline_bloom_intensity > 200)
2570  }
2571  break;
2572  case KEY_N:
2573  if (!PostProcessing_override) {
2575  if (Cmdline_bloom_intensity < 0)
2577  }
2578  break;
2579 
2580  case KEY_T:
2581  if (color_itr == Team_Colors.begin()) {
2582  color_itr = --Team_Colors.end();
2583  Lab_team_color = color_itr->first;
2584  } else {
2585  --color_itr;
2586  Lab_team_color = color_itr->first;
2587  }
2588  break;
2589 
2590  case KEY_Y:
2591  ++color_itr;
2592  if (color_itr == Team_Colors.end())
2593  color_itr = Team_Colors.begin();
2594  Lab_team_color = color_itr->first;
2595  break;
2596 
2597  // bail...
2598  case KEY_ESC:
2599  labviewer_exit(NULL);
2600  break;
2601 
2602  default: {
2603  // check for game-specific controls
2604  if (Lab_mode == LAB_MODE_SHIP) {
2606  Lab_thrust_len += 0.05f;
2607  else if ( check_control(MINUS_5_PERCENT_THROTTLE, key) )
2608  Lab_thrust_len -= 0.05f;
2609 
2610  CLAMP( Lab_thrust_len, 0.0f, 1.0f );
2611 
2612  if ( check_control(AFTERBURNER, key) )
2613  Lab_thrust_afterburn = !Lab_thrust_afterburn;
2614  }
2615 
2616  break;
2617  }
2618  }
2619  }
2620 
2621  gr_flip();
2622 }
2623 
2625 {
2626  int i;
2627 
2628  Lab_toolbar = NULL;
2629  Lab_class_toolbar = NULL;
2630  Lab_class_window = NULL;
2631  Lab_flags_window = NULL;
2632  Lab_render_options_window = NULL;
2633 
2634  delete Lab_screen;
2635 
2636  Lab_screen = NULL;
2637 
2638 
2639  if (Lab_species_nodes != NULL) {
2640  for (i = 0; i < (int)Species_info.size(); i++) {
2641  delete Lab_species_nodes[i];
2642  }
2643 
2644  delete[] Lab_species_nodes;
2645  Lab_species_nodes = NULL;
2646  }
2647 
2648  if (Lab_insignia_bitmap >= 0) {
2649  bm_release(Lab_insignia_bitmap);
2650  Lab_insignia_bitmap = -1;
2651  }
2652 
2653  Lab_insignia_index = -1;
2654 
2655  if (Lab_model_num != -1) {
2656  model_page_out_textures(Lab_model_num, true);
2657  model_unload(Lab_model_num);
2658  Lab_model_num = -1;
2659  }
2660 
2661  for (i = 0; i < MAX_SHIP_WEAPONS; i++) {
2662  if (Lab_weaponmodel_num[i] >= 0) {
2663  model_page_out_textures(Lab_weaponmodel_num[i], true);
2664  model_unload(Lab_weaponmodel_num[i]);
2665  Lab_weaponmodel_num[i] = -1;
2666  }
2667  }
2668 
2669  if (Lab_screen_save_bitmap != 1) {
2670  gr_free_screen(Lab_screen_save_bitmap);
2671  Lab_screen_save_bitmap = -1;
2672  }
2673 
2674  Lab_ship_model_subsys.clear();
2675 
2676  if (Lab_ship_subsys != NULL) {
2677  delete[] Lab_ship_subsys;
2678  Lab_ship_subsys = NULL;
2679  }
2680 
2681  memset( Lab_model_filename, 0, sizeof(Lab_model_filename) );
2682 
2683  Basemap_override = false;
2684  Envmap_override = false;
2685  Specmap_override = false;
2686  Normalmap_override = false;
2687  Heightmap_override = false;
2688  Glowpoint_override = false;
2689  PostProcessing_override = false;
2690 
2691  // reset detail levels to default
2692  Detail.hardware_textures = Lab_detail_texture_save;
2693 
2695  //audiostream_unpause_all();
2696  game_flush();
2697 }
#define KEY_0
Definition: key.h:71
void light_add_directional(const vec3d *dir, float intensity, float r, float g, float b, float spec_r, float spec_g, float spec_b, bool specular)
Definition: lighting.cpp:209
void game_flush()
Definition: fredstubs.cpp:83
Definition: wmcgui.h:560
bool uses_team_colors
Definition: ship.h:1365
float g3_draw_laser_rgb(const vec3d *headp, float head_width, const vec3d *tailp, float tail_width, int r, int g, int b, uint tmap_flags=TMAP_FLAG_TEXTURED|TMAP_FLAG_RGB, float max_len=0.0f)
Definition: 3dlaser.cpp:267
void labviewer_update_flags_window()
Definition: lab.cpp:1514
#define WIF_EMP
Definition: weapon.h:73
void labviewer_make_desc_window(Button *caller)
Definition: lab.cpp:2025
#define gr_scene_texture_end
Definition: 2d.h:911
#define MAX_FILENAME_LEN
Definition: pstypes.h:324
#define ADD_RENDER_BOOL(text, flag)
Definition: lab.cpp:1904
bsp_info * submodel
Definition: model.h:764
void submodel_render_immediate(model_render_params *render_info, int model_num, int submodel_num, matrix *orient, vec3d *pos)
int timestamp(int delta_ms)
Definition: timer.cpp:226
#define SIF2_SURFACE_SHIELDS
Definition: ship.h:922
int i
Definition: multi_pxo.cpp:466
thrust_pair_bitmap thruster_secondary_glow_info
Definition: ship.h:1382
#define KEY_6
Definition: key.h:77
#define WP_UNUSED
Definition: weapon.h:26
int lock_pixels_per_sec
Definition: weapon.h:402
thrust_pair flames
Definition: species_defs.h:35
void DeleteChildren(GUIObject *exception=NULL)
Definition: wmcgui.cpp:770
void model_show_damaged(int model_num, int show_damaged)
float p
Definition: pstypes.h:111
void game_get_framerate()
Definition: freespace.cpp:2102
GUIScreen * PushScreen(GUIScreen *csp)
Definition: wmcgui.cpp:562
ubyte shield_icon_index
Definition: ship.h:1337
#define WIF_CMEASURE
Definition: weapon.h:51
#define TMAP_FLAG_XPARENT
Definition: tmapper.h:44
#define gr_clear
Definition: 2d.h:749
#define MR_SHOW_OUTLINE_HTL
Definition: model.h:885
#define SIF2_SHOW_SHIP_MODEL
Definition: ship.h:921
void ship_init_thrusters()
Definition: ship.cpp:8530
#define SIF_NO_COLLIDE
Definition: ship.h:874
float Proj_fov
Definition: 3dsetup.cpp:31
float max_weapon_reserve
Definition: ship.h:1276
float warpout_speed
Definition: ship.h:1220
float min_lock_time
Definition: weapon.h:401
#define MR_NO_CULL
Definition: model.h:879
generic_bitmap normal
Definition: species_defs.h:24
int Cmdline_old_collision_sys
Definition: cmdline.cpp:489
void model_find_world_point(vec3d *outpnt, vec3d *mpnt, int model_num, int submodel_num, const matrix *objorient, const vec3d *objpos)
Definition: modelread.cpp:4099
float vm_vec_mag_quick(const vec3d *v)
Definition: vecmat.cpp:371
int secondary_bank_weapons[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:1299
float max_overclocked_speed
Definition: ship.h:1275
matrix * vm_matrix_x_matrix(matrix *dest, const matrix *src0, const matrix *src1)
Definition: vecmat.cpp:1006
thrust_pair_bitmap thruster_tertiary_glow_info
Definition: ship.h:1383
char name[NAME_LENGTH]
Definition: weapon.h:322
#define KEY_Y
Definition: key.h:106
bool draw_primary_models[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:1302
int SwarmWait
Definition: weapon.h:511
GLfloat GLfloat GLfloat GLfloat h
Definition: Glext.h:7280
shockwave_create_info shockwave
Definition: ship.h:1237
#define SIF_PLAYER_SHIP
Definition: ship.h:875
void vm_vec_scale_add(vec3d *dest, const vec3d *src1, const vec3d *src2, float k)
Definition: vecmat.cpp:266
#define VAR_POS_RIGHTWIDTH
Definition: lab.cpp:1581
void gr_flip()
Definition: 2d.cpp:2113
bool Basemap_override
Definition: systemvars.cpp:70
#define GST_MOUSE_LEFT_BUTTON
Definition: wmcgui.h:186
void model_set_instance(int model_num, int sub_model_num, submodel_instance_info *sii, int flags=0)
Definition: modelread.cpp:4726
polymodel * model_get(int model_num)
Definition: modelread.cpp:3134
weapon_info Weapon_info[MAX_WEAPON_TYPES]
Definition: weapons.cpp:79
#define SIF_SUPERCAP
Definition: ship.h:901
#define KEY_5
Definition: key.h:76
#define MOUSE_LEFT_BUTTON
Definition: mouse.h:43
#define SIF_IN_TECH_DATABASE_M
Definition: ship.h:898
void labviewer_change_ship(Tree *caller)
Definition: lab.cpp:2211
float fire_wait
Definition: weapon.h:359
void weapon_load_bitmaps(int weapon_index)
Definition: weapons.cpp:3275
int debris_objects[MAX_DEBRIS_OBJECTS]
Definition: model.h:742
int GetStatus()
Definition: wmcgui.h:370
#define gr_end_view_matrix
Definition: 2d.h:896
generic_anim laser_bitmap
Definition: weapon.h:346
int gameseq_get_pushed_state()
submodel_instance_info submodel_info_1
Definition: ship.h:368
Definition: wmcgui.h:395
float flFrametime
Definition: fredstubs.cpp:22
bool Glowpoint_override
Definition: systemvars.cpp:75
#define WIF2_CYCLE
Definition: weapon.h:89
void lab_do_frame(float frametime)
Definition: lab.cpp:2456
#define MR_ALL_XPARENT
Definition: model.h:877
#define WIF_BIG_ONLY
Definition: weapon.h:61
#define KEY_8
Definition: key.h:79
void set_thruster_info(mst_info &info)
#define MR_FORCE_CLAMP
Definition: model.h:888
#define LAB_MODE_SHIP
Definition: lab.cpp:49
matrix * vm_angles_2_matrix(matrix *m, const angles *a)
Definition: vecmat.cpp:752
#define WIF_HUGE
Definition: weapon.h:64
#define SIF_HAS_AWACS
Definition: ship.h:906
void vm_rotate_matrix_by_angles(matrix *orient, const angles *tangles)
Definition: vecmat.cpp:1338
#define gr_restore_screen
Definition: 2d.h:826
thrust_pair thruster_glow_info
Definition: ship.h:1381
void labviewer_close_desc_window(GUIObject *caller)
Definition: lab.cpp:1992
float thruster_glow_noise_mult
Definition: ship.h:1392
int class_type
Definition: ship.h:1167
#define SIF_CRUISER
Definition: ship.h:887
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
Assert(pm!=NULL)
int distortion_bitmap
Definition: model.h:1295
#define KEY_1
Definition: key.h:72
#define MR_NO_POLYS
Definition: model.h:866
Definition: pstypes.h:88
submodel_instance_info submodel_info_2
Definition: ship.h:369
#define gr_set_clear_color
Definition: 2d.h:850
void light_add_point(const vec3d *pos, float r1, float r2, float intensity, float r, float g, float b, int light_ignore_objnum, float spec_r, float spec_g, float spec_b, bool specular)
Definition: lighting.cpp:253
int shockwave_count
Definition: ship.h:1246
uint key_get_shift_status()
Definition: key.cpp:532
w_bank * gun_banks
Definition: model.h:772
__inline void gr_string(int x, int y, const char *string, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:769
char * Pilot_squad_image_names[MAX_PILOT_IMAGES]
Definition: managepilot.cpp:47
const float MAX_ARC_LENGTH_PERCENTAGE
Definition: shipfx.cpp:2413
Definition: 2d.h:95
matrix Eye_matrix
Definition: 3dsetup.cpp:26
int Cmdline_spec
Definition: cmdline.cpp:329
int OnFrame(float frametime, bool doevents, bool clearandflip)
Definition: wmcgui.cpp:601
#define WIF2_MR_NO_LIGHTING
Definition: weapon.h:92
float laser_head_radius
Definition: weapon.h:352
#define MR_DEBUG_SHIELDS
Definition: model.h:929
float total_time
Definition: generic.h:27
int flag
Definition: lab.cpp:1393
#define SIF_CARGO
Definition: ship.h:884
void labviewer_change_detail_texture(Tree *caller)
Definition: lab.cpp:1885
void set_flags(uint flags)
#define MARC_TYPE_NORMAL
Definition: model.h:252
#define MR_NO_LIGHTING
Definition: model.h:867
struct vec3d::@225::@227 xyz
int center_h
Definition: 2d.h:363
#define TMAP_HTL_3D_UNLIT
Definition: tmapper.h:63
int Num_weapon_subtypes
Definition: weapons.cpp:92
void model_render_immediate(model_render_params *render_info, int model_num, matrix *orient, vec3d *pos, int render, bool sort)
short swarm_count
Definition: weapon.h:398
struct lab_flag lab_flag
void labviewer_add_model_thrusters(model_render_params *render_info, ship_info *sip)
Definition: lab.cpp:539
char external_model_name[MAX_FILENAME_LEN]
Definition: weapon.h:330
float tertiary_glow_rad_factor
Definition: model.h:1304
GLclampf f
Definition: Glext.h:7097
float damp
Definition: ship.h:1193
GUIObject * Add(GUIObject *new_gauge)
Definition: wmcgui.cpp:424
void labviewer_make_variables_window(Button *caller)
Definition: lab.cpp:1860
#define WIF2_EXTERNAL_WEAPON_LNCH
Definition: weapon.h:109
float thruster_glow_factor
Definition: weapon.h:539
int bm_load_duplicate(const char *filename)
Reloads a bitmap as a duplicate.
Definition: bmpman.cpp:1668
int center_offset_y
Definition: 2d.h:364
float afterburner_fuel_capacity
Definition: ship.h:1283
#define SIF_BIG_DAMAGE
Definition: ship.h:905
Definition: 2d.h:82
#define VAR_POS_LEFTWIDTH
Definition: lab.cpp:1580
float factor
Definition: lua.cpp:440
void model_add_arc(int model_num, int sub_model_num, vec3d *v1, vec3d *v2, int arc_type)
Definition: modelread.cpp:5003
#define MR_SHOW_OUTLINE
Definition: model.h:859
void labviewer_close_variables_window(GUIObject *caller)
Definition: lab.cpp:1591
void labviewer_render_model(float frametime)
Definition: lab.cpp:714
#define LAB_FLAG_SUBMODEL_ROTATE
Definition: lab.cpp:40
void set_detail_level_lock(int detail_level_lock)
void submodel_stepped_rotate(model_subsystem *psub, submodel_instance_info *sii)
Definition: modelread.cpp:3474
GLenum mode
Definition: Glext.h:5794
void labviewer_change_ship_lod(Tree *caller)
Definition: lab.cpp:2160
int center_w
Definition: 2d.h:363
Definition: model.h:432
float max_speed
Definition: weapon.h:354
void set_insignia_bitmap(int bitmap)
int bitmap_id
Definition: generic.h:53
bool Shadow_override
Definition: systemvars.cpp:80
int mouse_get_pos(int *xpos, int *ypos)
Definition: mouse.cpp:512
void gr_set_color_fast(color *dst)
Definition: 2d.cpp:1197
#define MR_DEBUG_BAY_PATHS
Definition: model.h:930
#define LAB_FLAG_DESTROYED_SUBSYSTEMS
Definition: lab.cpp:45
int primary_bank_weapons[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:1294
ubyte blue
Definition: 2d.h:102
#define WIF_HOMING_ASPECT
Definition: weapon.h:45
float weapon_range
Definition: weapon.h:390
#define LAB_MODE_NONE
Definition: lab.cpp:48
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
Definition: vmallocator.h:21
int key
bool PostProcessing_override
Definition: systemvars.cpp:78
generic_anim afterburn
Definition: species_defs.h:31
#define MODEL_RENDER_TRANS
Definition: model.h:934
#define gr_scene_texture_begin
Definition: 2d.h:910
void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha)
Definition: 2d.cpp:2105
GLfloat GLfloat GLfloat v2
Definition: Glext.h:5640
int subtype
Definition: weapon.h:326
#define Int3()
Definition: pstypes.h:292
#define MODEL_RENDER_OPAQUE
Definition: model.h:933
float density
Definition: ship.h:1192
void labviewer_update_desc_window()
Definition: lab.cpp:1998
float Noise[NOISE_NUM_FRAMES]
Definition: systemvars.cpp:83
void labviewer_make_ship_window(Button *caller)
Definition: lab.cpp:2042
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
float subsystem_factor
Definition: weapon.h:378
#define GR_RESIZE_NONE
Definition: 2d.h:681
#define SIF_GAS_MINER
Definition: ship.h:909
int bm_release(int handle, int clear_render_targets)
Frees both a bitmap's data and it's associated slot.
Definition: bmpman.cpp:2603
#define gr_end_proj_matrix
Definition: 2d.h:894
GUISystem GUI_system
Definition: wmcgui.cpp:21
bool Teamcolor_override
Definition: systemvars.cpp:79
vec3d pnt[MAX_SLOTS]
Definition: model.h:434
#define WP_BEAM
Definition: weapon.h:29
GLenum type
Definition: Gl.h:1492
#define SIF2_FLASH
Definition: ship.h:920
float thruster03_glow_rad_factor
Definition: ship.h:1388
float laser_length
Definition: weapon.h:349
#define CLAMP(x, min, max)
Definition: pstypes.h:488
void labviewer_make_flags_window(Button *caller)
Definition: lab.cpp:1558
float laser_tail_radius
Definition: weapon.h:352
void shadows_end_render()
Definition: shadows.cpp:386
#define WIF2_TRANSPARENT
Definition: weapon.h:93
ubyte green
Definition: 2d.h:101
float lifetime
Definition: weapon.h:382
void g3_done_instance(bool set_api=false)
Definition: 3dsetup.cpp:341
bool HasChildren()
Definition: wmcgui.h:501
int species
Definition: ship.h:1166
const float weapon_glow_scale_r
Definition: weapons.cpp:3621
void ClearAllItems()
Definition: wmcgui.cpp:1683
int Cmdline_env
Definition: cmdline.cpp:323
int mouse_down(int btn)
Definition: mouse.cpp:315
#define WRT_POF
Definition: weapon.h:35
#define SIF_CAPITAL
Definition: ship.h:889
#define ADD_RENDER_FLAG(text, flag, var)
Definition: lab.cpp:1898
#define gr_set_view_matrix
Definition: 2d.h:895
#define SIF_BOMBER
Definition: ship.h:886
thrust_info thruster_info
Definition: species_defs.h:60
int num_frames
Definition: generic.h:20
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
#define gr_reset_clip
Definition: 2d.h:745
matrix shadows_start_render(matrix *eye_orient, vec3d *eye_pos, float fov, float aspect, float veryneardist, float neardist, float middist, float fardist)
Definition: shadows.cpp:349
int Cmdline_height
Definition: cmdline.cpp:332
void set_debug_flags(uint flags)
void batch_render_all(int stream_buffer)
Definition: grbatch.cpp:1124
void ship_page_out_textures(int ship_index, bool release)
Definition: ship.cpp:16711
int Cmdline_nohtl
Definition: cmdline.cpp:438
#define GR_ALPHABLEND_FILTER
Definition: 2d.h:349
const float PI2
Definition: pstypes.h:305
int GetWidth()
Definition: wmcgui.h:294
#define gr_set_proj_matrix
Definition: 2d.h:893
int GetKeyPressed()
Definition: wmcgui.h:374
int cmeasure_max
Definition: ship.h:1291
#define SIF2_NO_THRUSTER_GEO_NOISE
Definition: ship.h:926
#define KEY_9
Definition: key.h:80
void weapon_pause_sounds()
Definition: weapons.cpp:7248
#define SIF_BIG_SHIP
Definition: ship.h:944
#define MAX_SHIP_WEAPONS
Definition: globals.h:64
struct matrix::@228::@230 vec
#define SIF_NAVBUOY
Definition: ship.h:891
unsigned int uint
Definition: pstypes.h:64
void lab_close()
Definition: lab.cpp:2624
float mass
Definition: weapon.h:358
int subtype
Definition: lua.cpp:9763
void vm_vec_scale(vec3d *dest, float s)
Definition: vecmat.cpp:248
#define MR_NO_ZBUFFER
Definition: model.h:878
float Framerate
Definition: freespace.cpp:2081
float thruster_dist_rad_factor
Definition: ship.h:1390
void labviewer_exit(Button *caller)
Definition: lab.cpp:1338
bool use_ab
Definition: model.h:1297
bool GLSL_override
Definition: systemvars.cpp:77
detail_levels Detail
Definition: systemvars.cpp:478
int first_frame
Definition: generic.h:19
bool second
Definition: lab.cpp:1394
int GetHeight()
Definition: wmcgui.h:295
void gr_opengl_deferred_lighting_finish()
float glow_noise
Definition: model.h:1298
#define WIF_IN_TECH_DATABASE
Definition: weapon.h:67
void gr_opengl_deferred_lighting_end()
void labviewer_variables_clear()
Definition: lab.cpp:1598
float clip_aspect
Definition: 2d.h:372
#define MR_NO_TEXTURING
Definition: model.h:868
GLboolean GLboolean GLboolean GLboolean a
Definition: Glext.h:5781
#define gr_save_screen
Definition: 2d.h:825
float g3_draw_laser(const vec3d *headp, float head_width, const vec3d *tailp, float tail_width, uint tmap_flags=TMAP_FLAG_TEXTURED, float max_len=0.0f)
Definition: 3dlaser.cpp:116
int flags
Definition: ship.h:1227
void g3_set_view_matrix(const vec3d *view_pos, const matrix *view_matrix, float zoom)
Definition: 3dsetup.cpp:152
ai_profile_t * ai_profile
Definition: missionparse.h:168
#define MSS_FLAG_ROTATES
Definition: model.h:106
void model_clear_instance(int model_num)
Definition: modelread.cpp:4624
int Cmdline_normal
Definition: cmdline.cpp:331
#define LAB_FLAG_SHOW_DEBRIS
Definition: lab.cpp:39
void labviewer_populate_flags_window()
Definition: lab.cpp:1439
int damage_type_idx
Definition: weapon.h:519
vec3d rotvel
Definition: model.h:1299
#define T_EDITTABLE
Definition: wmcgui.h:541
void labviewer_setup_subsys_rotation()
Definition: lab.cpp:130
#define KEY_SHIFTED
Definition: key.h:62
int explosion_propagates
Definition: ship.h:1238
generic_anim thruster_glow
Definition: weapon.h:538
bool Specmap_override
Definition: systemvars.cpp:72
float WeaponMinRange
Definition: weapon.h:513
#define SIF_SHIP_CLASS_DONT_COLLIDE_INVIS
Definition: ship.h:903
float Max_draw_distance
Definition: 2d.cpp:85
ai_profile_t Ai_profiles[MAX_AI_PROFILES]
Definition: ai_profiles.cpp:22
#define WRT_LASER
Definition: weapon.h:34
#define w(p)
Definition: modelsinc.h:68
int Cmdline_glow
Definition: cmdline.cpp:326
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
bool Heightmap_override
Definition: systemvars.cpp:74
void set_team_color(team_color &clr)
void labviewer_variables_add(int *Y, char *var_name)
Definition: lab.cpp:1607
void labviewer_make_weap_window(Button *caller)
Definition: lab.cpp:2277
SCP_string default_team_name
Definition: ship.h:1366
void gr_shade(int x, int y, int w, int h, int resize_mode)
Definition: 2d.cpp:2085
void labviewer_flags_clear()
Definition: lab.cpp:1399
const char * bm_get_filename(int handle)
Gets the filename of the bitmap indexed by handle, which must exist.
Definition: bmpman.cpp:727
#define VAR_POS_RIGHTX
Definition: lab.cpp:1582
int n_subsystems
Definition: ship.h:1270
ubyte red
Definition: 2d.h:100
#define SIF_SENTRYGUN
Definition: ship.h:892
#define SUBSYSTEM_TURRET
Definition: model.h:54
#define GST_MOUSE_RIGHT_BUTTON
Definition: wmcgui.h:187
#define KEY_N
Definition: key.h:95
float distortion_length_factor
Definition: model.h:1307
generic_anim normal
Definition: species_defs.h:30
Definition: wmcgui.h:509
int hardware_textures
Definition: systemvars.h:169
bool draw_distortion
Definition: model.h:1308
#define LAB_FLAG_INITIAL_ROTATION
Definition: lab.cpp:44
float max_shield_strength
Definition: ship.h:1310
AFTERBURNER.
#define WIF_PARTICLE_SPEW
Definition: weapon.h:72
int primary_glow_bitmap
Definition: model.h:1292
#define LAB_MODE_WEAPON
Definition: lab.cpp:50
vec3d closeup_pos
Definition: ship.h:1327
void labviewer_change_model(char *model_fname, int lod=0, int sel_index=-1)
Definition: lab.cpp:212
vec3d offset
Definition: model.h:330
float fov
Definition: weapon.h:407
#define MR_DEBUG_PIVOTS
Definition: model.h:926
int flags2
Definition: ship.h:1228
#define SIF_BALLISTIC_PRIMARIES
Definition: ship.h:880
generic_bitmap afterburn
Definition: species_defs.h:25
int model_load(char *filename, int n_subsystems, model_subsystem *subsystems, int ferror=1, int duplicate=0)
Definition: modelread.cpp:2573
int num_slots
Definition: model.h:433
void SetText(const SCP_string &in_content)
Definition: wmcgui.cpp:2110
#define MR_DEBUG_PATHS
Definition: model.h:927
void submodel_rotate(model_subsystem *psub, submodel_instance_info *sii)
Definition: modelread.cpp:3688
#define WS_NOTITLEBAR
Definition: wmcgui.h:383
void model_page_in_textures(int modelnum, int ship_info_index=-1)
#define SIF_DEFAULT_PLAYER_SHIP
Definition: ship.h:876
void set_color(color &clr)
int idx
Definition: multiui.cpp:761
char * Weapon_subtype_names[]
Definition: weapons.cpp:87
#define KEY_7
Definition: key.h:78
#define KEY_T
Definition: key.h:101
generic_anim laser_glow_bitmap
Definition: weapon.h:347
#define SIF_IN_TECH_DATABASE
Definition: ship.h:897
int Cmdline_bloom_intensity
Definition: cmdline.cpp:336
void SetCloseFunction(void(*in_closefunc)(GUIObject *caller))
Definition: wmcgui.h:291
vec3d * vm_vec_unrotate(vec3d *dest, const vec3d *src, const matrix *m)
Definition: vecmat.cpp:959
Checkbox * cb
Definition: lab.cpp:1392
void mouse_get_delta(int *dx, int *dy, int *dz)
Definition: mouse.cpp:358
#define KEY_DIVIDE
Definition: key.h:111
void labviewer_close_render_options_window(GUIObject *caller)
Definition: lab.cpp:1893
char name[NAME_LENGTH]
Definition: ship.h:1163
int Cmdline_shadow_quality
Definition: cmdline.cpp:344
GLint GLint GLint GLint GLint x
Definition: Glext.h:5182
#define SIF_STEALTH
Definition: ship.h:900
void submodel_get_two_random_points(int model_num, int submodel_num, vec3d *v1, vec3d *v2, vec3d *n1=NULL, vec3d *n2=NULL)
GLclampd n
Definition: Glext.h:7286
#define MR_SHOW_THRUSTERS
Definition: model.h:864
unsigned char ubyte
Definition: pstypes.h:62
TreeItem * AddItem(TreeItem *parent, const SCP_string &in_name, int in_data=0, bool in_delete_data=true, void(*in_function)(Tree *caller)=NULL)
Definition: wmcgui.cpp:1902
int wi_flags
Definition: weapon.h:384
void labviewer_set_class_window(int mode)
Definition: lab.cpp:1362
int ship_create(matrix *orient, vec3d *pos, int ship_type, char *ship_name)
Definition: ship.cpp:9690
GUIObject * AddChild(GUIObject *cgp)
Definition: wmcgui.cpp:819
#define ZERO_VECTOR
Definition: vecmat.h:60
#define SIF_DRYDOCK
Definition: ship.h:902
void vm_trackball(int idx, int idy, matrix *RotMat)
Definition: vecmat.cpp:1151
#define WIF_HOMING_HEAT
Definition: weapon.h:44
int max_w
Definition: 2d.h:360
int wi_flags2
Definition: weapon.h:385
int catchup_pixels_per_sec
Definition: weapon.h:403
int tertiary_glow_bitmap
Definition: model.h:1294
#define TMAP_FLAG_RGB
Definition: tmapper.h:39
float glow_length_factor
Definition: model.h:1305
float rad
Definition: model.h:340
GLfloat GLfloat v1
Definition: Glext.h:5639
void model_page_out_textures(int model_num, bool release=false)
float glow_rad_factor
Definition: model.h:1302
float thruster01_glow_rad_factor
Definition: ship.h:1386
int catchup_pixel_penalty
Definition: weapon.h:404
void lab_init()
Definition: lab.cpp:2381
GLbitfield flags
Definition: Glext.h:6722
int Num_weapon_types
Definition: weapons.cpp:105
color laser_color_1
Definition: weapon.h:350
#define WIF2_PIERCE_SHIELDS
Definition: weapon.h:85
#define SIF_HUGE_SHIP
Definition: ship.h:945
int GetData()
Definition: wmcgui.h:500
void labviewer_change_bitmap(int ship_index=-1, int weapon_index=-1)
Definition: lab.cpp:170
int num_secondary_banks
Definition: ship.h:1298
GLuint const GLchar * name
Definition: Glext.h:5608
#define IDENTITY_MATRIX
Definition: vecmat.h:64
void labviewer_update_variables_window()
Definition: lab.cpp:1759
#define WIF_ELECTRONICS
Definition: weapon.h:46
void labviewer_change_weapon(Tree *caller)
Definition: lab.cpp:2243
float thruster02_glow_len_factor
Definition: ship.h:1389
void vm_vec_sub(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:168
#define REVOLUTION_RATE
Definition: techmenu.cpp:37
void weapon_unpause_sounds()
Definition: weapons.cpp:7257
void labviewer_add_model_arcs()
Definition: lab.cpp:347
int primary_bitmap
Definition: model.h:1291
#define SIF_SUPPORT
Definition: ship.h:878
vec3d Eye_position
Definition: 3dsetup.cpp:27
#define VAR_SET_VALUE(value)
Definition: lab.cpp:1740
#define WIF_SHUDDER
Definition: weapon.h:78
thrust_pair glow
Definition: species_defs.h:36
#define SIF_FREIGHTER
Definition: ship.h:888
GLboolean GLboolean GLboolean b
Definition: Glext.h:5781
thrust_pair thruster_flame_info
Definition: ship.h:1380
#define SIF_ESCAPEPOD
Definition: ship.h:893
#define KEY_B
Definition: key.h:83
#define MOUSE_RIGHT_BUTTON
Definition: mouse.h:44
typedef float(SCP_EXT_CALLCONV *SCPTRACKIR_PFFLOATVOID)()
float warpin_speed
Definition: ship.h:1210
#define WIF_PLAYER_ALLOWED
Definition: weapon.h:68
void pilot_load_squad_pic_list()
void gr_opengl_deferred_lighting_begin()
float power_output
Definition: ship.h:1274
int Num_pilot_squad_images
Definition: managepilot.cpp:48
void obj_delete(int objnum)
Definition: object.cpp:522
color Color_white
Definition: alphacolors.cpp:32
#define KEY_ESC
Definition: key.h:124
float frand()
Return random value in range 0.0..1.0- (1.0- means the closest number less than 1.0)
Definition: floating.cpp:35
int num_debris_objects
Definition: model.h:741
float rad
Definition: model.h:757
int n_models
Definition: model.h:744
void submodel_get_two_random_points_better(int model_num, int submodel_num, vec3d *v1, vec3d *v2)
int Default_ai_profile
Definition: ai_profiles.cpp:21
#define fl2i(fl)
Definition: floating.h:33
void labviewer_close_weap_window(GUIObject *caller)
bool Envmap_override
Definition: systemvars.cpp:71
#define SIF_SHIP_COPY
Definition: ship.h:896
#define KEY_4
Definition: key.h:75
#define g3_end_frame()
Definition: 3d.h:49
screen gr_screen
Definition: 2d.cpp:46
void gr_get_string_size(int *w, int *h, const char *text, int len=9999)
Definition: font.cpp:196
#define WIF_BEAM
Definition: weapon.h:76
void model_set_instance_info(submodel_instance_info *sii, float turn_rate, float turn_accel)
Definition: modelread.cpp:4708
#define MAX_SHIP_ARCS
Definition: ship.h:517
void labviewer_populate_variables_window()
Definition: lab.cpp:1630
#define MARC_TYPE_EMP
Definition: model.h:253
SCP_vector< SCP_string > Hud_shield_filenames
Definition: hudshield.cpp:41
#define WIF_ENERGY_SUCK
Definition: weapon.h:74
float model_get_radius(int modelnum)
Definition: modelread.cpp:3105
#define WIF_SUPERCAP
Definition: weapon.h:50
int gr_get_font_height()
Definition: font.cpp:187
#define LAB_FLAG_SHOW_WEAPONS
Definition: lab.cpp:43
void light_reset()
Definition: lighting.cpp:150
int center_offset_x
Definition: 2d.h:364
bool Normalmap_override
Definition: systemvars.cpp:73
void ClearContent()
Definition: wmcgui.cpp:1535
SCP_vector< ship_info > Ship_info
Definition: ship.cpp:164
#define LOCATION
Definition: pstypes.h:245
#define SIF_KNOSSOS_DEVICE
Definition: ship.h:912
#define SIF_TRANSPORT
Definition: ship.h:890
float shield_factor
Definition: weapon.h:378
#define MR_FULL_DETAIL
Definition: model.h:887
int max_h
Definition: 2d.h:360
vec3d length
Definition: model.h:1300
#define SIF_AWACS
Definition: ship.h:910
#define LAB_FLAG_NO_ROTATION
Definition: lab.cpp:37
#define SIF_FIGHTER
Definition: ship.h:885
void g3_start_instance_matrix(const vec3d *pos, const matrix *orient, bool set_api=true)
Definition: 3dsetup.cpp:249
#define TMAP_FLAG_TEXTURED
Definition: tmapper.h:36
#define timestamp_elapsed(stamp)
Definition: timer.h:102
SCP_vector< species_info > Species_info
#define LAB_FLAG_LIGHTNING_ARCS
Definition: lab.cpp:41
MINUS_5_PERCENT_THROTTLE.
const float weapon_glow_scale_l
Definition: weapons.cpp:3622
void labviewer_show_tech_model(Tree *caller)
Definition: lab.cpp:2226
#define LAB_FLAG_SHOW_INSIGNIA
Definition: lab.cpp:38
int is_thruster
Definition: model.h:355
#define WIF_PUNCTURE
Definition: weapon.h:49
#define gr_copy_effect_texture
Definition: 2d.h:912
int secondary_glow_bitmap
Definition: model.h:1293
#define MR_DEBUG_RADIUS
Definition: model.h:928
float thruster_dist_len_factor
Definition: ship.h:1391
int check_control(int id, int key)
#define gr_free_screen
Definition: 2d.h:827
void light_set_all_relevent()
Definition: lighting.cpp:644
int Cmdline_fxaa_preset
Definition: cmdline.cpp:338
#define VAR_SET_VALUE_SAVE(value, max_size)
Definition: lab.cpp:1746
bool draw_secondary_models[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:1303
void SetCaption(const SCP_string &in_caption)
Definition: wmcgui.h:433
#define GSOF_NOTHINGPRESSED
Definition: wmcgui.h:299
#define timestamp_rand(a, b)
Definition: timer.h:92
#define GR_BITBLT_MODE_NORMAL
Definition: 2d.h:351
float frametotal
Definition: freespace.cpp:246
float secondary_glow_rad_factor
Definition: model.h:1303
TreeItem * GetSelectedItem()
Definition: wmcgui.h:536
SCP_string Lab_team_color
Definition: lab.cpp:119
bool is_minimum_GLSL_version()
Definition: gropengl.cpp:2064
#define WIF2_BALLISTIC
Definition: weapon.h:84
polymodel * pm
Definition: lua.cpp:1598
int Cmdline_postprocess
Definition: cmdline.cpp:335
void gr_create_shader(shader *shade, ubyte r, ubyte g, ubyte b, ubyte c)
Definition: 2d.cpp:1211
float subsys_repair_rate
Definition: ship.h:1321
#define MSS_FLAG_STEPPED_ROTATE
Definition: model.h:107
float closeup_zoom
Definition: ship.h:1328
SCP_map< SCP_string, team_color > Team_Colors
Definition: alphacolors.cpp:15
void labviewer_show_external_model(Tree *caller)
Definition: lab.cpp:2234
Definition: wmcgui.h:449
void batch_render_distortion_map_bitmaps(int buffer_handle)
Definition: grbatch.cpp:1245
float max_hull_strength
Definition: ship.h:1309
void labviewer_flags_add(int *X, int *Y, char *flag_name, int flag, bool flags2=false)
Definition: lab.cpp:1408
void _cdecl gr_printf_no_resize(int x, int y, const char *format,...)
Definition: font.cpp:342
mission The_mission
float rotdamp
Definition: ship.h:1194
void labviewer_close_class_window(GUIObject *caller)
Definition: lab.cpp:1347
GLint lod
Definition: Glext.h:7352
float h
Definition: pstypes.h:111
#define MAX_DETAIL_LEVEL
Definition: systemvars.h:159
int model_num
Definition: lua.cpp:4996
void set_object_number(int num)
vec3d vmd_zero_vector
Definition: vecmat.cpp:24
vec3d max_vel
Definition: ship.h:1196
float distortion_rad_factor
Definition: model.h:1306
shockwave_create_info shockwave
Definition: weapon.h:367
#define MR_NO_GLOWMAPS
Definition: model.h:886
float damage
Definition: weapon.h:363
color laser_color_2
Definition: weapon.h:351
void gr_set_shader(shader *shade)
Definition: 2d.cpp:1220
bool Cmdline_fxaa
Definition: cmdline.cpp:337
float afterburner_recover_rate
Definition: ship.h:1285
#define KEY_2
Definition: key.h:73
float armor_factor
Definition: weapon.h:378
int timer_get_milliseconds()
Definition: timer.cpp:150
void gameseq_post_event(int event)
#define MR_NO_FOGGING
Definition: model.h:884
void gr_init_color(color *c, int r, int g, int b)
Definition: 2d.cpp:1155
void labviewer_render_bitmap(float frametime)
Definition: lab.cpp:1087
void labviewer_close_flags_window(GUIObject *caller)
Definition: lab.cpp:1551
matrix vmd_identity_matrix
Definition: vecmat.cpp:28
#define timestamp_valid(stamp)
Definition: timer.h:104
float turn_time
Definition: weapon.h:387
float afterburner_burn_rate
Definition: ship.h:1284
generic_anim thruster_flame
Definition: weapon.h:537
thrust_pair_bitmap thruster_distortion_info
Definition: ship.h:1384
void light_rotate_all()
Definition: lighting.cpp:585
const GLubyte * c
Definition: Glext.h:8376
int myrand()
Definition: systemvars.cpp:102
float thruster02_glow_rad_factor
Definition: ship.h:1387
SCP_vector< ship_type_info > Ship_types
Definition: ship.cpp:168
void labviewer_make_render_options_window(Button *caller)
Definition: lab.cpp:1910
const int weapon_glow_alpha
Definition: weapons.cpp:3623
const float weapon_glow_scale_f
Definition: weapons.cpp:3620
bool draw_distortion
Definition: ship.h:1394
float b
Definition: pstypes.h:111
#define SIF_CORVETTE
Definition: ship.h:908
GLint y
Definition: Gl.h:1505
void model_unload(int modelnum, int force=0)
Definition: modelread.cpp:162
PLUS_5_PERCENT_THROTTLE.
#define KEY_L
Definition: key.h:93
#define WS_NONMOVEABLE
Definition: wmcgui.h:384
float hull_repair_rate
Definition: ship.h:1320
int num_primary_banks
Definition: ship.h:1293
#define g3_start_frame(zbuffer_flag)
Definition: 3d.h:39
GLfloat GLfloat GLfloat GLfloat v3
Definition: Glext.h:5641
void labviewer_do_render(float frametime)
Definition: lab.cpp:1264
TreeItem * GetParentItem()
Definition: wmcgui.h:499
float vm_vec_normalize(vec3d *v)
Definition: vecmat.cpp:460
#define strcpy_s(...)
Definition: safe_strings.h:67
#define VAR_ADD_HEADER(name)
Definition: lab.cpp:1584
#define KEY_3
Definition: key.h:74
#define MR_AUTOCENTER
Definition: model.h:875