Files
fs2open.github.com/code/lab/lab.cpp
T

1097 lines
32 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.
*
*/
/*
* $Logfile: /Freespace2/code/lab/lab.cpp $
* $Revision: 1.26 $
* $Date: 2006-01-18 16:17:33 $
* $Author: taylor $
*
* $Log: not supported by cvs2svn $
* Revision 1.25 2005/12/29 08:08:36 wmcoolmon
* Codebase commit, most notably including objecttypes.tbl
*
* Revision 1.24 2005/12/04 19:12:53 wmcoolmon
* Post-final commit
*
* Revision 1.22 2005/10/30 06:44:57 wmcoolmon
* Codebase commit - nebula.tbl, scripting, new dinky explosion/shockwave stuff, moving muzzle flashes
*
* Revision 1.21 2005/10/17 01:54:15 wmcoolmon
* Make weapons clip less
*
* Revision 1.20 2005/10/17 01:51:01 wmcoolmon
* Weapon models now shown in lab
*
* Revision 1.19 2005/10/09 09:18:10 wmcoolmon
* Added warpin/warpout speed values to the lab
*
* Revision 1.18 2005/10/09 00:43:08 wmcoolmon
* Extendable modular tables (XMTs); added weapon dialogs to the Lab
*
* Revision 1.17 2005/09/25 07:27:33 Goober5000
* and again
* --Goober5000
*
* Revision 1.16 2005/09/25 07:26:05 Goober5000
* try to fix the headers
* --Goober5000
*
*/
#include "wmcgui.h"
#include "gamesequence/gamesequence.h"
#include "io/key.h"
#include "freespace2/freespace.h"
#include "cmdline/cmdline.h"
#include "ship/ship.h"
#include "weapon/weapon.h"
#include "render/3d.h"
#include "lighting/lighting.h"
#include "model/model.h"
#include "missionui/missionscreencommon.h"
#include "weapon/beam.h"
#include "mission/missionparse.h"
#include "species_defs/species_defs.h"
//All sorts of globals
static GUIScreen *Lab_screen = NULL;
static int Selected_weapon_index = -1;
static int LabViewerShipIndex = -1;
static int LabViewerModelNum = -1;
static int LabViewerModelLOD = 0;
static int ModelFlags = MR_LOCK_DETAIL | MR_AUTOCENTER | MR_NO_FOGGING;
void change_ship_lod(Tree* caller);
//*****************************Ship Options Window*******************************
static Window* ShipOptWin = NULL;
#define NUM_SHIP_FLAGS 50
Checkbox *soc[NUM_SHIP_FLAGS];
void set_ship_flags_ship(ship_info *sip)
{
unsigned int i=0;
soc[i++]->SetFlag(&sip->flags, SIF_SUPPORT);
soc[i++]->SetFlag(&sip->flags, SIF_CARGO);
soc[i++]->SetFlag(&sip->flags, SIF_FIGHTER);
soc[i++]->SetFlag(&sip->flags, SIF_BOMBER);
soc[i++]->SetFlag(&sip->flags, SIF_CRUISER);
soc[i++]->SetFlag(&sip->flags, SIF_CORVETTE);
soc[i++]->SetFlag(&sip->flags, SIF_FREIGHTER);
soc[i++]->SetFlag(&sip->flags, SIF_CAPITAL);
soc[i++]->SetFlag(&sip->flags, SIF_TRANSPORT);
soc[i++]->SetFlag(&sip->flags, SIF_NAVBUOY);
soc[i++]->SetFlag(&sip->flags, SIF_SENTRYGUN);
soc[i++]->SetFlag(&sip->flags, SIF_ESCAPEPOD);
soc[i++]->SetFlag(&sip->flags, SIF_GAS_MINER);
soc[i++]->SetFlag(&sip->flags, SIF_AWACS);
soc[i++]->SetFlag(&sip->flags, SIF_STEALTH);
soc[i++]->SetFlag(&sip->flags, SIF_SUPERCAP);
soc[i++]->SetFlag(&sip->flags, SIF_KNOSSOS_DEVICE);
soc[i++]->SetFlag(&sip->flags, SIF_DRYDOCK);
soc[i++]->SetFlag(&sip->flags, SIF_SHIP_COPY);
soc[i++]->SetFlag(&sip->flags, SIF_BIG_DAMAGE);
soc[i++]->SetFlag(&sip->flags, SIF_HAS_AWACS);
soc[i++]->SetFlag(&sip->flags, SIF_SHIP_CLASS_DONT_COLLIDE_INVIS);
soc[i++]->SetFlag(&sip->flags, SIF_DO_COLLISION_CHECK);
soc[i++]->SetFlag(&sip->flags, SIF_PLAYER_SHIP);
soc[i++]->SetFlag(&sip->flags, SIF_DEFAULT_PLAYER_SHIP);
soc[i++]->SetFlag(&sip->flags, SIF_BALLISTIC_PRIMARIES);
soc[i++]->SetFlag(&sip->flags, SIF2_FLASH);
soc[i++]->SetFlag(&sip->flags, SIF2_SURFACE_SHIELDS);
soc[i++]->SetFlag(&sip->flags, SIF2_SHOW_SHIP_MODEL);
soc[i++]->SetFlag(&sip->flags, SIF_IN_TECH_DATABASE);
soc[i++]->SetFlag(&sip->flags, SIF_IN_TECH_DATABASE_M);
//ShipOptWin->SetCaption(sip->name);
}
void zero_ship_flags_win(GUIObject *caller)
{
ShipOptWin = NULL;
}
void ship_flags_window(Button *caller)
{
if(ShipOptWin != NULL)
return;
GUIObject* cwp = Lab_screen->Add(new Window("Ship options", gr_screen.max_w - 200, 200));
ShipOptWin = (Window*)cwp;
unsigned int i=0;
int y = 0;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("SUPPORT", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("CARGO", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("FIGHTER", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("BOMBER", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("CRUISER", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("CORVETTE", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("FREIGHTER", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("CAPITAL", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("TRANSPORT", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("NAVBUOY", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("SENTRYGUN", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("ESCAPEPOD", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("GAS MINER", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("AWACS", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("STEALTH", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("SUPERCAP", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("KNOSSOS DEVICE", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("DRYDOCK", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("SHIP COPY", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("BIG DAMAGE", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("HAS AWACS", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("NO COLLIDE INVISIBLE", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("DO COLLISION CHECK", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("PLAYER SHIP", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("DEFAULT PLAYER SHIP", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("BALLISTIC PRIMARIES", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("FLASH", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("SURFACE SHIELDS", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("SHOW SHIP MODEL", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("IN TECH DATABASE", 0, y));
y += soc[i++]->GetHeight() + 10;
soc[i] = (Checkbox*) cwp->AddChild(new Checkbox("IN TECH DATABASE MULTI", 0, y));
if(LabViewerShipIndex != -1)
set_ship_flags_ship(&Ship_info[LabViewerShipIndex]);
cwp->SetCloseFunction(zero_ship_flags_win);
}
//*****************************Ship Variables Window*******************************
static Window* ShipVarWin = NULL;
#define NUM_SHIP_VARIABLES 50
Text *svt[NUM_SHIP_VARIABLES];
#define SVW_SET_SI_VAR(var) svt[i]->SetText(sip->var); \
svt[i++]->SetSaveLoc(&sip->var, T_ST_ONENTER)
#define SVW_SET_VAR(var) svt[i]->SetText(var); \
svt[i++]->SetSaveLoc(&var, T_ST_ONENTER)
extern int Hud_shield_filename_count;
extern int Num_species;
void set_ship_variables_ship(ship_info *sip)
{
unsigned int i=0;
svt[i++]->SetText(sip->name);
svt[i]->SetText(sip->species);
svt[i++]->SetSaveLoc(&sip->species, T_ST_ONENTER, Num_species-1, 0);
svt[i]->SetText(sip->class_type);
svt[i++]->SetSaveLoc(&sip->class_type, T_ST_ONENTER, Ship_types.size()-1, 0);
SVW_SET_SI_VAR(density);
SVW_SET_SI_VAR(damp);
SVW_SET_SI_VAR(rotdamp);
SVW_SET_SI_VAR(max_vel.xyz.x);
SVW_SET_SI_VAR(max_vel.xyz.y);
SVW_SET_SI_VAR(max_vel.xyz.z);
SVW_SET_SI_VAR(warpin_speed);
SVW_SET_SI_VAR(warpout_speed);
SVW_SET_SI_VAR(max_shield_strength);
SVW_SET_SI_VAR(max_hull_strength);
SVW_SET_SI_VAR(subsys_repair_rate);
SVW_SET_SI_VAR(hull_repair_rate);
SVW_SET_SI_VAR(cmeasure_max);
svt[i]->SetText(sip->shield_icon_index);
svt[i++]->SetSaveLoc(&sip->shield_icon_index, T_ST_ONENTER, Hud_shield_filename_count-1, 0);
SVW_SET_SI_VAR(power_output);
SVW_SET_SI_VAR(max_overclocked_speed);
SVW_SET_SI_VAR(max_weapon_reserve);
SVW_SET_SI_VAR(afterburner_fuel_capacity);
SVW_SET_SI_VAR(afterburner_burn_rate);
SVW_SET_SI_VAR(afterburner_recover_rate);
SVW_SET_SI_VAR(shockwave.inner_rad);
SVW_SET_SI_VAR(shockwave.outer_rad);
SVW_SET_SI_VAR(shockwave.damage);
SVW_SET_SI_VAR(shockwave.blast);
SVW_SET_SI_VAR(explosion_propagates);
SVW_SET_SI_VAR(shockwave.speed);
SVW_SET_SI_VAR(shockwave_count);
SVW_SET_SI_VAR(closeup_zoom);
SVW_SET_SI_VAR(closeup_pos.xyz.x);
SVW_SET_SI_VAR(closeup_pos.xyz.y);
SVW_SET_SI_VAR(closeup_pos.xyz.z);
//Test
/*
SVW_SET_VAR(Objects[Ships[0].objnum].pos.xyz.x);
SVW_SET_VAR(Objects[Ships[0].objnum].pos.xyz.y);
SVW_SET_VAR(Objects[Ships[0].objnum].pos.xyz.z);
SVW_SET_VAR(Objects[Ships[0].objnum].phys_info.vel.xyz.x);
SVW_SET_VAR(Objects[Ships[0].objnum].phys_info.vel.xyz.y);
SVW_SET_VAR(Objects[Ships[0].objnum].phys_info.vel.xyz.z);*/
}
#define SVW_LEFTWIDTH 150
#define SVW_RIGHTWIDTH 100
#define SVW_RIGHTX 160
void zero_ship_var_win(GUIObject *caller)
{
ShipVarWin = NULL;
}
#define SVW_ADD_TEXT_HEADER(name) y += (cwp->AddChild(new Text(name, name, SVW_RIGHTX/2, y + 10, SVW_RIGHTWIDTH))->GetHeight() + 15)
#define SVW_ADD_TEXT(name) cwp->AddChild(new Text(name, name, 0, y, SVW_LEFTWIDTH)); \
svt[i] = (Text*) cwp->AddChild(new Text(std::string (name) + std::string("Editbox"), "", SVW_RIGHTX, y, SVW_RIGHTWIDTH, 12, T_EDITTABLE)); \
y += svt[i++]->GetHeight() + 5 \
void ship_variables_window(Button *caller)
{
if(ShipVarWin != NULL)
return;
GUIObject* cwp = Lab_screen->Add(new Window("Ship variables", gr_screen.max_w - (SVW_RIGHTX + SVW_RIGHTWIDTH + 25), 200));
ShipVarWin = (Window*)cwp;
unsigned int i = 0;
int y = 0;
cwp->AddChild(new Text("Name", "", y, SVW_LEFTWIDTH));
svt[i] = (Text*) cwp->AddChild(new Text("Ship name", "<None>", SVW_RIGHTX, y, SVW_RIGHTWIDTH, 12));
y += svt[i++]->GetHeight() + 5;
SVW_ADD_TEXT("Species");
SVW_ADD_TEXT("Type");
//Physics
SVW_ADD_TEXT_HEADER("Physics");
SVW_ADD_TEXT("Density");
SVW_ADD_TEXT("Damp");
SVW_ADD_TEXT("Rotdamp");
SVW_ADD_TEXT("Max vel (x)");
SVW_ADD_TEXT("Max vel (y)");
SVW_ADD_TEXT("Max vel (z)");
SVW_ADD_TEXT("Warp in speed");
SVW_ADD_TEXT("Warp out speed");
//Other
SVW_ADD_TEXT_HEADER("Stats");
SVW_ADD_TEXT("Shields");
SVW_ADD_TEXT("Hull");
SVW_ADD_TEXT("Subsys repair rate");
SVW_ADD_TEXT("Hull repair rate");
SVW_ADD_TEXT("Countermeasures");
SVW_ADD_TEXT("HUD Icon");
SVW_ADD_TEXT_HEADER("Power");
SVW_ADD_TEXT("Power output");
SVW_ADD_TEXT("Max oclk speed");
SVW_ADD_TEXT("Max weapon reserve");
SVW_ADD_TEXT_HEADER("Afterburner");
SVW_ADD_TEXT("Fuel");
SVW_ADD_TEXT("Burn rate");
SVW_ADD_TEXT("Recharge rate");
SVW_ADD_TEXT_HEADER("Explosion");
SVW_ADD_TEXT("Inner radius");
SVW_ADD_TEXT("Outer radius");
SVW_ADD_TEXT("Damage");
SVW_ADD_TEXT("Blast");
SVW_ADD_TEXT("Propagates");
SVW_ADD_TEXT("Shockwave speed");
SVW_ADD_TEXT("Shockwave count");
//Techroom
SVW_ADD_TEXT_HEADER("Techroom");
SVW_ADD_TEXT("Closeup zoom");
SVW_ADD_TEXT("Closeup pos (x)");
SVW_ADD_TEXT("Closeup pos (y)");
SVW_ADD_TEXT("Closeup pos (z)");
//Test
/*
SVW_ADD_TEXT_HEADER(Ships[0].ship_name);
SVW_ADD_TEXT("Mission pos (x)");
SVW_ADD_TEXT("Mission pos (y)");
SVW_ADD_TEXT("Mission pos (z)");
SVW_ADD_TEXT("Mission vel (x)");
SVW_ADD_TEXT("Mission vel (y)");
SVW_ADD_TEXT("Mission vel (z)");
*/
if(LabViewerShipIndex != -1)
set_ship_variables_ship(&Ship_info[LabViewerShipIndex]);
ShipVarWin->SetCloseFunction(zero_ship_var_win);
}
//*****************************Options Window*******************************
static Window* RenderOptWin = NULL;
void zero_render_opt_win(GUIObject *caller)
{
RenderOptWin = NULL;
}
void make_options_window(Button *caller)
{
if(RenderOptWin != NULL)
return;
GUIObject* ccp;
RenderOptWin = (Window*)Lab_screen->Add(new Window("Options", gr_screen.max_w - 300, 200));
int y = 0;
ccp = RenderOptWin->AddChild(new Checkbox("No lighting", 0, y));
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_NO_LIGHTING);
/*y += ccp->GetHeight() + 10;
ccp = RenderOptWin->AddChild(new Checkbox("No texturing", 0, y));
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_NO_TEXTURING);*/
y += ccp->GetHeight() + 10;
ccp = RenderOptWin->AddChild(new Checkbox("No smoothing", 0, y));
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_NO_SMOOTHING);
y += ccp->GetHeight() + 10;
ccp = RenderOptWin->AddChild(new Checkbox("No Z-buffer", 0, y));
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_NO_ZBUFFER);
y += ccp->GetHeight() + 10;
ccp = RenderOptWin->AddChild(new Checkbox("No culling", 0, y));
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_NO_CULL);
y += ccp->GetHeight() + 10;
ccp = RenderOptWin->AddChild(new Checkbox("No Fogging", 0, y));
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_NO_FOGGING);
y += ccp->GetHeight() + 10;
ccp = RenderOptWin->AddChild(new Checkbox("Wireframe", 0, y));
if (!Cmdline_nohtl)
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_SHOW_OUTLINE_HTL | MR_NO_POLYS);
else
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_SHOW_OUTLINE | MR_NO_POLYS);
y += ccp->GetHeight() + 10;
ccp = RenderOptWin->AddChild(new Checkbox("Transparent", 0, y));
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_ALL_XPARENT);
y += ccp->GetHeight() + 10;
ccp = RenderOptWin->AddChild(new Checkbox("Away norms transparent", 0, y));
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_EDGE_ALPHA);
y += ccp->GetHeight() + 10;
ccp = RenderOptWin->AddChild(new Checkbox("Toward norms transparent", 0, y));
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_CENTER_ALPHA);
y += ccp->GetHeight() + 10;
ccp = RenderOptWin->AddChild(new Checkbox("Show pivots", 0, y));
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_SHOW_PIVOTS);
y += ccp->GetHeight() + 10;
ccp = RenderOptWin->AddChild(new Checkbox("Show paths", 0, y));
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_SHOW_PATHS);
y += ccp->GetHeight() + 10;
ccp = RenderOptWin->AddChild(new Checkbox("Show bay paths", 0, y));
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_BAY_PATHS);
y += ccp->GetHeight() + 10;
ccp = RenderOptWin->AddChild(new Checkbox("Show radius", 0, y));
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_SHOW_RADIUS);
/*y += ccp->GetHeight() + 10;
ccp = RenderOptWin->AddChild(new Checkbox("Show damage", 0, y));
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_SHOW_DAMAGE);*/
y += ccp->GetHeight() + 10;
ccp = RenderOptWin->AddChild(new Checkbox("Show shields", 0, y));
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_SHOW_SHIELDS);
/*y += ccp->GetHeight() + 10;
ccp = RenderOptWin->AddChild(new Checkbox("Show thrusters", 0, y));
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_SHOW_THRUSTERS);*/
y += ccp->GetHeight() + 10;
ccp = RenderOptWin->AddChild(new Checkbox("Show invisible faces", 0, y));
((Checkbox*)ccp)->SetFlag(&ModelFlags, MR_SHOW_INVISIBLE_FACES);
RenderOptWin->SetCloseFunction(zero_render_opt_win);
}
//*****************************Shiplist Window*******************************
static Window* ShipClassWin = NULL;
void zero_ship_class_win(GUIObject *caller)
{
ShipClassWin = NULL;
}
void ships_make_window(Button* caller)
{
if(ShipClassWin != NULL)
return;
//GUIObject* cgp;
ShipClassWin = (Window*)Lab_screen->Add(new Window("Ship classes", 50, 50));
Tree* cmp = (Tree*)ShipClassWin->AddChild(new Tree("Ship tree", 0, 0));
TreeItem *ctip, *stip;
TreeItem **species_nodes = new TreeItem*[Num_species+1];
int i,j;
//Add species nodes
for(i = 0; i < Num_species; i++)
{
species_nodes[i] = cmp->AddItem(NULL, Species_info[i].species_name, 0, false);
}
//Just in case. I don't actually think this is possible though.
species_nodes[Num_species] = cmp->AddItem(NULL, "Other", 0, false);
//Now add the ships
std::string lod_name;
char buf[8];
for(i = 0; i < Num_ship_classes; i++)
{
if(Ship_info[i].species >= 0 && Ship_info[i].species < Num_species)
stip = species_nodes[Ship_info[i].species];
else
stip = species_nodes[Num_species];
ctip = cmp->AddItem(stip, Ship_info[i].name, i, false);
for(j = 0; j < Ship_info[i].num_detail_levels; j++)
{
itoa(j, buf, 10);
lod_name = "LOD ";
lod_name += buf;
cmp->AddItem(ctip, lod_name, j, false, change_ship_lod);
}
}
//Get rid of any empty nodes
//No the <= is not a mistake :)
for(i = 0; i <= Num_species; i++)
{
if(!species_nodes[i]->HasChildren())
{
delete species_nodes[i];
}
}
ShipClassWin->SetCloseFunction(zero_ship_class_win);
}
//*****************************Description Window*******************************
static Window* DescWin = NULL;
static Text* DescText = NULL;
void zero_descwin(GUIObject* caller)
{
DescWin = NULL;
DescText = NULL;
}
void make_another_window(Button* caller)
{
if(DescWin != NULL)
return;
DescWin = (Window*)Lab_screen->Add(new Window("Description", gr_screen.max_w - gr_screen.max_w/3 - 50, gr_screen.max_h - gr_screen.max_h/6 - 50, gr_screen.max_w/3, gr_screen.max_h/6));
DescText = (Text*)DescWin->AddChild(new Text("Description Text", "No ship selected.", 0, 0));
if(LabViewerShipIndex != -1)
{
DescText->SetText(Ship_info[LabViewerShipIndex].tech_desc);
DescWin->SetCaption(Ship_info[LabViewerShipIndex].name);
//DescText->SetSaveStringPtr(&Ship_info[LabViewerShipIndex].tech_desc, T_ST_ONENTER, T_ST_MALLOC);
}
DescText->SetCloseFunction(zero_descwin);
}
//*****************************Subsystem Window*******************************
//WMC - disabled because I don't feel like making it work right now
/*static Text *sst[NUM_SHIP_VARIABLES];
static int ssn = 0;
#define SSW_LEFTWIDTH 150
#define SSW_RIGHTWIDTH 100
#define SSW_RIGHTX 160
#define SSW_SET_MS_VAR(var) sst[i]->SetText(msp->var); \
sst[i++]->SetSaveLoc(&msp->var, T_ST_ONENTER)
#define SSW_ADD_TEXT(name) cwp->AddChild(new Text(name, name, 0, y, SSW_LEFTWIDTH)); \
sst[ssn] = (Text*) cwp->AddChild(new Text(std::string (name) + std::string("Editbox"), "", SSW_RIGHTX, y, SSW_RIGHTWIDTH, 12, T_EDITTABLE)); \
y += sst[ssn++]->GetHeight() + 5
static Window* ShipSubsysWin = NULL;
static Tree* ShipSubsysTree = NULL;
void ship_zero_subsys(GUIObject* caller)
{
ShipSubsysWin = NULL;
}
void ship_change_subsys(Tree *caller)
{
ship_info *sip = &Ship_info[LabViewerShipIndex];
model_subsystem *msp = &sip->subsystems[(int)(caller->GetSelectedItem()->GetData())];
int i = 0;
sst[i++]->SetText(std::string(msp->name));
SSW_SET_MS_VAR(radius);
SSW_SET_MS_VAR(turn_rate);
}
void ship_update_subsys_window(ship_info *sip)
{
ShipSubsysTree->ClearItems();
int i;
//Add species nodes
ShipSubsysTree->ClearItems();
for(i = 0; i < sip->n_subsystems; i++)
{
ShipSubsysTree->AddItem(NULL, sip->subsystems[i].subobj_name, i, false, ship_change_subsys);
}
}
void ship_subsys_window(Button* caller)
{
if(ShipSubsysWin != NULL)
return;
Window * cwp = ShipSubsysWin = (Window*)Lab_screen->Add(new Window("Ship subsystems", 200, 200));
ShipSubsysTree = (Tree*)ShipSubsysWin->AddChild(new Tree("Ship tree", 0, 0));
int y = 200;
cwp->AddChild(new Text("Name", "", y, SSW_LEFTWIDTH));
sst[ssn] = (Text*) cwp->AddChild(new Text("Subsys name", "<None>", SSW_RIGHTX, y, SSW_RIGHTWIDTH, 12));
y += sst[ssn++]->GetHeight() + 5;
SSW_ADD_TEXT("Radius");
SSW_ADD_TEXT("Turn rate");
if(LabViewerShipIndex != -1)
ship_update_subsys_window(&Ship_info[LabViewerShipIndex]);
ShipSubsysWin->SetCloseFunction(ship_zero_subsys);
}
*/
//*****************************Ship display stuff*******************************
void labviewer_change_model(char* model_fname, int lod=0, int ship_index=-1)
{
if(LabViewerModelNum != -1)
{
model_page_out_textures(LabViewerModelNum);
model_unload(LabViewerModelNum);
}
LabViewerModelNum = model_load(model_fname, 0, NULL, 0);
LabViewerModelLOD = lod;
LabViewerShipIndex = ship_index;
}
void change_ship_lod(Tree* caller)
{
int ship_index = (int)(caller->GetSelectedItem()->GetParentItem()->GetData());
labviewer_change_model(Ship_info[ship_index].pof_file
, caller->GetSelectedItem()->GetData()
, ship_index);
if(DescText != NULL && DescWin != NULL)
{
DescWin->SetCaption(Ship_info[LabViewerShipIndex].name);
DescText->SetText(Ship_info[LabViewerShipIndex].tech_desc);
//DescText->SetSaveStringPtr(&Ship_info[LabViewerShipIndex].tech_desc, T_ST_ONENTER, T_ST_MALLOC);
}
if(ShipOptWin != NULL)
{
set_ship_flags_ship(&Ship_info[LabViewerShipIndex]);
}
if(ShipVarWin != NULL)
{
set_ship_variables_ship(&Ship_info[LabViewerShipIndex]);
}
//WMC - disabled because I don't feel like making it work right now
/*
if(ShipSubsysWin != NULL)
{
ship_update_subsys_window(&Ship_info[LabViewerShipIndex]);
}
*/
}
//*****************************Weapon list*******************************
void change_weapon(Tree* caller);
static Window* WeapClassWin = NULL;
void zero_weap_class_win(GUIObject *caller)
{
WeapClassWin = NULL;
}
void weaps_make_window(Button* caller)
{
if(WeapClassWin != NULL)
return;
//GUIObject* cgp;
WeapClassWin = (Window*)Lab_screen->Add(new Window("Weapon classes", 50, 50));
Tree* cmp = (Tree*)WeapClassWin->AddChild(new Tree("Weapon tree", 0, 0));
TreeItem *cwip, *stip;
//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 & WIF_BEAM)
stip = type_nodes[WP_BEAM];
else
stip = type_nodes[Weapon_info[i].subtype];
cwip = cmp->AddItem(stip, Weapon_info[i].name, i, false, change_weapon);
}
//Get rid of any empty nodes
//No the <= is not a mistake :)
for(i = 0; i < Num_weapon_subtypes; i++)
{
if(!type_nodes[i]->HasChildren())
{
delete type_nodes[i];
}
}
WeapClassWin->SetCloseFunction(zero_weap_class_win);
}
//*****************************Weapon Variables Window*******************************
static Window* WeapVarWin = NULL;
#define NUM_WEAP_VARIABLES 50
Text *wvt[NUM_WEAP_VARIABLES];
#define WVW_SET_WI_VAR(var) wvt[i]->SetText(wip->var); \
wvt[i++]->SetSaveLoc(&wip->var, T_ST_ONENTER)
#define WVW_SET_VAR(var) wvt[i]->SetText(var); \
wvt[i++]->SetSaveLoc(&var, T_ST_ONENTER)
void weap_set_variables(weapon_info *wip)
{
unsigned int i=0;
wvt[i++]->SetText(std::string(wip->name));
wvt[i]->SetText(wip->subtype);
wvt[i++]->SetSaveLoc(&wip->subtype, T_ST_ONENTER, Num_weapon_subtypes-1, 0);
WVW_SET_WI_VAR(mass);
WVW_SET_WI_VAR(max_speed);
WVW_SET_WI_VAR(lifetime);
WVW_SET_WI_VAR(weapon_range);
WVW_SET_WI_VAR(WeaponMinRange);
WVW_SET_WI_VAR(fire_wait);
WVW_SET_WI_VAR(damage);
WVW_SET_WI_VAR(armor_factor);
WVW_SET_WI_VAR(shield_factor);
WVW_SET_WI_VAR(subsystem_factor);
WVW_SET_WI_VAR(damage_type_idx);
WVW_SET_WI_VAR(shockwave.speed);
WVW_SET_WI_VAR(turn_time);
WVW_SET_WI_VAR(fov);
WVW_SET_WI_VAR(min_lock_time);
WVW_SET_WI_VAR(lock_pixels_per_sec);
WVW_SET_WI_VAR(catchup_pixels_per_sec);
WVW_SET_WI_VAR(catchup_pixel_penalty);
WVW_SET_WI_VAR(swarm_count);
WVW_SET_WI_VAR(SwarmWait);
}
#define WVW_LEFTWIDTH 150
#define WVW_RIGHTWIDTH 100
#define WVW_RIGHTX 160
void zero_weap_var_win(GUIObject *caller)
{
WeapVarWin = NULL;
}
#define WVW_ADD_TEXT_HEADER(name) y += (cwp->AddChild(new Text(name, name, WVW_RIGHTX/2, y + 10, WVW_RIGHTWIDTH))->GetHeight() + 15)
#define WVW_ADD_TEXT(name) cwp->AddChild(new Text(name, name, 0, y, SVW_LEFTWIDTH)); \
wvt[i] = (Text*) cwp->AddChild(new Text(std::string (name) + std::string("Editbox"), "", WVW_RIGHTX, y, WVW_RIGHTWIDTH, 12, T_EDITTABLE)); \
y += wvt[i++]->GetHeight() + 5 \
void weap_variables_window(Button *caller)
{
if(WeapVarWin != NULL)
return;
GUIObject* cwp = Lab_screen->Add(new Window("Weapon variables", gr_screen.max_w - (WVW_RIGHTX + WVW_RIGHTWIDTH + 25), 200));
WeapVarWin = (Window*)cwp;
unsigned int i = 0;
int y = 0;
cwp->AddChild(new Text("Name", "", y, WVW_LEFTWIDTH));
wvt[i] = (Text*) cwp->AddChild(new Text("Weapon name", "<None>", WVW_RIGHTX, y, WVW_RIGHTWIDTH, 12));
y += wvt[i++]->GetHeight() + 5;
WVW_ADD_TEXT("Subtype");
//Physics
WVW_ADD_TEXT_HEADER("Physics");
WVW_ADD_TEXT("Mass");
WVW_ADD_TEXT("Max speed");
WVW_ADD_TEXT("Lifetime");
WVW_ADD_TEXT("Range");
WVW_ADD_TEXT("Min Range");
WVW_ADD_TEXT_HEADER("Damage");
WVW_ADD_TEXT("Fire wait");
WVW_ADD_TEXT("Damage");
WVW_ADD_TEXT("Armor factor");
WVW_ADD_TEXT("Shield factor");
WVW_ADD_TEXT("Subsys factor");
WVW_ADD_TEXT_HEADER("Armor");
WVW_ADD_TEXT("Damage type");
WVW_ADD_TEXT_HEADER("Shockwave");
WVW_ADD_TEXT("Speed");
WVW_ADD_TEXT_HEADER("Missiles");
WVW_ADD_TEXT("Turn time");
WVW_ADD_TEXT("FOV");
WVW_ADD_TEXT("Min locktime");
WVW_ADD_TEXT("Pixels/sec");
WVW_ADD_TEXT("Catchup pixels/sec");
WVW_ADD_TEXT("Catchup pixel pen.");
WVW_ADD_TEXT("Swarm count");
WVW_ADD_TEXT("Swarm wait");
if(Selected_weapon_index != -1)
weap_set_variables(&Weapon_info[Selected_weapon_index]);
WeapVarWin->SetCloseFunction(zero_weap_var_win);
}
//*****************************Weapon thingy*******************************
void change_weapon(Tree* caller)
{
Selected_weapon_index = (int)(caller->GetSelectedItem()->GetData());
if(Weapon_info[Selected_weapon_index].render_type == WRT_POF)
{
labviewer_change_model(Weapon_info[Selected_weapon_index].pofbitmap_name);
}
if(WeapVarWin != NULL)
{
weap_set_variables(&Weapon_info[Selected_weapon_index]);
}
}
//************************Ship renderer****************************
extern float View_zoom;
static int Trackball_mode = 1;
static int Trackball_active = 0;
void show_ship(float frametime)
{
static float LabViewerShipRot = 0.0f;
static matrix LabViewerOrient = IDENTITY_MATRIX;
if(LabViewerModelNum == -1) {
int w, h;
gr_get_string_size(&w, &h, "Viewer off");
gr_string(gr_screen.clip_right - w, gr_screen.clip_bottom - h, "Viewer off", false);
return;
}
/*if(sip == NULL)
{
draw_model_icon(LabViewerModelNum, ModelFlags, .5f / 1.25f, 0, 0, gr_screen.clip_right, gr_screen.clip_bottom);
return;
}*/
float rev_rate;
angles rot_angles, view_angles;
int z;
ship_info *sip = NULL;
if(LabViewerShipIndex > -1) {
sip = &Ship_info[LabViewerShipIndex];
}
// get correct revolution rate
rev_rate = REVOLUTION_RATE;
if(sip != NULL)
{
z = sip->flags;
if (z & SIF_BIG_SHIP) {
rev_rate *= 1.7f;
}
if (z & SIF_HUGE_SHIP) {
rev_rate *= 3.0f;
}
}
// rotate the ship as much as required for this frame
if (Trackball_active) {
int dx, dy;
matrix mat1, mat2;
mouse_get_delta(&dx, &dy);
if (dx || dy) {
vm_trackball(-dx, -dy, &mat1);
vm_matrix_x_matrix(&mat2, &mat1, &LabViewerOrient);
LabViewerOrient = mat2;
}
}
else
{
LabViewerShipRot += PI2 * frametime / rev_rate;
while (LabViewerShipRot > PI2){
LabViewerShipRot -= 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(&LabViewerOrient, &view_angles);
rot_angles.p = 0.0f;
rot_angles.b = 0.0f;
rot_angles.h = LabViewerShipRot;
vm_rotate_matrix_by_angles(&LabViewerOrient, &rot_angles);
}
// gr_set_clip(Tech_ship_display_coords[gr_screen.res][0], Tech_ship_display_coords[gr_screen.res][1], Tech_ship_display_coords[gr_screen.res][2], Tech_ship_display_coords[gr_screen.res][3]);
//gr_set_clip(Ship_anim_coords[gr_screen.res][0], Ship_anim_coords[gr_screen.res][1], Tech_ship_display_coords[gr_screen.res][2], Tech_ship_display_coords[gr_screen.res][3]);
// render the ship
g3_start_frame(1);
if(sip != NULL) {
g3_set_view_matrix(&sip->closeup_pos, &vmd_identity_matrix, sip->closeup_zoom * 1.3f);
}
else
{
//FIND THE LARGEST RADIUS
polymodel *pm = model_get(LabViewerModelNum);
bsp_info *bs = NULL; //tehe
float largest_radius = 0.0f;
for(int i = 0; i < pm->n_models; i++)
{
if(!pm->submodel[i].is_thruster)
{
bs = &pm->submodel[i];
if(bs->rad > largest_radius)
largest_radius = bs->rad;
break;
}
}
//MAKE A VECTOR FROM IT
vec3d closeup_pos;
closeup_pos.xyz.x = 0.0f;
closeup_pos.xyz.y = 0.0f;
closeup_pos.xyz.z = -(largest_radius);
g3_set_view_matrix(&closeup_pos, &vmd_identity_matrix, PI/2.0f);
}
if (!Cmdline_nohtl) gr_set_proj_matrix( (4.0f/9.0f) * 3.14159f * View_zoom, gr_screen.aspect*(float)gr_screen.clip_width/(float)gr_screen.clip_height, 0.1f, Max_draw_distance);
if (!Cmdline_nohtl) gr_set_view_matrix(&Eye_position, &Eye_matrix);
// lighting for techroom
light_reset();
vec3d light_dir = vmd_zero_vector;
light_dir.xyz.y = 1.0f;
light_add_directional(&light_dir, 0.65f, 1.0f, 1.0f, 1.0f);
// light_filter_reset();
light_rotate_all();
// lighting for techroom
model_set_outline_color(255, 255, 255);
model_clear_instance(LabViewerModelNum);
model_set_detail_level(LabViewerModelLOD);
model_render(LabViewerModelNum, &LabViewerOrient, &vmd_zero_vector, ModelFlags);
if (!Cmdline_nohtl)
{
gr_end_view_matrix();
gr_end_proj_matrix();
}
g3_end_frame();
//gr_reset_clip();
}
void get_out_of_lab(Button* caller)
{
gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
}
//***************************************
static bool Lab_in_mission;
void lab_init()
{
if(gameseq_get_pushed_state() == GS_STATE_GAME_PLAY)
Lab_in_mission = true;
else
Lab_in_mission = false;
beam_pause_sounds();
//If we were viewing a ship, load 'er up
if(LabViewerShipIndex != -1)
{
LabViewerModelNum = model_load(Ship_info[LabViewerShipIndex].pof_file, 0, NULL);
}
//If you want things to stay as you left them, uncomment this and "delete Lab_screen"
//of course, you still need to delete it somewhere else (ie when Freespace closes)
/*
if(Lab_screen != NULL)
{
GUI_system->PushScreen(Lab_screen);
return;
}
*/
//We start by creating the screen/toolbar
Lab_screen = GUI_system.PushScreen(new GUIScreen("Lab"));
GUIObject *cwp;
GUIObject *cbp;
cwp = Lab_screen->Add(new Window("Toolbar", 0, 0, -1, -1, WS_NOTITLEBAR | WS_NONMOVEABLE));
int x = 0;
cbp = cwp->AddChild(new Button("Ship classes", 0, 0, ships_make_window));
x += cbp->GetWidth() + 10;
cbp = cwp->AddChild(new Button("Class Description", x, 0, make_another_window));
x += cbp->GetWidth() + 10;
if(!Lab_in_mission)
{
cbp = cwp->AddChild(new Button("Render options", x, 0, make_options_window));
x += cbp->GetWidth() + 10;
}
cbp = cwp->AddChild(new Button("Class options", x, 0, ship_flags_window));
x += cbp->GetWidth() + 10;
cbp = cwp->AddChild(new Button("Class variables", x, 0, ship_variables_window));
//WMC - disabled because I don't feel like making it work right now
/*
x += cbp->GetWidth() + 10;
cbp = cwp->AddChild(new Button("Class subsystems", x, 0, ship_subsys_window));
*/
x += cbp->GetWidth() + 10;
cbp = cwp->AddChild(new Button("Exit", x, 0, get_out_of_lab));
cwp = Lab_screen->Add(new Window("Weapons toolbar", 0, cwp->GetHeight(), -1, -1, WS_NOTITLEBAR | WS_NONMOVEABLE));
x = 0;
cbp = cwp->AddChild(new Button("Weapon classes", 0, 0, weaps_make_window));
x += cbp->GetWidth() + 10;
cbp = cwp->AddChild(new Button("Weapon variables", x, 0, weap_variables_window));
}
extern void game_render_frame_setup(vec3d *eye_pos, matrix *eye_orient);
extern void game_render_frame(vec3d *eye_pos, matrix *eye_orient);
void lab_do_frame(float frametime)
{
gr_clear();
if(Lab_in_mission)
{
vec3d eye_pos;
matrix eye_orient;
game_render_frame_setup(&eye_pos, &eye_orient);
game_render_frame( &eye_pos, &eye_orient );
}
else
{
show_ship(frametime);
}
if(GUI_system.OnFrame(frametime, Trackball_active==0 ? true : false, false) == GSOF_NOTHINGPRESSED && mouse_down(MOUSE_LEFT_BUTTON))
{
Trackball_active = 1;
Trackball_mode = 1;
}
else
{
Trackball_active = 0;
}
gr_flip();
}
void lab_close()
{
delete Lab_screen;
if(LabViewerModelNum != -1)
{
model_page_out_textures(LabViewerModelNum);
//model_unload(LabViewerModelNum);
}
LabViewerModelNum = -1;
beam_unpause_sounds();
//audiostream_unpause_all();
game_flush();
}