/**
* This is an example of program that uses cake library.
* In this file, the coder has to write the main function, create the window
* (for instance by using GLUT like here), define the keys, manage the mouse
* behaviour, order the map loading, and make the main loop for update and redraw.
*/
#ifdef WIN32
#pragma comment(lib, "cake/glsetup/lib/glut32.lib") // Link for GLUT 3.7.6
#ifdef _DEBUG
#pragma comment(lib, "obj_files/caked.lib") // Link for cake library
#else
#pragma comment(lib, "obj_files/cake.lib") // Link for cake library
#endif
#endif
#include "cake/alias.h" // aliases
#include "cake/app.h" // application
#include "cake/cake.h" // main cake header
#include "cake/client.h" // clients
#include "cake/commands.h" // commands
#include "cake/console.h" // console
#include "cake/definitions.h" // cake definitions
#include "cake/demo.h" // demo support
#include "cake/files.h" // files support
#include "cake/framework.h" // framework
#include "cake/logfile.h" // logfile
#include "cake/math.h" // math funcs
#include "cake/mem.h" // memory
#include "cake/overlay.h" // overlay
#include "cake/render.h" // render
#include "cake/sound.h" // sound/music support
#include "cake/system.h" // exceptions
#include "cake/timer.h" // timer
#include "cake/vars.h" // variables
#include "cake/world.h" // world
#include "cake/glsetup/glut.h" // OpenGL + GLUT
#define DEFAULT_MUSIC "music/sonic1.wav" // default music when no map is loaded
//-----------------------------------------------------------------------------
// Variables
//-----------------------------------------------------------------------------
// App and world stuff
App* app = NULL; // main application
int preview = -1; // map preview state
// clients stuff
int nstartpos, currstartpos; // client start pos
// inputs
Var invertMouseX("invertMouseX", -1, VF_PERSISTENT); // mouse x inversion
Var invertMouseY("invertMouseY", -1, VF_PERSISTENT); // mouse y inversion
struct { int x, y; } mousepos; // mouse x and y position
bool AutoCenterMouse = true; // the mouse is always centered
bool lButton = false, mButton = false, rButton = false; // mouse buttons state
int dx, dy; // mouse rot backup
Var mouse_speed("mouse_speed", 0.5f, VF_PERSISTENT); // camera rotation speed (if camera is rotated with mouse)
Var zoomspeed("zoomspeed", 300, VF_PERSISTENT); // zoom speed
int lastkey; // last key pressed backup
typedef enum { KEYUP = 0, KEYDOWN = 1 } key_state; // keyboard key state
key_state up, down, left, right, pgnup, pgndown, zoom; // keys that use keystate system (to avoid the dependance to keyboard repetition speed)
// console
int histLine; // commands history scrolling value
Var consoleKey("consoleKey", 96, VF_PERSISTENT); // key used for console opening/closing
int tabmode = 1; // console tabulation mode
// window
int window_index; // window index
int width, height; // window width and height
int toppos, leftpos; // window position (top and pos) - not used
int freq; // window frequency
int colorbits; // window color bits (8, 16, 24 or 32)
bool fullscr; // is window in fullscreen mode
int backupWidth, backupHeight; // backup used for maximisation/reduce
#define nwidths 17
#define nheights 17
#define ncolors 5
#define nfreqs 11
int widths[nwidths] = {320, 400, 480, 512, 640, 720, 768, 800, 856, 960, 1024, 1152, 1200, 1280, 1600, 1920, 2048};
int heights[nheights] = {200, 240, 300, 360, 384, 400, 480, 576, 600, 720, 768, 864, 900, 960, 1080, 1200, 1536};
int colors[ncolors] = {8, 15, 16, 24, 32};
int freqs[nfreqs] = {43, 50, 56, 60, 70, 72, 75, 85, 95, 100, 120};
//-----------------------------------------------------------------------------
// Functions declarations
//-----------------------------------------------------------------------------
void AddCommands(void);
void RegisterVariables(void);
void Keyboard(unsigned char key, int x, int y);
void KeyboardUp(unsigned char key, int x, int y);
void KeyboardSpec(int key, int x, int y);
void KeyboardSpecUp(int key, int x, int y);
void MouseClic(int button, int state, int x, int y);
void MouseMove(int x, int y);
void MouseMovePassive(int x, int y);
static void Draw(void);
void Reshape(int w, int h);
void Idle(void);
void Init();
void ParseArgs(int argc, char *argv[]);
void Shut(int status);
int ScreenShot(char *fName, int hideconsole = 1);
void CheckForAllAvailableResolutions(void);
void ToggleFullScreen(void);
//-----------------------------------------------------------------------------
// Commands declarations
//-----------------------------------------------------------------------------
void cmd_quit(int argc, char *argv[]);
void cmd_load(int argc, char *argv[]);
void cmd_reload(int argc, char *argv[]);
void cmd_defineviewport(int argc, char *argv[]);
void cmd_noclip(int argc, char *argv[]);
void cmd_lockfrustum(int argc, char *argv[]);
void cmd_unload(int argc, char *argv[]);
void cmd_record(int argc, char *argv[]);
void cmd_stopdemo(int argc, char *argv[]);
void cmd_demo(int argc, char *argv[]);
void cmd_demodump(int argc, char *argv[]);
void cmd_shaderpreview(int argc, char *argv[]);
void cmd_resolutions(int argc, char *argv[]);
void cmd_screenshot(int argc, char *argv[]);
void cmd_fontsize (int argc, char *argv[]);
void cmd_tabmode (int argc, char *argv[]);
void cmd_togglemousecenter (int argc, char *argv[]);
void cmd_preview (int argc, char *argv[]);
void cmd_credits(int argc, char *argv[]);
void cmd_speed(int argc, char *argv[]);
void cmd_fov(int argc, char *argv[]);
void cmd_zoomlimit(int argc, char *argv[]);
void cmd_tpl(int argc, char *argv[]);
void cmd_acceleration(int argc, char *argv[]);
void cmd_friction(int argc, char *argv[]);
void cmd_getpos(int argc, char *argv[]);
void cmd_getrot(int argc, char *argv[]);
void cmd_setpos(int argc, char *argv[]);
void cmd_setrot(int argc, char *argv[]);
void cmd_addpos(int argc, char *argv[]);
void cmd_addangle(int argc, char *argv[]);
void cmd_getfps(int argc, char *argv[]);
void cmd_setnclients(int argc, char *argv[]);
void cmd_entityreport(int argc, char *argv[]);
void cmd_bspreport(int argc, char *argv[]);
void cmd_loadplayer(int argc, char *argv[]);
// Save a screenshot in an output file
int ScreenShot(char *fName, int hideconsole)
{
unsigned char *fBuffer3 = (unsigned char*) cake_malloc(3*width*height*sizeof(unsigned char), "Main::ScreenShot.fBuffer3");
if (!fBuffer3) return 0; // no memory allocated for image data
memset(fBuffer3, 0, 3*width*height*sizeof(unsigned char));
char fBMPName[255];
strncpy(fBMPName, fName, 255);
_strlwr(fBMPName); // makes the filename lowercase
if (strcmp(&fBMPName[strlen(fBMPName)-4], ".bmp")) // add a ".bmp" extension if not already present
sprintf(fBMPName, "%s.bmp", fBMPName);
enum_ConsoleStates consolestate = gConsole->GetState();
if (hideconsole) gConsole->SetState(CLOSED);
Draw();
glutSwapBuffers();
// read our image data from the frame buffer
glReadPixels(0, 0,
width, height,
GL_RGB,
GL_UNSIGNED_BYTE,
fBuffer3);
// write the image data to a .bmp file
if (!WriteBitmapFile(fBMPName, width, height, 3, fBuffer3)) return 0;
cake_free(fBuffer3);
gConsole->SetState(consolestate);
return 1;
}
// Displays a list of all available resolutions
void CheckForAllAvailableResolutions(void)
{
char resolution[128];
gConsole->Insertln("List of available resolutions :");
gLogFile->OpenFile();
for (int i = 0; i < nwidths; ++i)
for (int j = 0; j < nheights; ++j)
for (int k = 0; k < ncolors; ++k)
for (int l = 0; l < nfreqs; ++l)
{
sprintf(resolution, "%dx%d:%d@%d", widths[i], heights[j], colors[k], freqs[l]);
glutGameModeString(resolution);
if (glutGameModeGet(GLUT_GAME_MODE_POSSIBLE))
{
gConsole->Insertln("%s ", resolution);
}
}
gLogFile->CloseFile();
}
// Toggles the mode fullscreen/windowed
void ToggleFullScreen(void)
{
fullscr = !fullscr;
if (fullscr)
{
backupWidth = width;
backupHeight = height;
glutFullScreen();
}
else
{
width = backupWidth;
height = backupHeight;
glutReshapeWindow(width, height);
}
}
//-----------------------------------------------------------------------------
// Keyboard
// The following functions manage the keyboard.
//-----------------------------------------------------------------------------
void Keyboard(unsigned char key, int x, int y)
{
// Console opening/closing
if (key == (unsigned char) consoleKey.ivalue)
{
if (!app->GetWorld()) { beep(); return; }
if (gConsole->ToggleState() == OPENING) histLine = 0;
lastkey = key;
return;
}
// if console is active and opened, keyboard actions are done in the console
if ((gConsole->GetState() == OPEN || gConsole->GetState() == OPENING) && gConsole->isActive)
{
bool do_return = true;
switch (key)
{
case 13:
char ConsoleBufferCommand[CONSOLE_LINELENGTH];
strncpy(ConsoleBufferCommand, gConsole->GetCurrentCommand(), CONSOLE_LINELENGTH);
if (strlen(ConsoleBufferCommand) > 0)
{
histLine = 0;
if (!gCommands->ExecuteCommand(ConsoleBufferCommand))
gConsole->Insertln("\"%s\" : ^5Command not found", ConsoleBufferCommand);
}
break;
case 27:
if (strlen(gConsole->GetCurrentCommand()))
gConsole->ReInitCurrentCommand();
else if (app->GetWorld())
{
gConsole->Close();
gConsole->ReInitCurrentCommand();
}
else do_return = false;
break;
case 8: gConsole->DelChar(); break;
case 9:
if (tabmode)
{
if (lastkey == key)
{
if (glutGetModifiers() == GLUT_ACTIVE_SHIFT)
gCommands->PrevSolution();
else
gCommands->NextSolution();
}
else
{
gCommands->FirstSolution(gConsole->GetCurrentCommand());
}
}
else
{
gCommands->CompleteCommand(gConsole->GetCurrentCommand());
}
break;
default:
gConsole->AddChar((char) key);
break;
}
lastkey = key;
if (do_return) return;
}
// if console is not active, keyboard is attached to engine (or clients camera)
switch (key)
{
case 27:
if (!app->StopDemo()) Shut(0);
break;
case 32:
// zoom
zoom = KEYDOWN;
break;
case 'a':
case 'A':
// move left
left = KEYDOWN;
break;
case 'w':
case 'W':
// move forwards
up = KEYDOWN;
break;
case 'd':
case 'D':
// move right
right = KEYDOWN;
break;
case 's':
case 'S':
// move backwards
down = KEYDOWN;
break;
case 'e':
case 'E':
// move up
pgnup = KEYDOWN;
break;
case 'q':
case 'Q':
// move down
pgndown = KEYDOWN;
break;
case 'f':
case 'F':
// toggle fps display
gVars->SetKeyValue("cg_drawFPS", 1-gVars->IntForKey("cg_drawFPS"));
break;
case 't':
case 'T':
// toggle time display
gVars->SetKeyValue("cg_drawtime", 1-gVars->IntForKey("cg_drawtime"));
break;
case 'G':
case 'g':
// changes wireframe mode
gVars->SetKeyValue("r_grid", 1-gVars->IntForKey("r_grid"));
break;
case 'B':
case 'b':
gVars->SetKeyValue("r_showbbox", 1-gVars->IntForKey("r_showbbox"));
break;
case 'c':
case 'C':
// toggle clear mode
gVars->SetKeyValue("r_clear", 1-gVars->IntForKey("r_clear"));
gConsole->Insertln("r_clear value changed to %d", gVars->IntForKey("r_clear"));
break;
case 'n':
case 'N':
// change current client (has effect only if clients are unlinked)
app->SetCurrentClient((app->GetCurrentClientIndex()+1)%app->GetNumClients());
gConsole->Insertln("Current client : %d", app->GetCurrentClientIndex());
break;
case 'p':
case 'P':
// change start pos for current client
if (!app->GetWorld()) break;
if (app->GetWorld()->GetNumStartPos())
{
if (key == 'P')
{
currstartpos = (currstartpos-1)%app->GetWorld()->GetNumStartPos();
if (currstartpos < 0) currstartpos = app->GetWorld()->GetNumStartPos()-1;
}
else currstartpos = (currstartpos+1)%app->GetWorld()->GetNumStartPos();
app->GetWorld()->SetStartPos(app->GetCurrentClient(), currstartpos);
gConsole->Insertln("using start pos %d/%d for client %d", currstartpos+1, app->GetWorld()->GetNumStartPos(), app->GetCurrentClientIndex());
}
break;
case 'm':
case 'M':
{
Client *client = app->GetCurrentClient();
if (client)
{
client->flying = !client->flying;
gConsole->Insertln("client flying state: %s", client->flying?"ON":"OFF");
}
}
break;
default:
gConsole->Insertln("%d : invalid key", key);
break;
}
lastkey = key;
}
//-----------------------------------------------------------------------------
// KeyboardUp
//-----------------------------------------------------------------------------
void KeyboardUp(unsigned char key, int x, int y)
{
switch (key)
{
case 'a':
case 'A':
left = KEYUP;
break;
case 'w':
case 'W':
up = KEYUP;
break;
case 'd':
case 'D':
right = KEYUP;
break;
case 's':
case 'S':
down = KEYUP;
break;
case 'e':
case 'E':
pgnup = KEYUP;
break;
case 'q':
case 'Q':
pgndown = KEYUP;
break;
case 32:
zoom = KEYUP;
break;
default:
// should not happen
break;
}
}
//-----------------------------------------------------------------------------
// KeyboardSpec
//-----------------------------------------------------------------------------
void KeyboardSpec(int key, int x, int y)
{
// if console is active and onpened
if ((gConsole->GetState() == OPEN ||
gConsole->GetState() == OPENING) &&
gConsole->isActive)
{
switch (key)
{
case GLUT_KEY_UP:
++histLine;
if (histLine > gCommands->GetNbrCommHistLines())
{
histLine = gCommands->GetNbrCommHistLines();
beep();
}
gConsole->SetCurrentCommand(gCommands->GetHistoryLine(histLine));
break;
case GLUT_KEY_DOWN:
--histLine;
if (histLine < 0)
{
histLine = 0;
beep();
}
gConsole->SetCurrentCommand(gCommands->GetHistoryLine(histLine));
break;
case GLUT_KEY_LEFT:
gConsole->MoveCursor(LEFT);
break;
case GLUT_KEY_RIGHT:
gConsole->MoveCursor(RIGHT);
break;
case GLUT_KEY_HOME:
if (glutGetModifiers() == GLUT_ACTIVE_CTRL) gConsole->ScrollConsole(TOP);
else gConsole->MoveCursor(C_EXTREM_LEFT);
break;
case GLUT_KEY_END:
if (glutGetModifiers() == GLUT_ACTIVE_CTRL) gConsole->ScrollConsole(BOTTOM);
else gConsole->MoveCursor(C_EXTREM_RIGHT);
break;
case GLUT_KEY_PAGE_UP:
gConsole->ScrollConsole(UP);
break;
case GLUT_KEY_PAGE_DOWN:
gConsole->ScrollConsole(DOWN);
break;
default:
// does nothing
break;
}
lastkey = key;
return;
}
histLine = 0;
switch (key)
{
case GLUT_KEY_F4:
gCommands->RepeatLastCommand();
break;
case 100:
left = KEYDOWN;
break;
case 101:
up = KEYDOWN;
break;
case 102:
right = KEYDOWN;
break;
case 103:
down = KEYDOWN;
break;
case 104:
pgnup = KEYDOWN;
break;
case 105:
pgndown = KEYDOWN;
break;
default:
gConsole->Insertln("%d : invalid key", key);
break;
}
lastkey = key;
}
//-----------------------------------------------------------------------------
// KeyboardSpecUp
//-----------------------------------------------------------------------------
void KeyboardSpecUp(int key, int x, int y)
{
switch (key)
{
case 100:
left = KEYUP;
break;
case 101:
up = KEYUP;
break;
case 102:
right = KEYUP;
break;
case 103:
down = KEYUP;
break;
case 104:
pgnup = KEYUP;
break;
case 105:
pgndown = KEYUP;
break;
default:
break;
}
}
//-----------------------------------------------------------------------------
// MouseClic
// Manage the mouse clics.
//-----------------------------------------------------------------------------
void MouseClic(int button, int state, int x, int y)
{
if (preview >= 0)
{
gFramework->shaders.DeleteShader(preview);
preview = -1;
}
switch (button)
{
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN)
{
lButton = true;
dx = x;
dy = y;
}
else if (state == GLUT_UP) lButton = false;
break;
case GLUT_RIGHT_BUTTON:
if (state == GLUT_DOWN)
{
rButton = true;
dx = x;
dy = y;
Client *client = app->GetCurrentClient();
if (client) client->Jump();
}
else if (state == GLUT_UP) rButton = false;
break;
default:
break;
}
}
//-----------------------------------------------------------------------------
// MouseMove
// Clients camera rotation following mouse
//-----------------------------------------------------------------------------
void MouseMove(int x, int y)
{
if (lButton && !fullscr)
{
Client *client = app->GetCurrentClient();
if (client) client->MoveMouseXY((float) (dx-x), (float) (dy-y));
dx = x;
dy = y;
}
else
{
mousepos.x = x;
mousepos.y = y;
}
}
//-----------------------------------------------------------------------------
// MouseMovePassive
// Updates the mouse x and y position
//-----------------------------------------------------------------------------
void MouseMovePassive(int x, int y)
{
mousepos.x = x;
mousepos.y = y;
}
//-----------------------------------------------------------------------------
// Draw
// Calls the display refresh.
//-----------------------------------------------------------------------------
static void Draw(void)
{
if (!width || !height) return;
gRender->BeginFrame(); // clears the screen and the z buffer
int numclients = app->GetNumClients();
app->DrawWorld();
app->DrawInterface();
if (preview >= 0)
{
gOver->Quad(preview, width-196, height-156, 156, 128);
gFramework->Render(); // used for displaying the gOver with framework shaders (quite tricky, I know !!)
}
gRender->EndFrame(); // flips the screen and force the flushing
glutSwapBuffers();
}
//-----------------------------------------------------------------------------
// Reshape
//-----------------------------------------------------------------------------
void Reshape(int w, int h)
{
if (gLogFile) gLogFile->Insert("reshaping to %dx%d\n", w, h);
width = w;
height = h;
gRender->SetWindowSettings(w, h);
if (gConsole) gConsole->Resize(-1, app->GetWorld()?h/2:h);
app->InitClients();
Draw();
}
//-----------------------------------------------------------------------------
// Idle
//-----------------------------------------------------------------------------
void Idle(void)
{
Client *client = app->GetCurrentClient();
if (client)
{
// Updates camera rotation
if (fullscr && AutoCenterMouse)
{
client->MoveMouseXY(invertMouseX.fvalue*(mousepos.x-(float)width /2.f)*mouse_speed.fvalue,
invertMouseY.fvalue*(mousepos.y-(float)height/2.f)*mouse_speed.fvalue);
glutWarpPointer((int)((float)width/2.f), (int)((float)height/2.f));
}
// Updates camera position
if (up == KEYDOWN && down == KEYUP) client->MoveForward();
else if (up == KEYUP && down == KEYDOWN) client->MoveBackward();
if (right == KEYDOWN && left == KEYUP) client->MoveRight();
else if (right == KEYUP && left == KEYDOWN) client->MoveLeft();
if (pgnup == KEYDOWN && pgndown == KEYUP) client->MoveUp();
else if (pgnup == KEYUP && pgndown == KEYDOWN) client->MoveDown();
if (zoom == KEYDOWN) client->Zoom(-zoomspeed.fvalue);
else if (zoom == KEYUP) client->Zoom(zoomspeed.fvalue);
}
glutPostRedisplay();
}
//-----------------------------------------------------------------------------
// Init
//-----------------------------------------------------------------------------
void Init()
{
if (!gRender->Init(glutSwapBuffers)) ThrowException(FATAL_ERROR, "Couldn't initialize render !");
gConsole->Insertln("
^6----- Application starts --------------------------------------");
// Initialize the keys
up = down = left = right = pgnup = pgndown = zoom = KEYUP;
// Set window settings
gRender->SetWindowSettings(width, height, colorbits, freq);
// Load console shaders and intialize the console
gConsole->SetFont(gConsole->shaders.AddShader("gfx/2d/bigchars", 0, 0, FACETYPE_MESH), 16, 16);
gConsole->SetBack(gConsole->shaders.AddShader("console", 0, 0, FACETYPE_MESH));
gConsole->Init();
// Load framework shaders
gFramework->SetFont(gFramework->shaders.AddShader("gfx/2d/bigchars", 0, 0, FACETYPE_MESH), NORMAL_CHAR);
gFramework->SetFont(gFramework->shaders.AddShader("menu/art/font1_prop", 0, 0, FACETYPE_MESH), PROPFONT1_CHAR);
gFramework->SetFont(gFramework->shaders.AddShader("menu/art/font1_prop_glo", 0, 0, FACETYPE_MESH), PROPFONT1_GLOW_CHAR);
gFramework->SetFont(gFramework->shaders.AddShader("menu/art/font2_prop", 0, 0, FACETYPE_MESH), PROPFONT2_CHAR);
gFramework->Init();
if (fullscr) glutWarpPointer((int)((float)width/2.f), (int)((float) height/2.f));
}
void ParseArgs(int argc, char *argv[])
{
bool displayinfos = true;
gConsole->Insertln("Parsing the command line...");
for (int i = 1; i < argc; ++i)
{
// +map
if (!stricmp(argv[i], "+map"))
{
if (++i >= argc)
{
gConsole->Insertln("^1Missing argument for \"+map\" command");
displayinfos = true;
}
else if (argv[i][0] == '+')
{
gConsole->Insertln("^1Invalid argument for \"+map\" command");
displayinfos = true;
}
else if (app->LoadMap(argv[i])) displayinfos = false;
else displayinfos = true;
}
// +demo
if (!stricmp(argv[i], "+demo"))
{
int j;
for (j = 1; j < argc; ++j)
{
if (!stricmp(argv[j], "+map"))
{
gConsole->Insertln("^1You cannot use \"+demo\" and \"+map\" simultaneously; \"+demo\" argument ignored");
displayinfos = true;
break;
}
}
if (j >= argc) // if +map not found
{
if (++i >= argc)
{
gConsole->Insertln("^1Missing argument for \"+demo\" command");
displayinfos = true;
}
else if (argv[i][0] == '+')
{
gConsole->Insertln("^1Invalid argument for \"+demo\" command");
displayinfos = true;
}
else
{
// compute last argument for function
j = i+1;
while (j < argc && argv[j][0] != '+') ++j;
cmd_demo(j-i+1, argv+i-1); // the keyword 'demo' must be included
displayinfos = false;
}
}
}
}
if (displayinfos)
{
setBGMusic(DEFAULT_MUSIC); // Load a default music
gConsole->Insertln("^2You can get a list of available maps with command \"bsplist\".");
gConsole->Insertln("^2Map can be loaded with command \"load mapname\".");
gConsole->Insertln("^2Commands names are displayed with \"cmdlist\".");
gConsole->Insertln("^2Variables names are displayed with \"varlist\".");
gConsole->SetState(OPEN);
}
}
//-----------------------------------------------------------------------------
// Shut
//-----------------------------------------------------------------------------
void Shut(int status)
{
gConsole->Insertln("
^6----- Application shuting down --------------------------------");
// Unregistering variables
gVars->UnregisterVar(invertMouseX);
gVars->UnregisterVar(invertMouseY);
gVars->UnregisterVar(mouse_speed);
gVars->UnregisterVar(zoomspeed);
gVars->UnregisterVar(consoleKey);
app->Shut();
delete app;
if (fullscr)
glutLeaveGameMode();
else
glutDestroyWindow(window_index);
exit(status);
}
//-----------------------------------------------------------------------------
// main
// Creates the window and the application
//-----------------------------------------------------------------------------
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
// Creates the application. It is important to create it very early in the
// code because it reads the "config.ini" file, register variables, read
// available packages, etc.
app = new App;
if (!app) ThrowException(ALLOCATION_ERROR, "Couldn't create the application");
RegisterVariables();
AddCommands();
app->Init();
// Get window sizes from variables (initialized with "config.ini" values)
width = gVars->IntForKey("v_width");
height = gVars->IntForKey("v_height");
toppos = gVars->IntForKey("v_top");
leftpos = gVars->IntForKey("v_left");
freq = gVars->IntForKey("v_hz");
colorbits = gVars->IntForKey("v_colorBits");
fullscr = (gVars->IntForKey("v_fullscreen"))?true:false;
// Creates the window
if (fullscr)
{
char resolution[128];
sprintf(resolution,
"%dx%d:%d@%d",
width,
height,
colorbits,
freq);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutGameModeString(resolution);
glutEnterGameMode();
glutSetCursor(GLUT_CURSOR_NONE);
}
else
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(width, height);
glutInitWindowPosition(leftpos, toppos);
window_index = glutCreateWindow(_VERSION_);
}
glutReshapeFunc(Reshape);
glutDisplayFunc(Draw);
glutKeyboardFunc(Keyboard);
glutKeyboardUpFunc(KeyboardUp);
glutSpecialUpFunc(KeyboardSpecUp);
glutSpecialFunc(KeyboardSpec);
glutMouseFunc(MouseClic);
glutMotionFunc(MouseMove);
glutPassiveMotionFunc(MouseMovePassive);
glutIdleFunc(Idle);
// Initialize resting values
Init();
// Change the engine mode from initialization to running mode
app->Run();
// Parse the command arguments
ParseArgs(argc, argv);
// runs the main loop
glutMainLoop();
return 0;
}
void RegisterVariables(void)
{
gVars->RegisterVar(invertMouseX);
gVars->RegisterVar(invertMouseY);
gVars->RegisterVar(mouse_speed);
gVars->RegisterVar(zoomspeed);
gVars->RegisterVar(consoleKey);
}
//-----------------------------------------------------------------------------
// Commands
// It is possible to set commands that can be executed from the console
// during engine running. It is very useful for debugging or setting
// evenments during execution. Commands have all the same prototype:
// void commandname(int argc, char *argv[])
// like the main function.
//-----------------------------------------------------------------------------
// Quit the application
void cmd_quit(int argc, char *argv[])
{
Shut(0);
}
// Load a map
void cmd_load(int argc, char *argv[])
{
if (argc > 1)
{
if (app->LoadMap(argv[1]))
{
gConsole->Resize(-1, height/2);
}
else
{
setBGMusic(DEFAULT_MUSIC); // Load a default music
}
}
else gConsole->Insertln("usage: %s ", argv[0]);
}
// Reload the current map
void cmd_reload(int argc, char *argv[])
{
if (app->ReloadMap())
{
gConsole->Resize(-1, height/2);
}
else
{
setBGMusic(DEFAULT_MUSIC); // Load a default music
}
}
void cmd_defineviewport(int argc, char *argv[])
{
if (argc > 5)
{
Client *client = app->GetClient(atoi(argv[1]));
if (client) client->Init(atoi(argv[2]), atoi(argv[3]), atoi(argv[4]), atoi(argv[5]));
else gConsole->Insertln("^1Invalid client index");
}
else gConsole->Insertln("usage: %s ");
}
void cmd_noclip(int argc, char *argv[])
{
int currclient = app->GetCurrentClientIndex();
if (currclient < 0)
{
gConsole->Insert("^1No available client");
return;
}
app->GetClient(currclient)->noclip = !app->GetClient(currclient)->noclip;
gConsole->Insertln("noclip %s for client %d", app->GetClient(currclient)->noclip?"ON":"OFF", currclient);
}
void cmd_lockfrustum(int argc, char *argv[])
{
int currclient = app->GetCurrentClientIndex();
if (currclient < 0)
{
gConsole->Insert("^1No available client");
return;
}
app->GetClient(currclient)->cam.lockfrustum = !app->GetClient(currclient)->cam.lockfrustum;
gConsole->Insertln("frustum lock %s for client %d", app->GetClient(currclient)->cam.lockfrustum?"ON":"OFF", currclient);
}
// Unload the current map
void cmd_unload(int argc, char *argv[])
{
app->UnloadMap();
setBGMusic(DEFAULT_MUSIC); // Load a default music
}
void cmd_record(int argc, char *argv[])
{
app->RecordDemo((argc>1)?(float)atof(argv[1]):0.1f);
}
void cmd_stopdemo(int argc, char *argv[])
{
if (argc > 1) app->StopDemo(argv[1]);
else app->StopDemo();
}
void cmd_demo(int argc, char *argv[])
{
if (argc > 1)
{
int i;
bool looping = false;
for (i = 2; i < argc; ++i)
{
// get last valid value
if (!stricmp(argv[i], "loop")) looping = true;
}
enum_InterpolationMode mode = AUTO_INTERPOLATION;
for (i = 2; i < argc; ++i)
{
// get last valid value
if (!stricmp(argv[i], "linear")) mode = LINEAR_INTERPOLATION;
else if (!stricmp(argv[i], "spline")) mode = SPLINE_INTERPOLATION;
}
app->PlayDemo(argv[1], looping, mode);
}
else gConsole->Insertln("usage: %s {\"loop\"} {\"linear\", \"spline\"}", argv[0]);
}
void cmd_demodump(int argc, char *argv[])
{
if (argc > 1)
{
Demo demo;
demo.DemoDump(argv[1], (argc > 2)?atol(argv[2]):0);
}
}
void cmd_shaderpreview(int argc, char *argv[])
{
if (argc > 1)
{
if (app->GetWorld())
{
preview = gFramework->shaders.AddShader(argv[1], 0, 0, FACETYPE_MESH);
gFramework->Update();
}
else gConsole->Insertln("^6Some shaders require camera position. Camera is created when "
"map is loaded, so load a map to be able to preview shaders.");
}
}
// Display available resolutions
void cmd_resolutions(int argc, char *argv[])
{
CheckForAllAvailableResolutions();
}
// Save a screenshot of current scene (without console)
void cmd_screenshot(int argc, char *argv[])
{
if (argc > 1)
{
if (!ScreenShot(argv[1]))
gConsole->Insertln("^5!! An error occured while trying to save screenshot bitmap.");
}
else gConsole->Insertln("usage: %s ", argv[0]);
}
// Change the fontsize
void cmd_fontsize (int argc, char *argv[])
{
if (argc < 3) return;
gConsole->SetFontSize(atol(argv[1]), atol(argv[2]));
}
// Sets the tabulation key mode for console
void cmd_tabmode (int argc, char *argv[])
{
if (argc > 1)
{
if (!strcmp(argv[1], "0")) tabmode = 0;
else tabmode = 1;
}
}
// Toggles the mouse auto center mode
void cmd_togglemousecenter (int argc, char *argv[])
{
AutoCenterMouse = !AutoCenterMouse;
}
// Displays a preview (levelshot) of an available map
void cmd_preview (int argc, char *argv[])
{
if (argc > 1)
{
char levelshot_name[256] = { '\0' };
sprintf(levelshot_name, "levelshots/%s", argv[1]);
preview = gFramework->shaders.AddShader(levelshot_name, 0, 0, FACETYPE_MESH);
gFramework->Update();
}
}
// Displays credits
void cmd_credits(int argc, char *argv[])
{
gConsole->Insertln("^5Credits:");
gConsole->Insertln("^2Base engine: TITAN PROJECT - Ignacio Castano Aguado");
gConsole->Insertln("^2Addons and new elements: morbac");
gConsole->Insertln("^2With special thanks to: Kaspar, Max, and all cool guys who make demos and tutorials on the web :)");
}
void cmd_speed(int argc, char *argv[])
{
Client *client = app->GetCurrentClient();
if (!client)
{
gConsole->Insert("^1No available client");
return;
}
if (argc > 1) client->max_speed = (float) atof(argv[1]);
else gConsole->Insertln("Client speed: %f", app->GetCurrentClient()->max_speed);
}
void cmd_fov(int argc, char *argv[])
{
Client *client = app->GetCurrentClient();
if (!client)
{
gConsole->Insert("^1No available client");
return;
}
if (argc > 1)
{
client->fov = (float) atof(argv[1]);
client->UpdateCam();
}
else gConsole->Insertln("FOV : %f", client->fov);
}
void cmd_zoomlimit(int argc, char *argv[])
{
Client *client = app->GetCurrentClient();
if (!client)
{
gConsole->Insert("^1No available client");
return;
}
if (argc > 1)
{
client->zoomlimit = (float) atof(argv[1]);
}
else gConsole->Insertln("zoom limit : %f", client->zoomlimit);
}
void cmd_tpl(int argc, char *argv[])
{
Client *client = app->GetCurrentClient();
if (!client)
{
gConsole->Insert("^1No available client");
return;
}
client->pitchLimit = !client->pitchLimit;
}
void cmd_acceleration(int argc, char *argv[])
{
Client *client = app->GetCurrentClient();
if (!client)
{
gConsole->Insert("^1No available client");
return;
}
if (argc > 1) client->acceleration = (float) atof(argv[1]);
else gConsole->Insertln("Client acceleration value: %f", client->acceleration);
}
void cmd_friction(int argc, char *argv[])
{
Client *client = app->GetCurrentClient();
if (!client)
{
gConsole->Insert("^1No available client");
return;
}
if (argc > 1) client->friction = (float) atof(argv[1]);
else gConsole->Insertln("Client friction value: %f", client->friction);
}
void cmd_getpos(int argc, char *argv[])
{
Client *client = app->GetCurrentClient();
if (!client)
{
gConsole->Insert("^1No available client");
return;
}
gConsole->Insertln("Client position : [%f;%f;%f]",
client->cam.pos[0], client->cam.pos[1], client->cam.pos[2]);
}
void cmd_getrot(int argc, char *argv[])
{
Client *client = app->GetCurrentClient();
if (!client)
{
gConsole->Insert("^1No available client");
return;
}
gConsole->Insertln("Client angle : [%f;%f;%f]",
client->cam.rot[PITCH], client->cam.rot[YAW], client->cam.rot[ROLL]);
}
void cmd_setpos(int argc, char *argv[])
{
if (argc > 3)
{
Client *client = app->GetCurrentClient();
if (!client)
{
gConsole->Insert("^1No available client");
return;
}
client->SetPos((float) atof(argv[1]), (float) atof(argv[2]), (float) atof(argv[3]));
}
else gConsole->Insertln("usage: %s ", argv[0]);
}
void cmd_setrot(int argc, char *argv[])
{
if (argc > 3)
{
Client *client = app->GetCurrentClient();
if (!client)
{
gConsole->Insert("^1No available client");
return;
}
client->SetAngle((float) atof(argv[1]), (float) atof(argv[2]), (float) atof(argv[3]));
}
else gConsole->Insertln("usage: %s ", argv[0]);
}
void cmd_addpos(int argc, char *argv[])
{
if (argc > 3)
{
Client *client = app->GetCurrentClient();
if (!client)
{
gConsole->Insert("^1No available client");
return;
}
client->AddPos((float) atof(argv[1]), (float) atof(argv[2]), (float) atof(argv[3]));
}
else if (argc > 2)
{
Client *client = app->GetCurrentClient();
if (!client)
{
gConsole->Insert("^1No available client");
return;
}
client->AddPos((float) atof(argv[1]), (float) atof(argv[2]), 0);
}
else if (argc > 1)
{
Client *client = app->GetCurrentClient();
if (!client)
{
gConsole->Insert("^1No available client");
return;
}
client->AddPos((float) atof(argv[1]), 0, 0);
}
else gConsole->Insertln("usage: %s ", argv[0]);
}
void cmd_addangle(int argc, char *argv[])
{
if (argc > 3)
{
Client *client = app->GetCurrentClient();
if (!client)
{
gConsole->Insert("^1No available client");
return;
}
client->AddAngle((float) atof(argv[1]), (float) atof(argv[2]), (float) atof(argv[3]));
}
if (argc > 2)
{
Client *client = app->GetCurrentClient();
if (!client)
{
gConsole->Insert("^1No available client");
return;
}
client->AddAngle((float) atof(argv[1]), (float) atof(argv[2]), 0);
}
if (argc > 1)
{
Client *client = app->GetCurrentClient();
if (!client)
{
gConsole->Insert("^1No available client");
return;
}
client->AddAngle((float) atof(argv[1]), 0, 0);
}
else gConsole->Insertln("usage: %s ", argv[0]);
}
void cmd_getfps(int argc, char *argv[])
{
gConsole->Insertln("%4.2f fps", app->GetFPS());
}
void cmd_setnclients(int argc, char *argv[])
{
if (argc > 1)
{
int numclients = atol(argv[1]);
// Create the clients
if (numclients <= 0) numclients = 1;
app->CreateClients(numclients);
if ((nstartpos = app->GetWorld()->GetNumStartPos()))
{
currstartpos = 0;
for (int i = 0; i < numclients; ++i)
{
app->GetWorld()->SetStartPos(app->GetClient(i), currstartpos);
currstartpos = (currstartpos+1)%nstartpos;
}
}
}
else gConsole->Insertln("usage: %s ", argv[0]);
}
void cmd_entityreport(int argc, char *argv[])
{
if (app->GetWorld()) app->GetWorld()->GetBSP()->GetEntities()->Report();
else gConsole->Insertln("^1No world !");
}
void cmd_bspreport(int argc, char *argv[])
{
if (app->GetWorld()) app->GetWorld()->GetBSP()->Report();
else gConsole->Insertln("^1No world !");
}
void cmd_loadplayer(int argc, char *argv[])
{
if (!app->GetNumClients())
{
gConsole->Insertln("^5WARNING: No available client !");
return;
}
if (argc > 1)
{
app->GetCurrentClient()->LoadPlayer(argv[1]);
}
else gConsole->Insertln("usage: %s ", argv[0]);
}
// Add the commands to the engine commands list
void AddCommands(void)
{
gCommands->AddCommand("quit", cmd_quit, "exit the application");
gAlias->SetAlias("exit", "quit");
gCommands->AddCommand("map", cmd_load, "load a bsp map");
gAlias->SetAlias("load", "map");
gCommands->AddCommand("map_restart", cmd_reload, "reload the current map");
gAlias->SetAlias("reload", "map_restart");
gCommands->AddCommand("unload", cmd_unload, "unload the current map");
gCommands->AddCommand("noclip", cmd_noclip, "toggle the collisions for clients");
gCommands->AddCommand("lockfrustum", cmd_lockfrustum, "loks the frustum for clients");
gCommands->AddCommand("record", cmd_record, "start recording a demo");
gCommands->AddCommand("stopdemo", cmd_stopdemo, "stop recording a demo");
gCommands->AddCommand("demo", cmd_demo, "play recorded demo");
gCommands->AddCommand("demodump", cmd_demodump, "dump demo file content");
gCommands->AddCommand("preview", cmd_preview, "displays the levelshot of a map (if it exists)");
gCommands->AddCommand("shaderpreview", cmd_shaderpreview, "display a sample of shader");
gCommands->AddCommand("fontsize", cmd_fontsize, "sets the font size");
gCommands->AddCommand("tabmode", cmd_tabmode, "sets the current tabulation key comportement");
gCommands->AddCommand("togglemousecenter", cmd_togglemousecenter, "toggles the mouse autocentering");
gAlias->SetAlias("tmc", "togglemousecenter");
gCommands->AddCommand("credits", cmd_credits, "displays the engine and test program credits");
gCommands->AddCommand("speed", cmd_speed, "defines the moving speed of camera");
gCommands->AddCommand("fov", cmd_fov, "defines the camera fov");
gCommands->AddCommand("zoomlimit", cmd_zoomlimit, "defines the camera zoom limit");
gCommands->AddCommand("togglepitchlimit", cmd_tpl, "toggles the camera rotation limitation on Ox axis");
gAlias->SetAlias("tpl", "togglepitchlimit");
gCommands->AddCommand("accel", cmd_acceleration, "defines the acceleration value of client");
gCommands->AddCommand("friction", cmd_friction, "defines the friction value of client");
gCommands->AddCommand("getpos", cmd_getpos, "gets the current camera position");
gCommands->AddCommand("setpos", cmd_setpos, "sets the current camera position");
gCommands->AddCommand("addpos", cmd_addpos, "increments the current client camera position");
gCommands->AddCommand("getrot", cmd_getrot, "gets the current rotation angle");
gCommands->AddCommand("setrot", cmd_setrot, "sets the current rotation angle");
gCommands->AddCommand("addangle", cmd_addangle, "increments the current client camera angle");
gCommands->AddCommand("getfps", cmd_getfps, "returns the current fps rate");
gCommands->AddCommand("setnclients", cmd_setnclients, "sets the number of clients");
gCommands->AddCommand("resolutions", cmd_resolutions, "displays a list of all available screen resolution");
gCommands->AddCommand("screenshot", cmd_screenshot, "takes a screenshot of current window");
gCommands->AddCommand("entityreport", cmd_entityreport, "writes a report on entities in logfile");
gCommands->AddCommand("bspreport", cmd_bspreport, "writes a report on bsp in logfile");
gCommands->AddCommand("defineviewport", cmd_defineviewport, "define the viewport for a client");
gCommands->AddCommand("loadplayer", cmd_loadplayer, "load player skin, sounds, etc.");
}