mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-10 17:46:53 -10:00
If the object number is set for the render info the renderer uses the instance information of that object to render the model. That is not correct for the lab since the instance data is handled by the lab code in that case. This fixes #643.
2737 lines
80 KiB
C++
2737 lines
80 KiB
C++
/*
|
|
* lab.cpp
|
|
* created by WMCoolmon
|
|
*
|
|
* You may not sell or otherwise commercially exploit the source or things you
|
|
* create based on the source.
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
#include "cmdline/cmdline.h"
|
|
#include "freespace.h"
|
|
#include "gamesequence/gamesequence.h"
|
|
#include "graphics/opengl/gropengldraw.h"
|
|
#include "graphics/opengl/gropengllight.h"
|
|
#include "graphics/opengl/gropenglshader.h"
|
|
#include "graphics/shadows.h"
|
|
#include "hud/hudshield.h"
|
|
#include "io/key.h"
|
|
#include "io/timer.h"
|
|
#include "lab/wmcgui.h"
|
|
#include "lighting/lighting.h"
|
|
#include "mission/missionparse.h"
|
|
#include "missionui/missionscreencommon.h"
|
|
#include "model/model.h"
|
|
#include "object/objectsnd.h"
|
|
#include "playerman/managepilot.h"
|
|
#include "render/3d.h"
|
|
#include "render/batching.h"
|
|
#include "ship/ship.h"
|
|
#include "species_defs/species_defs.h"
|
|
#include "weapon/beam.h"
|
|
#include "weapon/weapon.h"
|
|
|
|
// flags
|
|
#define LAB_FLAG_NORMAL (0) // default
|
|
#define LAB_FLAG_NO_ROTATION (1<<0) // don't rotate models
|
|
#define LAB_FLAG_SHOW_INSIGNIA (1<<1) // show ships with insignia applied
|
|
#define LAB_FLAG_SHOW_DEBRIS (1<<2) // render debris instead of normal LOD
|
|
#define LAB_FLAG_SUBMODEL_ROTATE (1<<3) // do rotation for any rotating ship subobjects
|
|
#define LAB_FLAG_LIGHTNING_ARCS (1<<4) // show damage lightning
|
|
#define LAB_FLAG_UNUSED (1<<5) // feel free to change that to something you need - Valathil
|
|
#define LAB_FLAG_SHOW_WEAPONS (1<<6) // determines if external weapons models are displayed
|
|
#define LAB_FLAG_INITIAL_ROTATION (1<<7) // initial rotation setting
|
|
#define LAB_FLAG_DESTROYED_SUBSYSTEMS (1<<8) // render model as if all subsystems are destroyed
|
|
|
|
// modes
|
|
#define LAB_MODE_NONE 0 // not showing anything
|
|
#define LAB_MODE_SHIP 1 // dealing with ships
|
|
#define LAB_MODE_WEAPON 2 // dealing with weapons
|
|
|
|
|
|
// variables
|
|
static GUIScreen *Lab_screen = NULL;
|
|
static Window *Lab_toolbar = NULL;
|
|
static Window *Lab_class_window = NULL;
|
|
static Window *Lab_class_toolbar = NULL;
|
|
static Window *Lab_flags_window = NULL;
|
|
static Window *Lab_render_options_window = NULL;
|
|
static Window *Lab_material_override_window = NULL;
|
|
static Window *Lab_variables_window = NULL;
|
|
static Window *Lab_description_window = NULL;
|
|
static Text *Lab_description_text = NULL;
|
|
static TreeItem **Lab_species_nodes = NULL;
|
|
|
|
static bool Lab_in_mission = false;
|
|
static int Lab_screen_save_bitmap = -1;
|
|
static shader Lab_shader;
|
|
|
|
static int Lab_insignia_bitmap = -1;
|
|
static int Lab_insignia_index = -1;
|
|
|
|
static ubyte Lab_mode = LAB_MODE_NONE;
|
|
static int Lab_selected_index = -1;
|
|
static int Lab_last_selected_ship = -1;
|
|
static int Lab_selected_object = -1;
|
|
static int Lab_last_selected_weapon = -1;
|
|
|
|
static int Lab_model_num = -1;
|
|
static int Lab_weaponmodel_num[MAX_SHIP_WEAPONS];
|
|
static int Lab_model_LOD = 0;
|
|
static int Lab_model_flags = MR_AUTOCENTER | MR_NO_FOGGING;
|
|
static int Lab_model_debug_flags = 0;
|
|
static char Lab_model_filename[MAX_FILENAME_LEN];
|
|
static char Lab_weaponmodel_filename[MAX_SHIP_WEAPONS][MAX_FILENAME_LEN];
|
|
|
|
static int Lab_bitmap_id = -1;
|
|
static char Lab_bitmap_filename[MAX_FILENAME_LEN];
|
|
|
|
static float Lab_viewer_zoom = 1.2f;
|
|
static vec3d Lab_viewer_pos = ZERO_VECTOR;
|
|
static matrix Lab_viewer_orient = IDENTITY_MATRIX;
|
|
static float Lab_viewer_rotation = 0.0f;
|
|
static int Lab_viewer_flags = LAB_MODE_NONE;
|
|
|
|
static ship_subsys *Lab_ship_subsys = NULL;
|
|
static SCP_vector<model_subsystem> Lab_ship_model_subsys;
|
|
|
|
static int Lab_detail_texture_save = 0;
|
|
|
|
static int anim_timer_start = 0;
|
|
|
|
// damage lightning stuff
|
|
static vec3d Lab_arc_pts[MAX_SHIP_ARCS][2];
|
|
static int Lab_arc_timestamp[MAX_SHIP_ARCS];
|
|
static ubyte Lab_arc_type[MAX_SHIP_ARCS];
|
|
static int Lab_arc_next_time = -1;
|
|
static bool Lab_arc_disrupted = false;
|
|
|
|
static float Lab_thrust_len = 1.0f;
|
|
static bool Lab_thrust_afterburn = false;
|
|
|
|
// Trackball_mode:
|
|
// 1 == rotate (left-mouse)
|
|
// 2 == pan (shift-left-mouse)
|
|
// 3 == zoom (right-mouse)
|
|
static int Trackball_mode = 1;
|
|
static int Trackball_active = 0;
|
|
|
|
SCP_string Lab_team_color = "<none>";
|
|
|
|
// functions
|
|
void labviewer_change_ship_lod(Tree *caller);
|
|
void labviewer_change_ship(Tree *caller);
|
|
void labviewer_make_desc_window(Button *caller);
|
|
void labviewer_close_weap_window(GUIObject *caller);
|
|
void labviewer_update_flags_window();
|
|
|
|
|
|
// ---------------------- General/Utility Functions ----------------------------
|
|
void labviewer_setup_subsys_rotation()
|
|
{
|
|
if (Lab_ship_subsys != NULL) {
|
|
delete[] Lab_ship_subsys;
|
|
Lab_ship_subsys = NULL;
|
|
}
|
|
|
|
Lab_ship_model_subsys.clear();
|
|
|
|
// whole lot of of get-outs
|
|
if (Lab_mode != LAB_MODE_SHIP) {
|
|
return;
|
|
}
|
|
|
|
if (Lab_selected_index < 0) {
|
|
return;
|
|
}
|
|
|
|
if (Lab_selected_index >= static_cast<int>(Ship_info.size())) {
|
|
Int3();
|
|
return;
|
|
}
|
|
|
|
if (Ship_info[Lab_selected_index].n_subsystems <= 0) {
|
|
return;
|
|
}
|
|
|
|
|
|
uint n_subsystems = Ship_info[Lab_selected_index].n_subsystems;
|
|
|
|
Lab_ship_subsys = new ship_subsys[n_subsystems];
|
|
for (uint i = 0; i < n_subsystems; i++)
|
|
Lab_ship_subsys[i].clear();
|
|
|
|
Lab_ship_model_subsys.reserve(n_subsystems);
|
|
for (uint idx = 0; idx < n_subsystems; idx++) {
|
|
Lab_ship_model_subsys.push_back( Ship_info[Lab_selected_index].subsystems[idx] );
|
|
}
|
|
}
|
|
|
|
void labviewer_change_bitmap(int ship_index = -1, int weapon_index = -1)
|
|
{
|
|
if ( (ship_index < 0) && (weapon_index < 0) ) {
|
|
if (Lab_bitmap_id >= 0) {
|
|
bm_release(Lab_bitmap_id);
|
|
if (Lab_last_selected_weapon >= 0) {
|
|
Weapon_info[Lab_last_selected_weapon].laser_bitmap.first_frame = -1;
|
|
}
|
|
Lab_bitmap_id = -1;
|
|
Lab_last_selected_weapon = -1;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if ( !Lab_in_mission ) {
|
|
if (ship_index >= 0) {
|
|
// TODO: Ship stuff!!
|
|
} else if (weapon_index >= 0) {
|
|
// release old bitmap if required
|
|
if ( (Lab_last_selected_weapon >= 0) && (Lab_last_selected_weapon != weapon_index)) {
|
|
Weapon_info[Lab_last_selected_weapon].laser_bitmap.first_frame = -1;
|
|
if (Lab_bitmap_id >= 0) {
|
|
bm_release(Lab_bitmap_id);
|
|
}
|
|
}
|
|
// load up the weapon bitmaps
|
|
extern void weapon_load_bitmaps(int);
|
|
weapon_load_bitmaps(weapon_index);
|
|
Lab_bitmap_id = Weapon_info[weapon_index].laser_bitmap.first_frame;
|
|
}
|
|
}
|
|
|
|
if (Lab_bitmap_id >= 0) {
|
|
bm_get_filename(Lab_bitmap_id, Lab_bitmap_filename);
|
|
} else {
|
|
memset( Lab_bitmap_filename, 0, sizeof(Lab_bitmap_filename) );
|
|
}
|
|
|
|
labviewer_update_flags_window();
|
|
}
|
|
|
|
void labviewer_change_model(char *model_fname, int lod = 0, int sel_index = -1)
|
|
{
|
|
bool change_model = true;
|
|
int j,l;
|
|
ship_info *sip = NULL;
|
|
|
|
anim_timer_start = timer_get_milliseconds();
|
|
|
|
if ( (model_fname != NULL) && (Lab_mode == LAB_MODE_SHIP) ) {
|
|
if ( (Lab_selected_index >= 0) && (Lab_selected_index == sel_index) ) {
|
|
change_model = false;
|
|
}
|
|
}
|
|
|
|
Lab_selected_index = sel_index;
|
|
|
|
if (change_model) {
|
|
bool valid_ship = ( (Lab_mode == LAB_MODE_SHIP) && (sel_index >= 0) );
|
|
|
|
if (Lab_model_num != -1) {
|
|
model_page_out_textures(Lab_model_num, true);
|
|
model_unload(Lab_model_num);
|
|
Lab_model_num = -1;
|
|
|
|
for (j = 0; j < MAX_SHIP_WEAPONS; j++) {
|
|
if (Lab_weaponmodel_num[j] >= 0) {
|
|
model_page_out_textures(Lab_weaponmodel_num[j], true);
|
|
model_unload(Lab_weaponmodel_num[j]);
|
|
Lab_weaponmodel_num[j] = -1;
|
|
}
|
|
}
|
|
|
|
if (Lab_last_selected_ship >= 0) {
|
|
ship_page_out_textures(Lab_last_selected_ship, true);
|
|
}
|
|
}
|
|
|
|
labviewer_setup_subsys_rotation();
|
|
|
|
Lab_viewer_zoom = 1.2f;
|
|
|
|
if (valid_ship) {
|
|
memcpy( &Lab_viewer_pos, &Ship_info[sel_index].closeup_pos, sizeof(vec3d) );
|
|
} else {
|
|
Lab_viewer_pos.xyz.x = Lab_viewer_pos.xyz.y = 0.0f;
|
|
}
|
|
|
|
// only load a new model if we are supposed to (so that we can use this function to reset states)
|
|
if (model_fname != NULL) {
|
|
model_subsystem *subsystems = NULL;
|
|
|
|
if ( !Lab_ship_model_subsys.empty() ) {
|
|
subsystems = &Lab_ship_model_subsys[0];
|
|
}
|
|
|
|
Lab_model_num = model_load(model_fname, (valid_ship) ? Ship_info[sel_index].n_subsystems : 0, subsystems, 0);
|
|
|
|
if (Lab_model_num >= 0) {
|
|
strcpy_s(Lab_model_filename, model_fname);
|
|
} else {
|
|
memset( Lab_model_filename, 0, sizeof(Lab_model_filename) );
|
|
}
|
|
|
|
if (valid_ship) {
|
|
if (Lab_model_num >= 0) {
|
|
model_page_in_textures(Lab_model_num, sel_index);
|
|
}
|
|
|
|
for (int idx = 0; idx < Ship_info[sel_index].n_subsystems; idx++) {
|
|
model_set_instance_info(&Lab_ship_subsys[idx].submodel_info_1, Lab_ship_model_subsys[idx].turn_rate, 0.5f);
|
|
}
|
|
}
|
|
|
|
// do the same for weapon models if necessary
|
|
if (Lab_mode == LAB_MODE_SHIP) {
|
|
sip = &Ship_info[Lab_selected_index];
|
|
l = 0;
|
|
for (j = 0; j < sip->num_primary_banks; j++) {
|
|
weapon_info *wip = &Weapon_info[sip->primary_bank_weapons[j]];
|
|
if (!sip->draw_primary_models[j])
|
|
continue;
|
|
Lab_weaponmodel_num[l] = -1;
|
|
if ( strlen(wip->external_model_name) ){
|
|
Lab_weaponmodel_num[l] = model_load(wip->external_model_name, 0, NULL);
|
|
}
|
|
if (Lab_weaponmodel_num[l] >= 0) {
|
|
strcpy_s(Lab_weaponmodel_filename[l], wip->external_model_name);
|
|
} else {
|
|
memset( Lab_weaponmodel_filename[l], 0, sizeof(Lab_weaponmodel_filename[l]) );
|
|
}
|
|
l++;
|
|
}
|
|
|
|
for (j = 0; j < sip->num_secondary_banks; j++) {
|
|
weapon_info *wip = &Weapon_info[sip->secondary_bank_weapons[j]];
|
|
if (!sip->draw_secondary_models[j])
|
|
continue;
|
|
Lab_weaponmodel_num[l] = -1;
|
|
if ( strlen(wip->external_model_name) ){
|
|
Lab_weaponmodel_num[l] = model_load(wip->external_model_name, 0, NULL);
|
|
}
|
|
if (Lab_weaponmodel_num[l] >= 0) {
|
|
strcpy_s(Lab_weaponmodel_filename[l], wip->external_model_name);
|
|
} else {
|
|
memset( Lab_weaponmodel_filename[l], 0, sizeof(Lab_weaponmodel_filename[l]) );
|
|
}
|
|
l++;
|
|
}
|
|
}
|
|
} else {
|
|
// clear out the model filename
|
|
memset( Lab_model_filename, 0, sizeof(Lab_model_filename) );
|
|
if (Lab_weaponmodel_num[0] >= 0) {
|
|
for (j = 0; j < MAX_SHIP_WEAPONS; j++) {
|
|
memset( Lab_weaponmodel_filename[j], 0, sizeof(Lab_weaponmodel_filename[j]) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (lod == 99) {
|
|
Lab_model_LOD = 0;
|
|
Lab_viewer_flags |= LAB_FLAG_SHOW_DEBRIS;
|
|
} else {
|
|
Lab_model_LOD = lod;
|
|
Lab_viewer_flags &= ~LAB_FLAG_SHOW_DEBRIS;
|
|
}
|
|
|
|
if (model_fname == NULL) {
|
|
Lab_last_selected_ship = -1;
|
|
}
|
|
|
|
labviewer_update_flags_window();
|
|
}
|
|
|
|
void labviewer_add_model_arcs()
|
|
{
|
|
int i;
|
|
float mradius = 0.0f;
|
|
const float MAX_ARC_LENGTH_PERCENTAGE = 0.25f;
|
|
|
|
if (Lab_mode != LAB_MODE_SHIP) {
|
|
return;
|
|
}
|
|
|
|
|
|
// Kill off old sparks
|
|
for (i = 0; i < MAX_SHIP_ARCS; i++) {
|
|
if ( timestamp_valid(Lab_arc_timestamp[i]) && timestamp_elapsed(Lab_arc_timestamp[i]) ) {
|
|
Lab_arc_timestamp[i] = timestamp(-1);
|
|
}
|
|
}
|
|
|
|
|
|
if ( !timestamp_valid(Lab_arc_next_time) ) {
|
|
// start the next fireball up in the next 10 seconds or so...
|
|
int freq;
|
|
|
|
if (Lab_arc_disrupted) {
|
|
freq = 150;
|
|
} else {
|
|
// 1% hull left
|
|
freq = 550;
|
|
}
|
|
|
|
// set the next arc time
|
|
Lab_arc_next_time = timestamp_rand(freq * 2, freq * 4);
|
|
}
|
|
|
|
mradius = model_get_radius(Lab_model_num);
|
|
|
|
if ( timestamp_elapsed(Lab_arc_next_time) ) {
|
|
|
|
Lab_arc_next_time = timestamp(-1); // invalid, so it gets restarted next frame
|
|
|
|
int n, n_arcs = ((rand() >> 5) % 3) + 1; // Create 1-3 sparks
|
|
|
|
vec3d v1, v2, v3, v4;
|
|
|
|
if ( Cmdline_old_collision_sys ) {
|
|
submodel_get_two_random_points(Lab_model_num, -1, &v1, &v2);
|
|
submodel_get_two_random_points(Lab_model_num, -1, &v3, &v4);
|
|
} else {
|
|
submodel_get_two_random_points_better(Lab_model_num, -1, &v1, &v2);
|
|
submodel_get_two_random_points_better(Lab_model_num, -1, &v3, &v4);
|
|
}
|
|
|
|
// For large ships, cap the length to be 25% of max radius
|
|
if (mradius > 200.0f) {
|
|
float max_dist = mradius * MAX_ARC_LENGTH_PERCENTAGE;
|
|
|
|
vec3d tmp;
|
|
float d;
|
|
|
|
// Cap arc 2->1
|
|
vm_vec_sub( &tmp, &v1, &v2 );
|
|
d = vm_vec_mag_quick( &tmp );
|
|
if ( d > max_dist ) {
|
|
vm_vec_scale_add( &v1, &v2, &tmp, max_dist / d );
|
|
}
|
|
|
|
// Cap arc 2->3
|
|
vm_vec_sub( &tmp, &v3, &v2 );
|
|
d = vm_vec_mag_quick( &tmp );
|
|
if ( d > max_dist ) {
|
|
vm_vec_scale_add( &v3, &v2, &tmp, max_dist / d );
|
|
}
|
|
|
|
|
|
// Cap arc 2->4
|
|
vm_vec_sub( &tmp, &v4, &v2 );
|
|
d = vm_vec_mag_quick( &tmp );
|
|
if ( d > max_dist ) {
|
|
vm_vec_scale_add( &v4, &v2, &tmp, max_dist / d );
|
|
}
|
|
}
|
|
|
|
n = 0;
|
|
|
|
float factor = 1.0f + 0.0025f * mradius;
|
|
int a = fl2i(factor * 100.0f);
|
|
int b = fl2i(factor * 1000.0f);
|
|
int lifetime = (myrand() % ((b) - (a) + 1)) + (a);
|
|
|
|
// Create the arc effects
|
|
for (i = 0; i < MAX_SHIP_ARCS; i++) {
|
|
if ( !timestamp_valid(Lab_arc_timestamp[i]) ) {
|
|
Lab_arc_timestamp[i] = timestamp(lifetime); // live up to a second
|
|
|
|
switch (n) {
|
|
case 0:
|
|
Lab_arc_pts[i][0] = v1;
|
|
Lab_arc_pts[i][1] = v2;
|
|
break;
|
|
|
|
case 1:
|
|
Lab_arc_pts[i][0] = v2;
|
|
Lab_arc_pts[i][1] = v3;
|
|
break;
|
|
|
|
case 2:
|
|
Lab_arc_pts[i][0] = v2;
|
|
Lab_arc_pts[i][1] = v4;
|
|
break;
|
|
|
|
default:
|
|
Int3();
|
|
}
|
|
|
|
// determine what kind of arc to create
|
|
if (Lab_arc_disrupted) {
|
|
Lab_arc_type[i] = MARC_TYPE_EMP;
|
|
} else {
|
|
Lab_arc_type[i] = MARC_TYPE_NORMAL;
|
|
}
|
|
|
|
if ( ++n == n_arcs ) {
|
|
// Don't need to create anymore
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// maybe move arc points around
|
|
for (i = 0; i < MAX_SHIP_ARCS; i++) {
|
|
if ( timestamp_valid(Lab_arc_timestamp[i]) ) {
|
|
if ( !timestamp_elapsed(Lab_arc_timestamp[i]) ) {
|
|
// Maybe move a vertex.... 20% of the time maybe?
|
|
int mr = myrand();
|
|
|
|
if ( mr < (RAND_MAX / 5) ) {
|
|
vec3d v1, v2;
|
|
if ( Cmdline_old_collision_sys ) {
|
|
submodel_get_two_random_points(Lab_model_num, -1, &v1, &v2);
|
|
} else {
|
|
submodel_get_two_random_points_better(Lab_model_num, -1, &v1, &v2);
|
|
}
|
|
|
|
vec3d static_one;
|
|
|
|
if (mr % 2) {
|
|
static_one = Lab_arc_pts[i][0];
|
|
} else {
|
|
static_one = Lab_arc_pts[i][1];
|
|
}
|
|
|
|
// For large ships, cap the length to be 25% of max radius
|
|
if (mradius > 200.0f) {
|
|
float max_dist = mradius * MAX_ARC_LENGTH_PERCENTAGE;
|
|
|
|
vec3d tmp;
|
|
float d;
|
|
|
|
// Cap arc 2->1
|
|
vm_vec_sub( &tmp, &v1, &static_one );
|
|
d = vm_vec_mag_quick( &tmp );
|
|
|
|
if (d > max_dist) {
|
|
vm_vec_scale_add( &v1, &static_one, &tmp, max_dist / d );
|
|
}
|
|
}
|
|
|
|
Lab_arc_pts[i][mr % 2] = v1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < MAX_SHIP_ARCS; i++) {
|
|
if ( timestamp_valid(Lab_arc_timestamp[i]) ) {
|
|
model_add_arc(Lab_model_num, -1, &Lab_arc_pts[i][0], &Lab_arc_pts[i][1], Lab_arc_type[i]);
|
|
|
|
// maybe add lighting for the arc
|
|
if (Detail.lighting > 2) {
|
|
// Move arc endpoints into world coordinates
|
|
vec3d tmp1, tmp2;
|
|
vm_vec_unrotate(&tmp1, &Lab_arc_pts[i][0], &Lab_viewer_orient);
|
|
vm_vec_unrotate(&tmp2, &Lab_arc_pts[i][1], &Lab_viewer_orient);
|
|
|
|
light_add_point( &tmp1, 10.0f, 20.0f, frand(), 1.0f, 1.0f, 1.0f, -1 );
|
|
light_add_point( &tmp2, 10.0f, 20.0f, frand(), 1.0f, 1.0f, 1.0f, -1 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void labviewer_add_model_thrusters(model_render_params *render_info, ship_info *sip)
|
|
{
|
|
static float thruster_frame = 0.0f;
|
|
static float thruster_glow_frame = 0.0f;
|
|
static int thruster_bitmap = -1;
|
|
static int thruster_glow_bitmap = -1;
|
|
static float thruster_glow_noise = 1.0f;
|
|
|
|
float rate;
|
|
int framenum;
|
|
int secondary_glow_bitmap = -1;
|
|
int tertiary_glow_bitmap = -1;
|
|
static int thruster_distortion_bitmap = -1;
|
|
generic_anim *flame_anim = NULL, *glow_anim = NULL;
|
|
species_info *species = &Species_info[0];
|
|
weapon_info *wip = NULL;
|
|
mst_info mst;
|
|
|
|
|
|
if (Lab_mode == LAB_MODE_SHIP) {
|
|
Assert( sip != NULL );
|
|
species = &Species_info[sip->species];
|
|
}
|
|
|
|
if (Lab_mode == LAB_MODE_WEAPON) {
|
|
wip = &Weapon_info[Lab_selected_index];
|
|
}
|
|
|
|
// init thruster graphics (species stuff)
|
|
extern void ship_init_thrusters();
|
|
ship_init_thrusters();
|
|
|
|
if ( Lab_thrust_afterburn && (Lab_mode != LAB_MODE_WEAPON) ) {
|
|
flame_anim = &sip->thruster_flame_info.afterburn; // select afterburner flame
|
|
glow_anim = &sip->thruster_glow_info.afterburn; // select afterburner glow
|
|
secondary_glow_bitmap = sip->thruster_secondary_glow_info.afterburn.bitmap_id;
|
|
tertiary_glow_bitmap = sip->thruster_tertiary_glow_info.afterburn.bitmap_id;
|
|
thruster_distortion_bitmap = sip->thruster_distortion_info.afterburn.bitmap_id;
|
|
|
|
rate = 1.5f; // go at 1.5x faster when afterburners on
|
|
} else {
|
|
flame_anim = &species->thruster_info.flames.normal; // select normal flame
|
|
glow_anim = &species->thruster_info.glow.normal; // select normal glow
|
|
|
|
if (Lab_mode == LAB_MODE_WEAPON) {
|
|
if (wip->thruster_flame.first_frame >= 0)
|
|
flame_anim = &wip->thruster_flame;
|
|
|
|
if (wip->thruster_glow.first_frame >= 0)
|
|
glow_anim = &wip->thruster_glow;
|
|
}
|
|
|
|
if (Lab_mode == LAB_MODE_SHIP) {
|
|
flame_anim = &sip->thruster_flame_info.normal; // select normal flame
|
|
glow_anim = &sip->thruster_glow_info.normal; // select normal glow
|
|
secondary_glow_bitmap = sip->thruster_secondary_glow_info.normal.bitmap_id;
|
|
tertiary_glow_bitmap = sip->thruster_tertiary_glow_info.normal.bitmap_id;
|
|
thruster_distortion_bitmap = sip->thruster_distortion_info.normal.bitmap_id;
|
|
}
|
|
|
|
// If thrust at 0, go at half as fast, full thrust; full framerate
|
|
// so set rate from 0.5 to 1.0, depending on thrust from 0 to 1
|
|
// rate = 0.5f + objp->phys_info.forward_thrust / 2.0f;
|
|
rate = 0.67f * (1.0f + Lab_thrust_len);
|
|
}
|
|
|
|
Assert( flFrametime > 0.0f );
|
|
|
|
if (flame_anim->first_frame >= 0) {
|
|
thruster_frame += flFrametime * rate;
|
|
|
|
framenum = bm_get_anim_frame(flame_anim->first_frame, thruster_frame, flame_anim->total_time, true);
|
|
|
|
// Get the bitmap for this frame
|
|
thruster_bitmap = flame_anim->first_frame + framenum;
|
|
} else {
|
|
thruster_frame = 0.0f;
|
|
thruster_bitmap = -1;
|
|
}
|
|
|
|
// Do it for glow bitmaps
|
|
|
|
if (glow_anim->first_frame >= 0) {
|
|
thruster_glow_frame += flFrametime * rate;
|
|
|
|
framenum = bm_get_anim_frame(glow_anim->first_frame, thruster_glow_frame, glow_anim->total_time, true);
|
|
|
|
// Get the bitmap for this frame
|
|
thruster_glow_bitmap = glow_anim->first_frame; // + framenum;
|
|
thruster_glow_noise = Noise[framenum];
|
|
} else {
|
|
thruster_glow_frame = 0.0f;
|
|
thruster_glow_bitmap = -1;
|
|
thruster_glow_noise = 1.0f;
|
|
}
|
|
|
|
|
|
// ok, we've worked out the bitmaps, so now we need to set up the thrust info
|
|
mst.length.xyz.z = Lab_thrust_len;
|
|
mst.length.xyz.x = 0.0f;
|
|
mst.length.xyz.y = 0.0f;
|
|
|
|
// Add noise to thruster geometry.
|
|
if ( Lab_mode == LAB_MODE_SHIP ) {
|
|
if (!(sip->flags[Ship::Info_Flags::No_thruster_geo_noise])) {
|
|
mst.length.xyz.z *= (1.0f + frand()/5.0f - 0.1f);
|
|
mst.length.xyz.y *= (1.0f + frand()/5.0f - 0.1f);
|
|
mst.length.xyz.x *= (1.0f + frand()/5.0f - 0.1f);
|
|
}
|
|
} else {
|
|
mst.length.xyz.z *= (1.0f + frand()/5.0f - 0.1f);
|
|
mst.length.xyz.y *= (1.0f + frand()/5.0f - 0.1f);
|
|
mst.length.xyz.x *= (1.0f + frand()/5.0f - 0.1f);
|
|
}
|
|
|
|
CLAMP(mst.length.xyz.z, -1.0f, 1.0f);
|
|
CLAMP(mst.length.xyz.y, -1.0f, 1.0f);
|
|
CLAMP(mst.length.xyz.x, -1.0f, 1.0f);
|
|
|
|
mst.primary_bitmap = thruster_bitmap;
|
|
mst.primary_glow_bitmap =thruster_glow_bitmap;
|
|
mst.secondary_glow_bitmap = secondary_glow_bitmap;
|
|
mst.tertiary_glow_bitmap = tertiary_glow_bitmap;
|
|
mst.distortion_bitmap = thruster_distortion_bitmap;
|
|
|
|
mst.use_ab = Lab_thrust_afterburn;
|
|
mst.rotvel = vmd_zero_vector;
|
|
|
|
if (Lab_mode == LAB_MODE_SHIP) {
|
|
mst.glow_noise = thruster_glow_noise * sip->thruster_glow_noise_mult;
|
|
mst.glow_rad_factor = sip->thruster01_glow_rad_factor;
|
|
mst.secondary_glow_rad_factor = sip->thruster02_glow_rad_factor;
|
|
mst.tertiary_glow_rad_factor = sip->thruster03_glow_rad_factor;
|
|
mst.glow_length_factor = sip->thruster02_glow_len_factor;
|
|
mst.distortion_length_factor = sip->thruster_dist_len_factor;
|
|
mst.distortion_rad_factor = sip->thruster_dist_rad_factor;
|
|
mst.draw_distortion = sip->draw_distortion;
|
|
}
|
|
|
|
if (Lab_mode == LAB_MODE_WEAPON) {
|
|
mst.glow_noise = thruster_glow_noise;
|
|
mst.glow_rad_factor = wip->thruster_glow_factor;
|
|
}
|
|
|
|
// set, and go...
|
|
render_info->set_thruster_info(mst);
|
|
}
|
|
|
|
void light_set_all_relevent();
|
|
|
|
void labviewer_render_model(float frametime)
|
|
{
|
|
int i, j;
|
|
float rev_rate;
|
|
angles rot_angles, view_angles;
|
|
ship_info *sip = NULL;
|
|
|
|
if ( (Lab_mode == LAB_MODE_SHIP) && (Lab_selected_index >= 0) ) {
|
|
sip = &Ship_info[Lab_selected_index];
|
|
}
|
|
|
|
model_render_params render_info;
|
|
|
|
model_clear_instance(Lab_model_num);
|
|
|
|
// get correct revolution rate
|
|
rev_rate = REVOLUTION_RATE;
|
|
|
|
if (sip != NULL) {
|
|
if (sip->is_big_ship()) {
|
|
rev_rate *= 1.7f;
|
|
} else if (sip->is_huge_ship()) {
|
|
rev_rate *= 3.0f;
|
|
}
|
|
|
|
if (sip->uses_team_colors && !Teamcolor_override) {
|
|
render_info.set_team_color(Lab_team_color, "none", 0, 0);
|
|
}
|
|
}
|
|
|
|
// rotate/pan/zoom the model as much as required for this frame
|
|
if (Trackball_active) {
|
|
int dx, dy;
|
|
matrix mat1, mat2;
|
|
|
|
mouse_get_delta(&dx, &dy);
|
|
|
|
if (dx || dy) {
|
|
// rotation mode
|
|
if (Trackball_mode == 1) {
|
|
vm_trackball(-dx, -dy, &mat1);
|
|
vm_matrix_x_matrix(&mat2, &mat1, &Lab_viewer_orient);
|
|
Lab_viewer_orient = mat2;
|
|
}
|
|
// pan mode
|
|
else if (Trackball_mode == 2) {
|
|
double scale_x = dx * (double)model_get_radius(Lab_model_num) * 0.005;
|
|
double scale_y = dy * (double)model_get_radius(Lab_model_num) * 0.005;
|
|
|
|
Lab_viewer_pos.xyz.x -= (float)scale_x;
|
|
Lab_viewer_pos.xyz.y += (float)scale_y;
|
|
}
|
|
// zoom mode
|
|
else if ( dy && (Trackball_mode == 3) ) {
|
|
float scale_y = dy * 0.01f;
|
|
|
|
Lab_viewer_zoom += scale_y;
|
|
}
|
|
}
|
|
}
|
|
// otherwise do orient/rotation calculation, if we are supposed to
|
|
else if ( !(Lab_viewer_flags & LAB_FLAG_NO_ROTATION) ) {
|
|
Lab_viewer_rotation += PI2 * frametime / rev_rate;
|
|
|
|
while (Lab_viewer_rotation > PI2)
|
|
Lab_viewer_rotation -= PI2;
|
|
|
|
// setup stuff needed to render the ship
|
|
view_angles.p = -0.6f;
|
|
view_angles.b = 0.0f;
|
|
view_angles.h = 0.0f;
|
|
vm_angles_2_matrix(&Lab_viewer_orient, &view_angles);
|
|
|
|
rot_angles.p = 0.0f;
|
|
rot_angles.b = 0.0f;
|
|
rot_angles.h = Lab_viewer_rotation;
|
|
vm_rotate_matrix_by_angles(&Lab_viewer_orient, &rot_angles);
|
|
}
|
|
|
|
|
|
// render the ship
|
|
g3_start_frame(1);
|
|
|
|
if (sip != NULL) {
|
|
Lab_viewer_pos.xyz.z = sip->closeup_pos.xyz.z;
|
|
|
|
float my_zoom = sip->closeup_zoom * Lab_viewer_zoom;
|
|
// clamp it down so that we don't get too close or too far away
|
|
CLAMP(my_zoom, 0.08f, 1.8f);
|
|
|
|
g3_set_view_matrix(&Lab_viewer_pos, &vmd_identity_matrix, my_zoom);
|
|
} else {
|
|
// find the largest radius
|
|
polymodel *pm = model_get(Lab_model_num);
|
|
float largest_radius = 0.0f;
|
|
|
|
Assert( pm != NULL );
|
|
|
|
for (i = 0; i < pm->n_models; i++) {
|
|
if ( !pm->submodel[i].is_thruster ) {
|
|
if (pm->submodel[i].rad > largest_radius) {
|
|
largest_radius = pm->submodel[i].rad;
|
|
}
|
|
}
|
|
}
|
|
|
|
Lab_viewer_pos.xyz.z = -(largest_radius * 2.0f);
|
|
|
|
CLAMP(Lab_viewer_zoom, 0.08f, 1.8f);
|
|
|
|
g3_set_view_matrix(&Lab_viewer_pos, &vmd_identity_matrix, Lab_viewer_zoom);
|
|
}
|
|
|
|
|
|
|
|
// lighting for techroom
|
|
light_reset();
|
|
vec3d light_dir = vmd_zero_vector;
|
|
light_dir.xyz.y = 1.0f;
|
|
light_dir.xyz.x = 0.0000001f;
|
|
light_add_directional(&light_dir, 0.65f, 1.0f, 1.0f, 1.0f,-1);
|
|
int mx, my;
|
|
mouse_get_pos( &mx, &my );
|
|
light_dir.xyz.y = 0.0000001f;
|
|
light_dir.xyz.x = sinf(my/150.0f);
|
|
light_dir.xyz.z = cosf(my/150.0f);
|
|
vm_vec_normalize(&light_dir);
|
|
vm_vec_scale(&light_dir, mx*10.1f);
|
|
light_add_point(&light_dir,1,mx*10.2f+0.1f, 0.5f, 1.0f, 1.0f, 1.0f,-1);
|
|
|
|
light_rotate_all();
|
|
// lighting for techroom
|
|
|
|
render_info.set_color(255, 255, 255);
|
|
render_info.set_detail_level_lock(Lab_model_LOD);
|
|
|
|
int flagggs = Lab_model_flags;
|
|
|
|
// only render the insignia when the flag is set
|
|
if (Lab_viewer_flags & LAB_FLAG_SHOW_INSIGNIA) {
|
|
render_info.set_insignia_bitmap(Lab_insignia_bitmap);
|
|
}
|
|
|
|
// render special if we are showing debris
|
|
if (Lab_viewer_flags & LAB_FLAG_SHOW_DEBRIS) {
|
|
polymodel *pm = model_get(Lab_model_num);
|
|
|
|
gr_set_proj_matrix(Proj_fov, gr_screen.clip_aspect, 1.0f, Max_draw_distance);
|
|
gr_set_view_matrix(&Eye_position, &Eye_matrix);
|
|
|
|
for (i = 0; i < pm->num_debris_objects; i++) {
|
|
vec3d world_point = ZERO_VECTOR;
|
|
|
|
model_find_world_point(&world_point, &pm->submodel[pm->debris_objects[i]].offset, Lab_model_num, -1, &Lab_viewer_orient, &vmd_zero_vector);
|
|
Shadow_override = true;
|
|
|
|
render_info.set_flags(Lab_model_flags);
|
|
|
|
submodel_render_immediate(&render_info, Lab_model_num, pm->debris_objects[i], &Lab_viewer_orient, &world_point);
|
|
Shadow_override = false;
|
|
}
|
|
}
|
|
// render normally otherwise
|
|
else {
|
|
// show damage arcs if wanted
|
|
if ( (sip != NULL) && (Lab_viewer_flags & LAB_FLAG_LIGHTNING_ARCS) ) {
|
|
labviewer_add_model_arcs();
|
|
}
|
|
|
|
// ship/weapon thrusters
|
|
if (Lab_model_flags & MR_SHOW_THRUSTERS) {
|
|
labviewer_add_model_thrusters(&render_info, sip);
|
|
}
|
|
|
|
// do initial rotation
|
|
if (sip != NULL) {
|
|
if (Lab_viewer_flags & LAB_FLAG_INITIAL_ROTATION) {
|
|
for (i = 0; i < sip->n_subsystems; i++) {
|
|
if (Lab_ship_model_subsys[i].type == SUBSYSTEM_TURRET) {
|
|
|
|
for (j = 0; j < Lab_ship_model_subsys[i].n_triggers; j++) {
|
|
|
|
// special case for turrets
|
|
Lab_ship_subsys[i].submodel_info_2.angs.p = Lab_ship_model_subsys[i].triggers[j].angle.xyz.x;
|
|
Lab_ship_subsys[i].submodel_info_1.angs.h = Lab_ship_model_subsys[i].triggers[j].angle.xyz.y;
|
|
}
|
|
if ( Lab_ship_model_subsys[i].subobj_num >= 0 ) {
|
|
model_set_instance(Lab_model_num, Lab_ship_model_subsys[i].subobj_num, &Lab_ship_subsys[i].submodel_info_1 );
|
|
}
|
|
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) ) {
|
|
model_set_instance(Lab_model_num, Lab_ship_model_subsys[i].turret_gun_sobj, &Lab_ship_subsys[i].submodel_info_2 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// rotate submodels if wanted
|
|
if ( (sip != NULL) && (Lab_viewer_flags & LAB_FLAG_SUBMODEL_ROTATE) ) {
|
|
for (i = 0; i < sip->n_subsystems; i++) {
|
|
if ( !(Lab_ship_model_subsys[i].flags[Model::Subsystem_Flags::Rotates]) ) {
|
|
continue;
|
|
}
|
|
|
|
model_set_instance(Lab_model_num, Lab_ship_model_subsys[i].subobj_num, &Lab_ship_subsys[i].submodel_info_1 );
|
|
|
|
// if we got this far, we can rotate - so choose which method to use
|
|
if (Lab_ship_model_subsys[i].flags[Model::Subsystem_Flags::Stepped_rotate]) {
|
|
submodel_stepped_rotate(&Lab_ship_model_subsys[i], &Lab_ship_subsys[i].submodel_info_1);
|
|
} else {
|
|
submodel_rotate(&Lab_ship_model_subsys[i], &Lab_ship_subsys[i].submodel_info_1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
if (sip != NULL) {
|
|
if (Lab_viewer_flags & LAB_FLAG_DESTROYED_SUBSYSTEMS) {
|
|
model_show_damaged(Lab_model_num, 1);
|
|
}
|
|
}
|
|
|
|
if( !( flagggs & MR_NO_LIGHTING ) && Cmdline_shadow_quality ) {
|
|
polymodel *pm = model_get(Lab_model_num);
|
|
|
|
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);
|
|
|
|
render_info.set_flags(MR_NO_TEXTURING | MR_NO_LIGHTING | MR_AUTOCENTER);
|
|
|
|
model_render_immediate(&render_info, Lab_model_num, &Lab_viewer_orient, &vmd_zero_vector);
|
|
|
|
//render weapon models if selected
|
|
if ( Lab_mode == LAB_MODE_SHIP && ( Lab_viewer_flags & LAB_FLAG_SHOW_WEAPONS ) ) {
|
|
int k,l;
|
|
g3_start_instance_matrix(&vmd_zero_vector, &Lab_viewer_orient, true);
|
|
l = 0;
|
|
|
|
// no thrusters for attached missiles
|
|
int render_flags = MR_NO_TEXTURING | MR_NO_LIGHTING;
|
|
|
|
//primary weapons
|
|
for (j = 0; j < sip->num_primary_banks; j++) {
|
|
if (!sip->draw_primary_models[j])
|
|
continue;
|
|
if (Lab_weaponmodel_num[l] >= 0) {
|
|
w_bank *bank = &model_get(Lab_model_num)->gun_banks[j];
|
|
for(k = 0; k < bank->num_slots; k++) {
|
|
|
|
render_info.set_flags(render_flags);
|
|
render_info.set_object_number(-1);
|
|
model_render_immediate(&render_info, Lab_weaponmodel_num[l], &vmd_identity_matrix, &bank->pnt[k]);
|
|
}
|
|
}
|
|
l++;
|
|
}
|
|
//secondary weapons
|
|
vec3d secondary_weapon_pos;
|
|
w_bank* bank;
|
|
|
|
for (j = 0; j < sip->num_secondary_banks; j++) {
|
|
if (!sip->draw_secondary_models[j])
|
|
continue;
|
|
if (Lab_weaponmodel_num[l] >= 0) {
|
|
bank = &(model_get(Lab_model_num))->missile_banks[j];
|
|
if (Weapon_info[sip->secondary_bank_weapons[j]].wi_flags[Weapon::Info_Flags::External_weapon_lnch]) {
|
|
for(k = 0; k < bank->num_slots; k++) {
|
|
render_info.set_flags(render_flags);
|
|
render_info.set_object_number(-1);
|
|
model_render_immediate(&render_info, Lab_weaponmodel_num[l], &vmd_identity_matrix, &bank->pnt[k]);
|
|
}
|
|
} else {
|
|
for(k = 0; k < bank->num_slots; k++)
|
|
{
|
|
secondary_weapon_pos = bank->pnt[k];
|
|
render_info.set_flags(render_flags);
|
|
render_info.set_object_number(-1);
|
|
model_render_immediate(&render_info, Lab_weaponmodel_num[l], &vmd_identity_matrix, &secondary_weapon_pos);
|
|
}
|
|
}
|
|
}
|
|
l++;
|
|
}
|
|
g3_done_instance(true);
|
|
}
|
|
|
|
shadows_end_render();
|
|
}
|
|
|
|
gr_set_proj_matrix(Proj_fov, gr_screen.clip_aspect, 1.0f, Max_draw_distance);
|
|
gr_set_view_matrix(&Eye_position, &Eye_matrix);
|
|
|
|
gr_opengl_deferred_lighting_begin();
|
|
|
|
// render_info.set_animated_effect(
|
|
// ANIMATED_SHADER_LOADOUTSELECT_FS1,
|
|
// MIN((timer_get_milliseconds()-anim_timer_start)/1500.0f, 2.0f)
|
|
// );
|
|
|
|
//render weapon models if selected
|
|
if (Lab_mode == LAB_MODE_SHIP && (Lab_viewer_flags & LAB_FLAG_SHOW_WEAPONS)) {
|
|
int k,l;
|
|
g3_start_instance_matrix(&vmd_zero_vector, &Lab_viewer_orient, true);
|
|
l = 0;
|
|
|
|
// no thrusters for attached missiles
|
|
int render_flags = flagggs;
|
|
render_flags &= ~MR_SHOW_THRUSTERS;
|
|
|
|
//primary weapons
|
|
for (j = 0; j < sip->num_primary_banks; j++) {
|
|
if (!sip->draw_primary_models[j])
|
|
continue;
|
|
if (Lab_weaponmodel_num[l] >= 0) {
|
|
w_bank *bank = &model_get(Lab_model_num)->gun_banks[j];
|
|
for(k = 0; k < bank->num_slots; k++) {
|
|
render_info.set_flags(render_flags);
|
|
render_info.set_object_number(-1);
|
|
model_render_immediate(&render_info, Lab_weaponmodel_num[l], &vmd_identity_matrix, &bank->pnt[k]);
|
|
}
|
|
}
|
|
l++;
|
|
}
|
|
//secondary weapons
|
|
vec3d secondary_weapon_pos;
|
|
w_bank* bank;
|
|
|
|
for (j = 0; j < sip->num_secondary_banks; j++) {
|
|
if (!sip->draw_secondary_models[j])
|
|
continue;
|
|
if (Lab_weaponmodel_num[l] >= 0) {
|
|
bank = &(model_get(Lab_model_num))->missile_banks[j];
|
|
if (Weapon_info[sip->secondary_bank_weapons[j]].wi_flags[Weapon::Info_Flags::External_weapon_lnch]) {
|
|
for(k = 0; k < bank->num_slots; k++) {
|
|
render_info.set_flags(render_flags);
|
|
model_render_immediate(&render_info, Lab_weaponmodel_num[l], &vmd_identity_matrix, &bank->pnt[k]);
|
|
}
|
|
} else {
|
|
for(k = 0; k < bank->num_slots; k++)
|
|
{
|
|
secondary_weapon_pos = bank->pnt[k];
|
|
render_info.set_flags(render_flags);
|
|
render_info.set_object_number(-1);
|
|
model_render_immediate(&render_info, Lab_weaponmodel_num[l], &vmd_identity_matrix, &secondary_weapon_pos);
|
|
}
|
|
}
|
|
}
|
|
l++;
|
|
}
|
|
g3_done_instance(true);
|
|
}
|
|
|
|
render_info.set_debug_flags(Lab_model_debug_flags);
|
|
render_info.set_flags(flagggs);
|
|
|
|
model_render_immediate(&render_info, Lab_model_num, &Lab_viewer_orient, &vmd_zero_vector, MODEL_RENDER_OPAQUE);
|
|
gr_opengl_deferred_lighting_end();
|
|
gr_opengl_deferred_lighting_finish();
|
|
bool gpo_save = Glowpoint_override;
|
|
Glowpoint_override = true;
|
|
model_render_immediate(&render_info, Lab_model_num, &Lab_viewer_orient, &vmd_zero_vector, MODEL_RENDER_TRANS);
|
|
Glowpoint_override = gpo_save;
|
|
}
|
|
|
|
batching_render_all();
|
|
gr_copy_effect_texture();
|
|
batching_render_all(true);
|
|
gr_end_view_matrix();
|
|
gr_end_proj_matrix();
|
|
|
|
g3_end_frame();
|
|
}
|
|
|
|
void labviewer_render_bitmap(float frametime)
|
|
{
|
|
static float current_frame = 0.0f;
|
|
static float current_glow_frame = 0.0f;
|
|
int framenum = 0;
|
|
|
|
// if not valid then bail
|
|
if ( (Lab_selected_index < 0) || (Lab_mode != LAB_MODE_WEAPON) || (Lab_bitmap_id < 0) ) {
|
|
return;
|
|
}
|
|
|
|
|
|
weapon_info *wip = &Weapon_info[Lab_selected_index];
|
|
|
|
if (wip->laser_bitmap.first_frame < 0) {
|
|
return;
|
|
}
|
|
|
|
|
|
float rev_rate = REVOLUTION_RATE;
|
|
angles rot_angles, view_angles;
|
|
|
|
if (Trackball_active) {
|
|
int dx, dy;
|
|
matrix mat1, mat2;
|
|
|
|
mouse_get_delta(&dx, &dy);
|
|
|
|
if (dx || dy) {
|
|
// rotation mode
|
|
if (Trackball_mode == 1) {
|
|
vm_trackball(-dx, -dy, &mat1);
|
|
vm_matrix_x_matrix(&mat2, &mat1, &Lab_viewer_orient);
|
|
Lab_viewer_orient = mat2;
|
|
}
|
|
// pan mode
|
|
else if (Trackball_mode == 2) {
|
|
double scale_x = dx * (double)wip->laser_length * 0.005;
|
|
double scale_y = dy * (double)wip->laser_length * 0.005;
|
|
|
|
Lab_viewer_pos.xyz.x -= (float)scale_x;
|
|
Lab_viewer_pos.xyz.y += (float)scale_y;
|
|
}
|
|
// zoom mode
|
|
else if ( dy && (Trackball_mode == 3) ) {
|
|
float scale_y = dy / 100.0f;
|
|
|
|
Lab_viewer_zoom += scale_y;
|
|
}
|
|
}
|
|
}
|
|
// otherwise do orient/rotation calculation, if we are supposed to
|
|
else if ( !(Lab_viewer_flags & LAB_FLAG_NO_ROTATION) ) {
|
|
Lab_viewer_rotation += PI2 * frametime / rev_rate;
|
|
|
|
while (Lab_viewer_rotation > PI2) {
|
|
Lab_viewer_rotation -= PI2;
|
|
}
|
|
|
|
// setup stuff needed to render the ship
|
|
view_angles.p = -0.6f;
|
|
view_angles.b = 0.0f;
|
|
view_angles.h = 0.0f;
|
|
vm_angles_2_matrix(&Lab_viewer_orient, &view_angles);
|
|
|
|
rot_angles.p = 0.0f;
|
|
rot_angles.b = 0.0f;
|
|
rot_angles.h = Lab_viewer_rotation;
|
|
vm_rotate_matrix_by_angles(&Lab_viewer_orient, &rot_angles);
|
|
}
|
|
|
|
g3_start_frame(1);
|
|
|
|
Lab_viewer_pos.xyz.z = -(wip->laser_length * 2.0f);
|
|
|
|
CLAMP(Lab_viewer_zoom, 0.08f, 1.8f);
|
|
|
|
g3_set_view_matrix(&Lab_viewer_pos, &vmd_identity_matrix, Lab_viewer_zoom * 1.3f);
|
|
|
|
gr_set_proj_matrix(Proj_fov, gr_screen.clip_aspect, 1.0f, Max_draw_distance);
|
|
gr_set_view_matrix(&Eye_position, &Eye_matrix);
|
|
|
|
|
|
// draw the primary laser bitmap
|
|
//gr_set_color_fast(&wip->laser_color_1);
|
|
|
|
if (wip->laser_bitmap.num_frames > 1) {
|
|
current_frame += frametime;
|
|
|
|
framenum = bm_get_anim_frame(wip->laser_bitmap.first_frame, current_frame, wip->laser_bitmap.total_time, true);
|
|
}
|
|
|
|
vec3d headp;
|
|
vm_vec_scale_add(&headp, &vmd_zero_vector, &Lab_viewer_orient.vec.fvec, wip->laser_length);
|
|
|
|
//gr_set_bitmap(wip->laser_bitmap.first_frame + framenum, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 0.99999f);
|
|
if(wip->laser_length > 0.0001f) {
|
|
//g3_draw_laser(&headp, wip->laser_head_radius, &vmd_zero_vector, wip->laser_tail_radius, TMAP_FLAG_TEXTURED | TMAP_FLAG_XPARENT | TMAP_HTL_3D_UNLIT);
|
|
material mat_params;
|
|
material_set_unlit_color(&mat_params, wip->laser_bitmap.first_frame + framenum, &wip->laser_color_1, true, true);
|
|
g3_render_laser(&mat_params, &headp, wip->laser_head_radius, &vmd_zero_vector, wip->laser_tail_radius);
|
|
}
|
|
|
|
// now draw the laser glow bitmap, if there is one, and if we are supposed to
|
|
if ( !(Lab_model_flags & MR_NO_GLOWMAPS) && (wip->laser_glow_bitmap.first_frame >= 0) ) {
|
|
vec3d headp2, tailp;
|
|
color c;
|
|
|
|
float weapon_glow_scale_f = 2.3f;
|
|
float weapon_glow_scale_r = 2.3f;
|
|
float weapon_glow_scale_l = 1.5f;
|
|
float weapon_glow_alpha = 0.85f;
|
|
|
|
// get the laser color
|
|
if ( (wip->laser_color_2.red == 0) && (wip->laser_color_2.green == 0) && (wip->laser_color_2.blue == 0) ) {
|
|
c = wip->laser_color_1;
|
|
} else {
|
|
// lifetime pct
|
|
float pct = 1.0f;
|
|
|
|
// otherwise interpolate between the colors
|
|
gr_init_color( &c, (int)((float)wip->laser_color_1.red + (((float)wip->laser_color_2.red - (float)wip->laser_color_1.red) * pct)),
|
|
(int)((float)wip->laser_color_1.green + (((float)wip->laser_color_2.green - (float)wip->laser_color_1.green) * pct)),
|
|
(int)((float)wip->laser_color_1.blue + (((float)wip->laser_color_2.blue - (float)wip->laser_color_1.blue) * pct)) );
|
|
}
|
|
|
|
vm_vec_scale_add(&headp2, &vmd_zero_vector, &Lab_viewer_orient.vec.fvec, wip->laser_length * weapon_glow_scale_l);
|
|
vm_vec_scale_add(&tailp, &vmd_zero_vector, &Lab_viewer_orient.vec.fvec, wip->laser_length * (1 - weapon_glow_scale_l) );
|
|
|
|
framenum = 0;
|
|
|
|
if (wip->laser_glow_bitmap.num_frames > 1) {
|
|
current_glow_frame += frametime;
|
|
|
|
// Sanity checks
|
|
if (current_glow_frame < 0.0f) {
|
|
current_glow_frame = 0.0f;
|
|
} else if (current_glow_frame > 100.0f) {
|
|
current_glow_frame = 0.0f;
|
|
}
|
|
|
|
while (current_glow_frame > wip->laser_glow_bitmap.total_time) {
|
|
current_glow_frame -= wip->laser_glow_bitmap.total_time;
|
|
}
|
|
|
|
framenum = fl2i( (current_glow_frame * wip->laser_glow_bitmap.num_frames) / wip->laser_glow_bitmap.total_time );
|
|
|
|
CLAMP(framenum, 0, wip->laser_glow_bitmap.num_frames-1);
|
|
}
|
|
|
|
//gr_set_bitmap(wip->laser_glow_bitmap.first_frame + framenum, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, weapon_glow_alpha);
|
|
if(wip->laser_length > 0.0001f) {
|
|
//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);
|
|
material mat_params;
|
|
material_set_unlit_color(&mat_params, wip->laser_glow_bitmap.first_frame + framenum, &c, weapon_glow_alpha, true, false);
|
|
g3_render_laser(&mat_params, &headp2, wip->laser_head_radius * weapon_glow_scale_f, &tailp, wip->laser_tail_radius * weapon_glow_scale_r);
|
|
}
|
|
}
|
|
|
|
// clean up and move on ...
|
|
|
|
gr_end_view_matrix();
|
|
gr_end_proj_matrix();
|
|
|
|
g3_end_frame();
|
|
}
|
|
|
|
void labviewer_do_render(float frametime)
|
|
{
|
|
int w, h;
|
|
|
|
if ( (Lab_model_num < 0) && (Lab_bitmap_id < 0) ) {
|
|
gr_get_string_size(&w, &h, "Viewer off");
|
|
gr_set_color_fast(&Color_white);
|
|
gr_string(gr_screen.center_offset_x + gr_screen.center_w - w, gr_screen.center_offset_y + gr_screen.center_h - h, "Viewer off", GR_RESIZE_NONE);
|
|
|
|
return;
|
|
}
|
|
|
|
// render our particular thing
|
|
if (Lab_model_num >= 0) {
|
|
|
|
gr_scene_texture_begin();
|
|
|
|
labviewer_render_model(frametime);
|
|
|
|
gr_scene_texture_end();
|
|
|
|
// print out the current pof filename, to help with... something
|
|
if ( strlen(Lab_model_filename) ) {
|
|
gr_get_string_size(&w, &h, Lab_model_filename);
|
|
gr_set_color_fast(&Color_white);
|
|
gr_string(gr_screen.center_offset_x + gr_screen.center_w - w, gr_screen.center_offset_y + gr_screen.center_h - h, Lab_model_filename, GR_RESIZE_NONE);
|
|
}
|
|
} else if (Lab_bitmap_id >= 0) {
|
|
gr_scene_texture_begin();
|
|
|
|
labviewer_render_bitmap(frametime);
|
|
|
|
gr_scene_texture_end();
|
|
|
|
// print out the current bitmap filename, to help with... something
|
|
if ( strlen(Lab_bitmap_filename) ) {
|
|
gr_get_string_size(&w, &h, Lab_bitmap_filename);
|
|
gr_set_color_fast(&Color_white);
|
|
gr_string(gr_screen.center_offset_x + gr_screen.center_w - w, gr_screen.center_offset_y + gr_screen.center_h - h, Lab_bitmap_filename, GR_RESIZE_NONE);
|
|
}
|
|
}
|
|
|
|
// print FPS at bottom left, might be helpful
|
|
extern void game_get_framerate();
|
|
extern float frametotal;
|
|
extern float Framerate;
|
|
|
|
game_get_framerate();
|
|
|
|
gr_set_color_fast(&Color_white);
|
|
|
|
if (frametotal != 0.0f) {
|
|
gr_printf_no_resize(gr_screen.center_offset_x + 2, gr_screen.center_offset_y + gr_screen.center_h - gr_get_font_height(), "FPS: %i", fl2i(Framerate + 0.5f));
|
|
} else {
|
|
gr_string(gr_screen.center_offset_x + 10, gr_screen.center_offset_y + gr_screen.center_h - gr_get_font_height(), "FPS: ?", GR_RESIZE_NONE);
|
|
}
|
|
|
|
//Print FXAA preset
|
|
if (Cmdline_fxaa && !PostProcessing_override)
|
|
gr_printf_no_resize(gr_screen.center_offset_x + 2, gr_screen.center_offset_y + gr_screen.center_h - (gr_get_font_height() * 2) - 3, "FXAA Preset: %i", Cmdline_fxaa_preset);
|
|
|
|
//Print bloom intensity
|
|
if (Cmdline_bloom_intensity && !PostProcessing_override)
|
|
gr_printf_no_resize(gr_screen.center_offset_x + 2, gr_screen.center_offset_y + gr_screen.center_h - (gr_get_font_height() * 3) - 3, "Bloom intensity: %i", Cmdline_bloom_intensity);
|
|
|
|
//Print current Team Color setting, if any
|
|
if (Lab_team_color != "<none>")
|
|
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());
|
|
|
|
//Display helpful text
|
|
if (!PostProcessing_override)
|
|
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.");
|
|
}
|
|
|
|
void labviewer_exit(Button *caller)
|
|
{
|
|
if(Lab_selected_object != -1) {
|
|
obj_delete(Lab_selected_object);
|
|
}
|
|
gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
|
|
}
|
|
|
|
// ---------------------------- Class Window ----------------------------------
|
|
void labviewer_close_class_window(GUIObject *caller)
|
|
{
|
|
if (Lab_class_toolbar) {
|
|
Lab_class_toolbar->DeleteChildren();
|
|
}
|
|
|
|
Lab_class_window = NULL;
|
|
|
|
Lab_mode = LAB_MODE_NONE;
|
|
|
|
// reset any existing model/bitmap that is showing
|
|
labviewer_change_model(NULL);
|
|
labviewer_change_bitmap();
|
|
}
|
|
|
|
void labviewer_set_class_window(int mode)
|
|
{
|
|
if (Lab_class_window == NULL) {
|
|
Lab_class_window = (Window*)Lab_screen->Add(new Window("Class Window", gr_screen.center_offset_x + 50, gr_screen.center_offset_y + 50));
|
|
Lab_class_window->SetCloseFunction(labviewer_close_class_window);
|
|
}
|
|
|
|
if (Lab_class_toolbar == NULL) {
|
|
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));
|
|
}
|
|
|
|
// clear out all existing children
|
|
Lab_class_window->ClearContent();
|
|
Lab_class_toolbar->ClearContent();
|
|
|
|
// set our new title
|
|
if (mode == LAB_MODE_SHIP) {
|
|
Lab_class_window->SetCaption("Ship Classes");
|
|
} else if (mode == LAB_MODE_WEAPON) {
|
|
Lab_class_window->SetCaption("Weapon Classes");
|
|
}
|
|
|
|
// reset any existing model/bitmap that is showing
|
|
labviewer_change_model(NULL);
|
|
labviewer_change_bitmap();
|
|
}
|
|
|
|
|
|
// ------------------------------ Flags Window --------------------------------
|
|
typedef struct lab_flag {
|
|
Checkbox *cb;
|
|
int flag;
|
|
bool second;
|
|
} lab_flag;
|
|
|
|
static SCP_vector<lab_flag> Lab_flags;
|
|
|
|
void labviewer_flags_clear()
|
|
{
|
|
if (Lab_flags_window != NULL) {
|
|
Lab_flags_window->DeleteChildren();
|
|
}
|
|
|
|
Lab_flags.clear();
|
|
}
|
|
|
|
void labviewer_flags_add(int *X, int *Y, char *flag_name, int flag, bool flags2 = false)
|
|
{
|
|
int x = 0, y = 0;
|
|
|
|
Assert( (Lab_flags_window != NULL) && (flag_name != NULL) );
|
|
|
|
lab_flag new_flag;
|
|
|
|
if (X) {
|
|
x = *X;
|
|
}
|
|
|
|
if (Y) {
|
|
y = *Y;
|
|
}
|
|
|
|
new_flag.cb = (Checkbox*) Lab_flags_window->AddChild(new Checkbox(flag_name, x, y));
|
|
new_flag.flag = flag;
|
|
new_flag.second = flags2;
|
|
|
|
Lab_flags.push_back( new_flag );
|
|
|
|
if (X) {
|
|
*X += new_flag.cb->GetWidth() + 2;
|
|
}
|
|
|
|
if (Y) {
|
|
*Y += new_flag.cb->GetHeight() + 1;
|
|
}
|
|
}
|
|
|
|
void labviewer_populate_flags_window()
|
|
{
|
|
if (Lab_mode == LAB_MODE_NONE) {
|
|
return;
|
|
}
|
|
|
|
if (Lab_flags_window == NULL) {
|
|
return;
|
|
}
|
|
|
|
// clear out anything that already exists
|
|
labviewer_flags_clear();
|
|
|
|
// ship flags ...
|
|
if (Lab_mode == LAB_MODE_SHIP) {
|
|
//Needs reimplementation
|
|
}
|
|
// weapon flags ...
|
|
else if (Lab_mode == LAB_MODE_WEAPON) {
|
|
//Needs reimplementation
|
|
}
|
|
}
|
|
|
|
void labviewer_update_flags_window()
|
|
{
|
|
if ( (Lab_selected_index < 0) || (Lab_mode == LAB_MODE_NONE) ) {
|
|
return;
|
|
}
|
|
|
|
// no flags? then don't bother
|
|
if (Lab_flags.empty()) {
|
|
return;
|
|
}
|
|
|
|
|
|
if (Lab_mode == LAB_MODE_SHIP) {
|
|
//Needs reimplementation
|
|
}
|
|
else if (Lab_mode == LAB_MODE_WEAPON) {
|
|
//Needs reimplementation
|
|
}
|
|
}
|
|
|
|
void labviewer_close_flags_window(GUIObject *caller)
|
|
{
|
|
Lab_flags_window = NULL;
|
|
|
|
Lab_flags.clear();
|
|
}
|
|
|
|
void labviewer_make_flags_window(Button *caller)
|
|
{
|
|
if (Lab_flags_window == NULL) {
|
|
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));
|
|
Lab_flags_window->SetCloseFunction(labviewer_close_flags_window);
|
|
}
|
|
|
|
// set our new title
|
|
if (Lab_mode == LAB_MODE_SHIP) {
|
|
Lab_flags_window->SetCaption("Ship Flags");
|
|
} else if (Lab_mode == LAB_MODE_WEAPON) {
|
|
Lab_flags_window->SetCaption("Weapon Flags");
|
|
}
|
|
|
|
// populate the window with our flags (controls both ships and weapons flags)
|
|
labviewer_populate_flags_window();
|
|
|
|
// update content, if we need to
|
|
labviewer_update_flags_window();
|
|
}
|
|
|
|
// ----------------------- Variables Window --------------------------------
|
|
#define VAR_POS_LEFTWIDTH 150
|
|
#define VAR_POS_RIGHTWIDTH 100
|
|
#define VAR_POS_RIGHTX 160
|
|
|
|
#define VAR_ADD_HEADER(name) { \
|
|
ntp = (Text*)Lab_variables_window->AddChild(new Text((name), (name), VAR_POS_RIGHTX/2, y + 8, VAR_POS_RIGHTWIDTH)); \
|
|
y += ntp->GetHeight() + 10; \
|
|
}
|
|
|
|
static SCP_vector<Text*> Lab_variables;
|
|
|
|
void labviewer_close_variables_window(GUIObject *caller)
|
|
{
|
|
Lab_variables_window = NULL;
|
|
|
|
Lab_variables.clear();
|
|
}
|
|
|
|
void labviewer_variables_clear()
|
|
{
|
|
if (Lab_variables_window != NULL) {
|
|
Lab_variables_window->DeleteChildren();
|
|
}
|
|
|
|
Lab_variables.clear();
|
|
}
|
|
|
|
void labviewer_variables_add(int *Y, const char *var_name)
|
|
{
|
|
int y = 0;
|
|
Text *new_text;
|
|
|
|
Assert( (Lab_variables_window != NULL) && (var_name != NULL) );
|
|
|
|
if (Y) {
|
|
y = *Y;
|
|
}
|
|
|
|
// variable
|
|
Lab_variables_window->AddChild(new Text((var_name), (var_name), 0, y, VAR_POS_LEFTWIDTH));
|
|
// edit box
|
|
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));
|
|
|
|
if (Y) {
|
|
*Y += new_text->GetHeight() + 2;
|
|
}
|
|
|
|
Lab_variables.push_back( new_text );
|
|
}
|
|
|
|
void labviewer_populate_variables_window()
|
|
{
|
|
Text *ntp;
|
|
int y;
|
|
|
|
if (Lab_mode == LAB_MODE_NONE) {
|
|
return;
|
|
}
|
|
|
|
if (Lab_variables_window == NULL) {
|
|
return;
|
|
}
|
|
|
|
// clear out anything that already exists
|
|
labviewer_variables_clear();
|
|
|
|
y = 0;
|
|
|
|
// IMPORTANT NOTE: If you add something here, make sure you add it to labviewer_update_variables_window() as well!
|
|
// ship vFEWfe<ariables ...
|
|
if (Lab_mode == LAB_MODE_SHIP) {
|
|
labviewer_variables_add(&y, "Name");
|
|
labviewer_variables_add(&y, "Species");
|
|
labviewer_variables_add(&y, "Type");
|
|
labviewer_variables_add(&y, "Default Team Color");
|
|
|
|
// physics
|
|
VAR_ADD_HEADER("Physics");
|
|
labviewer_variables_add(&y, "Density");
|
|
labviewer_variables_add(&y, "Damp");
|
|
labviewer_variables_add(&y, "Rotdamp");
|
|
labviewer_variables_add(&y, "Max vel (x)");
|
|
labviewer_variables_add(&y, "Max vel (y)");
|
|
labviewer_variables_add(&y, "Max vel (z)");
|
|
labviewer_variables_add(&y, "Warp in speed");
|
|
labviewer_variables_add(&y, "Warp out speed");
|
|
|
|
// other
|
|
VAR_ADD_HEADER("Stats");
|
|
labviewer_variables_add(&y, "Shields");
|
|
labviewer_variables_add(&y, "Hull");
|
|
labviewer_variables_add(&y, "Subsys repair rate");
|
|
labviewer_variables_add(&y, "Hull repair rate");
|
|
labviewer_variables_add(&y, "Countermeasures");
|
|
labviewer_variables_add(&y, "HUD Icon");
|
|
|
|
VAR_ADD_HEADER("Power");
|
|
labviewer_variables_add(&y, "Power output");
|
|
labviewer_variables_add(&y, "Max oclk speed");
|
|
labviewer_variables_add(&y, "Max weapon reserve");
|
|
|
|
VAR_ADD_HEADER("Afterburner");
|
|
labviewer_variables_add(&y, "Fuel");
|
|
labviewer_variables_add(&y, "Burn rate");
|
|
labviewer_variables_add(&y, "Recharge rate");
|
|
|
|
VAR_ADD_HEADER("Explosion");
|
|
labviewer_variables_add(&y, "Inner radius");
|
|
labviewer_variables_add(&y, "Outer radius");
|
|
labviewer_variables_add(&y, "Damage");
|
|
labviewer_variables_add(&y, "Blast");
|
|
labviewer_variables_add(&y, "Propagates");
|
|
labviewer_variables_add(&y, "Shockwave speed");
|
|
labviewer_variables_add(&y, "Shockwave count");
|
|
|
|
// techroom
|
|
VAR_ADD_HEADER("Techroom");
|
|
labviewer_variables_add(&y, "Closeup zoom");
|
|
labviewer_variables_add(&y, "Closeup pos (x)");
|
|
labviewer_variables_add(&y, "Closeup pos (y)");
|
|
labviewer_variables_add(&y, "Closeup pos (z)");
|
|
}
|
|
// weapon variables ...
|
|
else if (Lab_mode == LAB_MODE_WEAPON) {
|
|
labviewer_variables_add(&y, "Name");
|
|
labviewer_variables_add(&y, "Subtype");
|
|
|
|
// physics
|
|
VAR_ADD_HEADER("Physics");
|
|
labviewer_variables_add(&y, "Mass");
|
|
labviewer_variables_add(&y, "Max speed");
|
|
labviewer_variables_add(&y, "Lifetime");
|
|
labviewer_variables_add(&y, "Range");
|
|
labviewer_variables_add(&y, "Min Range");
|
|
|
|
VAR_ADD_HEADER("Damage");
|
|
labviewer_variables_add(&y, "Fire wait");
|
|
labviewer_variables_add(&y, "Damage");
|
|
labviewer_variables_add(&y, "Armor factor");
|
|
labviewer_variables_add(&y, "Shield factor");
|
|
labviewer_variables_add(&y, "Subsys factor");
|
|
|
|
VAR_ADD_HEADER("Armor");
|
|
labviewer_variables_add(&y, "Damage type");
|
|
|
|
VAR_ADD_HEADER("Shockwave");
|
|
labviewer_variables_add(&y, "Speed");
|
|
|
|
VAR_ADD_HEADER("Missiles");
|
|
labviewer_variables_add(&y, "Turn time");
|
|
labviewer_variables_add(&y, "FOV");
|
|
labviewer_variables_add(&y, "Min locktime");
|
|
labviewer_variables_add(&y, "Pixels/sec");
|
|
labviewer_variables_add(&y, "Catchup pixels/sec");
|
|
labviewer_variables_add(&y, "Catchup pixel pen.");
|
|
labviewer_variables_add(&y, "Swarm count");
|
|
labviewer_variables_add(&y, "Swarm wait");
|
|
}
|
|
}
|
|
|
|
#define VAR_SET_VALUE(value) { \
|
|
Assert( i < Lab_variables.size() ); \
|
|
Lab_variables[i]->SetText((value)); \
|
|
i++; \
|
|
}
|
|
|
|
#define VAR_SET_VALUE_SAVE(value, max_size) { \
|
|
Assert( i < Lab_variables.size() ); \
|
|
Lab_variables[i]->SetText((value)); \
|
|
if ((max_size) < 1) { \
|
|
Assert( (max_size) == 0 ); \
|
|
Lab_variables[i]->SetSaveLoc(&(value), T_ST_ONENTER); \
|
|
} else { \
|
|
Lab_variables[i]->SetSaveLoc(&(value), T_ST_ONENTER, (max_size), 0); \
|
|
} \
|
|
i++; \
|
|
}
|
|
extern SCP_vector<SCP_string> Hud_shield_filenames;
|
|
|
|
void labviewer_update_variables_window()
|
|
{
|
|
uint i = 0;
|
|
|
|
if (Lab_mode == LAB_MODE_NONE) {
|
|
return;
|
|
}
|
|
|
|
if (Lab_variables_window == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (Lab_selected_index < 0) {
|
|
return;
|
|
}
|
|
|
|
// IMPORTANT NOTE: If you add something here, make sure you add it to labviewer_populate_variables_window() as well!
|
|
// ship variables ...
|
|
if (Lab_mode == LAB_MODE_SHIP) {
|
|
Assert( Lab_selected_index < static_cast<int>(Ship_info.size()) );
|
|
ship_info *sip = &Ship_info[Lab_selected_index];
|
|
|
|
VAR_SET_VALUE(sip->name);
|
|
VAR_SET_VALUE_SAVE(sip->species, (int)(Species_info.size()-1));
|
|
VAR_SET_VALUE_SAVE(sip->class_type, (int)(Ship_types.size()-1));
|
|
VAR_SET_VALUE(sip->default_team_name);
|
|
|
|
VAR_SET_VALUE_SAVE(sip->density, 0);
|
|
VAR_SET_VALUE_SAVE(sip->damp, 0);
|
|
VAR_SET_VALUE_SAVE(sip->rotdamp, 0);
|
|
VAR_SET_VALUE_SAVE(sip->max_vel.xyz.x, 0);
|
|
VAR_SET_VALUE_SAVE(sip->max_vel.xyz.y, 0);
|
|
VAR_SET_VALUE_SAVE(sip->max_vel.xyz.z, 0);
|
|
VAR_SET_VALUE_SAVE(sip->warpin_speed, 0);
|
|
VAR_SET_VALUE_SAVE(sip->warpout_speed, 0);
|
|
|
|
VAR_SET_VALUE_SAVE(sip->max_shield_strength, 0);
|
|
VAR_SET_VALUE_SAVE(sip->max_hull_strength, 0);
|
|
VAR_SET_VALUE_SAVE(sip->subsys_repair_rate, 0);
|
|
VAR_SET_VALUE_SAVE(sip->hull_repair_rate, 0);
|
|
VAR_SET_VALUE_SAVE(sip->cmeasure_max, 0);
|
|
VAR_SET_VALUE_SAVE(sip->shield_icon_index, (int)(Hud_shield_filenames.size()-1));
|
|
|
|
VAR_SET_VALUE_SAVE(sip->power_output, 0);
|
|
VAR_SET_VALUE_SAVE(sip->max_overclocked_speed, 0);
|
|
VAR_SET_VALUE_SAVE(sip->max_weapon_reserve, 0);
|
|
// VAR_SET_VALUE_SAVE(sip->max_shield_regen_per_second, 0);
|
|
// VAR_SET_VALUE_SAVE(sip->max_weapon_regen_per_second, 0);
|
|
|
|
VAR_SET_VALUE_SAVE(sip->afterburner_fuel_capacity, 0);
|
|
VAR_SET_VALUE_SAVE(sip->afterburner_burn_rate, 0);
|
|
VAR_SET_VALUE_SAVE(sip->afterburner_recover_rate, 0);
|
|
|
|
VAR_SET_VALUE_SAVE(sip->shockwave.inner_rad, 0);
|
|
VAR_SET_VALUE_SAVE(sip->shockwave.outer_rad, 0);
|
|
VAR_SET_VALUE_SAVE(sip->shockwave.damage, 0);
|
|
VAR_SET_VALUE_SAVE(sip->shockwave.blast, 0);
|
|
VAR_SET_VALUE_SAVE(sip->explosion_propagates, 0);
|
|
VAR_SET_VALUE_SAVE(sip->shockwave.speed, 0);
|
|
VAR_SET_VALUE_SAVE(sip->shockwave_count, 0);
|
|
|
|
VAR_SET_VALUE_SAVE(sip->closeup_zoom, 0);
|
|
VAR_SET_VALUE_SAVE(sip->closeup_pos.xyz.x, 0);
|
|
VAR_SET_VALUE_SAVE(sip->closeup_pos.xyz.y, 0);
|
|
VAR_SET_VALUE_SAVE(sip->closeup_pos.xyz.z, 0);
|
|
}
|
|
// weapon variables ...
|
|
else if (Lab_mode == LAB_MODE_WEAPON) {
|
|
Assert( Lab_selected_index < Num_weapon_types );
|
|
weapon_info *wip = &Weapon_info[Lab_selected_index];
|
|
|
|
VAR_SET_VALUE(wip->name);
|
|
VAR_SET_VALUE_SAVE(wip->subtype, Num_weapon_subtypes-1);
|
|
|
|
VAR_SET_VALUE_SAVE(wip->mass, 0);
|
|
VAR_SET_VALUE_SAVE(wip->max_speed, 0);
|
|
VAR_SET_VALUE_SAVE(wip->lifetime, 0);
|
|
VAR_SET_VALUE_SAVE(wip->weapon_range, 0);
|
|
VAR_SET_VALUE_SAVE(wip->WeaponMinRange, 0);
|
|
|
|
VAR_SET_VALUE_SAVE(wip->fire_wait, 0);
|
|
VAR_SET_VALUE_SAVE(wip->damage, 0);
|
|
VAR_SET_VALUE_SAVE(wip->armor_factor, 0);
|
|
VAR_SET_VALUE_SAVE(wip->shield_factor, 0);
|
|
VAR_SET_VALUE_SAVE(wip->subsystem_factor, 0);
|
|
|
|
VAR_SET_VALUE_SAVE(wip->damage_type_idx, 0);
|
|
|
|
VAR_SET_VALUE_SAVE(wip->shockwave.speed, 0);
|
|
|
|
VAR_SET_VALUE_SAVE(wip->turn_time, 0);
|
|
VAR_SET_VALUE_SAVE(wip->fov, 0);
|
|
VAR_SET_VALUE_SAVE(wip->min_lock_time, 0);
|
|
VAR_SET_VALUE_SAVE(wip->lock_pixels_per_sec, 0);
|
|
VAR_SET_VALUE_SAVE(wip->catchup_pixels_per_sec, 0);
|
|
VAR_SET_VALUE_SAVE(wip->catchup_pixel_penalty, 0);
|
|
VAR_SET_VALUE_SAVE(wip->swarm_count, 0);
|
|
VAR_SET_VALUE_SAVE(wip->SwarmWait, 0);
|
|
}
|
|
}
|
|
|
|
void labviewer_make_variables_window(Button *caller)
|
|
{
|
|
if (Lab_variables_window != NULL) {
|
|
return;
|
|
}
|
|
|
|
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));
|
|
|
|
// set our new title
|
|
if (Lab_mode == LAB_MODE_SHIP) {
|
|
Lab_variables_window->SetCaption("Ship Variables");
|
|
} else if (Lab_mode == LAB_MODE_WEAPON) {
|
|
Lab_variables_window->SetCaption("Weapon Variables");
|
|
}
|
|
|
|
// populate the window with our flags (controls both ships and weapons flags)
|
|
labviewer_populate_variables_window();
|
|
|
|
// update content, if we need to
|
|
labviewer_update_variables_window();
|
|
|
|
Lab_variables_window->SetCloseFunction(labviewer_close_variables_window);
|
|
}
|
|
|
|
// -------------------- Render Options Window ------------------------------
|
|
void labviewer_change_detail_texture(Tree *caller)
|
|
{
|
|
int slider_pos = (int)(caller->GetSelectedItem()->GetData());
|
|
Assert( (slider_pos >= 0) && (slider_pos <= MAX_DETAIL_LEVEL) );
|
|
|
|
Detail.hardware_textures = slider_pos;
|
|
}
|
|
|
|
void labviewer_close_render_options_window(GUIObject *caller)
|
|
{
|
|
Lab_render_options_window = NULL;
|
|
}
|
|
|
|
#define ADD_RENDER_FLAG(text, flag, var) { \
|
|
cbp = (Checkbox*)Lab_render_options_window->AddChild(new Checkbox((text), 2, y)); \
|
|
cbp->SetFlag(&(flag), (var)); \
|
|
y += cbp->GetHeight() + 2; \
|
|
}
|
|
|
|
#define ADD_RENDER_BOOL(text, flag) { \
|
|
cbp = (Checkbox*)Lab_render_options_window->AddChild(new Checkbox((text), 2, y)); \
|
|
cbp->SetBool(&(flag)); \
|
|
y += cbp->GetHeight() + 1; \
|
|
}
|
|
|
|
void labviewer_make_render_options_window(Button *caller)
|
|
{
|
|
Checkbox *cbp;
|
|
Tree *cmp;
|
|
TreeItem *ctip;
|
|
int y = 0;
|
|
|
|
if (Lab_render_options_window != NULL) {
|
|
return;
|
|
}
|
|
|
|
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));
|
|
Assert( Lab_render_options_window != NULL );
|
|
|
|
// add all of the flags that we want/need...
|
|
|
|
// viewer flags
|
|
ADD_RENDER_FLAG("Disable Model Rotation", Lab_viewer_flags, LAB_FLAG_NO_ROTATION);
|
|
ADD_RENDER_FLAG("Show Insignia", Lab_viewer_flags, LAB_FLAG_SHOW_INSIGNIA);
|
|
ADD_RENDER_FLAG("Show Damage Lightning", Lab_viewer_flags, LAB_FLAG_LIGHTNING_ARCS);
|
|
ADD_RENDER_FLAG("Rotate Subsystems", Lab_viewer_flags, LAB_FLAG_SUBMODEL_ROTATE);
|
|
|
|
if (Cmdline_postprocess) {
|
|
ADD_RENDER_BOOL("Hide Post Processing", PostProcessing_override);
|
|
ADD_RENDER_BOOL("Use FXAA", Cmdline_fxaa);
|
|
}
|
|
|
|
// map related flags
|
|
ADD_RENDER_BOOL("No Diffuse Map", Basemap_override);
|
|
if (Cmdline_glow) {
|
|
ADD_RENDER_FLAG("No Glow Map", Lab_model_flags, MR_NO_GLOWMAPS);
|
|
}
|
|
if (Cmdline_spec) {
|
|
ADD_RENDER_BOOL("No Specular Map", Specmap_override);
|
|
}
|
|
if (Cmdline_env) {
|
|
ADD_RENDER_BOOL("No Environment Map", Envmap_override);
|
|
}
|
|
if (Cmdline_normal) {
|
|
ADD_RENDER_BOOL("No Normal Map", Normalmap_override);
|
|
}
|
|
if (Cmdline_height) {
|
|
ADD_RENDER_BOOL("No Height Map", Heightmap_override);
|
|
}
|
|
ADD_RENDER_BOOL("No Team Colors", Teamcolor_override);
|
|
ADD_RENDER_BOOL("No Glow Points", Glowpoint_override);
|
|
// model flags
|
|
ADD_RENDER_FLAG("Wireframe", Lab_model_flags, MR_SHOW_OUTLINE_HTL | MR_NO_POLYS | MR_NO_TEXTURING);
|
|
ADD_RENDER_FLAG("Transparent", Lab_model_flags, MR_ALL_XPARENT);
|
|
ADD_RENDER_FLAG("No Lighting", Lab_model_flags, MR_NO_LIGHTING);
|
|
ADD_RENDER_FLAG("No Z-Buffer", Lab_model_flags, MR_NO_ZBUFFER);
|
|
ADD_RENDER_FLAG("No Culling", Lab_model_flags, MR_NO_CULL);
|
|
ADD_RENDER_FLAG("Force Clamp", Lab_model_flags, MR_FORCE_CLAMP);
|
|
ADD_RENDER_FLAG("Show Full Detail", Lab_model_flags, MR_FULL_DETAIL);
|
|
ADD_RENDER_FLAG("Show Pivots", Lab_model_debug_flags, MR_DEBUG_PIVOTS);
|
|
ADD_RENDER_FLAG("Show Paths", Lab_model_debug_flags, MR_DEBUG_PATHS);
|
|
ADD_RENDER_FLAG("Show Bay Paths", Lab_model_debug_flags, MR_DEBUG_BAY_PATHS);
|
|
ADD_RENDER_FLAG("Show Radius", Lab_model_debug_flags, MR_DEBUG_RADIUS);
|
|
ADD_RENDER_FLAG("Show Shields", Lab_model_debug_flags, MR_DEBUG_SHIELDS);
|
|
ADD_RENDER_FLAG("Show Thrusters", Lab_model_flags, MR_SHOW_THRUSTERS);
|
|
ADD_RENDER_FLAG("Show Ship Weapons", Lab_viewer_flags, LAB_FLAG_SHOW_WEAPONS);
|
|
ADD_RENDER_FLAG("Initial Rotation", Lab_viewer_flags, LAB_FLAG_INITIAL_ROTATION);
|
|
ADD_RENDER_FLAG("Show Destroyed Subsystems", Lab_viewer_flags, LAB_FLAG_DESTROYED_SUBSYSTEMS);
|
|
|
|
// start tree
|
|
cmp = (Tree*)Lab_render_options_window->AddChild(new Tree("Detail Options Tree", 0, y + 2, NULL, Lab_render_options_window->GetWidth()));
|
|
|
|
// 3d hardware texture slider options
|
|
ctip = cmp->AddItem(NULL, "3D Hardware Textures", 0, false);
|
|
|
|
cmp->AddItem(ctip, "Minimum", 0, false, labviewer_change_detail_texture);
|
|
cmp->AddItem(ctip, "Low", 1, false, labviewer_change_detail_texture);
|
|
cmp->AddItem(ctip, "Medium", 2, false, labviewer_change_detail_texture);
|
|
cmp->AddItem(ctip, "High", 3, false, labviewer_change_detail_texture);
|
|
cmp->AddItem(ctip, "Maximum", 4, false, labviewer_change_detail_texture);
|
|
|
|
// set close function
|
|
Lab_render_options_window->SetCloseFunction(labviewer_close_render_options_window);
|
|
}
|
|
// ------------------------- Material Override Window ------------------------------
|
|
|
|
void labviewer_close_material_override_window(GUIObject *caller)
|
|
{
|
|
Lab_material_override_window = NULL;
|
|
|
|
Basemap_color_override_set = false;
|
|
Basemap_color_override[0] = 0.0f;
|
|
Basemap_color_override[1] = 0.0f;
|
|
Basemap_color_override[2] = 0.0f;
|
|
Basemap_color_override[3] = 1.0f;
|
|
|
|
Glowmap_color_override_set = false;
|
|
Glowmap_color_override[0] = 0.0f;
|
|
Glowmap_color_override[1] = 0.0f;
|
|
Glowmap_color_override[2] = 0.0f;
|
|
|
|
Specmap_color_override_set = false;
|
|
Specmap_color_override[0] = 0.0f;
|
|
Specmap_color_override[1] = 0.0f;
|
|
Specmap_color_override[2] = 0.0f;
|
|
}
|
|
|
|
void labviewer_set_material_override_diffuse_red(Slider *caller)
|
|
{
|
|
Basemap_color_override[0] = caller->GetSliderValue() / 255.0f;
|
|
}
|
|
|
|
void labviewer_set_material_override_diffuse_green(Slider *caller)
|
|
{
|
|
Basemap_color_override[1] = caller->GetSliderValue() / 255.0f;
|
|
}
|
|
|
|
void labviewer_set_material_override_diffuse_blue(Slider *caller)
|
|
{
|
|
Basemap_color_override[2] = caller->GetSliderValue() / 255.0f;
|
|
}
|
|
void labviewer_set_material_override_glow_red(Slider *caller)
|
|
{
|
|
Glowmap_color_override[0] = caller->GetSliderValue() / 255.0f;
|
|
}
|
|
|
|
void labviewer_set_material_override_glow_green(Slider *caller)
|
|
{
|
|
Glowmap_color_override[1] = caller->GetSliderValue() / 255.0f;
|
|
}
|
|
|
|
void labviewer_set_material_override_glow_blue(Slider *caller)
|
|
{
|
|
Glowmap_color_override[2] = caller->GetSliderValue() / 255.0f;
|
|
}
|
|
|
|
void labviewer_set_material_override_specular_red(Slider *caller)
|
|
{
|
|
Specmap_color_override[0] = caller->GetSliderValue() / 255.0f;
|
|
}
|
|
|
|
void labviewer_set_material_override_specular_green(Slider *caller)
|
|
{
|
|
Specmap_color_override[1] = caller->GetSliderValue() / 255.0f;
|
|
}
|
|
|
|
void labviewer_set_material_override_specular_blue(Slider *caller)
|
|
{
|
|
Specmap_color_override[2] = caller->GetSliderValue() / 255.0f;
|
|
}
|
|
|
|
void labviewer_set_material_override_specular_gloss(Slider *caller)
|
|
{
|
|
Gloss_override = caller->GetSliderValue() / 255.0f;
|
|
}
|
|
|
|
void labviewer_make_material_override_window(Button *caller)
|
|
{
|
|
Checkbox *cbp;
|
|
Slider *sldr;
|
|
int y = 0;
|
|
|
|
if (Lab_material_override_window != NULL) {
|
|
return;
|
|
}
|
|
|
|
Lab_material_override_window = (Window*)Lab_screen->Add(new Window("Material Override", gr_screen.max_w - 300, 200));
|
|
Assert(Lab_material_override_window != NULL);
|
|
|
|
// add all of the flags that we want/need...
|
|
|
|
// map related flags
|
|
|
|
cbp = (Checkbox*)Lab_material_override_window->AddChild(new Checkbox("Override Diffuse Color", 2, y));
|
|
cbp->SetBool(&Basemap_color_override_set);
|
|
y += cbp->GetHeight() + 1;
|
|
|
|
sldr = (Slider*)Lab_material_override_window->AddChild(new Slider("Red", 0.0f, 255.0f, 0, y + 2, labviewer_set_material_override_diffuse_red, 275));
|
|
y += sldr->GetHeight() + 1;
|
|
|
|
sldr = (Slider*)Lab_material_override_window->AddChild(new Slider("Green", 0.0f, 255.0f, 0, y + 2, labviewer_set_material_override_diffuse_green, 275));
|
|
y += sldr->GetHeight() + 1;
|
|
|
|
sldr = (Slider*)Lab_material_override_window->AddChild(new Slider("Blue", 0.0f, 255.0f, 0, y + 2, labviewer_set_material_override_diffuse_blue, 275));
|
|
y += sldr->GetHeight() + 1;
|
|
|
|
if (Cmdline_glow) {
|
|
cbp = (Checkbox*)Lab_material_override_window->AddChild(new Checkbox("Override Glow Color", 2, y));
|
|
cbp->SetBool(&Glowmap_color_override_set);
|
|
y += cbp->GetHeight() + 1;
|
|
|
|
sldr = (Slider*)Lab_material_override_window->AddChild(new Slider("Red", 0.0f, 255.0f, 0, y + 2, labviewer_set_material_override_glow_red, 275));
|
|
y += sldr->GetHeight() + 1;
|
|
|
|
sldr = (Slider*)Lab_material_override_window->AddChild(new Slider("Green", 0.0f, 255.0f, 0, y + 2, labviewer_set_material_override_glow_green, 275));
|
|
y += sldr->GetHeight() + 1;
|
|
|
|
sldr = (Slider*)Lab_material_override_window->AddChild(new Slider("Blue", 0.0f, 255.0f, 0, y + 2, labviewer_set_material_override_glow_blue, 275));
|
|
y += sldr->GetHeight() + 1;
|
|
}
|
|
if (Cmdline_spec) {
|
|
cbp = (Checkbox*)Lab_material_override_window->AddChild(new Checkbox("Override Spec Color", 2, y));
|
|
cbp->SetBool(&Specmap_color_override_set);
|
|
y += cbp->GetHeight() + 1;
|
|
|
|
sldr = (Slider*)Lab_material_override_window->AddChild(new Slider("Red", 0.0f, 255.0f, 0, y + 2, labviewer_set_material_override_specular_red, 275));
|
|
y += sldr->GetHeight() + 1;
|
|
|
|
sldr = (Slider*)Lab_material_override_window->AddChild(new Slider("Green", 0.0f, 255.0f, 0, y + 2, labviewer_set_material_override_specular_green, 275));
|
|
y += sldr->GetHeight() + 1;
|
|
|
|
sldr = (Slider*)Lab_material_override_window->AddChild(new Slider("Blue", 0.0f, 255.0f, 0, y + 2, labviewer_set_material_override_specular_blue, 275));
|
|
y += sldr->GetHeight() + 1;
|
|
|
|
cbp = (Checkbox*)Lab_material_override_window->AddChild(new Checkbox("Override Gloss", 2, y));
|
|
cbp->SetBool(&Gloss_override_set);
|
|
y += cbp->GetHeight() + 1;
|
|
|
|
sldr = (Slider*)Lab_material_override_window->AddChild(new Slider("Gloss", 0.0f, 255.0f, 0, y + 2, labviewer_set_material_override_specular_gloss, 275));
|
|
y += sldr->GetHeight() + 1;
|
|
}
|
|
|
|
// set close function
|
|
Lab_material_override_window->SetCloseFunction(labviewer_close_material_override_window);
|
|
}
|
|
|
|
// ------------------------- Description Window ------------------------------
|
|
void labviewer_close_desc_window(GUIObject *caller)
|
|
{
|
|
Lab_description_text = NULL;
|
|
Lab_description_window = NULL;
|
|
}
|
|
|
|
void labviewer_update_desc_window()
|
|
{
|
|
if ( (Lab_description_window == NULL) || (Lab_description_text == NULL) ) {
|
|
return;
|
|
}
|
|
|
|
if (Lab_selected_index != -1) {
|
|
if (Lab_mode == LAB_MODE_SHIP) {
|
|
Lab_description_window->SetCaption(Ship_info[Lab_selected_index].name);
|
|
|
|
if (Ship_info[Lab_selected_index].tech_desc != NULL) {
|
|
Lab_description_text->SetText(Ship_info[Lab_selected_index].tech_desc);
|
|
} else {
|
|
Lab_description_text->SetText("No description available.");
|
|
}
|
|
} else if (Lab_mode == LAB_MODE_WEAPON) {
|
|
Lab_description_window->SetCaption(Weapon_info[Lab_selected_index].name);
|
|
|
|
if (Weapon_info[Lab_selected_index].tech_desc != NULL) {
|
|
Lab_description_text->SetText(Weapon_info[Lab_selected_index].tech_desc);
|
|
} else {
|
|
Lab_description_text->SetText("No description available.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void labviewer_make_desc_window(Button *caller)
|
|
{
|
|
if (Lab_description_window != NULL) {
|
|
return;
|
|
}
|
|
|
|
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,
|
|
gr_screen.center_offset_y + gr_screen.center_h - gr_screen.center_h/6 - 50, gr_screen.center_w/3,
|
|
gr_screen.center_h/6));
|
|
Lab_description_text = (Text*)Lab_description_window->AddChild(new Text("Description Text", "No ship selected.", 0, 0));
|
|
|
|
labviewer_update_desc_window();
|
|
|
|
Lab_description_window->SetCloseFunction(labviewer_close_desc_window);
|
|
}
|
|
|
|
// ------------------------ Ships Window -----------------------------------
|
|
void labviewer_make_ship_window(Button *caller)
|
|
{
|
|
GUIObject *cbp;
|
|
TreeItem *ctip, *stip;
|
|
int x, idx;
|
|
|
|
if (Lab_mode == LAB_MODE_SHIP) {
|
|
return;
|
|
}
|
|
|
|
|
|
// switch the class window to ship mode
|
|
labviewer_set_class_window(LAB_MODE_SHIP);
|
|
|
|
if ( (Lab_class_window == NULL) || (Lab_class_toolbar == NULL) ) {
|
|
Int3();
|
|
Lab_mode = LAB_MODE_SHIP;
|
|
return;
|
|
}
|
|
|
|
|
|
// populate the class toolbar
|
|
x = 0;
|
|
cbp = Lab_class_toolbar->AddChild(new Button("Class Description", x, 0, labviewer_make_desc_window));
|
|
|
|
x += cbp->GetWidth() + 10;
|
|
cbp = Lab_class_toolbar->AddChild(new Button("Class Options", x, 0, labviewer_make_flags_window));
|
|
|
|
x += cbp->GetWidth() + 10;
|
|
cbp = Lab_class_toolbar->AddChild(new Button("Class Variables", x, 0, labviewer_make_variables_window));
|
|
|
|
|
|
// populate ship class window
|
|
Tree *cmp = (Tree*)Lab_class_window->AddChild(new Tree("Ship Tree", 0, 0));
|
|
|
|
if (Lab_species_nodes != NULL) {
|
|
for (idx = 0; idx < (int)Species_info.size(); idx++) {
|
|
Lab_species_nodes[idx]->ClearAllItems();
|
|
}
|
|
|
|
delete [] Lab_species_nodes;
|
|
Lab_species_nodes = NULL;
|
|
}
|
|
|
|
Lab_species_nodes = new TreeItem*[Species_info.size()+1];
|
|
|
|
// Add species nodes
|
|
for (idx = 0; idx < (int)Species_info.size(); idx++) {
|
|
Lab_species_nodes[idx] = cmp->AddItem(NULL, Species_info[idx].species_name, 0, false);
|
|
}
|
|
|
|
// Just in case. I don't actually think this is possible though.
|
|
Lab_species_nodes[Species_info.size()] = cmp->AddItem(NULL, "Other", 0, false);
|
|
|
|
// Now add the ships
|
|
SCP_string lod_name;
|
|
char buf[33];
|
|
|
|
for (auto it = Ship_info.cbegin(); it != Ship_info.cend(); ++it) {
|
|
if ( (it->species >= 0) && (it->species < (int)Species_info.size()) ) {
|
|
stip = Lab_species_nodes[it->species];
|
|
} else {
|
|
stip = Lab_species_nodes[Species_info.size()];
|
|
}
|
|
|
|
ctip = cmp->AddItem(stip, it->name, (int)std::distance(Ship_info.cbegin(), it), false, labviewer_change_ship);
|
|
|
|
if ( !Lab_in_mission ) {
|
|
for (int j = 0; j < it->num_detail_levels; j++) {
|
|
sprintf(buf, "%d", j);
|
|
lod_name = "LOD ";
|
|
lod_name += buf;
|
|
|
|
cmp->AddItem(ctip, lod_name, j, false, labviewer_change_ship_lod);
|
|
}
|
|
|
|
cmp->AddItem(ctip, "Debris", 99, false, labviewer_change_ship_lod);
|
|
}
|
|
}
|
|
|
|
// if any nodes are empty, just add a single "<none>" entry so we know that species doesn't have anything yet
|
|
// No the <= is not a mistake :)
|
|
for (idx = 0; idx < (int)Species_info.size(); idx++) {
|
|
if ( !Lab_species_nodes[idx]->HasChildren() ) {
|
|
cmp->AddItem(Lab_species_nodes[idx], "<none>", 0, false, NULL);
|
|
}
|
|
}
|
|
|
|
// if the "Other" entry doesn't contain anything then just delete it
|
|
if ( !Lab_species_nodes[Species_info.size()]->HasChildren() ) {
|
|
delete Lab_species_nodes[Species_info.size()];
|
|
}
|
|
|
|
|
|
// and... we're done!
|
|
Lab_mode = LAB_MODE_SHIP;
|
|
|
|
// populate the flags window, if it exists
|
|
// (NOTE: must be done *after* Lab_mode is set properly)
|
|
if (Lab_flags_window != NULL) {
|
|
Lab_flags_window->SetCaption("Ship Flags");
|
|
|
|
labviewer_populate_flags_window();
|
|
labviewer_update_flags_window();
|
|
}
|
|
|
|
if (Lab_description_window != NULL) {
|
|
labviewer_update_desc_window();
|
|
}
|
|
|
|
if (Lab_variables_window != NULL) {
|
|
Lab_variables_window->SetCaption("Ship Variables");
|
|
|
|
labviewer_populate_variables_window();
|
|
labviewer_update_variables_window();
|
|
}
|
|
}
|
|
|
|
void labviewer_change_ship_lod(Tree* caller)
|
|
{
|
|
int ship_index = (int)(caller->GetSelectedItem()->GetParentItem()->GetData());
|
|
Assert( ship_index >= 0 );
|
|
|
|
if (Lab_selected_object == -1)
|
|
{
|
|
// Goober5000 - The lab loads subsystems into its special lab-specific vector, but normally subsystems are loaded into the Ship_info
|
|
// entry. Note also that models are only loaded once each. If a lab model was previously loaded using the "lightweight" method,
|
|
// 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
|
|
// of error-checking and then immediately cleared so that it can be subsequently loaded the lab way.
|
|
|
|
// reset any existing model/bitmap that is showing
|
|
labviewer_change_model(NULL);
|
|
labviewer_change_bitmap();
|
|
|
|
The_mission.ai_profile = &Ai_profiles[Default_ai_profile];
|
|
Lab_selected_object = ship_create(&vmd_identity_matrix, &vmd_zero_vector, ship_index);
|
|
|
|
// unload the model we just loaded
|
|
model_page_out_textures(Ship_info[ship_index].model_num, true);
|
|
model_unload(Ship_info[ship_index].model_num);
|
|
Ship_info[ship_index].model_num = -1;
|
|
}
|
|
else
|
|
{
|
|
obj_delete(Lab_selected_object);
|
|
Lab_selected_object = ship_create(&vmd_identity_matrix, &vmd_zero_vector, ship_index);
|
|
}
|
|
|
|
Lab_last_selected_ship = Lab_selected_index;
|
|
|
|
labviewer_change_model(Ship_info[ship_index].pof_file, caller->GetSelectedItem()->GetData(), ship_index);
|
|
|
|
if (Ship_info[ship_index].uses_team_colors) {
|
|
Lab_team_color = Ship_info[ship_index].default_team_name;
|
|
} else {
|
|
Lab_team_color = "<none>";
|
|
}
|
|
|
|
labviewer_update_desc_window();
|
|
labviewer_update_flags_window();
|
|
labviewer_update_variables_window();
|
|
|
|
for (int i = 0; i < MAX_SHIP_ARCS; i++) {
|
|
Lab_arc_timestamp[i] = -1;
|
|
Lab_arc_type[i] = MARC_TYPE_NORMAL;
|
|
Lab_arc_next_time = -1;
|
|
}
|
|
}
|
|
|
|
void labviewer_change_ship(Tree *caller)
|
|
{
|
|
// this is really only for when we are in a mission
|
|
if ( !Lab_in_mission ) {
|
|
return;
|
|
}
|
|
|
|
Lab_selected_index = (int)(caller->GetSelectedItem()->GetData());
|
|
|
|
labviewer_update_desc_window();
|
|
labviewer_update_flags_window();
|
|
labviewer_update_variables_window();
|
|
}
|
|
|
|
// --------------------------- Weapons Window --------------------------------
|
|
void labviewer_show_tech_model(Tree *caller)
|
|
{
|
|
int weap_index = (int)(caller->GetSelectedItem()->GetParentItem()->GetData());
|
|
Assert( weap_index >= 0 );
|
|
|
|
labviewer_change_model(Weapon_info[weap_index].tech_model, caller->GetSelectedItem()->GetData(), weap_index);
|
|
}
|
|
|
|
void labviewer_show_external_model(Tree *caller)
|
|
{
|
|
int weap_index = (int)(caller->GetSelectedItem()->GetParentItem()->GetData());
|
|
Assert( weap_index >= 0 );
|
|
|
|
labviewer_change_model(Weapon_info[weap_index].external_model_name, caller->GetSelectedItem()->GetData(), weap_index);
|
|
}
|
|
|
|
extern void weapon_load_bitmaps(int weapon_index);
|
|
void labviewer_change_weapon(Tree *caller)
|
|
{
|
|
int weap_index = (int)(caller->GetSelectedItem()->GetData());
|
|
Assert( weap_index >= 0 );
|
|
|
|
if ( !(Weapon_info[weap_index].wi_flags[Weapon::Info_Flags::Beam]) ) {
|
|
switch (Weapon_info[weap_index].render_type) {
|
|
case WRT_POF:
|
|
labviewer_change_bitmap();
|
|
labviewer_change_model(Weapon_info[weap_index].pofbitmap_name, 0, weap_index);
|
|
weapon_load_bitmaps(weap_index);
|
|
break;
|
|
|
|
case WRT_LASER:
|
|
labviewer_change_model(NULL);
|
|
labviewer_change_bitmap(-1, weap_index);
|
|
break;
|
|
|
|
default:
|
|
labviewer_change_model(NULL);
|
|
labviewer_change_bitmap();
|
|
break;
|
|
}
|
|
}
|
|
|
|
Lab_selected_index = weap_index;
|
|
Lab_last_selected_weapon = Lab_selected_index;
|
|
|
|
labviewer_update_desc_window();
|
|
labviewer_update_flags_window();
|
|
labviewer_update_variables_window();
|
|
}
|
|
|
|
// weapon window create function
|
|
void labviewer_make_weap_window(Button* caller)
|
|
{
|
|
GUIObject *cbp;
|
|
TreeItem *cwip, *stip;
|
|
int x;
|
|
|
|
if (Lab_mode == LAB_MODE_WEAPON) {
|
|
return;
|
|
}
|
|
|
|
|
|
// switch the class window to weapon mode
|
|
labviewer_set_class_window(LAB_MODE_WEAPON);
|
|
|
|
if ( (Lab_class_window == NULL) || (Lab_class_toolbar == NULL) ) {
|
|
Int3();
|
|
Lab_mode = LAB_MODE_WEAPON;
|
|
return;
|
|
}
|
|
|
|
|
|
// populate the weapons toolbar
|
|
x = 0;
|
|
cbp = Lab_class_toolbar->AddChild(new Button("Class Description", x, 0, labviewer_make_desc_window));
|
|
|
|
x += cbp->GetWidth() + 10;
|
|
cbp = Lab_class_toolbar->AddChild(new Button("Class Options", x, 0, labviewer_make_flags_window));
|
|
|
|
x += cbp->GetWidth() + 10;
|
|
cbp = Lab_class_toolbar->AddChild(new Button("Class Variables", x, 0, labviewer_make_variables_window));
|
|
|
|
|
|
// populate the weapons window
|
|
Tree *cmp = (Tree*)Lab_class_window->AddChild(new Tree("Weapon Tree", 0, 0));
|
|
|
|
// Unfortunately these are hardcoded
|
|
TreeItem **type_nodes = new TreeItem*[Num_weapon_subtypes];
|
|
int i;
|
|
|
|
// Add type nodes
|
|
for (i = 0; i < Num_weapon_subtypes; i++) {
|
|
type_nodes[i] = cmp->AddItem(NULL, Weapon_subtype_names[i], 0, false);
|
|
}
|
|
|
|
// Now add the weapons
|
|
for (i = 0; i < Num_weapon_types; i++) {
|
|
if (Weapon_info[i].subtype == WP_UNUSED) {
|
|
continue;
|
|
} else if (Weapon_info[i].subtype >= Num_weapon_subtypes) {
|
|
Warning(LOCATION, "Invalid weapon subtype found on weapon %s", Weapon_info[i].name);
|
|
continue;
|
|
}
|
|
|
|
if (Weapon_info[i].wi_flags[Weapon::Info_Flags::Beam]) {
|
|
stip = type_nodes[WP_BEAM];
|
|
} else {
|
|
stip = type_nodes[Weapon_info[i].subtype];
|
|
}
|
|
|
|
cwip = cmp->AddItem(stip, Weapon_info[i].name, i, false, labviewer_change_weapon);
|
|
|
|
if (Weapon_info[i].tech_model[0] != '\0') {
|
|
cmp->AddItem(cwip, "Tech Model", 0, false, labviewer_show_tech_model);
|
|
}
|
|
if (Weapon_info[i].external_model_name[0] != '\0') {
|
|
cmp->AddItem(cwip, "External Model", 0, false, labviewer_show_external_model);
|
|
}
|
|
}
|
|
|
|
// Get rid of any empty nodes
|
|
for (i = 0; i < Num_weapon_subtypes; i++) {
|
|
if ( !type_nodes[i]->HasChildren() ) {
|
|
delete type_nodes[i];
|
|
}
|
|
}
|
|
delete[] type_nodes;
|
|
|
|
Lab_mode = LAB_MODE_WEAPON;
|
|
|
|
// populate the flags window, if it exists
|
|
// (NOTE: must be done *after* Lab_mode is set properly)
|
|
if (Lab_flags_window != NULL) {
|
|
Lab_flags_window->SetCaption("Weapon Flags");
|
|
|
|
labviewer_populate_flags_window();
|
|
labviewer_update_flags_window();
|
|
}
|
|
|
|
if (Lab_description_window != NULL) {
|
|
labviewer_update_desc_window();
|
|
}
|
|
|
|
if (Lab_variables_window != NULL) {
|
|
Lab_variables_window->SetCaption("Weapon Variables");
|
|
|
|
labviewer_populate_variables_window();
|
|
labviewer_update_variables_window();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------- Lab functions ---------------------------------
|
|
|
|
void lab_init()
|
|
{
|
|
GUIObject *cbp;
|
|
int x,i;
|
|
|
|
weapon_pause_sounds();
|
|
|
|
if (gameseq_get_pushed_state() == GS_STATE_GAME_PLAY) {
|
|
Lab_in_mission = true;
|
|
} else {
|
|
Lab_in_mission = false;
|
|
}
|
|
|
|
if (Lab_in_mission) {
|
|
Lab_screen_save_bitmap = gr_save_screen();
|
|
gr_create_shader(&Lab_shader, 0, 0, 0, 127);
|
|
} else {
|
|
gr_set_clear_color(0, 0, 0);
|
|
}
|
|
|
|
|
|
//We start by creating the screen/toolbar
|
|
Lab_screen = GUI_system.PushScreen(new GUIScreen("Lab"));
|
|
|
|
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));
|
|
|
|
// start filling the main toolbar
|
|
x = 0;
|
|
cbp = Lab_toolbar->AddChild(new Button("Ships", x, 0, labviewer_make_ship_window));
|
|
|
|
x += cbp->GetWidth() + 10;
|
|
cbp = Lab_toolbar->AddChild(new Button("Weapons", x, 0, labviewer_make_weap_window));
|
|
|
|
if ( !Lab_in_mission ) {
|
|
x += cbp->GetWidth() + 10;
|
|
cbp = Lab_toolbar->AddChild(new Button("Render Options", x, 0, labviewer_make_render_options_window));
|
|
|
|
x += cbp->GetWidth() + 10;
|
|
cbp = Lab_toolbar->AddChild(new Button("Material Overrides", x, 0, labviewer_make_material_override_window));
|
|
}
|
|
|
|
x += cbp->GetWidth() + 20;
|
|
cbp = Lab_toolbar->AddChild(new Button("Exit", x, 0, labviewer_exit));
|
|
|
|
|
|
// reset some defaults, just to be sure
|
|
Lab_viewer_zoom = 1.2f;
|
|
Lab_viewer_pos.xyz.x = Lab_viewer_pos.xyz.y = 0.0f;
|
|
Lab_mode = LAB_MODE_NONE;
|
|
Lab_thrust_len = 1.0f;
|
|
Lab_thrust_afterburn = false;
|
|
Lab_arc_next_time = -1;
|
|
Lab_arc_disrupted = false;
|
|
for (i = 0; i < MAX_SHIP_WEAPONS; i++) {
|
|
Lab_weaponmodel_num[i] = -1;
|
|
}
|
|
|
|
// save detail options
|
|
Lab_detail_texture_save = Detail.hardware_textures;
|
|
if ( !Lab_in_mission ) {
|
|
// load up the list of insignia that we might use on the ships
|
|
pilot_load_squad_pic_list();
|
|
|
|
// the default insignia bitmap
|
|
Lab_insignia_index = 0;
|
|
Assert( (Lab_insignia_index < Num_pilot_squad_images) );
|
|
|
|
Lab_insignia_bitmap = bm_load_duplicate(Pilot_squad_image_names[Lab_insignia_index]);
|
|
}
|
|
|
|
// enable post-processing by default in the lab
|
|
PostProcessing_override = false;
|
|
// disable model rotation by default in the lab
|
|
Lab_viewer_flags |= LAB_FLAG_NO_ROTATION;
|
|
Lab_viewer_flags |= LAB_FLAG_INITIAL_ROTATION;
|
|
}
|
|
|
|
#include "controlconfig/controlsconfig.h"
|
|
void lab_do_frame(float frametime)
|
|
{
|
|
gr_reset_clip();
|
|
gr_clear();
|
|
|
|
if (Lab_in_mission) {
|
|
gr_restore_screen(Lab_screen_save_bitmap);
|
|
gr_set_shader(&Lab_shader);
|
|
gr_shade(0, 0, gr_screen.max_w, gr_screen.max_h, GR_RESIZE_NONE);
|
|
} else {
|
|
labviewer_do_render(frametime);
|
|
}
|
|
|
|
|
|
bool test1 = ( GUI_system.OnFrame(frametime, !(Trackball_active) ? true : false, false) == GSOF_NOTHINGPRESSED );
|
|
|
|
if (test1) {
|
|
int key = GUI_system.GetKeyPressed();
|
|
int status = GUI_system.GetStatus();
|
|
|
|
// set trackball modes
|
|
if (status & GST_MOUSE_LEFT_BUTTON) {
|
|
Trackball_active = 1;
|
|
Trackball_mode = 1; // rotate
|
|
|
|
if ( key_get_shift_status() & KEY_SHIFTED ) {
|
|
Trackball_mode = 2; // pan
|
|
}
|
|
} else if (status & GST_MOUSE_RIGHT_BUTTON) {
|
|
Trackball_active = 1;
|
|
Trackball_mode = 3; // Zoom
|
|
} else if ( !mouse_down(MOUSE_LEFT_BUTTON | MOUSE_RIGHT_BUTTON) ) {
|
|
// reset trackball modes
|
|
Trackball_active = 0;
|
|
Trackball_mode = 0;
|
|
}
|
|
|
|
//Due to switch scoping rules, this has to be declared here
|
|
SCP_map<SCP_string, team_color>::iterator color_itr = Team_Colors.find(Lab_team_color);
|
|
// handle any key presses
|
|
switch (key) {
|
|
// switch between the current insignia bitmap to render with
|
|
case KEY_DIVIDE: {
|
|
if ( !(Lab_viewer_flags & LAB_FLAG_SHOW_INSIGNIA) ) {
|
|
break;
|
|
}
|
|
|
|
Lab_insignia_index = (Lab_insignia_index+1) % Num_pilot_squad_images;
|
|
Assert( (Lab_insignia_index >= 0) && (Lab_insignia_index < Num_pilot_squad_images) );
|
|
|
|
if (Lab_insignia_bitmap >= 0) {
|
|
bm_release(Lab_insignia_bitmap);
|
|
Lab_insignia_bitmap = -1;
|
|
}
|
|
|
|
Lab_insignia_bitmap = bm_load_duplicate(Pilot_squad_image_names[Lab_insignia_index]);
|
|
|
|
break;
|
|
}
|
|
|
|
// change between damage lightning effects
|
|
case KEY_L:
|
|
Lab_arc_disrupted = !Lab_arc_disrupted;
|
|
Lab_arc_next_time = -1;
|
|
break;
|
|
|
|
// Adjust FXAA presets
|
|
case KEY_0:
|
|
if (!PostProcessing_override)
|
|
Cmdline_fxaa_preset = 0;
|
|
break;
|
|
case KEY_1:
|
|
if (!PostProcessing_override)
|
|
Cmdline_fxaa_preset = 1;
|
|
break;
|
|
case KEY_2:
|
|
if (!PostProcessing_override)
|
|
Cmdline_fxaa_preset = 2;
|
|
break;
|
|
case KEY_3:
|
|
if (!PostProcessing_override)
|
|
Cmdline_fxaa_preset = 3;
|
|
break;
|
|
case KEY_4:
|
|
if (!PostProcessing_override)
|
|
Cmdline_fxaa_preset = 4;
|
|
break;
|
|
case KEY_5:
|
|
if (!PostProcessing_override)
|
|
Cmdline_fxaa_preset = 5;
|
|
break;
|
|
case KEY_6:
|
|
if (!PostProcessing_override)
|
|
Cmdline_fxaa_preset = 6;
|
|
break;
|
|
case KEY_7:
|
|
if (!PostProcessing_override)
|
|
Cmdline_fxaa_preset = 7;
|
|
break;
|
|
case KEY_8:
|
|
if (!PostProcessing_override)
|
|
Cmdline_fxaa_preset = 8;
|
|
break;
|
|
case KEY_9:
|
|
if (!PostProcessing_override)
|
|
Cmdline_fxaa_preset = 9;
|
|
break;
|
|
|
|
//adjust bloom intensity
|
|
case KEY_B:
|
|
if (!PostProcessing_override) {
|
|
Cmdline_bloom_intensity++;
|
|
if (Cmdline_bloom_intensity > 200)
|
|
Cmdline_bloom_intensity = 200;
|
|
}
|
|
break;
|
|
case KEY_N:
|
|
if (!PostProcessing_override) {
|
|
Cmdline_bloom_intensity--;
|
|
if (Cmdline_bloom_intensity < 0)
|
|
Cmdline_bloom_intensity = 0;
|
|
}
|
|
break;
|
|
|
|
case KEY_T:
|
|
if (color_itr == Team_Colors.begin()) {
|
|
color_itr = --Team_Colors.end();
|
|
Lab_team_color = color_itr->first;
|
|
} else {
|
|
--color_itr;
|
|
Lab_team_color = color_itr->first;
|
|
}
|
|
break;
|
|
|
|
case KEY_Y:
|
|
++color_itr;
|
|
if (color_itr == Team_Colors.end())
|
|
color_itr = Team_Colors.begin();
|
|
Lab_team_color = color_itr->first;
|
|
break;
|
|
|
|
// bail...
|
|
case KEY_ESC:
|
|
labviewer_exit(NULL);
|
|
break;
|
|
|
|
default: {
|
|
// check for game-specific controls
|
|
if (Lab_mode == LAB_MODE_SHIP) {
|
|
if ( check_control(PLUS_5_PERCENT_THROTTLE, key) )
|
|
Lab_thrust_len += 0.05f;
|
|
else if ( check_control(MINUS_5_PERCENT_THROTTLE, key) )
|
|
Lab_thrust_len -= 0.05f;
|
|
|
|
CLAMP( Lab_thrust_len, 0.0f, 1.0f );
|
|
|
|
if ( check_control(AFTERBURNER, key) )
|
|
Lab_thrust_afterburn = !Lab_thrust_afterburn;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
gr_flip();
|
|
}
|
|
|
|
void lab_close()
|
|
{
|
|
int i;
|
|
|
|
Lab_toolbar = NULL;
|
|
Lab_class_toolbar = NULL;
|
|
Lab_class_window = NULL;
|
|
Lab_flags_window = NULL;
|
|
Lab_render_options_window = NULL;
|
|
|
|
delete Lab_screen;
|
|
|
|
Lab_screen = NULL;
|
|
|
|
|
|
if (Lab_species_nodes != NULL) {
|
|
for (i = 0; i < (int)Species_info.size(); i++) {
|
|
delete Lab_species_nodes[i];
|
|
}
|
|
|
|
delete[] Lab_species_nodes;
|
|
Lab_species_nodes = NULL;
|
|
}
|
|
|
|
if (Lab_insignia_bitmap >= 0) {
|
|
bm_release(Lab_insignia_bitmap);
|
|
Lab_insignia_bitmap = -1;
|
|
}
|
|
|
|
Lab_insignia_index = -1;
|
|
|
|
if (Lab_model_num != -1) {
|
|
model_page_out_textures(Lab_model_num, true);
|
|
model_unload(Lab_model_num);
|
|
Lab_model_num = -1;
|
|
}
|
|
|
|
for (i = 0; i < MAX_SHIP_WEAPONS; i++) {
|
|
if (Lab_weaponmodel_num[i] >= 0) {
|
|
model_page_out_textures(Lab_weaponmodel_num[i], true);
|
|
model_unload(Lab_weaponmodel_num[i]);
|
|
Lab_weaponmodel_num[i] = -1;
|
|
}
|
|
}
|
|
|
|
if (Lab_screen_save_bitmap != 1) {
|
|
gr_free_screen(Lab_screen_save_bitmap);
|
|
Lab_screen_save_bitmap = -1;
|
|
}
|
|
|
|
Lab_ship_model_subsys.clear();
|
|
|
|
if (Lab_ship_subsys != NULL) {
|
|
delete[] Lab_ship_subsys;
|
|
Lab_ship_subsys = NULL;
|
|
}
|
|
|
|
memset( Lab_model_filename, 0, sizeof(Lab_model_filename) );
|
|
|
|
Basemap_override = false;
|
|
Envmap_override = false;
|
|
Specmap_override = false;
|
|
Normalmap_override = false;
|
|
Heightmap_override = false;
|
|
Glowpoint_override = false;
|
|
PostProcessing_override = false;
|
|
|
|
// reset detail levels to default
|
|
Detail.hardware_textures = Lab_detail_texture_save;
|
|
|
|
weapon_unpause_sounds();
|
|
//audiostream_unpause_all();
|
|
game_flush();
|
|
}
|